def get_common_context(event: core_events.Event) -> dict:
        timestamp = event.get_timestamp()
        moment = datetime.datetime.fromtimestamp(timestamp)

        return {
            'event': event,
            'type': event.get_type(),
            'timestamp': int(timestamp),
            'moment': moment,
            'display_moment': moment.strftime('%c'),
            'public_url': settings.public_url
        }
    async def accepts(self, event: core_events.Event,
                      value_pair: Tuple[NullablePortValue, NullablePortValue],
                      old_attrs: Attributes, new_attrs: Attributes,
                      changed_attrs: Dict[str, Tuple[Attribute, Attribute]],
                      added_attrs: Attributes,
                      removed_attrs: Attributes) -> bool:

        if not self._filter_prepared:
            self._prepare_filter()

        if self._filter_event_types and event.get_type(
        ) not in self._filter_event_types:
            return False

        if (isinstance(event, core_events.DeviceEvent) and
                not await self.accepts_device(event, old_attrs, new_attrs)):

            return False

        elif (isinstance(event, core_events.PortEvent) and not await
              self.accepts_port(event, value_pair, old_attrs, new_attrs)):

            return False

        elif (isinstance(event, slaves_events.SlaveDeviceEvent)
              and not await self.accepts_slave(event, old_attrs, new_attrs)):

            return False

        return True
    async def on_value_change(self, event: core_events.Event,
                              port: core_ports.BasePort,
                              old_value: NullablePortValue,
                              new_value: NullablePortValue,
                              attrs: Attributes) -> None:

        # When period is specified, periodic_send_values() will take care of sending values
        if self._period is not None:
            return

        # Look up port id -> field number mapping; if not present, values for this port are not configured for sending
        field_no = self._fields.get(port.get_id())
        if field_no is None:
            return

        self._values_cache[field_no] = new_value

        # Don't send samples more often than min_period
        now = time.time()
        if now - self._last_send_time < self._min_period:
            return

        self._last_send_time = now
        created_at = datetime.datetime.fromtimestamp(event.get_timestamp(),
                                                     tz=pytz.UTC)

        try:
            await self.send_values(self._values_cache, created_at)

        except Exception as e:
            self.error('sending values failed: %s', e, exc_info=True)

        self._values_cache = {}
Example #4
0
    async def handle_event(self, event: core_events.Event) -> None:
        if not isinstance(event, core_events.ValueChange):
            return  # We're only interested in port value changes

        if not system.date.has_real_date_time():
            return  # Don't record history unless we've got real date/time

        port = event.get_port()
        history_interval = await port.get_history_interval()
        if history_interval != -1:
            return  # Only consider ports with history interval set to special -1 (on value change)

        now_ms = int(time.time() * 1000)

        await save_sample(port, now_ms)
        port.set_history_last_timestamp(now_ms)
Example #5
0
    def push(self, event: core_events.Event) -> None:
        # Deduplicate events
        while True:
            duplicates = [e for e in self.queue if event.is_duplicate(e)]
            if not duplicates:
                break

            for d in duplicates:
                self.queue.remove(d)
                logger.debug('dropping duplicate event %s from %s', d, self)

        # Ensure max queue size
        while len(self.queue) >= settings.core.event_queue_size:
            logger.warning('%s queue full, dropping oldest event', self)
            self.queue.pop()

        self.queue.insert(0, event)
Example #6
0
    def push(self, event: core_events.Event) -> None:
        # Deduplicate events
        while True:
            duplicates = [e for e in self.queue if event.is_duplicate(e)]
            if not duplicates:
                break

            for d in duplicates:
                self.queue.remove(d)
                self.debug('dropping duplicate event %s', d)

        # Ensure max queue size
        while len(self.queue) >= settings.core.event_queue_size:
            # This is a debug and not a warning because we often expect event drops from queues belonging to sessions
            # that are no longer active and will simply no longer consume the events
            self.debug('queue full, dropping oldest event')
            self.queue.pop()

        self.queue.insert(0, event)
    async def handle_event(self, event: core_events.Event) -> None:
        (value_pair, old_attrs, new_attrs, changed_attrs, added_attrs,
         removed_attrs) = await self._update_from_event(event)

        accepted = await self.accepts(event, value_pair, old_attrs, new_attrs,
                                      changed_attrs, added_attrs,
                                      removed_attrs)

        if not accepted:
            return

        self.debug('handling event %s', event)

        try:
            await self.on_event(event)

        except Exception as e:
            self.error('failed to handle event %s: %s',
                       event,
                       e,
                       exc_info=True)

        try:
            if isinstance(event, core_events.ValueChange):
                old_value, new_value = value_pair
                await self.on_value_change(event, event.get_port(), old_value,
                                           new_value, new_attrs)

            elif isinstance(event, core_events.PortUpdate):
                await self.on_port_update(event, event.get_port(), old_attrs,
                                          new_attrs, changed_attrs,
                                          added_attrs, removed_attrs)

            elif isinstance(event, core_events.PortAdd):
                await self.on_port_add(event, event.get_port(), new_attrs)

            elif isinstance(event, core_events.PortRemove):
                await self.on_port_remove(event, event.get_port(), new_attrs)

            elif isinstance(event, core_events.DeviceUpdate):
                await self.on_device_update(event, old_attrs, new_attrs,
                                            changed_attrs, added_attrs,
                                            removed_attrs)

            elif isinstance(event, core_events.FullUpdate):
                await self.on_full_update(event)

            elif isinstance(event, slaves_events.SlaveDeviceUpdate):
                await self.on_slave_device_update(event, event.get_slave(),
                                                  old_attrs, new_attrs,
                                                  changed_attrs, added_attrs,
                                                  removed_attrs)

            elif isinstance(event, slaves_events.SlaveDeviceAdd):
                await self.on_slave_device_add(event, event.get_slave(),
                                               new_attrs)

            elif isinstance(event, slaves_events.SlaveDeviceRemove):
                await self.on_slave_device_remove(event, event.get_slave(),
                                                  new_attrs)

        except Exception as e:
            self.error('failed to handle event %s: %s',
                       event,
                       e,
                       exc_info=True)
    async def _update_from_event(
        self, event: core_events.Event
    ) -> Tuple[Tuple[NullablePortValue, NullablePortValue], Attributes,
               Attributes, Dict[str, Tuple[
                   Attribute, Attribute]], Attributes, Attributes]:

        value_pair = (None, None)
        old_attrs = {}
        new_attrs = {}
        changed_attrs = {}
        added_attrs = {}
        removed_attrs = {}

        if isinstance(event, core_events.PortEvent):
            port = event.get_port()

            old_attrs = self._port_attrs.get(port.get_id(), {})
            new_attrs = await port.get_attrs()

            old_value = self._port_values.get(port.get_id())
            new_value = port.get_last_read_value()
            value_pair = (old_value, new_value)

            if isinstance(event,
                          (core_events.PortAdd, core_events.PortUpdate)):
                changed_attrs, added_attrs, removed_attrs = self._make_changed_added_removed(
                    old_attrs, new_attrs)
                self._port_values[port.get_id()] = new_value
                self._port_attrs[port.get_id()] = new_attrs

            elif isinstance(event, core_events.PortRemove):
                self._port_values.pop(port.get_id(), None)
                removed_attrs = self._port_attrs.pop(port.get_id(), {})

            elif isinstance(event, core_events.ValueChange):
                self._port_values[port.get_id()] = new_value

        elif isinstance(event, core_events.DeviceEvent):
            old_attrs = self._device_attrs
            new_attrs = event.get_attrs()

            changed_attrs, added_attrs, removed_attrs = self._make_changed_added_removed(
                old_attrs, new_attrs)
            self._device_attrs = new_attrs

        elif isinstance(event, slaves_events.SlaveDeviceEvent):
            slave = event.get_slave()
            slave_json = slave.to_json()

            # Flatten slave master properties and attributes
            old_attrs = self._slave_attrs.get(slave.get_name(), {})
            new_attrs = dict(slave_json, **slave_json.pop('attrs'))

            if isinstance(event, (slaves_events.SlaveDeviceAdd,
                                  slaves_events.SlaveDeviceUpdate)):
                changed_attrs, added_attrs, removed_attrs = self._make_changed_added_removed(
                    old_attrs, new_attrs)
                self._slave_attrs[slave.get_name()] = new_attrs

            elif isinstance(event, slaves_events.SlaveDeviceRemove):
                removed_attrs = self._slave_attrs.pop(slave.get_name(), {})

        return value_pair, old_attrs, new_attrs, changed_attrs, added_attrs, removed_attrs
Example #9
0
    async def push_template_message(self, event: core_events.Event,
                                    context: dict) -> None:
        template = await self.render(event.get_type(), context)

        await self.push_message(event, **template)
Example #10
0
 def is_duplicate(self, event: core_events.Event) -> bool:
     return isinstance(
         event, self.__class__) and event.get_slave() == self.get_slave()