async def broadcast(self, payload, level=None): if not isinstance(payload, bytes): payload = bytes(str(payload), "utf-8") topic = SLASH.join((self.btopic, b"$broadcast")) if level is not None: if isinstance(level, str): level = level.encode() topic = SLASH.join((topic, level)) # print("MQTT BROADCAST: {} --> {}".format(topic, payload)) await self.mqtt.publish(topic, payload, retain=False, qos=QOS)
async def publish(self, topic, payload, retain=True): if not isinstance(payload, bytes): payload = bytes(str(payload), "utf-8") t = SLASH.join((self.dtopic, topic)) # print('MQTT PUBLISH: {} --> {}'.format(t, payload)) await self.mqtt.publish(t, payload, retain, QOS)
async def connection_handler(self, client): """subscribe to all registered device and node topics""" if self._first_start is False: await self.publish(DEVICE_STATE, STATE_RECOVER) subscribe = self.subscribe unsubscribe = self.unsubscribe # device topics await self.mqtt.subscribe( SLASH.join((self.btopic, b"$broadcast/#")), QOS ) # node topics nodes = self.nodes for n in nodes: props = n._properties for p in props: if p.settable: nid_enc = n.id.encode() if nid_enc not in self.callback_topics: self.callback_topics[nid_enc] = n.callback # retained topics to restore messages if p.restore: t = b"{}/{}".format(n.id, p.id) await subscribe(t) await sleep_ms(RESTORE_DELAY) await unsubscribe(t) # final subscribe to /set topics t = b"{}/{}/set".format(n.id, p.id) await subscribe(t) # on first connection: # * publish device and node properties # * enable WDT # * run all coros if self._first_start is True: await self.publish_properties() self._first_start = False # activate WDT loop = get_event_loop() loop.create_task(self.wdt()) # start coros waiting for ready state _EVENT.set() await sleep_ms(MAIN_DELAY) _EVENT.clear() await self.publish(DEVICE_STATE, STATE_READY)
def __init__(self, settings): self._state = STATE_INIT self._extensions = getattr(settings, "EXTENSIONS", []) self._first_start = True self.async_tasks = [] self.stats_interval = getattr(settings, "DEVICE_STATS_INTERVAL", 60) self.nodes = [] self.callback_topics = {} self.device_name = getattr(settings, "DEVICE_NAME", b"mydevice") device_id = getattr(settings, "DEVICE_ID", get_unique_id()) self.btopic = getattr(settings, "MQTT_BASE_TOPIC", b"homie") self.dtopic = SLASH.join((self.btopic, device_id)) self.mqtt = MQTTClient( client_id=device_id, server=settings.MQTT_BROKER, port=getattr(settings, "MQTT_PORT", 1883), user=getattr(settings, "MQTT_USERNAME", None), password=getattr(settings, "MQTT_PASSWORD", None), keepalive=getattr(settings, "MQTT_KEEPALIVE", 30), ping_interval=getattr(settings, "MQTT_PING_INTERVAL", 0), ssl=getattr(settings, "MQTT_SSL", False), ssl_params=getattr(settings, "MQTT_SSL_PARAMS", {}), response_time=getattr(settings, "MQTT_RESPONSE_TIME", 10), clean_init=getattr(settings, "MQTT_CLEAN_INIT", True), clean=getattr(settings, "MQTT_CLEAN", True), max_repubs=getattr(settings, "MQTT_MAX_REPUBS", 4), will=(SLASH.join((self.dtopic, DEVICE_STATE)), b"lost", True, QOS), subs_cb=self.sub_cb, wifi_coro=None, connect_coro=self.connection_handler, ssid=getattr(settings, "WIFI_SSID", None), wifi_pw=getattr(settings, "WIFI_PASSWORD", None), )
def __init__(self, settings): self._state = "init" self._stime = time() self.stats_interval = settings.DEVICE_STATS_INTERVAL self.nodes = [] self.callback_topics = {} self.device_name = settings.DEVICE_NAME self.btopic = settings.MQTT_BASE_TOPIC self.dtopic = SLASH.join( (settings.MQTT_BASE_TOPIC, settings.DEVICE_ID) ) # setup networking utils.setup_network(settings.WIFI_PASSWORD) utils.wifi_connect(settings.WIFI_SSID) self.mqtt = MQTTClient( client_id=settings.DEVICE_ID, server=settings.MQTT_BROKER, port=settings.MQTT_PORT, user=settings.MQTT_USERNAME, password=settings.MQTT_PASSWORD, keepalive=settings.MQTT_KEEPALIVE, ssl=settings.MQTT_SSL, ssl_params=settings.MQTT_SSL_PARAMS, subs_cb=self.sub_cb, connect_coro=self.connection_handler, will=(SLASH.join((self.dtopic, DEVICE_STATE)), b"lost", True, QOS), ) # Start coros loop = get_event_loop() loop.create_task(self.publish_stats())
async def connection_handler(self, client): """subscribe to all registered device and node topics""" subscribe = self.subscribe unsubscribe = self.unsubscribe # device topics await self.mqtt.subscribe( SLASH.join((self.btopic, b"$broadcast/#")), QOS ) # node topics nodes = self.nodes for n in nodes: props = n._properties for p in props: is_array = p.range > 1 if p.settable: self.callback_topics[n.id.encode()] = n.callback # subscribe topic to restore retained messages if p.restore: if is_array: r = range(p.range) for i in r: t = b"{}_{}/{}".format(n.id, i, p.id) await subscribe(t) await sleep_ms(RESTORE_DELAY) await unsubscribe(t) else: t = b"{}/{}".format(n.id, p.id) await subscribe(t) await sleep_ms(RESTORE_DELAY) await unsubscribe(t) # final subscribe to /set topic if is_array: r = range(p.range) for i in r: t = b"{}_{}/{}/set".format(n.id, i, p.id) await subscribe(t) else: t = b"{}/{}/set".format(n.id, p.id) await subscribe(t) await self.publish_properties() await self.set_state("ready")
def format_topic(self, topic): return SLASH.join((self.dtopic, topic))