From 22ba8ba55799b62b77c69c78db61fb8eee7516bf Mon Sep 17 00:00:00 2001 From: AdrianPotter Date: Fri, 6 Jan 2017 15:17:00 +0000 Subject: [PATCH 01/39] Rename plankton_emulators to lewis_emulators because framework name has changed --- lewis_emulators/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 lewis_emulators/__init__.py diff --git a/lewis_emulators/__init__.py b/lewis_emulators/__init__.py new file mode 100644 index 0000000..3be6bd2 --- /dev/null +++ b/lewis_emulators/__init__.py @@ -0,0 +1 @@ +from __future__ import absolute_import \ No newline at end of file From 6f425de01349e9d00b5fb38db15cf1a25d186989 Mon Sep 17 00:00:00 2001 From: Matt Clarke Date: Thu, 1 Jun 2017 09:49:18 +0100 Subject: [PATCH 02/39] Update __init__.py --- lewis_emulators/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lewis_emulators/__init__.py b/lewis_emulators/__init__.py index 3be6bd2..c396168 100644 --- a/lewis_emulators/__init__.py +++ b/lewis_emulators/__init__.py @@ -1 +1 @@ -from __future__ import absolute_import \ No newline at end of file +from __future__ import absolute_import From 91fdfb655a8b084a0eff00c4b7c66de22c34696c Mon Sep 17 00:00:00 2001 From: Matt Clarke Date: Thu, 8 Jun 2017 12:28:08 +0100 Subject: [PATCH 03/39] Tidied up the formatting for a lot of files --- lewis_emulators/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lewis_emulators/__init__.py b/lewis_emulators/__init__.py index 3be6bd2..c396168 100644 --- a/lewis_emulators/__init__.py +++ b/lewis_emulators/__init__.py @@ -1 +1 @@ -from __future__ import absolute_import \ No newline at end of file +from __future__ import absolute_import From 815d3109120668a38dea2c52832c2367c70adbe1 Mon Sep 17 00:00:00 2001 From: AdrianPotter Date: Mon, 25 Sep 2017 12:25:41 +0100 Subject: [PATCH 04/39] Pin emulators to latest version --- lewis_emulators/lewis_versions.py | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 lewis_emulators/lewis_versions.py diff --git a/lewis_emulators/lewis_versions.py b/lewis_emulators/lewis_versions.py new file mode 100644 index 0000000..79a658b --- /dev/null +++ b/lewis_emulators/lewis_versions.py @@ -0,0 +1,2 @@ +LEWIS_1_1_1 = "1.1.1" +LEWIS_LATEST = LEWIS_1_1_1 \ No newline at end of file From f5543723f3e740322f5e4a956a8e2827b2111b29 Mon Sep 17 00:00:00 2001 From: David Keymer Date: Fri, 23 Mar 2018 17:23:22 +0000 Subject: [PATCH 05/39] Upgrade Lewis --- lewis_emulators/lewis_versions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lewis_emulators/lewis_versions.py b/lewis_emulators/lewis_versions.py index 79a658b..4d572c5 100644 --- a/lewis_emulators/lewis_versions.py +++ b/lewis_emulators/lewis_versions.py @@ -1,2 +1,2 @@ -LEWIS_1_1_1 = "1.1.1" -LEWIS_LATEST = LEWIS_1_1_1 \ No newline at end of file +LEWIS_1_2_0 = "1.2.0" +LEWIS_LATEST = LEWIS_1_2_0 \ No newline at end of file From 45128f561619ff076c87cbf95b71e444923b0eb8 Mon Sep 17 00:00:00 2001 From: esouthren Date: Tue, 3 Apr 2018 16:34:00 +0100 Subject: [PATCH 06/39] Update lewis_versions.py Added new line --- lewis_emulators/lewis_versions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lewis_emulators/lewis_versions.py b/lewis_emulators/lewis_versions.py index 4d572c5..beae6ab 100644 --- a/lewis_emulators/lewis_versions.py +++ b/lewis_emulators/lewis_versions.py @@ -1,2 +1,2 @@ LEWIS_1_2_0 = "1.2.0" -LEWIS_LATEST = LEWIS_1_2_0 \ No newline at end of file +LEWIS_LATEST = LEWIS_1_2_0 From 1a874b3452624865550018148948d15f3e2b74f7 Mon Sep 17 00:00:00 2001 From: Rory-Potter-Tessella Date: Fri, 1 Jun 2018 11:11:57 +0100 Subject: [PATCH 07/39] Changed module name and updated emulator to pass temp test. --- lewis_emulators/__init__.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 lewis_emulators/__init__.py diff --git a/lewis_emulators/__init__.py b/lewis_emulators/__init__.py deleted file mode 100644 index c396168..0000000 --- a/lewis_emulators/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import absolute_import From 59fbcd5089b1c6110822e5ec970d8aab4658349b Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Fri, 15 Jun 2018 13:42:05 +0100 Subject: [PATCH 08/39] Re-add lost init file, with comment saying do not delete. --- lewis_emulators/__init__.py | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 lewis_emulators/__init__.py diff --git a/lewis_emulators/__init__.py b/lewis_emulators/__init__.py new file mode 100644 index 0000000..ad92558 --- /dev/null +++ b/lewis_emulators/__init__.py @@ -0,0 +1,2 @@ +# DO NOT DELETE THIS FILE - LEWIS FRAMEWORK REQUIRES THE DIRECTORY TO BE IMPORTABLE +from __future__ import absolute_import From 4994dc1de1a4781e0660bdb99beca6ae9609bbd8 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Tue, 21 May 2019 15:56:33 +0100 Subject: [PATCH 09/39] Add device to test framework --- tests/tti355.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/tti355.py diff --git a/tests/tti355.py b/tests/tti355.py new file mode 100644 index 0000000..99c22e6 --- /dev/null +++ b/tests/tti355.py @@ -0,0 +1,34 @@ +import unittest + +from utils.channel_access import ChannelAccess +from utils.ioc_launcher import get_default_ioc_dir +from utils.test_modes import TestModes +from utils.testing import get_running_lewis_and_ioc, skip_if_recsim + + +DEVICE_PREFIX = "TTI355_01" + + +IOCS = [ + { + "name": DEVICE_PREFIX, + "directory": get_default_ioc_dir("TTI355"), + "macros": {}, + "emulator": "Tti355", + }, +] + + +TEST_MODES = [TestModes.RECSIM, TestModes.DEVSIM] + + +class Tti355Tests(unittest.TestCase): + """ + Tests for the Tti355 IOC. + """ + def setUp(self): + self._lewis, self._ioc = get_running_lewis_and_ioc("Tti355", DEVICE_PREFIX) + self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX) + + def test_that_fails(self): + self.fail("You haven't implemented any tests!") From d27c2a8b61837ba90a8534b23653cfaab0da4bc4 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Tue, 21 May 2019 15:56:48 +0100 Subject: [PATCH 10/39] Add template emulator --- lewis_emulators/tti355/__init__.py | 5 ++++ lewis_emulators/tti355/device.py | 25 +++++++++++++++++++ lewis_emulators/tti355/interfaces/__init__.py | 3 +++ .../tti355/interfaces/stream_interface.py | 12 +++++++++ lewis_emulators/tti355/states.py | 5 ++++ 5 files changed, 50 insertions(+) create mode 100644 lewis_emulators/tti355/__init__.py create mode 100644 lewis_emulators/tti355/device.py create mode 100644 lewis_emulators/tti355/interfaces/__init__.py create mode 100644 lewis_emulators/tti355/interfaces/stream_interface.py create mode 100644 lewis_emulators/tti355/states.py diff --git a/lewis_emulators/tti355/__init__.py b/lewis_emulators/tti355/__init__.py new file mode 100644 index 0000000..8318ff0 --- /dev/null +++ b/lewis_emulators/tti355/__init__.py @@ -0,0 +1,5 @@ +from .device import SimulatedTti355 +from ..lewis_versions import LEWIS_LATEST + +framework_version = LEWIS_LATEST +__all__ = ['SimulatedTti355'] diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py new file mode 100644 index 0000000..3333ff5 --- /dev/null +++ b/lewis_emulators/tti355/device.py @@ -0,0 +1,25 @@ +from collections import OrderedDict +from states import DefaultState +from lewis.devices import StateMachineDevice + + +class SimulatedTti355(StateMachineDevice): + + def _initialize_data(self): + """ + Initialize all of the device's attributes. + """ + pass + + def _get_state_handlers(self): + return { + 'default': DefaultState(), + } + + def _get_initial_state(self): + return 'default' + + def _get_transition_handlers(self): + return OrderedDict([ + ]) + diff --git a/lewis_emulators/tti355/interfaces/__init__.py b/lewis_emulators/tti355/interfaces/__init__.py new file mode 100644 index 0000000..9323ad2 --- /dev/null +++ b/lewis_emulators/tti355/interfaces/__init__.py @@ -0,0 +1,3 @@ +from .stream_interface import Tti355StreamInterface + +__all__ = ['Tti355StreamInterface'] diff --git a/lewis_emulators/tti355/interfaces/stream_interface.py b/lewis_emulators/tti355/interfaces/stream_interface.py new file mode 100644 index 0000000..479316e --- /dev/null +++ b/lewis_emulators/tti355/interfaces/stream_interface.py @@ -0,0 +1,12 @@ +from lewis.adapters.stream import StreamInterface, Cmd + + +class Tti355StreamInterface(StreamInterface): + + # Commands that we expect via serial during normal operation + commands = { + Cmd("catch_all", "^#9.*$"), # Catch-all command for debugging + } + + def catch_all(self): + pass diff --git a/lewis_emulators/tti355/states.py b/lewis_emulators/tti355/states.py new file mode 100644 index 0000000..e4ca48e --- /dev/null +++ b/lewis_emulators/tti355/states.py @@ -0,0 +1,5 @@ +from lewis.core.statemachine import State + + +class DefaultState(State): + pass From 6dc8d94583578db80d6ebec7fd42033e386dab87 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Wed, 22 May 2019 15:59:14 +0100 Subject: [PATCH 11/39] Started testing emulator --- tests/tti355.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index 99c22e6..0f17e53 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -7,14 +7,14 @@ DEVICE_PREFIX = "TTI355_01" - +DEVICE_NAME = "tti355" IOCS = [ { "name": DEVICE_PREFIX, "directory": get_default_ioc_dir("TTI355"), "macros": {}, - "emulator": "Tti355", + "emulator": DEVICE_NAME, }, ] @@ -27,8 +27,13 @@ class Tti355Tests(unittest.TestCase): Tests for the Tti355 IOC. """ def setUp(self): - self._lewis, self._ioc = get_running_lewis_and_ioc("Tti355", DEVICE_PREFIX) + self._lewis, self._ioc = get_running_lewis_and_ioc(DEVICE_NAME, DEVICE_PREFIX) self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX) - def test_that_fails(self): - self.fail("You haven't implemented any tests!") + #def test_that_fails(self): + #self.fail("You haven't implemented any tests!") + + def test_WHEN_voltage_is_set_THEN_voltage_setpoint_updates(self): + for volt in [0, 1, 2]: + self.ca.set_pv_value("VOLTAGE:SP", volt) + self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", volt) From a3cd5577183a282520bd35b3de62ce89886f940c Mon Sep 17 00:00:00 2001 From: Kirkham Date: Wed, 22 May 2019 16:00:16 +0100 Subject: [PATCH 12/39] Started building emulator --- lewis_emulators/tti355/device.py | 56 ++++++++++++++++++- .../tti355/interfaces/stream_interface.py | 37 ++++++++++-- 2 files changed, 87 insertions(+), 6 deletions(-) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index 3333ff5..d0cb818 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -1,6 +1,7 @@ from collections import OrderedDict from states import DefaultState from lewis.devices import StateMachineDevice +from random import random class SimulatedTti355(StateMachineDevice): @@ -9,7 +10,22 @@ def _initialize_data(self): """ Initialize all of the device's attributes. """ - pass + self.ident = "THURLBY EX355P, " + self.voltage = 1.00 + self.voltage_sp = 1.00 + self.current = 1.00 + self.current_sp = 1.00 + self.output_status = "OUT OFF" + self.output_status_sp = "OUT OFF" + self.output_mode = "M CC" + self.output_mode_sp = "M CC" + self.error = 0 + + self._max_voltage = 35.0 + self._max_current = 5.0 + + def reset(self): + self._initialize_data() def _get_state_handlers(self): return { @@ -23,3 +39,41 @@ def _get_transition_handlers(self): return OrderedDict([ ]) + def get_voltage(self): + if self.output_status == "OUT ON": + self.voltage = self.voltage_sp + random() + else: + self.voltage = random() + return self.voltage() + + def set_voltage_sp(self, voltage): + voltage = round(float(voltage), 2) + if voltage > self._max_voltage: + self.error = 2 + else: + self.voltage_sp = voltage + + + def get_current(self): + pass + + def set_current_sp(self): + pass + + def set_output_status(self): + pass + + def get_output_status(self): + pass + + def set_output_mode(self): + pass + + def get_output_mode(self): + pass + + def get_ident(self): + pass + + def get_error(self): + pass \ No newline at end of file diff --git a/lewis_emulators/tti355/interfaces/stream_interface.py b/lewis_emulators/tti355/interfaces/stream_interface.py index 479316e..19715b5 100644 --- a/lewis_emulators/tti355/interfaces/stream_interface.py +++ b/lewis_emulators/tti355/interfaces/stream_interface.py @@ -1,12 +1,39 @@ -from lewis.adapters.stream import StreamInterface, Cmd +from lewis.adapters.stream import StreamInterface +from lewis_emulators.utils.command_builder import CmdBuilder class Tti355StreamInterface(StreamInterface): - # Commands that we expect via serial during normal operation - commands = { - Cmd("catch_all", "^#9.*$"), # Catch-all command for debugging - } + in_terminator = "\n" + out_terminator = "\r\n" + + def __init__(self): + + super(Tti355StreamInterface, self).__init__() + # Commands that we expect via serial during normal operation + self.commands = { + #CmdBuilder(self.get).escape("*IDN?").eos().build(), + CmdBuilder(self.get_voltage_sp).escape("V?").eos().build(), + CmdBuilder(self.set_voltage_sp).escape("V ").float().eos().build(), + CmdBuilder(self.get_voltage).escape("VO?").eos().build(), + } def catch_all(self): pass + + def handle_error(self, request, error): + err_string = "command was: {}, error was: {}: {}\n".format(request, error.__class__.__name__, error) + print(err_string) + self.log.error(err_string) + return err_string + + def get_voltage(self): + volt = self.device.get_voltage() + return "V{:.2f}".format(volt) + + def get_voltage_sp(self): + return "V{:.2f}".format(self.device.voltage_sp) + + def set_voltage_sp(self, voltage_sp): + self.device.set_voltage_sp(float(voltage_sp)) + return self.out_terminator From 0aa12b7cbd7b909bfbe3025abb99981f9be84892 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Fri, 24 May 2019 16:26:06 +0100 Subject: [PATCH 13/39] Added additional features --- lewis_emulators/tti355/device.py | 53 ++++++++++--------- .../tti355/interfaces/stream_interface.py | 50 +++++++++++++++-- 2 files changed, 74 insertions(+), 29 deletions(-) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index d0cb818..120be27 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -10,17 +10,14 @@ def _initialize_data(self): """ Initialize all of the device's attributes. """ - self.ident = "THURLBY EX355P, " + self.identity = "THURLBY EX355P, " self.voltage = 1.00 self.voltage_sp = 1.00 self.current = 1.00 self.current_sp = 1.00 self.output_status = "OUT OFF" - self.output_status_sp = "OUT OFF" - self.output_mode = "M CC" - self.output_mode_sp = "M CC" - self.error = 0 - + self.output_mode = "M CV" + self.error = 0# "ERR {}".format(0) self._max_voltage = 35.0 self._max_current = 5.0 @@ -44,36 +41,42 @@ def get_voltage(self): self.voltage = self.voltage_sp + random() else: self.voltage = random() - return self.voltage() + return self.voltage def set_voltage_sp(self, voltage): voltage = round(float(voltage), 2) if voltage > self._max_voltage: - self.error = 2 + self.error = 2# "ERR {}".format(2) else: self.voltage_sp = voltage - def get_current(self): - pass + if self.output_status == "OUT ON": + self.current = self.current_sp + random() + else: + self.current = random() + return self.current - def set_current_sp(self): - pass + def set_current_sp(self, current): + current = round(float(current), 2) + print(self.current_sp) + if current > self._max_current: + self.error = 2# "ERR {}".format(2) + print(self.current_sp) + else: + self.current_sp = current - def set_output_status(self): - pass - + def set_output_status(self, status): + if status == "ON": + self.output_status = "OUT ON" + elif status == "OFF": + self.output_status = "OUT OFF" + def get_output_status(self): - pass - - def set_output_mode(self): - pass + return self.output_status def get_output_mode(self): - pass - - def get_ident(self): - pass + return self.output_mode - def get_error(self): - pass \ No newline at end of file + def get_error_status(self): + return self.error \ No newline at end of file diff --git a/lewis_emulators/tti355/interfaces/stream_interface.py b/lewis_emulators/tti355/interfaces/stream_interface.py index 19715b5..d4fb88d 100644 --- a/lewis_emulators/tti355/interfaces/stream_interface.py +++ b/lewis_emulators/tti355/interfaces/stream_interface.py @@ -10,17 +10,28 @@ class Tti355StreamInterface(StreamInterface): def __init__(self): super(Tti355StreamInterface, self).__init__() + # Commands that we expect via serial during normal operation self.commands = { - #CmdBuilder(self.get).escape("*IDN?").eos().build(), + CmdBuilder(self.get_identity).escape("*IDN?").eos().build(), + CmdBuilder(self.get_voltage_sp).escape("V?").eos().build(), CmdBuilder(self.set_voltage_sp).escape("V ").float().eos().build(), CmdBuilder(self.get_voltage).escape("VO?").eos().build(), + + CmdBuilder(self.get_current_sp).escape("I?").eos().build(), + CmdBuilder(self.set_current_sp).escape("I ").float().eos().build(), + CmdBuilder(self.get_current).escape("IO?").eos().build(), + + CmdBuilder(self.get_outputstatus).escape("OUT?").eos().build(), + CmdBuilder(self.set_outputstatus_on).escape("ON").eos().build(), + CmdBuilder(self.set_outputstatus_off).escape("OFF").eos().build(), + + CmdBuilder(self.get_output_mode).escape("M?").eos().build(), + CmdBuilder(self.get_error_status).escape("ERR?").eos().build(), + } - def catch_all(self): - pass - def handle_error(self, request, error): err_string = "command was: {}, error was: {}: {}\n".format(request, error.__class__.__name__, error) print(err_string) @@ -37,3 +48,34 @@ def get_voltage_sp(self): def set_voltage_sp(self, voltage_sp): self.device.set_voltage_sp(float(voltage_sp)) return self.out_terminator + + def get_current(self): + current = self.device.get_current() + return "I{:.2f}".format(current) + + def get_current_sp(self): + return "I{:.2f}".format(self.device.current_sp) + + def set_current_sp(self, current_sp): + self.device.set_current_sp(float(current_sp)) + return self.out_terminator + + def get_outputstatus(self): + return self.device.get_output_status() + + def set_outputstatus_on(self): + self.device.set_output_status("ON") + return self.out_terminator + + def set_outputstatus_off(self): + self.device.set_output_status("OFF") + return self.out_terminator + + def get_output_mode(self): + return self.device.get_output_mode() + + def get_error_status(self): + return self.device.get_error_status() + + def get_identity(self): + return self.device.identity \ No newline at end of file From 1014e17d8dcd234648e10b5332fe223e8797be3f Mon Sep 17 00:00:00 2001 From: Kirkham Date: Fri, 24 May 2019 16:26:56 +0100 Subject: [PATCH 14/39] added additional tests --- tests/tti355.py | 70 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index 0f17e53..63fdfd9 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -1,5 +1,5 @@ import unittest - +from parameterized import parameterized from utils.channel_access import ChannelAccess from utils.ioc_launcher import get_default_ioc_dir from utils.test_modes import TestModes @@ -29,11 +29,71 @@ class Tti355Tests(unittest.TestCase): def setUp(self): self._lewis, self._ioc = get_running_lewis_and_ioc(DEVICE_NAME, DEVICE_PREFIX) self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX) + self._lewis.backdoor_run_function_on_device("reset") + + + @parameterized.expand([ + [0], + [1,], + [2,] + ]) + def test_WHEN_voltage_is_set_THEN_voltage_setpoint_updates(self, volt): + self.ca.set_pv_value("VOLTAGE:SP", volt) + self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", volt) + + @parameterized.expand([ + [0,], + [0.1,], + [0.2,] + ]) + def test_WHEN_current_setpoint_is_set_THEN_current_readback_updates(self, current): + self.ca.set_pv_value("CURRENT:SP", current) + self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) - #def test_that_fails(self): - #self.fail("You haven't implemented any tests!") + @parameterized.expand([ + ["ON",], + ["OFF",] + ]) + def test_WHEN_outputstatus_is_set_THEN_outputstatus_readback_updates(self, status): + self.ca.set_pv_value("OUTPUTSTATUS:SP", status) + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", status) + + @skip_if_recsim("Relies on emulator logic") + def test_WHEN_voltage_setpoint_is_set_outside_max_limits_THEN_device_in_error_state(self): + self.ca.set_pv_value("VOLTAGE:SP", 38.0) + self.ca.assert_that_pv_is("ERROR", "Cmd outside limits") + + @skip_if_recsim("Relies on emulator logic") + def test_WHEN_current_setpoint_is_set_outside_max_limits_THEN_device_in_error_state(self): + self.ca.set_pv_value("CURRENT:SP", 7.0) + self.ca.assert_that_pv_is("ERROR", "Cmd outside limits") + - def test_WHEN_voltage_is_set_THEN_voltage_setpoint_updates(self): - for volt in [0, 1, 2]: + def test_WHEN_identity_requested_THEN_correct_identity_returned(self): + expected_identity = "THURLBY EX355P, " + self.ca.assert_that_pv_is("IDENT", expected_identity) + + def test_WHEN_ioc_in_error_state + xpected_value = 300 + self._lewis.backdoor_set_on_device("pressure", expected_value) + + self.ca.assert_that_pv_is("PRESSURE", expected_value, timeout=1) + """ + def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage_is_close_to_the_voltage_setpoint(self): + self.set_init_state(10, 0.1, 20, 1, "On") + self.ca.assert_that_pv_is("OUTPUT", "On") + for volt in [0, 5, 10]: self.ca.set_pv_value("VOLTAGE:SP", volt) + self.ca.assert_that_pv_is("OUTPUT", "On") self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", volt) + self.ca.assert_that_pv_is_number("VOLTAGE", volt, tolerance=0.1) + + def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_current_is_close_to_the_current_setpoint(self): + self.set_init_state(10, 0.1, 20, 1, "On") + self.ca.assert_that_pv_is("OUTPUT", "On") + for curr in [0, 0.1, 0.2]: + self.ca.set_pv_value("CURRENT:SP", curr) + self.ca.assert_that_pv_is("OUTPUT", "On") + self.ca.assert_that_pv_is("CURRENT:SP:RBV", curr) + self.ca.assert_that_pv_is_number("CURRENT", curr, tolerance=0.01) + """ \ No newline at end of file From b8e5a5e437240065dd39dd6beb61025ae790802a Mon Sep 17 00:00:00 2001 From: Kirkham Date: Tue, 28 May 2019 13:36:06 +0100 Subject: [PATCH 15/39] amended emulator to respond as the device does to error status requests --- lewis_emulators/tti355/device.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index 120be27..346e28c 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -17,7 +17,7 @@ def _initialize_data(self): self.current_sp = 1.00 self.output_status = "OUT OFF" self.output_mode = "M CV" - self.error = 0# "ERR {}".format(0) + self.error = "ERR {}".format(0) self._max_voltage = 35.0 self._max_current = 5.0 @@ -38,30 +38,30 @@ def _get_transition_handlers(self): def get_voltage(self): if self.output_status == "OUT ON": - self.voltage = self.voltage_sp + random() + self.voltage = self.voltage_sp + ((random()-0.5)/1000) else: - self.voltage = random() + self.voltage = ((random()-0.5)/1000) return self.voltage def set_voltage_sp(self, voltage): voltage = round(float(voltage), 2) if voltage > self._max_voltage: - self.error = 2# "ERR {}".format(2) + self.error = "ERR {}".format(2) else: self.voltage_sp = voltage def get_current(self): if self.output_status == "OUT ON": - self.current = self.current_sp + random() + self.current = self.current_sp + ((random()-0.5)/1000) else: - self.current = random() + self.current = ((random()-0.5)/1000) return self.current def set_current_sp(self, current): current = round(float(current), 2) print(self.current_sp) if current > self._max_current: - self.error = 2# "ERR {}".format(2) + self.error = "ERR {}".format(2) print(self.current_sp) else: self.current_sp = current From 891a1e9da229424e7e30120502792c3684b25978 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Tue, 28 May 2019 13:36:50 +0100 Subject: [PATCH 16/39] added additional tests --- tests/tti355.py | 89 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index 63fdfd9..22ffef6 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -58,42 +58,77 @@ def test_WHEN_outputstatus_is_set_THEN_outputstatus_readback_updates(self, statu self.ca.set_pv_value("OUTPUTSTATUS:SP", status) self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", status) - @skip_if_recsim("Relies on emulator logic") + @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_voltage_setpoint_is_set_outside_max_limits_THEN_device_in_error_state(self): self.ca.set_pv_value("VOLTAGE:SP", 38.0) self.ca.assert_that_pv_is("ERROR", "Cmd outside limits") - @skip_if_recsim("Relies on emulator logic") + @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_current_setpoint_is_set_outside_max_limits_THEN_device_in_error_state(self): self.ca.set_pv_value("CURRENT:SP", 7.0) self.ca.assert_that_pv_is("ERROR", "Cmd outside limits") - - + + @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_identity_requested_THEN_correct_identity_returned(self): expected_identity = "THURLBY EX355P, " self.ca.assert_that_pv_is("IDENT", expected_identity) - def test_WHEN_ioc_in_error_state - xpected_value = 300 - self._lewis.backdoor_set_on_device("pressure", expected_value) + @skip_if_recsim("Behaviour cannot be simulated in Recsim") + def test_WHEN_ioc_in_error_state_2_THEN_correct_error_state_returned(self): + expected_value = "Cmd outside limits" + self._lewis.backdoor_set_on_device("error", "ERR 2") + self.ca.assert_that_pv_is("ERROR", expected_value, timeout=1) - self.ca.assert_that_pv_is("PRESSURE", expected_value, timeout=1) - """ - def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage_is_close_to_the_voltage_setpoint(self): - self.set_init_state(10, 0.1, 20, 1, "On") - self.ca.assert_that_pv_is("OUTPUT", "On") - for volt in [0, 5, 10]: - self.ca.set_pv_value("VOLTAGE:SP", volt) - self.ca.assert_that_pv_is("OUTPUT", "On") - self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", volt) - self.ca.assert_that_pv_is_number("VOLTAGE", volt, tolerance=0.1) - - def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_current_is_close_to_the_current_setpoint(self): - self.set_init_state(10, 0.1, 20, 1, "On") - self.ca.assert_that_pv_is("OUTPUT", "On") - for curr in [0, 0.1, 0.2]: - self.ca.set_pv_value("CURRENT:SP", curr) - self.ca.assert_that_pv_is("OUTPUT", "On") - self.ca.assert_that_pv_is("CURRENT:SP:RBV", curr) - self.ca.assert_that_pv_is_number("CURRENT", curr, tolerance=0.01) - """ \ No newline at end of file + @skip_if_recsim("Behaviour cannot be simulated in Recsim") + def test_WHEN_ioc_in_error_state_1_THEN_correct_error_state_returned(self): + expected_value = "Cmd not recognised" + self._lewis.backdoor_set_on_device("error", "ERR 1") + self.ca.assert_that_pv_is("ERROR", expected_value, timeout=1) + + @skip_if_recsim("Behaviour cannot be simulated in Recsim") + def test_WHEN_ioc_not_in_error_state_THEN_correct_error_state_returned(self): + expected_value = "No error" + self._lewis.backdoor_set_on_device("error", "ERR 0") + self.ca.assert_that_pv_is("ERROR", expected_value, timeout=1) + + @skip_if_recsim("Behaviour cannot be simulated in Recsim") + def test_WHEN_ioc_in_constant_current_mode_THEN_correct_mode_returned(self): + expected_value = "Constant Current" + self._lewis.backdoor_set_on_device("output_mode", "M CC") + self.ca.assert_that_pv_is("OUTPUTMODE", expected_value, timeout=1) + + @skip_if_recsim("Behaviour cannot be simulated in Recsim") + def test_WHEN_ioc_in_constant_voltage_mode_THEN_correct_mode_returned(self): + expected_value = "Constant Voltage" + self._lewis.backdoor_set_on_device("output_mode", "M CV") + self.ca.assert_that_pv_is("OUTPUTMODE", expected_value, timeout=1) + + @parameterized.expand([ + [0,], + [5,], + [10,] + ]) + def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage_is_close_to_the_voltage_setpoint(self, voltage): + + self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + self.ca.set_pv_value("VOLTAGE:SP", voltage) + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", voltage) + self.ca.assert_that_pv_is_number("VOLTAGE", voltage, tolerance=0.1) + + @parameterized.expand([ + [0], + [0.1], + [0.2] + ]) + def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_current_is_close_to_the_current_setpoint(self, current): + self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + + self.ca.set_pv_value("CURRENT:SP", current) + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) + self.ca.assert_that_pv_is_number("CURRENT", current, tolerance=0.01) + + \ No newline at end of file From 1c2cc9e85bc8ec0660aa79b4d520ea46fc985a43 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Thu, 30 May 2019 14:22:04 +0100 Subject: [PATCH 17/39] Added additional logic for switching to M CC --- lewis_emulators/tti355/device.py | 36 +++++++++++-------- .../tti355/interfaces/stream_interface.py | 18 +++++----- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index 346e28c..62e6819 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -14,12 +14,13 @@ def _initialize_data(self): self.voltage = 1.00 self.voltage_sp = 1.00 self.current = 1.00 - self.current_sp = 1.00 - self.output_status = "OUT OFF" + self.current_limit_sp = 1.00 + self.output_status = "OUT Off" self.output_mode = "M CV" self.error = "ERR {}".format(0) self._max_voltage = 35.0 self._max_current = 5.0 + self.load_resistance = self.calculate_load_resistance(self.voltage, self.current) def reset(self): self._initialize_data() @@ -36,8 +37,14 @@ def _get_transition_handlers(self): return OrderedDict([ ]) + def calculate_load_resistance(self, voltage, current): + return voltage/current + + def calculate_potential_current(self, voltage): + return voltage/self.load_resistance + def get_voltage(self): - if self.output_status == "OUT ON": + if self.output_status == "OUT On": self.voltage = self.voltage_sp + ((random()-0.5)/1000) else: self.voltage = ((random()-0.5)/1000) @@ -48,30 +55,31 @@ def set_voltage_sp(self, voltage): if voltage > self._max_voltage: self.error = "ERR {}".format(2) else: + if self.calculate_potential_current(voltage) > self.get_current(): + self.output_mode = "M CC" self.voltage_sp = voltage def get_current(self): - if self.output_status == "OUT ON": - self.current = self.current_sp + ((random()-0.5)/1000) + if self.output_status == "OUT On": + self.current = self.current_limit_sp + ((random()-0.5)/1000) else: self.current = ((random()-0.5)/1000) return self.current - def set_current_sp(self, current): + def set_current_limit_sp(self, current): current = round(float(current), 2) - print(self.current_sp) if current > self._max_current: self.error = "ERR {}".format(2) - print(self.current_sp) else: - self.current_sp = current + self.current_limit_sp = current def set_output_status(self, status): - if status == "ON": - self.output_status = "OUT ON" - elif status == "OFF": - self.output_status = "OUT OFF" - + if status == "On": + self.output_status = "OUT On" + elif status == "Off": + self.output_status = "OUT Off" + self.reset() + def get_output_status(self): return self.output_status diff --git a/lewis_emulators/tti355/interfaces/stream_interface.py b/lewis_emulators/tti355/interfaces/stream_interface.py index d4fb88d..f855a9b 100644 --- a/lewis_emulators/tti355/interfaces/stream_interface.py +++ b/lewis_emulators/tti355/interfaces/stream_interface.py @@ -14,18 +14,18 @@ def __init__(self): # Commands that we expect via serial during normal operation self.commands = { CmdBuilder(self.get_identity).escape("*IDN?").eos().build(), - + CmdBuilder(self.get_voltage_sp).escape("V?").eos().build(), CmdBuilder(self.set_voltage_sp).escape("V ").float().eos().build(), CmdBuilder(self.get_voltage).escape("VO?").eos().build(), CmdBuilder(self.get_current_sp).escape("I?").eos().build(), - CmdBuilder(self.set_current_sp).escape("I ").float().eos().build(), + CmdBuilder(self.set_current_limit_sp).escape("I ").float().eos().build(), CmdBuilder(self.get_current).escape("IO?").eos().build(), CmdBuilder(self.get_outputstatus).escape("OUT?").eos().build(), - CmdBuilder(self.set_outputstatus_on).escape("ON").eos().build(), - CmdBuilder(self.set_outputstatus_off).escape("OFF").eos().build(), + CmdBuilder(self.set_outputstatus_on).escape("On").eos().build(), + CmdBuilder(self.set_outputstatus_off).escape("Off").eos().build(), CmdBuilder(self.get_output_mode).escape("M?").eos().build(), CmdBuilder(self.get_error_status).escape("ERR?").eos().build(), @@ -54,21 +54,21 @@ def get_current(self): return "I{:.2f}".format(current) def get_current_sp(self): - return "I{:.2f}".format(self.device.current_sp) + return "I{:.2f}".format(self.device.current_limit_sp) - def set_current_sp(self, current_sp): - self.device.set_current_sp(float(current_sp)) + def set_current_limit_sp(self, current_limit_sp): + self.device.set_current_limit_sp(float(current_limit_sp)) return self.out_terminator def get_outputstatus(self): return self.device.get_output_status() def set_outputstatus_on(self): - self.device.set_output_status("ON") + self.device.set_output_status("On") return self.out_terminator def set_outputstatus_off(self): - self.device.set_output_status("OFF") + self.device.set_output_status("Off") return self.out_terminator def get_output_mode(self): From e70e3c9fb48471409af91d33a181108b9bcb2db3 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Thu, 30 May 2019 14:25:08 +0100 Subject: [PATCH 18/39] additional tests for mode switching --- tests/tti355.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index 22ffef6..ea36b51 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -51,8 +51,8 @@ def test_WHEN_current_setpoint_is_set_THEN_current_readback_updates(self, curren self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) @parameterized.expand([ - ["ON",], - ["OFF",] + ["On",], + ["Off",] ]) def test_WHEN_outputstatus_is_set_THEN_outputstatus_readback_updates(self, status): self.ca.set_pv_value("OUTPUTSTATUS:SP", status) @@ -110,10 +110,10 @@ def test_WHEN_ioc_in_constant_voltage_mode_THEN_correct_mode_returned(self): ]) def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage_is_close_to_the_voltage_setpoint(self, voltage): - self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + self.ca.set_pv_value("OUTPUTSTATUS:SP", "On") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "On") self.ca.set_pv_value("VOLTAGE:SP", voltage) - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "On") self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", voltage) self.ca.assert_that_pv_is_number("VOLTAGE", voltage, tolerance=0.1) @@ -123,12 +123,21 @@ def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage [0.2] ]) def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_current_is_close_to_the_current_setpoint(self, current): - self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + self.ca.set_pv_value("OUTPUTSTATUS:SP", "On") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "On") self.ca.set_pv_value("CURRENT:SP", current) - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "On") self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) self.ca.assert_that_pv_is_number("CURRENT", current, tolerance=0.01) - + + @skip_if_recsim("Behaviour cannot be simulated in Recsim") + def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_THEN_mode_is_CC(self): + self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") + self._lewis.backdoor_set_on_device("load_resistance", 8.00) + self.ca.set_pv_value("CURRENT:SP", 2.5) + self.ca.set_pv_value("VOLTAGE:SP", 25) + self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Current") + + \ No newline at end of file From 07f277efb068c86b7e214282163e4faaeeec3b9b Mon Sep 17 00:00:00 2001 From: Kirkham Date: Tue, 4 Jun 2019 11:52:54 +0100 Subject: [PATCH 19/39] Added error status logic, ERR gets reset once it has been checked --- lewis_emulators/tti355/device.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index 62e6819..59135d6 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -10,17 +10,17 @@ def _initialize_data(self): """ Initialize all of the device's attributes. """ - self.identity = "THURLBY EX355P, " - self.voltage = 1.00 + self.identity = "Thurlby Thandar,EL302P,0,v1.14" + self.voltage = 0.00 self.voltage_sp = 1.00 - self.current = 1.00 + self.current = 0.00 self.current_limit_sp = 1.00 self.output_status = "OUT Off" self.output_mode = "M CV" - self.error = "ERR {}".format(0) + self.error = "ERR 0" self._max_voltage = 35.0 self._max_current = 5.0 - self.load_resistance = self.calculate_load_resistance(self.voltage, self.current) + self.load_resistance = 0.01 def reset(self): self._initialize_data() @@ -53,7 +53,7 @@ def get_voltage(self): def set_voltage_sp(self, voltage): voltage = round(float(voltage), 2) if voltage > self._max_voltage: - self.error = "ERR {}".format(2) + self.error = "ERR 2" else: if self.calculate_potential_current(voltage) > self.get_current(): self.output_mode = "M CC" @@ -69,7 +69,7 @@ def get_current(self): def set_current_limit_sp(self, current): current = round(float(current), 2) if current > self._max_current: - self.error = "ERR {}".format(2) + self.error = "ERR 2" else: self.current_limit_sp = current @@ -79,7 +79,7 @@ def set_output_status(self, status): elif status == "Off": self.output_status = "OUT Off" self.reset() - + def get_output_status(self): return self.output_status @@ -87,4 +87,11 @@ def get_output_mode(self): return self.output_mode def get_error_status(self): - return self.error \ No newline at end of file + if self.error == "ERR 1": + self.error = "ERR 0" + return "ERR 1" + elif self.error == "ERR 2": + self.error = "ERR 0" + return "ERR 2" + else: + return self.error From 9494699b269b2c3b84f6270901f6ed608cddcfa7 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Tue, 4 Jun 2019 11:55:03 +0100 Subject: [PATCH 20/39] amended tests --- tests/tti355.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index ea36b51..23c8e8a 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -70,7 +70,7 @@ def test_WHEN_current_setpoint_is_set_outside_max_limits_THEN_device_in_error_st @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_identity_requested_THEN_correct_identity_returned(self): - expected_identity = "THURLBY EX355P, " + expected_identity = "Thurlby Thandar,EL302P,0,v1.14" self.ca.assert_that_pv_is("IDENT", expected_identity) @skip_if_recsim("Behaviour cannot be simulated in Recsim") @@ -130,7 +130,7 @@ def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_current self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "On") self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) self.ca.assert_that_pv_is_number("CURRENT", current, tolerance=0.01) - + @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_THEN_mode_is_CC(self): self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") @@ -138,6 +138,3 @@ def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_THEN_m self.ca.set_pv_value("CURRENT:SP", 2.5) self.ca.set_pv_value("VOLTAGE:SP", 25) self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Current") - - - \ No newline at end of file From 433e796a108ef5d5b98e06bb084ef8447ac53068 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Mon, 24 Jun 2019 17:01:42 +0100 Subject: [PATCH 21/39] Amended tests to correlate with new capitalisation --- tests/tti355.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index 23c8e8a..a9ff8b8 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -51,8 +51,8 @@ def test_WHEN_current_setpoint_is_set_THEN_current_readback_updates(self, curren self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) @parameterized.expand([ - ["On",], - ["Off",] + ["ON",], + ["OFF",] ]) def test_WHEN_outputstatus_is_set_THEN_outputstatus_readback_updates(self, status): self.ca.set_pv_value("OUTPUTSTATUS:SP", status) @@ -94,7 +94,7 @@ def test_WHEN_ioc_not_in_error_state_THEN_correct_error_state_returned(self): @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_ioc_in_constant_current_mode_THEN_correct_mode_returned(self): expected_value = "Constant Current" - self._lewis.backdoor_set_on_device("output_mode", "M CC") + self._lewis.backdoor_set_on_device("output_mode", "M CI") self.ca.assert_that_pv_is("OUTPUTMODE", expected_value, timeout=1) @skip_if_recsim("Behaviour cannot be simulated in Recsim") @@ -110,10 +110,10 @@ def test_WHEN_ioc_in_constant_voltage_mode_THEN_correct_mode_returned(self): ]) def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage_is_close_to_the_voltage_setpoint(self, voltage): - self.ca.set_pv_value("OUTPUTSTATUS:SP", "On") - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "On") + self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") self.ca.set_pv_value("VOLTAGE:SP", voltage) - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "On") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", voltage) self.ca.assert_that_pv_is_number("VOLTAGE", voltage, tolerance=0.1) @@ -123,16 +123,17 @@ def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage [0.2] ]) def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_current_is_close_to_the_current_setpoint(self, current): - self.ca.set_pv_value("OUTPUTSTATUS:SP", "On") - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "On") + self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + + self._lewis.backdoor_set_on_device("output_mode", "M CI") self.ca.set_pv_value("CURRENT:SP", current) - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "On") self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) self.ca.assert_that_pv_is_number("CURRENT", current, tolerance=0.01) @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_THEN_mode_is_CC(self): + def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_THEN_mode_is_CI(self): self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") self._lewis.backdoor_set_on_device("load_resistance", 8.00) self.ca.set_pv_value("CURRENT:SP", 2.5) From 2959325e7a5bc4a8edc39a83c2a8cb6fcb74a68c Mon Sep 17 00:00:00 2001 From: Kirkham Date: Mon, 24 Jun 2019 17:02:05 +0100 Subject: [PATCH 22/39] Added the reset command and capitalised commands --- lewis_emulators/tti355/device.py | 16 ++++++++-------- .../tti355/interfaces/stream_interface.py | 16 ++++++++++------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index 59135d6..d041040 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -15,7 +15,7 @@ def _initialize_data(self): self.voltage_sp = 1.00 self.current = 0.00 self.current_limit_sp = 1.00 - self.output_status = "OUT Off" + self.output_status = "OUT OFF" self.output_mode = "M CV" self.error = "ERR 0" self._max_voltage = 35.0 @@ -44,7 +44,7 @@ def calculate_potential_current(self, voltage): return voltage/self.load_resistance def get_voltage(self): - if self.output_status == "OUT On": + if self.output_status == "OUT ON": self.voltage = self.voltage_sp + ((random()-0.5)/1000) else: self.voltage = ((random()-0.5)/1000) @@ -56,11 +56,11 @@ def set_voltage_sp(self, voltage): self.error = "ERR 2" else: if self.calculate_potential_current(voltage) > self.get_current(): - self.output_mode = "M CC" + self.output_mode = "M CI" self.voltage_sp = voltage def get_current(self): - if self.output_status == "OUT On": + if self.output_status == "OUT ON" and self.output_mode == "M CI": self.current = self.current_limit_sp + ((random()-0.5)/1000) else: self.current = ((random()-0.5)/1000) @@ -74,10 +74,10 @@ def set_current_limit_sp(self, current): self.current_limit_sp = current def set_output_status(self, status): - if status == "On": - self.output_status = "OUT On" - elif status == "Off": - self.output_status = "OUT Off" + if status == "ON": + self.output_status = "OUT ON" + elif status == "OFF": + self.output_status = "OUT OFF" self.reset() def get_output_status(self): diff --git a/lewis_emulators/tti355/interfaces/stream_interface.py b/lewis_emulators/tti355/interfaces/stream_interface.py index f855a9b..ac51fa9 100644 --- a/lewis_emulators/tti355/interfaces/stream_interface.py +++ b/lewis_emulators/tti355/interfaces/stream_interface.py @@ -14,7 +14,7 @@ def __init__(self): # Commands that we expect via serial during normal operation self.commands = { CmdBuilder(self.get_identity).escape("*IDN?").eos().build(), - + CmdBuilder(self.reset).escape("*RST").eos().build(), CmdBuilder(self.get_voltage_sp).escape("V?").eos().build(), CmdBuilder(self.set_voltage_sp).escape("V ").float().eos().build(), CmdBuilder(self.get_voltage).escape("VO?").eos().build(), @@ -24,19 +24,23 @@ def __init__(self): CmdBuilder(self.get_current).escape("IO?").eos().build(), CmdBuilder(self.get_outputstatus).escape("OUT?").eos().build(), - CmdBuilder(self.set_outputstatus_on).escape("On").eos().build(), - CmdBuilder(self.set_outputstatus_off).escape("Off").eos().build(), + CmdBuilder(self.set_outputstatus_on).escape("ON").eos().build(), + CmdBuilder(self.set_outputstatus_off).escape("OFF").eos().build(), CmdBuilder(self.get_output_mode).escape("M?").eos().build(), CmdBuilder(self.get_error_status).escape("ERR?").eos().build(), } - + def handle_error(self, request, error): err_string = "command was: {}, error was: {}: {}\n".format(request, error.__class__.__name__, error) print(err_string) self.log.error(err_string) return err_string + + def reset(self): + self.device.reset() + return self.out_terminator def get_voltage(self): volt = self.device.get_voltage() @@ -64,11 +68,11 @@ def get_outputstatus(self): return self.device.get_output_status() def set_outputstatus_on(self): - self.device.set_output_status("On") + self.device.set_output_status("ON") return self.out_terminator def set_outputstatus_off(self): - self.device.set_output_status("Off") + self.device.set_output_status("OFF") return self.out_terminator def get_output_mode(self): From ffc450bbcde41c8200ad177cecd7f572fd7a5627 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Tue, 25 Jun 2019 16:49:33 +0100 Subject: [PATCH 23/39] Amended tests for new funtionality --- tests/tti355.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index a9ff8b8..f3612b7 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -125,17 +125,43 @@ def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_current_is_close_to_the_current_setpoint(self, current): self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") - self._lewis.backdoor_set_on_device("output_mode", "M CI") - self.ca.set_pv_value("CURRENT:SP", current) self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) self.ca.assert_that_pv_is_number("CURRENT", current, tolerance=0.01) @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_THEN_mode_is_CI(self): + def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_and_output_is_on_THEN_mode_is_CI_and_voltage_is_actual(self): + expected_voltage = 20 + self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") self._lewis.backdoor_set_on_device("load_resistance", 8.00) self.ca.set_pv_value("CURRENT:SP", 2.5) self.ca.set_pv_value("VOLTAGE:SP", 25) self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Current") + self.ca.assert_that_pv_is("VOLTAGE", expected_voltage) + + @skip_if_recsim("Behaviour cannot be simulated in Recsim") + def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_but_output_off_THEN_mode_is_CV_and_voltage_is_not_actual(self): + expected_voltage = 0 + self.ca.set_pv_value("OUTPUTSTATUS:SP", "OFF") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "OFF") + self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") + self._lewis.backdoor_set_on_device("load_resistance", 8.00) + self.ca.set_pv_value("CURRENT:SP", 2.5) + self.ca.set_pv_value("VOLTAGE:SP", 25) + self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") + self.ca.assert_that_pv_is("VOLTAGE", expected_voltage) + + @skip_if_recsim("Behaviour cannot be simulated in Recsim") + def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_but_output_off_THEN_mode_is_CV_and_voltage_is_not_actual_but_close_to_sp(self): + expected_voltage = 10 + self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") + self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") + self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") + self._lewis.backdoor_set_on_device("load_resistance", 8.00) + self.ca.set_pv_value("CURRENT:SP", 2.5) + self.ca.set_pv_value("VOLTAGE:SP", expected_voltage) + self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") + self.ca.assert_that_pv_is_number("VOLTAGE", expected_voltage, tolerance=0.1) \ No newline at end of file From e6da0dd3f841ec8f3cca83cce4e028eaee29553b Mon Sep 17 00:00:00 2001 From: Kirkham Date: Tue, 25 Jun 2019 16:50:24 +0100 Subject: [PATCH 24/39] Amended mode logic to calculate voltage dynamically --- lewis_emulators/tti355/device.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index d041040..2f34362 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -20,7 +20,7 @@ def _initialize_data(self): self.error = "ERR 0" self._max_voltage = 35.0 self._max_current = 5.0 - self.load_resistance = 0.01 + self.load_resistance = 10 def reset(self): self._initialize_data() @@ -37,15 +37,18 @@ def _get_transition_handlers(self): return OrderedDict([ ]) - def calculate_load_resistance(self, voltage, current): - return voltage/current - def calculate_potential_current(self, voltage): return voltage/self.load_resistance + + def calculate_actual_voltage(self): + return self.get_current() * self.load_resistance def get_voltage(self): if self.output_status == "OUT ON": - self.voltage = self.voltage_sp + ((random()-0.5)/1000) + if self.output_mode == "M CI": + self.voltage = self.calculate_actual_voltage() + else: + self.voltage = self.voltage_sp + ((random()-0.5)/1000) else: self.voltage = ((random()-0.5)/1000) return self.voltage @@ -55,10 +58,10 @@ def set_voltage_sp(self, voltage): if voltage > self._max_voltage: self.error = "ERR 2" else: - if self.calculate_potential_current(voltage) > self.get_current(): - self.output_mode = "M CI" self.voltage_sp = voltage - + if self.calculate_potential_current(voltage) > self.current_limit_sp and self.output_status == "OUT ON": + self.output_mode = "M CI" + def get_current(self): if self.output_status == "OUT ON" and self.output_mode == "M CI": self.current = self.current_limit_sp + ((random()-0.5)/1000) From 18a246e675109c855b9d85ec13aa4981411dada5 Mon Sep 17 00:00:00 2001 From: Kirkham Date: Wed, 26 Jun 2019 13:57:51 +0100 Subject: [PATCH 25/39] Amended tests to reflect the changes to the ERROR DB record, now only processed on set --- tests/tti355.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index f3612b7..42f551a 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -78,17 +78,11 @@ def test_WHEN_ioc_in_error_state_2_THEN_correct_error_state_returned(self): expected_value = "Cmd outside limits" self._lewis.backdoor_set_on_device("error", "ERR 2") self.ca.assert_that_pv_is("ERROR", expected_value, timeout=1) - - @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_WHEN_ioc_in_error_state_1_THEN_correct_error_state_returned(self): - expected_value = "Cmd not recognised" - self._lewis.backdoor_set_on_device("error", "ERR 1") - self.ca.assert_that_pv_is("ERROR", expected_value, timeout=1) @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_ioc_not_in_error_state_THEN_correct_error_state_returned(self): expected_value = "No error" - self._lewis.backdoor_set_on_device("error", "ERR 0") + self.ca.set_pv_value("CURRENT:SP", 3.0) self.ca.assert_that_pv_is("ERROR", expected_value, timeout=1) @skip_if_recsim("Behaviour cannot be simulated in Recsim") From f18f140998d40d551596b52e4038093122045fe3 Mon Sep 17 00:00:00 2001 From: aaronlong Date: Mon, 8 Jul 2019 10:35:44 +0100 Subject: [PATCH 26/39] Updated tests --- tests/tti355.py | 68 +++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index 42f551a..4ea2ac1 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -31,43 +31,48 @@ def setUp(self): self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX) self._lewis.backdoor_run_function_on_device("reset") - @parameterized.expand([ [0], - [1,], - [2,] + [1], + [2] ]) def test_WHEN_voltage_is_set_THEN_voltage_setpoint_updates(self, volt): self.ca.set_pv_value("VOLTAGE:SP", volt) self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", volt) @parameterized.expand([ - [0,], - [0.1,], - [0.2,] + [0.01], + [1.30], + [5.0] ]) def test_WHEN_current_setpoint_is_set_THEN_current_readback_updates(self, current): self.ca.set_pv_value("CURRENT:SP", current) self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) @parameterized.expand([ - ["ON",], - ["OFF",] + ["ON"], + ["OFF"] ]) def test_WHEN_outputstatus_is_set_THEN_outputstatus_readback_updates(self, status): self.ca.set_pv_value("OUTPUTSTATUS:SP", status) self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", status) - + + @parameterized.expand([ + ("lt_low_limit", -123.0, "low_limit", 0.0), + ("gt_high_limit", 123.2, "high_limit", 35.0)]) @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_WHEN_voltage_setpoint_is_set_outside_max_limits_THEN_device_in_error_state(self): - self.ca.set_pv_value("VOLTAGE:SP", 38.0) - self.ca.assert_that_pv_is("ERROR", "Cmd outside limits") - + def test_WHEN_voltage_setpoint_is_set_outside_max_limits_THEN_setpoint_within(self, case, case_value, limit, limit_value): + self.ca.set_pv_value("VOLTAGE:SP", case_value) + self.ca.assert_that_pv_is("VOLTAGE:SP", limit_value) + + @parameterized.expand([ + ("lt_low_limit", -31.0, "low_limit", 0.01), + ("gt_high_limit", 34.2, "high_limit", 5.0)]) @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_WHEN_current_setpoint_is_set_outside_max_limits_THEN_device_in_error_state(self): - self.ca.set_pv_value("CURRENT:SP", 7.0) - self.ca.assert_that_pv_is("ERROR", "Cmd outside limits") - + def test_WHEN_voltage_setpoint_is_set_outside_max_limits_THEN_setpoint_within(self, case, case_value, limit, limit_value): + self.ca.set_pv_value("CURRENT:SP", case_value) + self.ca.assert_that_pv_is("CURRENT:SP", limit_value) + @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_identity_requested_THEN_correct_identity_returned(self): expected_identity = "Thurlby Thandar,EL302P,0,v1.14" @@ -77,44 +82,45 @@ def test_WHEN_identity_requested_THEN_correct_identity_returned(self): def test_WHEN_ioc_in_error_state_2_THEN_correct_error_state_returned(self): expected_value = "Cmd outside limits" self._lewis.backdoor_set_on_device("error", "ERR 2") - self.ca.assert_that_pv_is("ERROR", expected_value, timeout=1) + self.ca.set_pv_value("ERROR.PROC", 1) + self.ca.assert_that_pv_is("ERROR", expected_value) @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_ioc_not_in_error_state_THEN_correct_error_state_returned(self): expected_value = "No error" self.ca.set_pv_value("CURRENT:SP", 3.0) - self.ca.assert_that_pv_is("ERROR", expected_value, timeout=1) + self.ca.assert_that_pv_is("ERROR", expected_value) @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_ioc_in_constant_current_mode_THEN_correct_mode_returned(self): expected_value = "Constant Current" self._lewis.backdoor_set_on_device("output_mode", "M CI") - self.ca.assert_that_pv_is("OUTPUTMODE", expected_value, timeout=1) + self.ca.assert_that_pv_is("OUTPUTMODE", expected_value) @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_ioc_in_constant_voltage_mode_THEN_correct_mode_returned(self): expected_value = "Constant Voltage" self._lewis.backdoor_set_on_device("output_mode", "M CV") - self.ca.assert_that_pv_is("OUTPUTMODE", expected_value, timeout=1) - + self.ca.assert_that_pv_is("OUTPUTMODE", expected_value) + @parameterized.expand([ - [0,], - [5,], - [10,] + [0], + [5], + [10] ]) def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage_is_close_to_the_voltage_setpoint(self, voltage): - + self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") self.ca.set_pv_value("VOLTAGE:SP", voltage) self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", voltage) self.ca.assert_that_pv_is_number("VOLTAGE", voltage, tolerance=0.1) - + @parameterized.expand([ - [0], - [0.1], - [0.2] + [0.01], + [1.30], + [5.0] ]) def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_current_is_close_to_the_current_setpoint(self, current): self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") @@ -158,4 +164,4 @@ def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_but_ou self.ca.set_pv_value("CURRENT:SP", 2.5) self.ca.set_pv_value("VOLTAGE:SP", expected_voltage) self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") - self.ca.assert_that_pv_is_number("VOLTAGE", expected_voltage, tolerance=0.1) \ No newline at end of file + self.ca.assert_that_pv_is_number("VOLTAGE", expected_voltage, tolerance=0.1) From 5064a476e9c711f4c14cf872089608128a0c2432 Mon Sep 17 00:00:00 2001 From: aaronlong Date: Mon, 8 Jul 2019 10:51:27 +0100 Subject: [PATCH 27/39] Added IOC macro's to test cases --- tests/tti355.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index 4ea2ac1..0d988c7 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -9,11 +9,21 @@ DEVICE_PREFIX = "TTI355_01" DEVICE_NAME = "tti355" +VOLT_LOW_LIMIT = 0.0 +VOLT_HIGH_LIMIT = 35.0 +CURR_LOW_LIMIT = 0.01 +CURR_HIGH_LIMIT = 5.0 + IOCS = [ { "name": DEVICE_PREFIX, "directory": get_default_ioc_dir("TTI355"), - "macros": {}, + "macros": { + "MIN_VOLT": VOLT_LOW_LIMIT, + "MAX_VOLT": VOLT_HIGH_LIMIT, + "MIN_CURR": CURR_LOW_LIMIT, + "MAX_CURR": CURR_HIGH_LIMIT, + }, "emulator": DEVICE_NAME, }, ] @@ -58,16 +68,16 @@ def test_WHEN_outputstatus_is_set_THEN_outputstatus_readback_updates(self, statu self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", status) @parameterized.expand([ - ("lt_low_limit", -123.0, "low_limit", 0.0), - ("gt_high_limit", 123.2, "high_limit", 35.0)]) + ("lt_low_limit", VOLT_LOW_LIMIT-1.0, "low_limit", VOLT_LOW_LIMIT), + ("gt_high_limit", VOLT_HIGH_LIMIT+1, "high_limit", VOLT_HIGH_LIMIT)]) @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_voltage_setpoint_is_set_outside_max_limits_THEN_setpoint_within(self, case, case_value, limit, limit_value): self.ca.set_pv_value("VOLTAGE:SP", case_value) self.ca.assert_that_pv_is("VOLTAGE:SP", limit_value) @parameterized.expand([ - ("lt_low_limit", -31.0, "low_limit", 0.01), - ("gt_high_limit", 34.2, "high_limit", 5.0)]) + ("lt_low_limit", CURR_LOW_LIMIT-1, "low_limit", CURR_LOW_LIMIT), + ("gt_high_limit", CURR_HIGH_LIMIT+1, "high_limit", CURR_HIGH_LIMIT)]) @skip_if_recsim("Behaviour cannot be simulated in Recsim") def test_WHEN_voltage_setpoint_is_set_outside_max_limits_THEN_setpoint_within(self, case, case_value, limit, limit_value): self.ca.set_pv_value("CURRENT:SP", case_value) From 0a2080c3999240b9a9b754f1add3a03d5c6caf1d Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Wed, 25 Sep 2019 16:58:41 +0100 Subject: [PATCH 28/39] Updated lewis version --- lewis_emulators/lewis_versions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lewis_emulators/lewis_versions.py b/lewis_emulators/lewis_versions.py index beae6ab..a805cfb 100644 --- a/lewis_emulators/lewis_versions.py +++ b/lewis_emulators/lewis_versions.py @@ -1,2 +1,2 @@ -LEWIS_1_2_0 = "1.2.0" -LEWIS_LATEST = LEWIS_1_2_0 +LEWIS_1_2_1 = "1.2.1" +LEWIS_LATEST = LEWIS_1_2_1 From 6bd44ec90cc558e6c2610a31f1f242bc46d0c632 Mon Sep 17 00:00:00 2001 From: ChrisColeExpControl Date: Tue, 15 Oct 2019 09:43:23 +0100 Subject: [PATCH 29/39] renamed to cryogenic_sms/CRYOSMS --- lewis_emulators/lewis_versions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lewis_emulators/lewis_versions.py b/lewis_emulators/lewis_versions.py index beae6ab..fc253d0 100644 --- a/lewis_emulators/lewis_versions.py +++ b/lewis_emulators/lewis_versions.py @@ -1,2 +1,3 @@ LEWIS_1_2_0 = "1.2.0" -LEWIS_LATEST = LEWIS_1_2_0 +LEWIS_1_2_1 = "1.2.1" +LEWIS_LATEST = LEWIS_1_2_1 From f88ab88136d6ed12306214d5def08ce6c2d586c5 Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Mon, 1 Jun 2020 18:29:20 +0100 Subject: [PATCH 30/39] Updated lewis version to 1.2.2 --- lewis_emulators/lewis_versions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lewis_emulators/lewis_versions.py b/lewis_emulators/lewis_versions.py index a805cfb..5849f8b 100644 --- a/lewis_emulators/lewis_versions.py +++ b/lewis_emulators/lewis_versions.py @@ -1,2 +1,2 @@ -LEWIS_1_2_1 = "1.2.1" +LEWIS_1_2_1 = "1.2.2" LEWIS_LATEST = LEWIS_1_2_1 From 7239040899f012af85cf75d1f0c0d4d26c6d667e Mon Sep 17 00:00:00 2001 From: aaronlong Date: Wed, 16 Sep 2020 13:28:31 +0100 Subject: [PATCH 31/39] Updated a number of imports, python3 syntax changes and minor PEP8 violations --- lewis_emulators/tti355/device.py | 2 +- lewis_emulators/tti355/interfaces/stream_interface.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index 2f34362..c35c517 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -1,5 +1,5 @@ from collections import OrderedDict -from states import DefaultState +from .states import DefaultState from lewis.devices import StateMachineDevice from random import random diff --git a/lewis_emulators/tti355/interfaces/stream_interface.py b/lewis_emulators/tti355/interfaces/stream_interface.py index ac51fa9..b230a42 100644 --- a/lewis_emulators/tti355/interfaces/stream_interface.py +++ b/lewis_emulators/tti355/interfaces/stream_interface.py @@ -82,4 +82,4 @@ def get_error_status(self): return self.device.get_error_status() def get_identity(self): - return self.device.identity \ No newline at end of file + return self.device.identity From 8fe914d1538c00dde94af628d89111d7ce204f44 Mon Sep 17 00:00:00 2001 From: aaronlong Date: Wed, 16 Sep 2020 14:48:32 +0100 Subject: [PATCH 32/39] Fixed variable name for lewis version number --- lewis_emulators/lewis_versions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lewis_emulators/lewis_versions.py b/lewis_emulators/lewis_versions.py index 5849f8b..5ae639f 100644 --- a/lewis_emulators/lewis_versions.py +++ b/lewis_emulators/lewis_versions.py @@ -1,2 +1,2 @@ -LEWIS_1_2_1 = "1.2.2" -LEWIS_LATEST = LEWIS_1_2_1 +LEWIS_1_2_2 = "1.2.2" +LEWIS_LATEST = LEWIS_1_2_2 From 68a1cef85926c96dea735a6f7cb5b4886df7f986 Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Tue, 10 Nov 2020 20:29:26 +0000 Subject: [PATCH 33/39] Updated to use latest lewis version and convert strings correctly --- lewis_emulators/lewis_versions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lewis_emulators/lewis_versions.py b/lewis_emulators/lewis_versions.py index 5ae639f..99831a8 100644 --- a/lewis_emulators/lewis_versions.py +++ b/lewis_emulators/lewis_versions.py @@ -1,2 +1,2 @@ -LEWIS_1_2_2 = "1.2.2" -LEWIS_LATEST = LEWIS_1_2_2 +LEWIS_2_0_0 = "2.0.0" +LEWIS_LATEST = LEWIS_2_0_0 From 647c803d0d1e2f9c95bf24e37d0219438205c901 Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Mon, 30 Nov 2020 14:18:57 +0000 Subject: [PATCH 34/39] Update lewis version --- lewis_emulators/lewis_versions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lewis_emulators/lewis_versions.py b/lewis_emulators/lewis_versions.py index 99831a8..0f6c45a 100644 --- a/lewis_emulators/lewis_versions.py +++ b/lewis_emulators/lewis_versions.py @@ -1,2 +1,2 @@ -LEWIS_2_0_0 = "2.0.0" -LEWIS_LATEST = LEWIS_2_0_0 +LEWIS_1_3_0 = "1.3.0" +LEWIS_LATEST = LEWIS_1_3_0 From a1ef4092d0ebe3ff11ec98097739805d8a4700fb Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Thu, 14 Jan 2021 14:18:56 +0000 Subject: [PATCH 35/39] Add tests for TTIEX355P ioc --- tests/tti355.py | 113 +++--------------------------------------------- 1 file changed, 7 insertions(+), 106 deletions(-) diff --git a/tests/tti355.py b/tests/tti355.py index 0d988c7..4596634 100644 --- a/tests/tti355.py +++ b/tests/tti355.py @@ -1,5 +1,7 @@ import unittest from parameterized import parameterized + +from common_tests.tti_common import TtiCommon from utils.channel_access import ChannelAccess from utils.ioc_launcher import get_default_ioc_dir from utils.test_modes import TestModes @@ -32,7 +34,7 @@ TEST_MODES = [TestModes.RECSIM, TestModes.DEVSIM] -class Tti355Tests(unittest.TestCase): +class Tti355Tests(TtiCommon, unittest.TestCase): """ Tests for the Tti355 IOC. """ @@ -41,31 +43,11 @@ def setUp(self): self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX) self._lewis.backdoor_run_function_on_device("reset") - @parameterized.expand([ - [0], - [1], - [2] - ]) - def test_WHEN_voltage_is_set_THEN_voltage_setpoint_updates(self, volt): - self.ca.set_pv_value("VOLTAGE:SP", volt) - self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", volt) - - @parameterized.expand([ - [0.01], - [1.30], - [5.0] - ]) - def test_WHEN_current_setpoint_is_set_THEN_current_readback_updates(self, current): - self.ca.set_pv_value("CURRENT:SP", current) - self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) + def get_on_state_name(self): + return "ON" - @parameterized.expand([ - ["ON"], - ["OFF"] - ]) - def test_WHEN_outputstatus_is_set_THEN_outputstatus_readback_updates(self, status): - self.ca.set_pv_value("OUTPUTSTATUS:SP", status) - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", status) + def get_off_state_name(self): + return "OFF" @parameterized.expand([ ("lt_low_limit", VOLT_LOW_LIMIT-1.0, "low_limit", VOLT_LOW_LIMIT), @@ -94,84 +76,3 @@ def test_WHEN_ioc_in_error_state_2_THEN_correct_error_state_returned(self): self._lewis.backdoor_set_on_device("error", "ERR 2") self.ca.set_pv_value("ERROR.PROC", 1) self.ca.assert_that_pv_is("ERROR", expected_value) - - @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_WHEN_ioc_not_in_error_state_THEN_correct_error_state_returned(self): - expected_value = "No error" - self.ca.set_pv_value("CURRENT:SP", 3.0) - self.ca.assert_that_pv_is("ERROR", expected_value) - - @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_WHEN_ioc_in_constant_current_mode_THEN_correct_mode_returned(self): - expected_value = "Constant Current" - self._lewis.backdoor_set_on_device("output_mode", "M CI") - self.ca.assert_that_pv_is("OUTPUTMODE", expected_value) - - @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_WHEN_ioc_in_constant_voltage_mode_THEN_correct_mode_returned(self): - expected_value = "Constant Voltage" - self._lewis.backdoor_set_on_device("output_mode", "M CV") - self.ca.assert_that_pv_is("OUTPUTMODE", expected_value) - - @parameterized.expand([ - [0], - [5], - [10] - ]) - def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_voltage_is_close_to_the_voltage_setpoint(self, voltage): - - self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") - self.ca.set_pv_value("VOLTAGE:SP", voltage) - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") - self.ca.assert_that_pv_is("VOLTAGE:SP:RBV", voltage) - self.ca.assert_that_pv_is_number("VOLTAGE", voltage, tolerance=0.1) - - @parameterized.expand([ - [0.01], - [1.30], - [5.0] - ]) - def test_GIVEN_set_output_conditions_WHEN_the_output_is_on_THEN_readback_current_is_close_to_the_current_setpoint(self, current): - self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") - self._lewis.backdoor_set_on_device("output_mode", "M CI") - self.ca.set_pv_value("CURRENT:SP", current) - self.ca.assert_that_pv_is("CURRENT:SP:RBV", current) - self.ca.assert_that_pv_is_number("CURRENT", current, tolerance=0.01) - - @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_and_output_is_on_THEN_mode_is_CI_and_voltage_is_actual(self): - expected_voltage = 20 - self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") - self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") - self._lewis.backdoor_set_on_device("load_resistance", 8.00) - self.ca.set_pv_value("CURRENT:SP", 2.5) - self.ca.set_pv_value("VOLTAGE:SP", 25) - self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Current") - self.ca.assert_that_pv_is("VOLTAGE", expected_voltage) - - @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_but_output_off_THEN_mode_is_CV_and_voltage_is_not_actual(self): - expected_voltage = 0 - self.ca.set_pv_value("OUTPUTSTATUS:SP", "OFF") - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "OFF") - self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") - self._lewis.backdoor_set_on_device("load_resistance", 8.00) - self.ca.set_pv_value("CURRENT:SP", 2.5) - self.ca.set_pv_value("VOLTAGE:SP", 25) - self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") - self.ca.assert_that_pv_is("VOLTAGE", expected_voltage) - - @skip_if_recsim("Behaviour cannot be simulated in Recsim") - def test_GIVEN_voltage_WHEN_current_limit_is_lower_than_potential_current_but_output_off_THEN_mode_is_CV_and_voltage_is_not_actual_but_close_to_sp(self): - expected_voltage = 10 - self.ca.set_pv_value("OUTPUTSTATUS:SP", "ON") - self.ca.assert_that_pv_is("OUTPUTSTATUS:SP:RBV", "ON") - self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") - self._lewis.backdoor_set_on_device("load_resistance", 8.00) - self.ca.set_pv_value("CURRENT:SP", 2.5) - self.ca.set_pv_value("VOLTAGE:SP", expected_voltage) - self.ca.assert_that_pv_is("OUTPUTMODE", "Constant Voltage") - self.ca.assert_that_pv_is_number("VOLTAGE", expected_voltage, tolerance=0.1) From 6a0502cd26cff76c2d8a2b2cb9a9271f75580cbd Mon Sep 17 00:00:00 2001 From: JamesKingWork Date: Thu, 15 Apr 2021 11:10:00 +0100 Subject: [PATCH 36/39] ttiex355p: Add minimum to current and voltage range --- lewis_emulators/tti355/device.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index c35c517..ce9d503 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -21,6 +21,8 @@ def _initialize_data(self): self._max_voltage = 35.0 self._max_current = 5.0 self.load_resistance = 10 + self.min_voltage = None + self.min_current = None def reset(self): self._initialize_data() @@ -57,6 +59,8 @@ def set_voltage_sp(self, voltage): voltage = round(float(voltage), 2) if voltage > self._max_voltage: self.error = "ERR 2" + elif self.min_voltage is not None and voltage < self.min_voltage: + self.error = "ERR 2" else: self.voltage_sp = voltage if self.calculate_potential_current(voltage) > self.current_limit_sp and self.output_status == "OUT ON": @@ -73,6 +77,8 @@ def set_current_limit_sp(self, current): current = round(float(current), 2) if current > self._max_current: self.error = "ERR 2" + elif self.min_current is not None and current < self.min_current: + self.error = "ERR 2" else: self.current_limit_sp = current From 3bf8768dd86725c848b079b496a782048d602f0d Mon Sep 17 00:00:00 2001 From: JamesKingWork Date: Wed, 19 May 2021 12:21:04 +0100 Subject: [PATCH 37/39] Refactor to use ttiex355p emulator - which is mostly subclassing the tti355 emulator with some additional logic - for test --- lewis_emulators/tti355/device.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lewis_emulators/tti355/device.py b/lewis_emulators/tti355/device.py index ce9d503..bf0b505 100644 --- a/lewis_emulators/tti355/device.py +++ b/lewis_emulators/tti355/device.py @@ -21,8 +21,6 @@ def _initialize_data(self): self._max_voltage = 35.0 self._max_current = 5.0 self.load_resistance = 10 - self.min_voltage = None - self.min_current = None def reset(self): self._initialize_data() @@ -44,6 +42,9 @@ def calculate_potential_current(self, voltage): def calculate_actual_voltage(self): return self.get_current() * self.load_resistance + + def voltage_within_limits(self, voltage): + return voltage <= self._max_voltage def get_voltage(self): if self.output_status == "OUT ON": @@ -57,14 +58,15 @@ def get_voltage(self): def set_voltage_sp(self, voltage): voltage = round(float(voltage), 2) - if voltage > self._max_voltage: - self.error = "ERR 2" - elif self.min_voltage is not None and voltage < self.min_voltage: + if not self.voltage_within_limits(voltage): self.error = "ERR 2" else: self.voltage_sp = voltage if self.calculate_potential_current(voltage) > self.current_limit_sp and self.output_status == "OUT ON": self.output_mode = "M CI" + + def current_within_limits(self, current): + return current <= self._max_current def get_current(self): if self.output_status == "OUT ON" and self.output_mode == "M CI": @@ -75,9 +77,7 @@ def get_current(self): def set_current_limit_sp(self, current): current = round(float(current), 2) - if current > self._max_current: - self.error = "ERR 2" - elif self.min_current is not None and current < self.min_current: + if not self.current_within_limits(current): self.error = "ERR 2" else: self.current_limit_sp = current From 272bde32dd1ef85b09e00cc5196f4427049c593a Mon Sep 17 00:00:00 2001 From: Dominic Oram Date: Thu, 10 Jun 2021 11:38:28 +0100 Subject: [PATCH 38/39] Moved utils into lewis itself --- lewis_emulators/tti355/interfaces/stream_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lewis_emulators/tti355/interfaces/stream_interface.py b/lewis_emulators/tti355/interfaces/stream_interface.py index b230a42..143d5a7 100644 --- a/lewis_emulators/tti355/interfaces/stream_interface.py +++ b/lewis_emulators/tti355/interfaces/stream_interface.py @@ -1,5 +1,5 @@ from lewis.adapters.stream import StreamInterface -from lewis_emulators.utils.command_builder import CmdBuilder +from lewis.utils.command_builder import CmdBuilder class Tti355StreamInterface(StreamInterface): From e77f42ab4b74d786ae098fdc4849d732ab76b67f Mon Sep 17 00:00:00 2001 From: aaronlong Date: Fri, 22 Apr 2022 15:01:44 +0100 Subject: [PATCH 39/39] Moved system tests to support module --- .gitignore | 4 ++++ Makefile | 4 ++++ system_tests/__init__.py | 0 .../lewis_emulators}/__init__.py | 0 .../lewis_emulators}/lewis_versions.py | 0 .../lewis_emulators}/tti355/__init__.py | 0 .../lewis_emulators}/tti355/device.py | 0 .../lewis_emulators}/tti355/interfaces/__init__.py | 0 .../tti355/interfaces/stream_interface.py | 0 .../lewis_emulators}/tti355/states.py | 0 system_tests/run_tests.bat | 10 ++++++++++ system_tests/tests/__init__.py | 0 {tests => system_tests/tests}/tti355.py | 0 13 files changed, 18 insertions(+) create mode 100644 system_tests/__init__.py rename {lewis_emulators => system_tests/lewis_emulators}/__init__.py (100%) rename {lewis_emulators => system_tests/lewis_emulators}/lewis_versions.py (100%) rename {lewis_emulators => system_tests/lewis_emulators}/tti355/__init__.py (100%) rename {lewis_emulators => system_tests/lewis_emulators}/tti355/device.py (100%) rename {lewis_emulators => system_tests/lewis_emulators}/tti355/interfaces/__init__.py (100%) rename {lewis_emulators => system_tests/lewis_emulators}/tti355/interfaces/stream_interface.py (100%) rename {lewis_emulators => system_tests/lewis_emulators}/tti355/states.py (100%) create mode 100644 system_tests/run_tests.bat create mode 100644 system_tests/tests/__init__.py rename {tests => system_tests/tests}/tti355.py (100%) diff --git a/.gitignore b/.gitignore index ed7e36d..241553b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,7 @@ relPaths.sh /doc/ *_info_positions.req *_info_settings.req +__pycache__/ +*.py[cod] +*$py.class +test-reports/ \ No newline at end of file diff --git a/Makefile b/Makefile index a484532..077c9f2 100644 --- a/Makefile +++ b/Makefile @@ -32,3 +32,7 @@ iocBoot_DEPEND_DIRS += $(filter %App,$(DIRS)) # Add any additional dependency rules here: include $(TOP)/configure/RULES_TOP + + +ioctests: + .\system_tests\run_tests.bat diff --git a/system_tests/__init__.py b/system_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lewis_emulators/__init__.py b/system_tests/lewis_emulators/__init__.py similarity index 100% rename from lewis_emulators/__init__.py rename to system_tests/lewis_emulators/__init__.py diff --git a/lewis_emulators/lewis_versions.py b/system_tests/lewis_emulators/lewis_versions.py similarity index 100% rename from lewis_emulators/lewis_versions.py rename to system_tests/lewis_emulators/lewis_versions.py diff --git a/lewis_emulators/tti355/__init__.py b/system_tests/lewis_emulators/tti355/__init__.py similarity index 100% rename from lewis_emulators/tti355/__init__.py rename to system_tests/lewis_emulators/tti355/__init__.py diff --git a/lewis_emulators/tti355/device.py b/system_tests/lewis_emulators/tti355/device.py similarity index 100% rename from lewis_emulators/tti355/device.py rename to system_tests/lewis_emulators/tti355/device.py diff --git a/lewis_emulators/tti355/interfaces/__init__.py b/system_tests/lewis_emulators/tti355/interfaces/__init__.py similarity index 100% rename from lewis_emulators/tti355/interfaces/__init__.py rename to system_tests/lewis_emulators/tti355/interfaces/__init__.py diff --git a/lewis_emulators/tti355/interfaces/stream_interface.py b/system_tests/lewis_emulators/tti355/interfaces/stream_interface.py similarity index 100% rename from lewis_emulators/tti355/interfaces/stream_interface.py rename to system_tests/lewis_emulators/tti355/interfaces/stream_interface.py diff --git a/lewis_emulators/tti355/states.py b/system_tests/lewis_emulators/tti355/states.py similarity index 100% rename from lewis_emulators/tti355/states.py rename to system_tests/lewis_emulators/tti355/states.py diff --git a/system_tests/run_tests.bat b/system_tests/run_tests.bat new file mode 100644 index 0000000..65ab1d6 --- /dev/null +++ b/system_tests/run_tests.bat @@ -0,0 +1,10 @@ +@echo off +setlocal +REM Run this directory's tests using the IOC Testing Framework + +call "%~dp0..\..\..\..\config_env.bat" + +REM Command line arguments always passed to the test script +SET ARGS=--test_and_emulator %~dp0 +call %PYTHON3% -u "%EPICS_KIT_ROOT%\support\IocTestFramework\master\run_tests.py" %ARGS% %* +IF %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL% diff --git a/system_tests/tests/__init__.py b/system_tests/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/tti355.py b/system_tests/tests/tti355.py similarity index 100% rename from tests/tti355.py rename to system_tests/tests/tti355.py