def test_socket_creation(): sock = TCP("example.com", 34567) assert sock.host == "example.com" assert sock.port == 34567 assert sock.auto_reconnect is True assert not sock.connected() assert sock.connection_counter == 0
def test_write_readline_fail(unused_tcp_port): sock = TCP('0', unused_tcp_port) assert not sock.connected assert sock.connection_counter == 0 with pytest.raises(ConnectionRefusedError): sock.write_readline(IDN_REQ) assert not sock.connected assert sock.connection_counter == 0
def test_open_fail(unused_tcp_port): sock = TCP('0', unused_tcp_port) assert not sock.connected assert sock.connection_counter == 0 with pytest.raises(ConnectionRefusedError): sock.open() assert not sock.connected assert sock.connection_counter == 0
def test_socket_creation(): sock = TCP('example.com', 34567) assert sock.host == 'example.com' assert sock.port == 34567 assert sock.auto_reconnect == True assert not sock.connected assert sock.connection_counter == 0
def __init__(self, host, port=SCPI_CONTROL_PORT, zmq_port=ZMQ_STREAMING_PORT): self.host = host self.port = port self._sock = TCP(host, port) self._zmq_receiver = ZmqStreamReceiver(host, zmq_port) # TODO: Remove when sardana allows to use the configuration file logging.getLogger('sockio').setLevel(logging.INFO) self.log = logging.getLogger('em2.Em2({0}:{1})'.format(host, port)) self.log.setLevel(logging.INFO) self.channels = [ Channel(self, i) for i in range(CHANNEL_MIN, CHANNEL_MAX + 1) ] self._software_version = None self._read_index_bug = None self._long_acquisition_scaling_bug = None self._zmq_streaming_supported = None
def connect_to_SOS(): """Establish a connection with the Science on a Sphere application""" while True: # Sleep for 5 seconds so that we don't spam the connection print("Connecting in 5 seconds...") time.sleep(5) try: # Send Science on a Sphere command to begin communication socket = TCP(config.defaults_dict["sos_ip_address"], 2468) socket.write_readline(b'enable\n') print("Connected!") break except ConnectionRefusedError as e: print("Error: Connection with Science on a Sphere failed to initialize. Make sure you have specificed sos_ip_address in defaults.ini, both computers are on the same network (or are the same machine), and port 2468 is accessible.") if DEBUG: print(e) return socket
def test_callbacks(sio_server): host, port = sio_server.sockets[0].getsockname() state = dict(made=0, lost=0, eof=0) def made(): state["made"] += 1 def lost(exc): state["lost"] += 1 def eof(): state["eof"] += 1 sio_tcp = TCP( host, port, on_connection_made=made, on_connection_lost=lost, on_eof_received=eof, ) assert not sio_tcp.connected() assert sio_tcp.connection_counter == 0 assert state["made"] == 0 assert state["lost"] == 0 assert state["eof"] == 0 sio_tcp.open() assert sio_tcp.connected() assert sio_tcp.connection_counter == 1 assert state["made"] == 1 assert state["lost"] == 0 assert state["eof"] == 0 with pytest.raises(ConnectionError): sio_tcp.open() assert sio_tcp.connected() assert sio_tcp.connection_counter == 1 assert state["made"] == 1 assert state["lost"] == 0 assert state["eof"] == 0 sio_tcp.close() assert not sio_tcp.connected() assert sio_tcp.connection_counter == 1 assert state["made"] == 1 assert state["lost"] == 1 assert state["eof"] == 0 sio_tcp.open() assert sio_tcp.connected() assert sio_tcp.connection_counter == 2 assert state["made"] == 2 assert state["lost"] == 1 assert state["eof"] == 0 sio_tcp.close() assert not sio_tcp.connected() assert sio_tcp.connection_counter == 2 assert state["made"] == 2 assert state["lost"] == 2 assert state["eof"] == 0 sio_tcp.close() assert not sio_tcp.connected() assert sio_tcp.connection_counter == 2 assert state["made"] == 2 assert state["lost"] == 2 assert state["eof"] == 0
class Em2(object): def __init__(self, host, port=SCPI_CONTROL_PORT, zmq_port=ZMQ_STREAMING_PORT): self.host = host self.port = port self._sock = TCP(host, port) self._zmq_receiver = ZmqStreamReceiver(host, zmq_port) # TODO: Remove when sardana allows to use the configuration file logging.getLogger('sockio').setLevel(logging.INFO) self.log = logging.getLogger('em2.Em2({0}:{1})'.format(host, port)) self.log.setLevel(logging.INFO) self.channels = [ Channel(self, i) for i in range(CHANNEL_MIN, CHANNEL_MAX + 1) ] self._software_version = None self._read_index_bug = None self._long_acquisition_scaling_bug = None self._zmq_streaming_supported = None @property def read_index_bug(self): if self._read_index_bug is None: self._read_index_bug = self.software_version <= (2, 0) return self._read_index_bug @property def long_acquisition_scaling_bug(self): if self._long_acquisition_scaling_bug is None: self._long_acquisition_scaling_bug = ((1, 3, 5) <= self.software_version < (2, 1)) return self._long_acquisition_scaling_bug @property def zmq_streaming_supported(self): if self._zmq_streaming_supported is None: self._zmq_streaming_supported = self.software_version >= (2, 2) return self._zmq_streaming_supported @property def zmq_streaming_required(self): return self.acquisition_mode.upper() == 'STREAMING' def __getitem__(self, i): return self.channels[i] def open(self): self._sock.open() def commands(self, *cmds): cmds = [cmd.encode() + b'\n' for cmd in cmds] self.log.debug('-> %r', cmds) result = [ line.strip().decode() for line in self._sock.writelines_readlines(cmds) ] self.log.debug('<- %r', result) return result def command(self, cmd): result = self.commands(cmd)[0] if result.startswith('ERROR:'): raise Em2Error(result.split(' ', 1)[-1]) return result @property def idn(self): return self.command('*idn?') @property def software_version(self): if self._software_version is None: str_version = self.idn.split(',')[-1].strip() self._software_version = tuple( [_try_make_int(x) for x in str_version.split('.')]) return self._software_version @property def acquisition_state(self): return self.command('ACQU:STAT?').split('_', 1)[1] @property def acquisition_time(self): return float(self.command('ACQU:TIME?')) * 1E-3 @acquisition_time.setter def acquisition_time(self, t): self.command('ACQU:TIME {0}'.format(t * 1E3)) @property def nb_points(self): return int(self.command('ACQU:NTRIG?')) @nb_points.setter def nb_points(self, value): self.command('ACQU:NTRIG {0}'.format(value)) @property def nb_points_ready(self): if self._zmq_receiver.started: return self._zmq_receiver.nb_points_received else: return self._get_nb_points_ready_via_scpi() def _get_nb_points_ready_via_scpi(self): return int(self.command('ACQU:NDAT?')) @property def trigger_input(self): return self.command('TRIG:INPU?') @trigger_input.setter def trigger_input(self, value): self.command('TRIG:INPU {0}'.format(value)) @property def trigger_mode(self): return self.command('TRIG:MODE?') @trigger_mode.setter def trigger_mode(self, value): self.command('TRIG:MODE {0}'.format(value)) @property def trigger_polarity(self): return self.command('TRIG:POLA?') @trigger_polarity.setter def trigger_polarity(self, value): self.command('TRIG:POLA {0}'.format(value)) @property def trigger_precision(self): return self.command('TRIG:PREC?').lower() == 'true' @trigger_precision.setter def trigger_precision(self, value): self.command('TRIG:PREC {0}'.format('True' if value else 'False')) @property def trigger_delay(self): return float(self.command('TRIG:DELA?')) * 1E-3 @trigger_delay.setter def trigger_delay(self, value): self.command('TRIG:DELA {0}'.format(value * 1E3)) def software_trigger(self): return self.command('TRIG:SWSE True') @property def acquisition_mode(self): return self.command('ACQU:MODE?') @acquisition_mode.setter def acquisition_mode(self, value): self.command('ACQU:MODE {0}'.format(value)) @property def timestamp_data(self): return self.command('TMST?').lower() == 'true' @timestamp_data.setter def timestamp_data(self, value): self.command('TMST {0}'.format('True' if value else 'False')) def start_acquisition(self, soft_trigger=True): if self.zmq_streaming_required and self.zmq_streaming_supported: self._zmq_receiver.start() self.command('ACQU:START' + (' SWTRIG' if soft_trigger else '')) def stop_acquisition(self): self.command('ACQU:STOP True') if self._zmq_receiver.started: self._zmq_receiver.stop() @property def data(self): return AcquisitionData(self) def read(self, start_position=0, nb_points=None): if self._zmq_receiver.started: data = self._zmq_receiver.read(start_position, nb_points) else: data = self._read_via_scpi(start_position, nb_points) return data def _read_via_scpi(self, start_position=0, nb_points=None): if self.read_index_bug: start_position -= 1 cmd = 'ACQU:MEAS? {0}'.format(start_position) if nb_points is not None: cmd += ',{0}'.format(nb_points) data = dict(eval(self.command(cmd))) if self.long_acquisition_scaling_bug: data = self._correct_for_long_acquisition_scaling_bug(data) return data def _correct_for_long_acquisition_scaling_bug(self, data): nb_samples_without_overflow = 8192 adc_raw_sampling_rate = 200e3 # Hz adc_oversampling_factor = 64 sampling_rate = adc_raw_sampling_rate / adc_oversampling_factor accumulator_overflow_time = nb_samples_without_overflow / sampling_rate # sec nb_accumulator_overflows = int(self.acquisition_time / accumulator_overflow_time) if nb_accumulator_overflows > 0: nb_bits_lost_for_overflow = int.bit_length( nb_accumulator_overflows) factor = 2**nb_bits_lost_for_overflow corrected_data = {} for channel, values in data.items(): corrected_data[channel] = [v * factor for v in values] else: corrected_data = data return corrected_data def __repr__(self): channels = '\n'.join(repr(c) for c in self.channels) return TEMPLATE.format(o=self, channels=channels)