async def __aenter__(self) -> Self: event_bus.register(self.topic + "/get", self.__get_sensors) event_bus.register(self.topic + "/get_config", self.__get_sensor_config) event_bus.publish(self.topic + "/status_update", True) # FIXME: use a proper event return self
async def monitor_changes(self, timeout): """ Push changes from the database onto the event_bus. Parameters ---------- timeout: float The timeout in seconds to wait after a connection error. """ async for change_type, change in self._monitor_database( TinkerforgeSensorModel, timeout): # Remember: Do not await in the iterator, as this stops the stream of updates if change_type == ChangeType.UPDATE: change_dict = change.dict() # Rename the id key, because we use the parameter uuid throughout the program, because `id` is already # used in Python change_dict["uuid"] = change_dict.pop( "id") # Note uuid will be moved to the end of the dict. event_bus.publish( f"nodes/by_uuid/{change_dict['uuid']}/remove", None) event_bus.publish( f"nodes/tinkerforge/{change_dict['uid']}/update", change_dict) elif change_type == ChangeType.ADD: change_dict = change.dict() change_dict["uuid"] = change_dict.pop( "id") # Note uuid will be moved to the end of the dict. event_bus.publish( f"nodes/by_uuid/{change_dict['uuid']}/remove", None) event_bus.publish( f"nodes/tinkerforge/{change_dict['uid']}/update", change_dict) elif change_type == ChangeType.REMOVE: # When removing sensors, the DB only returns the uuid event_bus.publish(f"nodes/by_uuid/{change_dict}/remove", None)
async def run(self) -> None: """ The main task, that reads data from the sensors and pushes it onto the event_bus. """ # Generate the UUIDs of new sensors sensor_stream = stream.chain( stream.iterate( iterate_safely(f"{self.__topic}/get", f"{self.__topic}/status_update")), stream.iterate(event_bus.subscribe(f"{self.__topic}/add_host")), ) | pipe.flatmap( lambda item: stream.chain( (stream.call(event_bus.call, f"{self.__topic}/get_config", item ) | catch.pipe(TopicNotRegisteredError)), stream.iterate( event_bus.subscribe(f"nodes/by_uuid/{item}/update")), ) | pipe.until(lambda config: config is None) | pipe.map(lambda config: config if self._is_config_valid( self.__node_id, config) else None) | pipe.map(self._create_transport) | pipe.switchmap(lambda transport: stream.empty() if transport is None else stream.iterate(transport.stream_data())) | pipe.action(lambda data: event_bus.publish("wamp/publish", data) )) await sensor_stream
def _stream_transport(transport: TinkerforgeTransport): sensor_stream = stream.chain( stream.call(transport.enumerate) | pipe.filter(lambda x: False), stream.iterate(transport.read_enumeration()) | pipe.action(lambda enumeration: event_bus.publish(f"nodes/tinkerforge/{enumeration[1].uid}/remove", None)) | pipe.filter(lambda enumeration: enumeration[0] is not EnumerationType.DISCONNECTED) | pipe.starmap(lambda enumeration_type, sensor: TinkerforgeSensor(sensor)) | pipe.map(lambda sensor: sensor.stream_data()) | pipe.flatten(), ) | context.pipe( transport, on_enter=lambda: logging.getLogger(__name__).info( "Connected to Tinkerforge host at %s (%s).", transport.uri, transport.label ), on_exit=lambda: logging.getLogger(__name__).info( "Disconnected from Tinkerforge host at %s (%s).", transport.uri, transport.label ), ) return sensor_stream