예제 #1
0
    def create_observation(self, data: Dict[str, Any]) -> Observation:
        """Creates an observation object.

        Args:
            data: The observation data.
        """
        data['id'] = Observation.get_new_id()
        data['sensorName'] = self._name
        data['sensorType'] = self._type

        # Character '\' is escaped in the JSON configuration file. Encoded
        # bytes have to be decoded.
        for set_name, request_set in data.get('requestSets').items():
            if request_set.get('request'):
                request_set['request'] = codecs.decode(
                    request_set.get('request'), 'unicode_escape')

            if request_set.get('responseDelimiter'):
                request_set['responseDelimiter'] = codecs.decode(
                    request_set.get('responseDelimiter'), 'unicode_escape')

            if request_set.get('responsePattern'):
                request_set['responsePattern'] = codecs.decode(
                    request_set.get('responsePattern'), 'unicode_escape')

        return Observation(data)
예제 #2
0
    def listen(self, obs_draft: Observation) -> None:
        """Threaded method for passive mode. Reads incoming data from serial
        port. Used for sensors which start streaming data without prior
        request.

        Args:
            obs_draft: The observation draft with the response pattern.
        """
        while self._is_running and self._is_passive:
            if not obs_draft:
                self.logger.warning(f'No draft observation set for passive '
                                    f'listener on port "{self.name}"')
                break

            if not self._serial:
                self._create()

            if self._serial is None:
                self.logger.error(f'Can\'t access port '
                                  f'"{self._serial_port_config.port}" for '
                                  f'passive listening')

                return

            if not self._serial.is_open:
                self.logger.info(f'Re-opening port '
                                 f'"{self._serial_port_config.port}" for '
                                 f'passive listening ...')
                self._serial.open()
                self._serial.reset_input_buffer()

            obs = copy.deepcopy(obs_draft)
            obs.set('id', Observation.get_new_id())
            obs.set('portName', self.name)

            draft = obs.get('requestSets').get('draft')

            timeout = draft.get('timeout', 1.0)
            response_delimiter = draft.get('responseDelimiter', '')
            length = draft.get('responseLength', 0)
            request = draft.get('request')

            if request:
                self._write(request)

            response = self._read(eol=response_delimiter,
                                  length=length,
                                  timeout=timeout)

            if response:
                self.logger.verbose(
                    f'Received "{self.sanitize(response)}" '
                    f'from sensor "{obs.get("sensorName")}" on '
                    f'port "{self._name}"')
                draft['response'] = response
                obs.set('timestamp', str(arrow.utcnow()))
                self.publish_observation(obs)
예제 #3
0
    def run(self) -> None:
        """Iterates trough the observation set and sends observations to an
        external callback function."""
        # Return if observation is disabled.
        if not self._obs.get('enabled'):
            return

        # Disable the observation if it should run one time only.
        if self._obs.get('onetime'):
            self._obs.set('enabled', False)

        # Make a deep copy, since we don't want to do any changes to the
        # observation in our observation set.
        obs_copy = copy.deepcopy(self._obs)

        # Set IDs.
        obs_copy.set('id', Observation.get_new_id())
        obs_copy.set('pid', self._project_id)
        obs_copy.set('nid', self._node_id)

        # Insert the name of the port module or the virtual sensor at the
        # beginning of the receivers list.
        receivers = obs_copy.get('receivers')
        receivers.insert(0, self._port_name)
        obs_copy.set('receivers', receivers)

        # Set the next receiver to the module following the port.
        obs_copy.set('nextReceiver', 1)

        self.logger.info(f'Starting job "{self._obs.get("name")}" for port '
                         f'"{self._port_name}" ...')

        # Get the sleep time of the whole observation.
        sleep_time = obs_copy.get('sleepTime', 0)

        # Create target, header, and payload in order to send the observation.
        target = self._port_name
        header = Observation.get_header()
        header['from'] = 'job'
        payload = obs_copy.data

        # Fire and forget the observation.
        self._uplink(target, header, payload)

        # Sleep until the next observation.
        self.logger.debug(f'Next observation starts in {sleep_time} s')
        time.sleep(sleep_time)