예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
    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),
        )
예제 #5
0
    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())
예제 #6
0
    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")
예제 #7
0
 def format_topic(self, topic):
     return SLASH.join((self.dtopic, topic))