Example #1
0
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
Example #2
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
Example #3
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
Example #4
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
Example #5
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
Example #6
0
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
Example #7
0
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
Example #8
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)