diff --git a/docs/agents/cryomech_cpa.rst b/docs/agents/cryomech_cpa.rst index 3af58368a..194cd14f2 100644 --- a/docs/agents/cryomech_cpa.rst +++ b/docs/agents/cryomech_cpa.rst @@ -91,3 +91,4 @@ Supporting APIs .. autoclass:: socs.agents.cryomech_cpa.agent.PTC :members: + :show-inheritance: diff --git a/docs/api.rst b/docs/api.rst index 2ef255f28..fb9a9e996 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -100,6 +100,15 @@ socs.snmp :undoc-members: :show-inheritance: +socs.tcp +--------- + +.. automodule:: socs.tcp + :members: + :undoc-members: + :show-inheritance: + :noindex: + socs.testing ------------ diff --git a/docs/developer/snmp.rst b/docs/developer/interfaces/snmp.rst similarity index 100% rename from docs/developer/snmp.rst rename to docs/developer/interfaces/snmp.rst diff --git a/docs/developer/interfaces/tcp.rst b/docs/developer/interfaces/tcp.rst new file mode 100644 index 000000000..7bed36869 --- /dev/null +++ b/docs/developer/interfaces/tcp.rst @@ -0,0 +1,83 @@ +.. _tcp: + +=================================== +Transmission Control Protocol (TCP) +=================================== + +SOCS provides a standard interface for connecting to devices using TCP. This +page details how to use this interface. The primary benefit to using this +interface is the included error handling. + +A few important things to know about the behavior of the interface class: + +* The interface tries to connect to the device when instantiated. +* It will log but not raise an error if it cannot connect, instead + ``self.comm`` will be ``None``. +* The connection will be reset when ``send()`` is called if this happens. + An exception will be raised if it still cannot connect. +* The interface is built to mimic ``socket.send()`` and ``socket.recv()``, but + uses ``socket.sendall()`` in its implementation, so all bytes in the included + message are sent to the socket. + +See the example below for how to implement use of the ``TCPInterface`` class in +your device drivers and how to add error handling to the agent. + +Example +------- +An example of using ``TCPInterface`` to create a class that interfaces with a +device:: + + from socs.tcp import TCPInterface + + class Device(TCPInterface): + def __init__(self, ip_address, port=501, timeout=10, *args, **kwargs): + # Setup the TCP Interface + super().__init__(ip_address, port, timeout) + + def get_data(self): + self.send(query_string) + data = self.recv() + # Optionally perform any decoding required + return data + +Within the agent code where ``Device.get_data`` is used you should now handle +the possible ``ConnectionError``, as shown below. + +.. note:: + This example is stripped down to focus on the error handling. Important + parts of the agent process are missing here, like obtaining the lock and + publishing data to a feed. + +.. code-block:: + + class DeviceAgent: + self.device = Device('192.168.1.2') + + def main(self, session, params): + """Main data acquisition process.""" + + while session.status in ['starting', 'running']: + try: + data = self.device.get_data() + if session.degraded: + self.log.info("Connection re-established.") + session.degraded = False + except ConnectionError: + self.log.error("Failed to get data from device. Check network connection.") + session.degraded = True + time.sleep(1) # wait between reconnection attempts + continue + + return True, "Main process exited successfully." + +See existing TCP agents, such as the Cryomech CPA Agent (which the above +example is based on) for more examples. + +API +--- + +If you are developing an agent that connects to a device using TCP, the +``TCPInterface`` class is available for use and detailed here: + +.. autoclass:: socs.tcp.TCPInterface + :members: diff --git a/docs/index.rst b/docs/index.rst index 518ed4125..33406c268 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -97,7 +97,8 @@ API Reference Full API documentation for core parts of the SOCS library. :caption: Developer Guide :maxdepth: 2 - developer/snmp + developer/interfaces/snmp + developer/interfaces/tcp developer/testing .. toctree:: diff --git a/socs/Lakeshore/Lakeshore372.py b/socs/Lakeshore/Lakeshore372.py index eb21609e2..0aa60fb57 100644 --- a/socs/Lakeshore/Lakeshore372.py +++ b/socs/Lakeshore/Lakeshore372.py @@ -1,11 +1,12 @@ # Lakeshore372.py -import socket import sys import time import numpy as np +from socs.tcp import TCPInterface + # Lookup keys for command parameters. autorange_key = {'0': 'off', '1': 'on', @@ -173,38 +174,7 @@ heater_display_lock = {v: k for k, v in heater_display_key.items()} -def _establish_socket_connection(ip, timeout, port=7777): - """Establish socket connection to the LS372. - - Parameters - ---------- - ip : str - IP address of the LS372 - timeout : int - timeout period for the socket connection in seconds - port : int - Port for the connection, defaults to the default LS372 port of 7777 - - Returns - ------- - socket.socket - The socket object with open connection to the 372 - - """ - com = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - com.connect((ip, port)) - except OSError as e: - if 'No route to host' in e.strerror: - raise ConnectionError("Cannot connect to LS372") - else: - raise e - com.settimeout(timeout) - - return com - - -class LS372: +class LS372(TCPInterface): """ Lakeshore 372 class. @@ -213,10 +183,12 @@ class LS372: index 0 corresponding to the control channel, 'A' """ - def __init__(self, ip, timeout=10, num_channels=16): - self.com = _establish_socket_connection(ip, timeout) + def __init__(self, ip_address, port=7777, timeout=10, num_channels=16): self.num_channels = num_channels + # Setup the TCP Interface + super().__init__(ip_address, port, timeout) + self.id = self.get_id() self.autoscan = self.get_autoscan() # Enable all channels @@ -237,11 +209,7 @@ def __init__(self, ip, timeout=10, num_channels=16): self.still_heater = Heater(self, 2) def msg(self, message): - """Send message to the Lakeshore 372 over ethernet. - - If we're asking for something from the Lakeshore (indicated by a ? in - the message string), then we will attempt to ask twice before giving up - due to potential communication timeouts. + """Send message to the Lakeshore 372 over TCP. Parameters ---------- @@ -257,20 +225,10 @@ def msg(self, message): msg_str = f'{message}\r\n'.encode() if '?' in message: - self.com.send(msg_str) - # Try once, if we timeout, try again. Usually gets around single event glitches. - for attempt in range(2): - try: - resp = str(self.com.recv(4096), 'utf-8').strip() - break - except socket.timeout: - print("Warning: Caught timeout waiting for response to '%s', trying again " - "before giving up" % message) - if attempt == 1: - raise RuntimeError('Query response to Lakeshore timed out after two ' - 'attempts. Check connection.') + self.send(msg_str) + resp = str(self.recv(), 'utf-8').strip() else: - self.com.send(msg_str) + self.send(msg_str) resp = '' return resp diff --git a/socs/agents/cryomech_cpa/drivers.py b/socs/agents/cryomech_cpa/drivers.py index 63e3c434e..8851011f5 100644 --- a/socs/agents/cryomech_cpa/drivers.py +++ b/socs/agents/cryomech_cpa/drivers.py @@ -1,8 +1,8 @@ import random -import selectors -import socket import struct +from socs.tcp import TCPInterface + STX = '\x02' ADDR = '\x10' CMD = '\x80' @@ -15,7 +15,29 @@ ESC_ESC = '\x32' -class PTC: +class PTC(TCPInterface): + """Interface class for connecting to the pulse tube compressor. + + Parameters + ---------- + ip_address : str + IP address of the device. + port : int + Associated port for TCP communication. Default is 502. + timeout : float + Duration in seconds that operations wait before giving up. Default is + 10 seconds. + fake_errors : bool + Flag that generates random fake errors if True. Does not generate + errors if False. Defaults to False. + + Attributes + ---------- + comm : socket.socket + Socket object that forms the connection to the compressor. + + """ + def __init__(self, ip_address, port=502, timeout=10, fake_errors=False): self.fake_errors = fake_errors @@ -23,89 +45,15 @@ def __init__(self, ip_address, port=502, timeout=10, fake_errors=False): self.serial = None self.software_revision = None - self.ip_address = ip_address - self.port = int(port) - self.timeout = timeout - self.comm = self._connect((self.ip_address, self.port)) - - def _connect(self, address): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(self.timeout) - try: - sock.connect(address) - except TimeoutError: - print(f"Connection not established within {self.timeout}.") - return - except OSError as e: - print(f"Unable to connect. {e}") - return - except Exception as e: - print(f"Caught unexpected {type(e).__name__} while connecting:") - print(f" {e}") - return - return sock - - def reset(self): - print("Resetting the connection to the compressor.") - self.comm = self._connect((self.ip_address, self.port)) - - def _write(self, msg): - if self.comm is None: - print("Connection not established. Unable to send command.") - self.reset() - return - - try: - self.comm.sendall(msg) - return - except (BrokenPipeError, ConnectionResetError) as e: - print(f"Connection error: {e}") - self.reset() - except TimeoutError as e: - print(f"Timeout error while writing: {e}") - self.reset() - except Exception as e: - print(f"Caught unexpected {type(e).__name__} during write:") - print(f" {e}") - self.reset() - - # Try a second time before giving up - try: - self.comm.sendall(msg) - except (BrokenPipeError, ConnectionResetError) as e: - print(f"Connection error: {e}") - raise ConnectionError - except TimeoutError as e: - print(f"Timeout error while writing: {e}") - raise ConnectionError - except AttributeError: - raise ConnectionError("Unable to reset connection.") - except Exception as e: - print(f"Caught unexpected {type(e).__name__} during write:") - print(f" {e}") - raise ConnectionError - - def _check_ready(self): - """Check socket is ready to read from.""" - if self.comm is None: - raise ConnectionError("Connection not established, not ready to read.") - - sel = selectors.DefaultSelector() - sel.register(self.comm, selectors.EVENT_READ) - if not sel.select(self.timeout): - raise ConnectionError - - def _read(self): - self._check_ready() - data = self.comm.recv(1024) - return data + # Setup the TCP Interface + super().__init__(ip_address, port, timeout) def get_data(self): """ - Gets the raw data from the ptc and returns it in a usable format. + Gets the raw data from the PTC and returns it in a usable format. """ - self._write(self.buildRegistersQuery()) - data = self._read() + self.send(self.buildRegistersQuery()) + data = self.recv(1024) data_flag, brd = self.breakdownReplyData(data) return data_flag, brd @@ -246,10 +194,3 @@ def breakdownReplyData(self, rawdata): f"Skipping this data block. Bad output string is {rawdata}") return data_flag, data - - def __del__(self): - """ - If the PTC class instance is destroyed, close the connection to the - ptc. - """ - self.comm.close() diff --git a/socs/tcp.py b/socs/tcp.py new file mode 100644 index 000000000..3b6746d6a --- /dev/null +++ b/socs/tcp.py @@ -0,0 +1,156 @@ +import selectors +import socket + + +class TCPInterface: + """Interface class for connecting to devices using TCP. + + Parameters + ---------- + ip_address : str + IP address of the device. + port : int + Associated port for TCP communication. + timeout : float + Duration in seconds that operations wait before giving up. + + Attributes + ---------- + ip_address : str + IP address of the device. + port : int + Associated port for TCP communication. + timeout : float + Duration in seconds that operations wait before giving up. + comm : socket.socket + Socket object that forms the connection to the device. + + """ + + def __init__(self, ip_address, port, timeout): + self.ip_address = ip_address + self.port = int(port) + self.timeout = timeout + self.comm = self._connect((self.ip_address, self.port)) + + def _connect(self, address): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(self.timeout) + try: + sock.connect(address) + except TimeoutError: + print(f"Connection not established within {self.timeout}.") + return + except OSError as e: + print(f"Unable to connect. {e}") + return + except Exception as e: + print(f"Caught unexpected {type(e).__name__} while connecting:") + print(f" {e}") + return + return sock + + def _reset(self): + print("Resetting the connection to the device.") + self.comm = self._connect((self.ip_address, self.port)) + + def send(self, msg): + """Send message to socket. + + This method will try to send the message and if it runs into any issues + will try to re-establish the socket connection before trying to send + the message again. If it fails a second time it raises an exception. + + If the connection has failed to reset from a previous ``send``, or has + not yet been established, it will first try to connnect before sending + the message. If it fails to establish the connection it will raise an + exception. + + Parameters + ---------- + msg : str + Message string to send on socket. + + Raises + ------ + ConnectionError + Raised if the communication fails for any reason. + + """ + if self.comm is None: + print("Connection not established.") + self._reset() + if self.comm is None: + raise ConnectionError("Unable to establish connection.") + + try: + self.comm.sendall(msg) + return + except (BrokenPipeError, ConnectionResetError) as e: + print(f"Connection error: {e}") + self._reset() + except TimeoutError as e: + print(f"Timeout error while writing: {e}") + self._reset() + except Exception as e: + print(f"Caught unexpected {type(e).__name__} during send:") + print(f" {e}") + self._reset() + + # Try a second time before giving up + try: + self.comm.sendall(msg) + except (BrokenPipeError, ConnectionResetError) as e: + print(f"Connection error: {e}") + raise ConnectionError + except TimeoutError as e: + print(f"Timeout error while writing: {e}") + raise ConnectionError + except AttributeError: + raise ConnectionError("Unable to reset connection.") + except Exception as e: + print(f"Caught unexpected {type(e).__name__} during send:") + print(f" {e}") + raise ConnectionError + + def _check_ready(self): + """Check socket is ready to read from.""" + if self.comm is None: + raise ConnectionError("Connection not established, not ready to read.") + + sel = selectors.DefaultSelector() + sel.register(self.comm, selectors.EVENT_READ) + if not sel.select(self.timeout): + raise ConnectionError("Socket not ready to read. Possible timeout.") + + def recv(self, bufsize=4096): + """Receive response from the device. + + This method will check if the socket is ready to be read from before + performing the recv. If there is no data to read, or the socket is + otherwise unready an exception is raised. + + Parameters + ---------- + bufsize : int + Amount of data to be recieved in bytes. Defaults to 4096. + + Returns + ------- + ``str`` or ``bytes`` + The response from the device. The return type + depends on the device. + + Raises + ------ + ConnectionError + Raised if the socket is not ready to read from. + + """ + self._check_ready() + data = self.comm.recv(bufsize) + return data + + def __del__(self): + if self.comm: + self.comm.close() diff --git a/tests/agents/test_ls372_agent.py b/tests/agents/test_ls372_agent.py index 34143e537..7d4954cc2 100644 --- a/tests/agents/test_ls372_agent.py +++ b/tests/agents/test_ls372_agent.py @@ -94,7 +94,7 @@ def side_effect(arg): # Tests -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_init_lakeshore(agent): """Run init_lakeshore, mocking a connection and the 372 messaging. @@ -111,7 +111,7 @@ def test_ls372_init_lakeshore(agent): assert res[0] is True -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_init_lakeshore_already_initialized(agent): """Initializing an already initialized LS372_Agent should just return True. @@ -126,32 +126,16 @@ def test_ls372_init_lakeshore_already_initialized(agent): # If we don't patch the reactor out, it'll mess up pytest when stop is called @mock.patch('socs.agents.lakeshore372.agent.reactor', mock.MagicMock()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_failed_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_init_lakeshore_failed_connection(agent): - """Leaving off the connection Mock, if the connection fails the init task - should fail and return False. - - """ - session = create_session('init_lakeshore') - res = agent.init_lakeshore(session, None) - assert res[0] is False - - -# If we don't patch the reactor out, it'll mess up pytest when stop is called -@mock.patch('socs.agents.lakeshore372.agent.reactor', mock.MagicMock()) -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_failed_connection()) -@mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) -def test_ls372_init_lakeshore_unhandled_error(agent): - """If we cause an unhandled exception during connection init task should - also fail and return False. - - """ + """If the connection fails the init task should fail and return False.""" session = create_session('init_lakeshore') res = agent.init_lakeshore(session, None) assert res[0] is False -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_init_lakeshore_auto_acquire(agent): """If we initalize and pass the auto_acquire param, we should expect the @@ -165,7 +149,7 @@ def test_ls372_init_lakeshore_auto_acquire(agent): # enable_control_chan -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_enable_control_chan(agent): """Normal operation of 'enable_control_chan' task.""" @@ -179,7 +163,7 @@ def test_ls372_enable_control_chan(agent): # disable_control_chan -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_disable_control_chan(agent): """Normal operation of 'disable_control_chan' task.""" @@ -193,7 +177,7 @@ def test_ls372_disable_control_chan(agent): # acq -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_acq(agent): """Test running the 'acq' Process once.""" @@ -210,7 +194,7 @@ def test_ls372_acq(agent): assert session.data['fields']['Channel_01']['R'] == 108.278 -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_acq_w_control_chan(agent): """Test running the 'acq' Process once with control channel active.""" @@ -230,7 +214,7 @@ def test_ls372_acq_w_control_chan(agent): assert session.data['fields']['control']['R'] == 0.0 -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_acq_w_sample_heater(agent): """Test running the 'acq' Process once with sample heater active.""" @@ -245,7 +229,7 @@ def test_ls372_acq_w_sample_heater(agent): # stop_acq -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_stop_acq_not_running(agent): """'stop_acq' should return False if acq Process isn't running.""" @@ -258,7 +242,7 @@ def test_ls372_stop_acq_not_running(agent): assert res[0] is False -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_stop_acq_while_running(agent): """'stop_acq' should return True if acq Process is running.""" @@ -276,7 +260,7 @@ def test_ls372_stop_acq_while_running(agent): # set_heater_range -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_heater_range_sample_heater(agent): """Set sample heater to different range than currently set. Normal @@ -293,7 +277,7 @@ def test_ls372_set_heater_range_sample_heater(agent): assert res[0] is True -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_heater_range_still_heater(agent): """Set still heater to different range than currently set. Normal @@ -310,7 +294,7 @@ def test_ls372_set_heater_range_still_heater(agent): assert res[0] is True -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_heater_range_identical_range(agent): """Set heater to same range as currently set. Should not change range, just @@ -333,7 +317,7 @@ def test_ls372_set_heater_range_identical_range(agent): # set_excitation_mode -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_excitation_mode(agent): """Normal operation of 'set_excitation_mode' task.""" @@ -348,7 +332,7 @@ def test_ls372_set_excitation_mode(agent): # set_excitation -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_excitation(agent): """Normal operation of 'set_excitation' task.""" @@ -362,7 +346,7 @@ def test_ls372_set_excitation(agent): assert res[0] is True -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_excitation_already_set(agent): """Setting to already set excitation value.""" @@ -377,7 +361,7 @@ def test_ls372_set_excitation_already_set(agent): # get_excitation -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_get_excitation(agent): session = create_session('get_excitation') @@ -391,7 +375,7 @@ def test_ls372_get_excitation(agent): # set_resistance_range -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_resistance_range(agent): session = create_session('get_resistance_range') @@ -404,7 +388,7 @@ def test_ls372_set_resistance_range(agent): assert res[0] is True -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_resistance_range_current_range(agent): session = create_session('get_resistance_range') @@ -419,7 +403,7 @@ def test_ls372_set_resistance_range_current_range(agent): # get_resistance_range -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_get_resistance_range_current_range(agent): session = create_session('get_resistance_range') @@ -434,7 +418,7 @@ def test_ls372_get_resistance_range_current_range(agent): # set_dwell -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_dwell(agent): session = create_session('set_dwell') @@ -449,7 +433,7 @@ def test_ls372_set_dwell(agent): # get_dwell -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_get_dwell(agent): session = create_session('get_dwell') @@ -464,7 +448,7 @@ def test_ls372_get_dwell(agent): # set_pid -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_pid(agent): """Normal operation of 'set_pid' task.""" @@ -479,7 +463,7 @@ def test_ls372_set_pid(agent): # set_active_channel -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_active_channel(agent): """Normal operation of 'set_active_channel' task.""" @@ -494,7 +478,7 @@ def test_ls372_set_active_channel(agent): # set_autoscan -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_autoscan_on(agent): """Normal operation of 'set_autoscan' task.""" @@ -508,7 +492,7 @@ def test_ls372_set_autoscan_on(agent): assert res[0] is True -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_autoscan_off(agent): """Normal operation of 'set_autoscan' task.""" @@ -529,7 +513,7 @@ def test_ls372_set_autoscan_off(agent): # set_output_mode -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_output_mode_still(agent): """Normal operation of 'set_output_mode' task for the still heater.""" @@ -543,7 +527,7 @@ def test_ls372_set_output_mode_still(agent): assert res[0] is True -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_output_mode_sample(agent): """Normal operation of 'set_output_mode' task for the sample heater.""" @@ -558,7 +542,7 @@ def test_ls372_set_output_mode_sample(agent): # set_heater_output -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_heater_output_still(agent): """Normal operation of 'set_heater_output' task for the still heater.""" @@ -572,7 +556,7 @@ def test_ls372_set_heater_output_still(agent): assert res[0] is True -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_heater_output_sample(agent): """Normal operation of 'set_heater_output' task for the sample heater.""" @@ -587,7 +571,7 @@ def test_ls372_set_heater_output_sample(agent): # set_still_output -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_set_still_output(agent): """Normal operation of 'set_still_output' task.""" @@ -602,7 +586,7 @@ def test_ls372_set_still_output(agent): # get_still_output -@mock.patch('socs.Lakeshore.Lakeshore372._establish_socket_connection', mock_connection()) +@mock.patch('socs.tcp.TCPInterface._connect', mock_connection()) @mock.patch('socs.Lakeshore.Lakeshore372.LS372.msg', mock_372_msg()) def test_ls372_get_still_output(agent): """Normal operation of 'get_still_output' task."""