async def advanced_example(): # We 💛 context managers. Let's create a stack to help # us manage them. async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit tasks = set() stack.push_async_callback(cancel_tasks, tasks) # Connect to the MQTT broker client = Client("144.217.242.17") await stack.enter_async_context(client) #client.will_set(serial_no+"/connection","Offline",1,retain=False) # Messages that doesn't match a filter will get logged here messages = await stack.enter_async_context( client.unfiltered_messages()) task = asyncio.create_task(log_messages(client, messages)) tasks.add(task) # Subscribe to topic(s) # 🤔 Note that we subscribe *after* starting the message # loggers. Otherwise, we may miss retained messages. await client.subscribe(serial_no + "/check_connection") task = asyncio.create_task(publish(client, "connection", "Online")) tasks.add(task) task = asyncio.create_task(post_gps(client, "gps")) tasks.add(task) # Wait for everything to complete (or fail due to, e.g., network # errors) await asyncio.gather(*tasks)
async def advanced_example(): # We 💛 context managers. Let's create a stack to help # us manage them. async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit tasks = set() stack.push_async_callback(cancel_tasks, tasks) tls_ctx = ssl.create_default_context( cafile="/srv/security/iot-hub-ca.pem") tls_ctx.load_cert_chain( "/srv/security/device-home-office-crt.pem", keyfile="/srv/security/device-home-office-key.pem", ) # Connect to the MQTT broker client = Client( "iot.fr-par.scw.cloud", port=8883, client_id="50ce1f12-ef04-4e25-806c-3c51aa3f044a", tls_context=tls_ctx, ) await stack.enter_async_context(client) # You can create any number of topic filters topic_filters = ( "floors/+/humidity", "floors/rooftop/#" # 👉 Try to add more filters! ) for topic_filter in topic_filters: # Log all messages that matches the filter manager = client.filtered_messages(topic_filter) messages = await stack.enter_async_context(manager) template = f'[topic_filter="{topic_filter}"] {{}}' task = asyncio.create_task(log_messages(messages, template)) tasks.add(task) # Messages that doesn't match a filter will get logged here messages = await stack.enter_async_context( client.unfiltered_messages()) task = asyncio.create_task(log_messages(messages, "[unfiltered] {}")) tasks.add(task) # Subscribe to topic(s) # 🤔 Note that we subscribe *after* starting the message # loggers. Otherwise, we may miss retained messages. await client.subscribe("floors/#") # Publish a random value to each of these topics topics = ( "floors/basement/humidity", "floors/rooftop/humidity", "floors/rooftop/illuminance", # 👉 Try to add more topics! ) task = asyncio.create_task(post_to_topics(client, topics)) tasks.add(task) # Wait for everything to complete (or fail due to, e.g., network # errors) await asyncio.gather(*tasks)
async def startSim(): global client, stack # change entries to modify test beds = [ ("W1", "1"), ("W1", "2"), ("W1", "3"), ("W1", "4"), ] async with AsyncExitStack() as stack: # Connect to the MQTT broker client = Client(BROKER_ADDRESS) await stack.enter_async_context(client) tasks = set() stack.push_async_callback(cancel_tasks, tasks) outbound_topics = [ "+/+/patientDetails", "+/+/HR", "+/+/spO2", "+/+/diaBP", "+/+/sysBP", "+/+/ppg", "+/+/ecg", ] for ot in outbound_topics: manager = client.filtered_messages(ot) messages = await stack.enter_async_context(manager) template = f'Outbound -- [topic="{{}}"] {{}}' task = asyncio.create_task(log_messages(messages, template)) tasks.add(task) inbound_topics = ["+/+/sendDetails"] for it in inbound_topics: manager = client.filtered_messages(it) messages = await stack.enter_async_context(manager) template = f'Inbound -- [topic="{{}}"] {{}}' task = asyncio.create_task(log_messages(messages, template)) tasks.add(task) # Messages that doesn't match a filter will get logged here messages = await stack.enter_async_context( client.unfiltered_messages()) task = asyncio.create_task( log_messages(messages, f'Other -- [topic="{{}}"] {{}}')) tasks.add(task) await client.subscribe('#') # subscribe to all messages for bed in beds: tasks.add(asyncio.create_task(onboardPatient(bed, client))) tasks.add(asyncio.create_task(startHRProducer(bed, client))) tasks.add(asyncio.create_task(startBPProducer(bed, client))) tasks.add(asyncio.create_task(startSpO2Producer(bed, client))) tasks.add(asyncio.create_task(startECGProducer(bed, client))) await asyncio.gather(*tasks)
async def main_loop(): global stop_gracefully # https://pypi.org/project/asyncio-mqtt/ logger.debug("Starting main event processing loop") cfg = Cfg() mqtt_broker_ip = cfg.mqtt_host or const.MQTT_DEFAULT_BROKER_IP mqtt_client_id = cfg.mqtt_client_id or const.MQTT_CLIENT_ID_DEFAULT mqtt_send_q = asyncio.Queue(maxsize=256) events_q = asyncio.Queue(maxsize=256) # We 💛 context managers. Let's create a stack to help # us manage them. async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit tasks = set() stack.push_async_callback(cancel_tasks, tasks) # Connect to the MQTT broker client = Client(mqtt_broker_ip, client_id=mqtt_client_id) await stack.enter_async_context(client) messages = await stack.enter_async_context(client.unfiltered_messages()) task = asyncio.create_task(handle_mqtt_messages(messages, events_q)) tasks.add(task) run_state = RunState() for topic, attrs in cfg.topics.items(): run_state.states[topic] = TopicState(topic, **attrs) await client.subscribe(topic) task = asyncio.create_task(handle_mqtt_publish(client, mqtt_send_q)) tasks.add(task) task = asyncio.create_task(periodic_timer_refresh_publish(events_q)) tasks.add(task) task = asyncio.create_task(periodic_timer_expirations(events_q)) tasks.add(task) task = asyncio.create_task(periodic_timer_reelection(events_q)) tasks.add(task) task = asyncio.create_task(handle_jobs(run_state, events_q, mqtt_send_q)) tasks.add(task) # Wait for everything to complete (or fail due to, e.g., network errors) await asyncio.gather(*tasks) logger.debug("all done!")
async def advanced_example(): # We 💛 context managers. Let's create a stack to help # us manage them. async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit tasks = set() stack.push_async_callback(cancel_tasks, tasks) # Connect to the MQTT broker client = Client(broker) await stack.enter_async_context(client) # You can create any number of topic filters topic_filters = ( "Battle/#/Trainer1/", "Battle/#/Trainer2/" # 👉 Try to add more filters! ) for topic_filter in topic_filters: # Log all messages that matches the filter manager = client.filtered_messages(topic_filter) messages = await stack.enter_async_context(manager) template = f'[topic_filter="{topic_filter}"] {{}}' task = asyncio.create_task(log_messages(messages, template)) tasks.add(task) # Messages that doesn't match a filter will get logged here messages = await stack.enter_async_context( client.unfiltered_messages()) task = asyncio.create_task(log_messages(messages, "[unfiltered] {}")) tasks.add(task) # Subscribe to topic(s) # 🤔 Note that we subscribe *after* starting the message # loggers. Otherwise, we may miss retained messages. await client.subscribe("Battle/#") # Publish a random value to each of these topics topics = ( "Battle/BattleLog", "Battle/Trainer1/", "Battle/Trainer2/", # 👉 Try to add more topics! ) task = asyncio.create_task(post_to_topics(client, topics)) tasks.add(task) # Wait for everything to complete (or fail due to, e.g., network # errors) await asyncio.gather(*tasks)
async def connect_to_mqtt_server(config): async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit tasks = set() stack.push_async_callback(cancel_tasks, tasks) if config.has_section('MQTT'): # Connect to the MQTT broker # client = Client("10.0.1.20", username="******", password="******") client = Client(config.get('MQTT', 'broker_address'), username=config.get('MQTT', 'usr'), password=config.get('MQTT', 'pswd')) await stack.enter_async_context(client) # Create angle fsm fsm = AngleFSM(config) # Messages that doesn't match a filter will get logged here messages = await stack.enter_async_context( client.unfiltered_messages()) task = asyncio.create_task( log_messages(messages, "[unfiltered] {}")) tasks.add(task) # Subscribe to chairState await client.subscribe("sensors/chairState") manager = client.filtered_messages('sensors/chairState') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_sensors_chair_state(client, messages, fsm)) tasks.add(task) # Subscribe to config notification settings changes await client.subscribe("goal/update_data") manager = client.filtered_messages('goal/update_data') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_goal_update_data(client, messages, fsm)) tasks.add(task) # Start periodic publish of chair state task = asyncio.create_task(publish_angle_fsm(client, fsm)) tasks.add(task) # Wait for everything to complete (or fail due to, e.g., network errors) await asyncio.gather(*tasks)
async def connect_to_mqtt_server(config): async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit tasks = set() stack.push_async_callback(cancel_tasks, tasks) if config.has_section('MQTT'): # Connect to the MQTT broker # client = Client("10.0.1.20", username="******", password="******") client = Client(config.get('MQTT', 'broker_address'), username=config.get('MQTT', 'usr'), password=config.get('MQTT', 'pswd')) await stack.enter_async_context(client) # Create PWM3901 driver # travel = PMW3901() # Create mpu6050 driver travel = mpu6050(address=0x68) # Create Travel State state = TravelState(config) # Messages that doesn't match a filter will get logged here messages = await stack.enter_async_context( client.unfiltered_messages()) task = asyncio.create_task( log_messages(messages, "[unfiltered] {}")) tasks.add(task) # Start periodic publish of travel state task = asyncio.create_task( travel_loop(client, travel, state, config)) tasks.add(task) # Wait for everything to complete (or fail due to, e.g., network errors) await asyncio.gather(*tasks)
async def main_loop(): global stop_gracefully # https://pypi.org/project/asyncio-mqtt/ logger.debug("Starting main event processing loop") cfg = Cfg() mqtt_send_q = asyncio.Queue(maxsize=256) garage_events_q = asyncio.Queue(maxsize=4) main_events_q = asyncio.Queue(maxsize=256) poller_ticker_q = asyncio.Queue(maxsize=1) # We 💛 context managers. Let's create a stack to help # us manage them. async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit tasks = set() stack.push_async_callback(cancel_tasks, tasks) client = Client( cfg.mqtt_host, username=cfg.mqtt_username, password=cfg.mqtt_password, client_id=cfg.mqtt_client_id, ) await stack.enter_async_context(client) messages = await stack.enter_async_context( client.unfiltered_messages()) task = asyncio.create_task( handle_mqtt_messages(messages, main_events_q)) tasks.add(task) GarageDoor.prepare_for_start() run_state = RunState() await client.subscribe(f"{cfg.mqtt_topic}/#") tasks.add(asyncio.create_task(handle_mqtt_publish(client, mqtt_send_q))) tasks.add( asyncio.create_task( handle_periodic_mqtt_report(run_state, mqtt_send_q))) tasks.add( asyncio.create_task( handle_garage_requests(run_state, garage_events_q))) tasks.add( asyncio.create_task( handle_garage_poller(run_state, main_events_q, poller_ticker_q))) tasks.add( asyncio.create_task( handle_garage_poller_ticker(cfg.poll_interval, poller_ticker_q))) task = asyncio.create_task( handle_main_events(run_state, mqtt_send_q, garage_events_q, main_events_q, poller_ticker_q)) tasks.add(task) # Wait for everything to complete (or fail due to, e.g., network errors) await asyncio.gather(*tasks) logger.debug("all done!")
async def process_yaml(data: dict, server: str, speed: float = 1.0): """Process YAML realtime data""" channel_config = data.get("mqtt_publish", {}) timeout = data.get("timeout", 3.0) mqtt = Client(hostname=server) ret = await mqtt.connect() logging.debug("MQTT connect to %s -> %s", server, ret) sub = [] subscribed_channels = {} for name, channel in data.get("mqtt_subscribe", {}).items(): logging.debug("Subscribe to: %s -> %s", name, channel) sub.append((channel["topic"], channel.get("qos", 1))) subscribed_channels[channel["topic"]] = name, channel.get( "format", "json") if sub: ret = await mqtt.subscribe(sub) logging.debug("MQTT subscribe: %s", ret) errors = 0 for tentry in data["testdata"]: logging.info("ID: %s", tentry["id"]) messages = [] has_time = False for channel_name, channel_contents in tentry["content"].items(): (topic, payload) = get_channel_contents(channel_config, channel_name, channel_contents) logging.debug("Topic %s, Payload %s", topic, payload) msg = (topic, payload) # Make sure we send time first if channel_name == "time": messages.insert(0, msg) has_time = True elif channel_name == "gps" and not has_time: messages.insert(0, msg) else: messages.append(msg) ret = await send_realtime(mqtt, messages) logging.info("Sent %s", ", ".join(tentry["content"])) if "expect" in tentry: expected = tentry["expect"] try: while expected: async with mqtt.unfiltered_messages() as messages: async for message in messages: message_channel, message_format = subscribed_channels[ message.topic] expect = expected[message_channel] if match_response(expect, message_format, message.payload): logging.debug( "Got expected result on channel %s", message_channel) del expected[message_channel] else: logging.error( "Got unexpected result on channel %s = %s", message_channel, message.payload, ) errors += 1 except asyncio.TimeoutError: logging.error( "Didn't receive expected result from channel(s): %s", ", ".join(expected), ) errors += len(expected) if speed != 0: delay = tentry.get("sleep", 0) / speed if delay > 0: logging.info("Sleeping for %f seconds", delay) time.sleep(delay) if errors > 0: logging.error("Test finished with %d errors", errors) else: logging.info("Test finished OK!") await mqtt.disconnect()
async def connect_to_mqtt_server(config): async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit tasks = set() stack.push_async_callback(cancel_tasks, tasks) if config.has_section('MQTT'): # Connect to the MQTT broker # client = Client("10.0.1.20", username="******", password="******") client = Client(config.get('MQTT', 'broker_address'), username=config.get('MQTT', 'usr'), password=config.get('MQTT', 'pswd')) await stack.enter_async_context(client) # Create PCA9536 driver pca = pca9536() # Create Alarm State state = AlarmState(config) # Messages that doesn't match a filter will get logged here messages = await stack.enter_async_context( client.unfiltered_messages()) task = asyncio.create_task( log_messages(messages, "[unfiltered] {}")) tasks.add(task) # sensors/alarm/enabled await client.subscribe("sensors/alarm/enabled") manager = client.filtered_messages('sensors/alarm/enabled') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_alarm_enabled(client, messages, pca, state)) tasks.add(task) # sensors/alarm/alternatingLedBlink await client.subscribe("sensors/alarm/alternatingLedBlink") manager = client.filtered_messages( 'sensors/alarm/alternatingLedBlink') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_alarm_alternating_led_blink(client, messages, pca, state)) tasks.add(task) # sensors/alarm/motorOn await client.subscribe("sensors/alarm/motorOn") manager = client.filtered_messages('sensors/alarm/motorOn') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_alarm_motor_on(client, messages, pca, state)) tasks.add(task) # sensors/alarm/redLedOn await client.subscribe("sensors/alarm/redLedOn") manager = client.filtered_messages('sensors/alarm/redLedOn') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_alarm_red_led_on(client, messages, pca, state)) tasks.add(task) # sensors/alarm/redLedBlink await client.subscribe("sensors/alarm/redLedBlink") manager = client.filtered_messages('sensors/alarm/redLedBlink') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_alarm_red_led_blink(client, messages, pca, state)) tasks.add(task) # sensors/alarm/greenLedOn await client.subscribe("sensors/alarm/greenLedOn") manager = client.filtered_messages('sensors/alarm/greenLedOn') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_alarm_green_led_on(client, messages, pca, state)) tasks.add(task) # sensors/alarm/greenLedBlink await client.subscribe("sensors/alarm/greenLedBlink") manager = client.filtered_messages('sensors/alarm/greenLedBlink') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_alarm_green_led_blink(client, messages, pca, state)) tasks.add(task) # Start periodic publish of alarm state task = asyncio.create_task(alarm_loop(client, pca, state)) tasks.add(task) # Wait for everything to complete (or fail due to, e.g., network errors) await asyncio.gather(*tasks)
class MQTTClient: """Represent an MQTT client.""" def __init__( self, host: str, port: int = 1883, **client_options: Any, ) -> None: """Set up client.""" self.host = host self.port = port if "client_id" not in client_options: client_options["client_id"] = mqtt.base62(uuid.uuid4().int, padding=22) if "logger" not in client_options: client_options["logger"] = PAHO_MQTT_LOGGER client_options["clean_session"] = True self.client_options = client_options self.asyncio_client: AsyncioClient = None self.create_client() self.reconnect_interval = 1 self.publish_queue: asyncio.Queue = asyncio.Queue() def create_client(self) -> None: """Create the asyncio client.""" self.asyncio_client = AsyncioClient( self.host, self.port, **self.client_options, ) async def connect(self, *, timeout: float = 10.0) -> None: """Connect to the broker. Can raise asyncio_mqtt.MqttError. """ await self.asyncio_client.connect(timeout=timeout) async def disconnect(self, *, timeout: float = 10.0) -> None: """Disconnect from the broker. Can raise asyncio_mqtt.MqttError. """ await self.asyncio_client.disconnect(timeout=timeout) async def publish( # pylint:disable=too-many-arguments self, topic: str, payload: Optional[str] = None, qos: int = 0, retain: bool = False, properties: Optional[Properties] = None, timeout: float = 10, ) -> None: """Publish to topic. Can raise asyncio_mqtt.MqttError. """ params: dict = {"qos": qos, "retain": retain, "timeout": timeout} if payload: params["payload"] = payload if properties: params["properties"] = properties LOGGER.debug("Sending message topic: %s, payload: %s", topic, payload) await self.asyncio_client.publish(topic, **params) async def subscribe( # pylint:disable=too-many-arguments self, topic: str, qos: int = 0, options: Optional[SubscribeOptions] = None, properties: Optional[Properties] = None, timeout: float = 10.0, ) -> None: """Subscribe to topic. Can raise asyncio_mqtt.MqttError. """ params: dict = {"qos": qos, "timeout": timeout} if options: params["options"] = options if properties: params["properties"] = properties await self.asyncio_client.subscribe(topic, **params) async def unsubscribe( self, topic: str, properties: Optional[Properties] = None, timeout: float = 10.0 ) -> None: """Unsubscribe from topic. Can raise asyncio_mqtt.MqttError. """ params: dict = {"timeout": timeout} if properties: params["properties"] = properties await self.asyncio_client.unsubscribe(topic, **params) def send_message(self, topic: str, payload: Union[str, dict]) -> None: """Send a message from the manager options.""" to_publish = (topic, json.dumps(payload)) self.publish_queue.put_nowait(to_publish) async def _handle_publish(self) -> None: """Publish messages as they are put on the queue.""" while True: to_publish: tuple = await self.publish_queue.get() await self.publish(*to_publish) self.publish_queue.task_done() async def start_client(self, manager: OZWManager) -> None: """Start the client with the manager.""" # Reconnect automatically until the client is stopped. while True: try: await self._subscribe_manager(manager) except MqttError as err: self.reconnect_interval = min(self.reconnect_interval * 2, 900) LOGGER.error( "MQTT error: %s. Reconnecting in %s seconds", err, self.reconnect_interval, ) await asyncio.sleep(self.reconnect_interval) self.create_client() # reset connect/reconnect futures async def _subscribe_manager(self, manager: OZWManager) -> None: """Connect and subscribe to manager topics.""" async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit. tasks: Set[asyncio.Task] = set() # Connect to the MQTT broker. await stack.enter_async_context(self.asyncio_client) # Reset the reconnect interval after successful connection. self.reconnect_interval = 1 publish_task = asyncio.create_task(self._handle_publish()) tasks.add(publish_task) # Messages that doesn't match a filter will get logged and handled here. messages = await stack.enter_async_context( self.asyncio_client.unfiltered_messages() ) messages_task = asyncio.create_task( handle_messages(messages, manager.receive_message) ) tasks.add(messages_task) # Note that we subscribe *after* starting the message loggers. # Otherwise, we may miss retained messages. topic = f"{manager.options.topic_prefix}#" await self.subscribe(topic) # Wait for everything to complete (or fail due to, e.g., network errors). await asyncio.gather(*tasks)
class SatelliteController: def __init__(self, cbpi): self.cbpi = cbpi self.client = None async def init(self): asyncio.create_task(self.init_client(self.cbpi)) async def publish(self, topic, message): print("MQTT ON") await self.client.publish(topic, message, qos=1) async def handle_message(self, messages): async for message in messages: print("FILTERED", message.payload.decode()) async def handle_unfilterd_message(self, messages): async for message in messages: print("UNFILTERED", message.payload.decode()) async def init_client(self, cbpi): async def log_messages(messages, template): async for message in messages: print(template.format(message.payload.decode())) async def cancel_tasks(tasks): for task in tasks: if task.done(): continue task.cancel() try: await task except asyncio.CancelledError: pass async with AsyncExitStack() as stack: tasks = set() stack.push_async_callback(cancel_tasks, tasks) self.client = Client("localhost", will=Will(topic="cbpi/diconnect", payload="CBPi Server Disconnected")) await stack.enter_async_context(self.client) topic_filters = ("cbpi/sensor/#", "cbpi/actor/#") for topic_filter in topic_filters: # Log all messages that matches the filter manager = self.client.filtered_messages(topic_filter) messages = await stack.enter_async_context(manager) task = asyncio.create_task(self.handle_message(messages)) tasks.add(task) messages = await stack.enter_async_context( self.client.unfiltered_messages()) task = asyncio.create_task(self.handle_unfilterd_message(messages)) tasks.add(task) await self.client.subscribe("cbpi/#") await asyncio.gather(*tasks)
class MQTTClient(MQTTTransport): """Represent an MQTT client.""" def __init__( self, host: str, port: int = 1883, in_prefix: str = "mygateway1-out", out_prefix: str = "mygateway1-in", ) -> None: """Set up client.""" super().__init__(in_prefix=in_prefix, out_prefix=out_prefix) self._host = host self._port = port self._client: Optional[AsyncioClient] = None self._incoming_task: Optional[asyncio.Task] = None async def _connect(self) -> None: """Connect to the broker.""" self._client = AsyncioClient( self._host, self._port, client_id=mqtt.base62(uuid.uuid4().int, padding=22), logger=PAHO_MQTT_LOGGER, clean_session=True, ) try: await self._client.connect(timeout=10) except MqttError as err: raise TransportError from err if self._incoming_task is not None: raise RuntimeError( "Client needs to disconnect before connecting again.") self._incoming_task = asyncio.create_task(self._handle_incoming()) async def _disconnect(self) -> None: """Disconnect from the broker.""" if not self._client or not self._incoming_task: raise RuntimeError("Client needs to connect before disconnecting.") self._incoming_task.cancel() await self._incoming_task self._incoming_task = None try: await self._client.disconnect(timeout=10) except MqttError: pass async def _publish(self, topic: str, payload: str, qos: int) -> None: """Publish to topic.""" if not self._client: raise RuntimeError("Client needs to connect before publishing.") params: dict = {"qos": qos, "retain": False, "timeout": 10} if payload: params["payload"] = payload try: await self._client.publish(topic, **params) except MqttError as err: raise TransportFailedError from err async def _subscribe(self, topic: str, qos: int) -> None: """Subscribe to topic.""" if not self._client: raise RuntimeError("Client needs to connect before subscribing.") try: await self._client.subscribe(topic, qos=qos, timeout=10) except MqttError as err: raise TransportError from err async def _handle_incoming(self) -> None: """Handle incoming messages.""" assert self._client try: async with self._client.unfiltered_messages() as messages: async for message in messages: message = cast(mqtt.MQTTMessage, message) self._receive(message.topic, message.payload.decode()) except MqttError: self._receive_error(TransportFailedError())
async def connect_to_mqtt_server(config): async with AsyncExitStack() as stack: # Keep track of the asyncio tasks that we create, so that # we can cancel them on exit tasks = set() stack.push_async_callback(cancel_tasks, tasks) if config.has_section('MQTT'): # Connect to the MQTT broker # client = Client("10.0.1.20", username="******", password="******") client = Client(config.get('MQTT', 'broker_address'), username=config.get('MQTT', 'usr'), password=config.get('MQTT', 'pswd')) await stack.enter_async_context(client) # Create chair state chair_state = ChairState() # Select topic filters # You can create any number of topic filters topic_filters = ( "sensors/#", # TODO add more filters ) # Log all messages # for topic_filter in topic_filters: # # Log all messages that matches the filter # manager = client.filtered_messages(topic_filter) # messages = await stack.enter_async_context(manager) # template = f'[topic_filter="{topic_filter}"] {{}}' # task = asyncio.create_task(log_messages(messages, template)) # tasks.add(task) # Messages that doesn't match a filter will get logged here messages = await stack.enter_async_context( client.unfiltered_messages()) task = asyncio.create_task( log_messages(messages, "[unfiltered] {}")) tasks.add(task) # Subscribe to pressure sensors await client.subscribe("sensors/pressure") manager = client.filtered_messages('sensors/pressure') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_sensors_pressure(client, messages, chair_state)) tasks.add(task) # Subscribe to angle sensors await client.subscribe("sensors/angle") manager = client.filtered_messages('sensors/angle') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_sensors_angle(client, messages, chair_state)) tasks.add(task) # Subscribe to travel sensors await client.subscribe("sensors/travel") manager = client.filtered_messages('sensors/travel') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_sensors_travel(client, messages, chair_state)) tasks.add(task) # Subscribe to alarm sensors await client.subscribe("sensors/alarm/state") manager = client.filtered_messages('sensors/alarm/state') messages = await stack.enter_async_context(manager) task = asyncio.create_task( handle_sensors_alarm(client, messages, chair_state)) tasks.add(task) # Start periodic publish of chair state task = asyncio.create_task(publish_chair_state( client, chair_state)) tasks.add(task) # Wait for everything to complete (or fail due to, e.g., network errors) await asyncio.gather(*tasks)