Ejemplo n.º 1
0
    def inspect(self):
        timeout_manager = future_timeout_manager(self.sync_timeout)
        request_changes = yield self.inspect_requests(timeout=timeout_manager.remaining())
        sensor_changes = yield self.inspect_sensors(timeout=timeout_manager.remaining())

        model_changes = AttrDict()
        if request_changes:
            model_changes.requests = request_changes
        if sensor_changes:
            model_changes.sensors = sensor_changes
        if model_changes:
            raise Return(model_changes)
Ejemplo n.º 2
0
    def inspect(self):
        """Inspect device requests and sensors, update model

        Returns
        -------

        Tornado future that resolves with:

        model_changes : Nested AttrDict or None
            Contains sets of added/removed request/sensor names

            Example structure:

            {'requests': {
                'added': set(['req1', 'req2']),
                'removed': set(['req10', 'req20'])}
             'sensors': {
                'added': set(['sens1', 'sens2']),
                'removed': set(['sens10', 'sens20'])}
            }

            If there are no changes keys may be omitted. If an item is in both
            the 'added' and 'removed' sets that means that it changed.

            If neither request not sensor changes are present, None is returned
            instead of a nested structure.

        """
        timeout_manager = future_timeout_manager(self.sync_timeout)
        sensor_index_before = copy.copy(self._sensors_index)
        request_index_before = copy.copy(self._requests_index)
        try:
            request_changes = yield self.inspect_requests(
                timeout=timeout_manager.remaining())
            sensor_changes = yield self.inspect_sensors(
                timeout=timeout_manager.remaining())
        except Exception:
            # Ensure atomicity of sensor and request updates ; if the one
            # fails, the other should act as if it has failed too.
            self._sensors_index = sensor_index_before
            self._requests_index = request_index_before
            raise

        model_changes = AttrDict()
        if request_changes:
            model_changes.requests = request_changes
        if sensor_changes:
            model_changes.sensors = sensor_changes
        if model_changes:
            raise Return(model_changes)
Ejemplo n.º 3
0
    def inspect_requests(self, name=None, timeout=None):
        """Inspect all or one requests on the device. Update requests index.

        Parameters
        ----------
        name : str or None, optional
            Name of the sensor or None to get all requests.
        timeout : float or None, optional
            Timeout for request inspection, None for no timeout

        Returns
        -------
        Tornado future that resolves with:

        changes : :class:`~katcp.core.AttrDict`
            AttrDict with keys ``added`` and ``removed`` (of type
            :class:`set`), listing the requests that have been added or removed
            respectively.  Modified requests are listed in both. If there are
            no changes, returns ``None`` instead.

            Example structure:

            {'added': set(['req1', 'req2']),
             'removed': set(['req10', 'req20'])}

        """
        if name is None:
            msg = katcp.Message.request('help')
        else:
            msg = katcp.Message.request('help', name)
        reply, informs = yield self.katcp_client.future_request(
            msg, timeout=timeout)
        if not reply.reply_ok():
            # If an unknown request is specified the desired result is to return
            # an empty list even though the request will fail
            if name is None or 'Unknown request' not in reply.arguments[1]:
                raise SyncError(
                    'Error reply during sync process for {}: {}'
                    .format(self.bind_address_string, reply))


        requests_old = set(self._requests_index.keys())
        requests_updated = set()
        for msg in informs:
            req_name = msg.arguments[0]
            req = {'description': msg.arguments[1]}
            requests_updated.add(req_name)
            self._update_index(self._requests_index, req_name, req)

        added, removed = self._difference(
            requests_old, requests_updated, name, self._requests_index)
        if added or removed:
            raise Return(AttrDict(added=added, removed=removed))
Ejemplo n.º 4
0
    def test_wrapping(self):
        test_dict = AttrDict(a=2, b=1)
        class TestWrapper(object):
            def __init__(self, wrappee):
                self.wrappee = wrappee

            def __eq__(self, other):
                return self.wrappee == other.wrappee

        wrapped_dict = resource_client.AttrMappingProxy(test_dict, TestWrapper)
        # Test keys
        self.assertEqual(wrapped_dict.keys(), test_dict.keys())
        # Test key access:
        for key in test_dict:
            self.assertEqual(wrapped_dict[key].wrappee, test_dict[key])
        # Test attribute access
        for key in test_dict:
            self.assertEqual(getattr(wrapped_dict, key).wrappee,
                             getattr(test_dict, key))
        # Test whole dict comparison
        self.assertEqual(wrapped_dict,
                         {k : TestWrapper(v) for k, v in test_dict.items()})
Ejemplo n.º 5
0
    def inspect(self):
        """Inspect device requests and sensors, update model"""
        timeout_manager = future_timeout_manager(self.sync_timeout)
        sensor_index_before = copy.copy(self._sensors_index)
        request_index_before = copy.copy(self._requests_index)
        try:
            request_changes = yield self.inspect_requests(timeout=timeout_manager.remaining())
            sensor_changes = yield self.inspect_sensors(timeout=timeout_manager.remaining())
        except Exception:
            # Ensure atomicity of sensor and request updates ; if the one
            # fails, the other should act as if it has failed too.
            self._sensors_index = sensor_index_before
            self._requests_index = request_index_before
            raise

        model_changes = AttrDict()
        if request_changes:
            model_changes.requests = request_changes
        if sensor_changes:
            model_changes.sensors = sensor_changes
        if model_changes:
            raise Return(model_changes)
Ejemplo n.º 6
0
    def inspect_sensors(self, name=None, timeout=None):
        """Inspect all or one sensor on the device. Update sensors index.

        Parameters
        ----------
        name : str or None, optional
            Name of the sensor or None to get all sensors.
        timeout : float or None, optional
            Timeout for sensors inspection, None for no timeout

        Returns
        -------
        Tornado future that resolves with:

        changes : :class:`~katcp.core.AttrDict`
            AttrDict with keys ``added`` and ``removed`` (of type
            :class:`set`), listing the sensors that have been added or removed
            respectively.  Modified sensors are listed in both. If there are no
            changes, returns ``None`` instead.

        Example structure:

            {'added': set(['sens1', 'sens2']),
             'removed': set(['sens10', 'sens20'])}

        """
        if name is None:
            msg = katcp.Message.request('sensor-list')
        else:
            msg = katcp.Message.request('sensor-list', name)

        reply, informs = yield self.katcp_client.future_request(
            msg, timeout=timeout)
        self._logger.debug(
            '{} received {} sensor-list informs, reply: {}'.format(
                self.bind_address_string, len(informs), reply))
        if not reply.reply_ok():
            # If an unknown sensor is specified the desired result is to return
            # an empty list, even though the request will fail
            if name is None or 'Unknown sensor' not in reply.arguments[1]:
                raise SyncError(
                    'Error reply during sync process: {}'.format(reply))

        sensors_old = set(self._sensors_index.keys())
        sensors_updated = set()
        for msg in informs:
            sen_name = msg.arguments[0]
            sensors_updated.add(sen_name)
            sen = {
                'description': msg.arguments[1],
                'units': msg.arguments[2],
                'sensor_type': msg.arguments[3],
                'params': msg.arguments[4:]
            }
            self._update_index(self._sensors_index, sen_name, sen)

        added, removed = self._difference(sensors_old, sensors_updated, name,
                                          self._sensors_index)

        for sensor_name in removed:
            if sensor_name in self._sensor_object_cache:
                del self._sensor_object_cache[sensor_name]

        if added or removed:
            raise Return(AttrDict(added=added, removed=removed))
Ejemplo n.º 7
0
 def _connect(self):
     assert get_thread_ident() == self.ioloop_thread_id
     self._stream = AttrDict(error=None)
     self._connected.set()
     self.notify_connected(True)
     self.preset_protocol_flags(ProtocolFlags(5, 0, set('IM')))