Example #1
0
def main( mqtt_broker='test.mosquitto.org', mqtt_port=1883, mqtt_user=None, mqtt_password=None, client_id=CLIENT_ID):

    global mqtt

    mqtt = MQTTClient( client_id, mqtt_broker, mqtt_port, mqtt_user, mqtt_password, keepalive=60 )
    mqtt.set_callback(mqtt_cb)
    mqtt.set_last_will( AVAILABILITY_TOPIC, b"offline", retain=True)

    mqtt.connect()
    mqtt.subscribe(COMMAND_TOPIC)

    #此处增加对亮度命令的订阅
    mqtt.subscribe(BRIGHTNESS_COMMAND_TOPIC)

    mqtt.publish( CONFIG_TOPIC, CONFIG_DATA.encode(), retain=True)
    mqtt.publish( AVAILABILITY_TOPIC, b"online", retain=True)

    mqtt.publish( STATE_TOPIC, light_state.encode(), retain=True )
    mqtt.publish( BRIGHTNESS_STATE_TOPIC, str(light_brightness).encode(), retain=True )

    print("链接到服务器:{s},端口:{p}".format(s=mqtt_broker,p=mqtt_port))
    print("接受开关命令topic:开关({c})".format(c=COMMAND_TOPIC))
    print("接受亮度命令topic:开关({c})".format(c=BRIGHTNESS_COMMAND_TOPIC))

    while True:
        mqtt.check_msg()
Example #2
0
def connect(settings=configuration.mqtt.settings):
    global client, connected, keepalive, topic_path

    client_id = common.hostname()
    client = MQTTClient(client_id,
                        settings["host"],
                        settings["port"],
                        keepalive=keepalive)

    client.set_callback(on_message)
    client.set_last_will(topic_path + "/state", "nil")
    try:
        client.connect()
        aiko.event.add_timer_handler(mqtt_ping_handler, keepalive * 1000)

        for topic in settings["topic_subscribe"]:
            if topic.startswith("$all/"): topic = "+/+/+" + topic[4:]
            if topic.startswith("$me/"): topic = topic_path + topic[3:]
            client.subscribe(topic)

        connected = True
        print(M + "Connected to %s: %s" % (settings["host"], topic_path))
        common.log("MQTT connected ...")
        common.log("  " + settings["host"])
        common.log("  " + topic_path)
        payload_out = "(boot %s %s)" % (common.AIKO_VERSION, "swagbadge")
        client.publish(topic_path + "/out", payload_out)
    except Exception:
        disconnect("connect")
Example #3
0
def connect_mqtt():
    global client
    # MQTT startup
    ESP_ONBOARD_LED.off()
    print("Connecting MQTT...")
    client = MQTTClient(
        client_id=SETTINGS_MQTT["name"],
        server=SETTINGS_MQTT["broker"],
        port=SETTINGS_MQTT["port"],
        user=SETTINGS_MQTT["user"] if SETTINGS_MQTT["user"] else None,
        password=SETTINGS_MQTT["password"]
        if SETTINGS_MQTT["password"] else None,
        keepalive=SETTINGS_MQTT["keepalive"])
    client.set_callback(sub_callback)
    client.set_last_will(topic=ftopic("stat").encode(),
                         msg="OFF".encode(),
                         retain=True)
    client.connect()
    # We subscribe to all 'cmd' topics
    client.subscribe(topic=(ftopic("cmd") + "/#").encode())
    client.publish(topic=ftopic("stat").encode(),
                   msg="ON".encode(),
                   retain=True)
    print("PC Monitor MQTT client connected!")
    ESP_ONBOARD_LED.on()
Example #4
0
def main(mqtt_broker='test.mosquitto.org',
         mqtt_port=1883,
         mqtt_user=None,
         mqtt_password=None,
         client_id=CLIENT_ID):

    global mqtt

    # 此处增加keepalive=60,表示60秒以上未通讯,客户端为断开
    mqtt = MQTTClient(client_id,
                      mqtt_broker,
                      mqtt_port,
                      mqtt_user,
                      mqtt_password,
                      keepalive=60)
    mqtt.set_callback(mqtt_cb)
    # 设置lastwill,相应消息会在断开mqtt连接后自动在服务器端发布
    # 注:在connect之前设置lastwill
    mqtt.set_last_will(AVAILABILITY_TOPIC, b"offline", retain=True)

    mqtt.connect()
    mqtt.subscribe(COMMAND_TOPIC)
    mqtt.publish(AVAILABILITY_TOPIC, b"online", retain=True)
    state = b"ON" if LED.value() == 1 else b"OFF"
    mqtt.publish(STATE_TOPIC, state, retain=True)

    print("链接到服务器:{s},端口:{p}".format(s=mqtt_broker, p=mqtt_port))
    print("接受命令topic:开关({c})".format(c=COMMAND_TOPIC))

    while True:
        mqtt.check_msg()
Example #5
0
    def _umqtt_connect(self):
        mqtt = MQTTClient(self.settings.DEVICE_ID,
                          self.settings.MQTT_BROKER,
                          port=self.settings.MQTT_PORT,
                          user=self.settings.MQTT_USERNAME,
                          password=self.settings.MQTT_PASSWORD,
                          keepalive=self.settings.MQTT_KEEPALIVE,
                          ssl=self.settings.MQTT_SSL,
                          ssl_params=self.settings.MQTT_SSL_PARAMS)

        mqtt.DEBUG = True

        mqtt.set_callback(self.sub_cb)  # for all callbacks
        mqtt.set_last_will(self.topic + b'/$online',
                           b'false',
                           retain=True,
                           qos=1)

        mqtt.connect()

        # subscribe to device topics
        mqtt.subscribe(self.topic + b'/$stats/interval/set')
        mqtt.subscribe(self.topic + b'/$broadcast/#')

        self.mqtt = mqtt
Example #6
0
def main():
    print('Device UP!')
    wdt = machine.WDT()
    wdt.feed()

    sensor = ESPSensors(pin=config['dht_pin'],
                        sensor_type=['t', 'h'],
                        sensor_model=config['dht_model'])
    sensor.set_name(config['device_name'])
    sensor.set_expire_after_seconds(int(config['sleep_time_sec']) + 10)
    sensor.register_sensor()
    wdt.feed()

    wlan = wlan_connect(config['wifi_ssid'], config['wifi_passwd'],
                        config['net_ip'], config['net_mask'], config['net_gw'],
                        config['net_dns'])
    print(wlan.ifconfig())
    wdt.feed()

    templates = sensor.get_template()
    discover_topics = sensor.get_discover_topic()
    values = sensor.get_value()
    print(values)
    json_attributes = {
        'name': config['device_name'],
        'ip_address': wlan.ifconfig()[0]
    }
    mqtt_client = MQTTClient(config['device_name'],
                             server=config['mqtt_server'],
                             port=1883,
                             user=bytearray(config['mqtt_user'], 'utf-8'),
                             password=bytearray(config['mqtt_password'],
                                                'utf-8'))
    mqtt_client.connect()
    for s_type in ['temperature', 'humidity']:
        lwt_topic = templates[s_type]['availability_topic']
        mqtt_client.set_last_will(lwt_topic, 'offline', retain=True)
        wdt.feed()
        mqtt_client.publish(bytearray(lwt_topic),
                            bytearray('online'),
                            retain=True)
        wdt.feed()
        mqtt_client.publish(bytearray(discover_topics[s_type]),
                            bytearray(dumps(templates[s_type])),
                            retain=True,
                            qos=0)
        wdt.feed()
        mqtt_client.publish(bytearray(templates[s_type]['state_topic']),
                            bytearray(str(values[s_type])),
                            retain=True,
                            qos=0)
        wdt.feed()
        mqtt_client.publish(bytearray(
            templates[s_type]['json_attributes_topic']),
                            bytearray(dumps(json_attributes)),
                            retain=True,
                            qos=0)
        wdt.feed()
    mqtt_client.disconnect()
Example #7
0
def main():
    load_config()
    print('Config =', config)
    tc_type = config['tc_type']
    led = Pin(2, Pin.OUT)
    led.value(1)

    i2c = I2C(sda=Pin(4), scl=Pin(5), freq=350000)
    disp = SSD1306_I2C(64, 48, i2c)
    disp.text('Type ' + tc_type, 0, 0)
    disp.show()

    spi = SPI(1, baudrate=1000000, polarity=1)
    cs = Pin(16, Pin.OUT)
    max31856 = Max31856(spi, cs, tc_type)

    wlan = network.WLAN(network.STA_IF)
    mqtt = None

    if wlan.isconnected():
        hostname = wlan.config('dhcp_hostname')
        root = b"emon/thermocouple_" + hostname + '/'
        mqtt = MQTTClient(hostname, **config['mqtt'])
        mqtt.connect()
        mqtt.set_last_will(root + 'alive', '0')
        mqtt.publish(root + 'alive', '1')
        mqtt.publish(root + 'status',
                     'Thermocouple type %s' % max31856.tc_type)

    while True:
        time.sleep(config['interval_seconds'])
        led.value(0)
        tc = max31856.temperature(read_chip=True)
        cj = max31856.cold_junction()
        f, fs = max31856.faults()
        tcs = '{:7.2f}'.format(tc)
        cjs = '{:7.2f}'.format(cj)
        print('Temperatures:', tcs, cjs)
        if mqtt:
            if f:
                print(fs)
                mqtt.publish(root + 'fault', fs)
            else:
                mqtt.publish(root + 'tc', tcs)
                mqtt.publish(root + 'cj', cjs)

        disp.framebuf.fill(0)
        disp.text('Type ' + tc_type, 0, 0)
        if f:
            disp.text('Fault', 0, 9)
            disp.text(fs, 0, 18)
        else:
            disp.text(tcs, 0, 9)
            disp.text(cjs, 0, 18)
        disp.show()
        led.value(1)
Example #8
0
 def init_mqtt(self):
     client = MQTTClient(self.mac, self.MQTT_BROKER)
     client.set_callback(self.mqtt_process_sub)
     client.set_last_will(
         self.mqtt_pub_sys,
         '{{"mac":"{}","cmd":"STATUS","sys":"OFFLINE"}}'.format(self.mac))
     time.sleep(0.1)
     client.connect()
     client.subscribe(self.mqtt_sub)
     return client
Example #9
0
class mqtt:
    def __init__(self, config, sub, receive):
        f = open('password.json', 'r')
        pwd = ujson.loads(f.read())
        f.close()

        self._client = MQTTClient(client_id=ubinascii.hexlify(
            machine.unique_id()),
                                  server=config["server"],
                                  user=pwd["user"],
                                  password=pwd["password"],
                                  keepalive=10)
        self._client.set_callback(self._callback)
        self._client.set_last_will(
            topic=self.tstatus,
            msg=b'{"battery":0.0,"connected":false,"load":0.0}',
            retain=True,
            qos=1)
        self._sub = sub
        self._receive = receive
        self.wait = 1

    def check(self):
        if self.wait == 1:
            try:
                self._client.connect()
                self._client.subscribe(self._sub)
                self.state = self._check
                self.wait = 0
            except Exception as e:
                print('connect', e)
                self.wait = 20
        elif self.wait > 0:
            self.wait -= 1
        else:
            try:
                self._client.check_msg()
            except Exception as e:
                print('check', e)
                self.wait = 4

    def publish(self, topic, msg, retain=False):
        try:
            self._client.publish(topic=topic, msg=msg, retain=retain)
            return True
        except Exception as e:
            print('publish', e)
            self.wait = 4
            return False

    def _callback(self, topic, msg):
        print('%s -> %s' % (topic, msg))
        if topic == self.tset:
            self._receive(msg)
Example #10
0
def connect_and_subscribe():
    global client
    client = MQTTClient(CONFIG['client_id'], CONFIG['broker'],
                        user=CONFIG['mqtt_user'],
                        password=CONFIG['mqtt_password'])
    client.set_last_will(topic_name(b'lwt'), 'our lwt')
    client.set_callback(callback)
    client.connect()
    print("Connected to {}".format(CONFIG['broker']))
    for topic in (b'config', b'control'):
        t = topic_name(topic)
        client.subscribe(t)
        print("Subscribed to {}".format(t))
Example #11
0
    def _umqtt_connect(self):
        mqtt = MQTTClient(
            self.settings.DEVICE_ID,
            self.settings.MQTT_BROKER,
            port=self.settings.MQTT_PORT,
            user=self.settings.MQTT_USERNAME,
            password=self.settings.MQTT_PASSWORD,
            keepalive=self.settings.MQTT_KEEPALIVE,
            ssl=self.settings.MQTT_SSL,
            ssl_params=self.settings.MQTT_SSL_PARAMS,
        )

        mqtt.DEBUG = True

        mqtt.set_callback(self.sub_cb)  # for all callbacks
        mqtt.set_last_will(b"/".join((self.topic, b"$state")),
                           b"lost",
                           retain=True,
                           qos=1)

        mqtt.connect()
        self.mqtt = mqtt
Example #12
0
class Sensor:
    def __init__(self, name, server, port, keyfile, certfile, root_topic):

        self.topic = root_topic + '/' + name
        self.repl = None
        self.on_repl_disabled = None

        with open(keyfile, 'rb') as f:
            key = f.read()

        with open(certfile, 'rb') as f:
            cert = f.read()

        self.client = MQTTClient(name,
                                 server=server,
                                 port=port,
                                 ssl=True,
                                 ssl_params={
                                     'key': key,
                                     'cert': cert
                                 },
                                 keepalive=60)

    def connect(self):
        self.client.set_callback(self._subscribe_callback)

        self.client.set_last_will(self.topic + '/status',
                                  b'offline',
                                  retain=True,
                                  qos=1)
        self.client.connect()

        self.publish_status(b'online')

        self.client.subscribe(self.topic + '/repl')
        self.client.wait_msg()

    def disconnect(self):
        self.publish_status(b'offline')
        self.client.disconnect()

    def publish(self, topic, data):
        t = self.topic + '/' + topic
        self.client.publish(t, data)
        print('Published {} = {}'.format(topic, data))

    def update(self):
        self.client.ping()
        self.client.wait_msg()

    def publish_measurment(self, measurment):
        data = measurment.to_line_protocol()
        self.publish('measurement', data)

    def publish_status(self, status):
        self.client.publish(self.topic + '/status', status, retain=True, qos=1)

    def _subscribe_callback(self, topic, msg):
        print('Received: ', topic, msg)

        if topic.decode() == self.topic + '/repl':

            prev = self.repl
            self.repl = (msg == b'1')

            if self.on_repl_disabled:
                if prev and not self.repl:
                    self.on_repl_disabled()
Example #13
0
class FanController:
    def __init__(self):
        self.t_start = time.ticks_ms()

    def setup_pins(self):
        self.pwm = machine.PWM(machine.Pin(config.PWM_PIN))
        self.pwm.freq(2000)
        self.power_pin = machine.Pin(config.POWER_PIN,
                                     machine.Pin.OUT,
                                     value=config.POWER_PIN_INVERTED)

    def setup_mqtt(self):
        self.t_mqtt_start = time.ticks_ms()
        self.mqtt_client = MQTTClient(
            server=config.MQTT_SERVER,
            client_id=config.MQTT_CLIENT_ID,
            user=config.MQTT_USER,
            password=config.MQTT_PASSWORD,
            keepalive=20,
        )
        self.mqtt_client.DEBUG = True
        self.mqtt_client.set_callback(self.mqtt_callback)
        self.mqtt_client.set_last_will(config.MQTT_TOPIC_AVAILABILITY,
                                       "offline",
                                       retain=True)
        self.mqtt_client.connect()

        self.mqtt_client.subscribe(config.MQTT_TOPIC_COMMAND)
        self.mqtt_client.subscribe(config.MQTT_TOPIC_PERCENTAGE_COMMAND)

        # Get and apply retained values before publishing state
        self.mqtt_client.check_msg()

        self.mqtt_client.publish(config.MQTT_TOPIC_AVAILABILITY,
                                 "online",
                                 retain=True)
        self.mqtt_client.publish(config.MQTT_TOPIC_STATE,
                                 "ON" if self.get_power() else "OFF",
                                 retain=True)
        self.mqtt_client.publish(config.MQTT_TOPIC_PERCENTAGE_STATE,
                                 str(self.get_speed()),
                                 retain=True)
        self.mqtt_client.publish(
            config.MQTT_AUTODISCOVERY_TOPIC,
            json.dumps(config.MQTT_AUTODISCOVERY_PAYLOAD),
            retain=True,
        )

    def mqtt_callback(self, topic, msg):
        topic = topic.decode("utf-8")
        msg = msg.decode("utf-8")
        print(f"Received topic:msg: {topic}:{msg}")
        # Handle state topics because we fetch from that initially to resume session
        if topic in [config.MQTT_TOPIC_STATE, config.MQTT_TOPIC_COMMAND
                     ] and msg in (
                         "ON",
                         "OFF",
                     ):
            self.set_power(msg == "ON")
            if topic == config.MQTT_TOPIC_COMMAND:
                self.mqtt_client.publish(config.MQTT_TOPIC_STATE,
                                         msg,
                                         retain=True)
        elif topic in [
                config.MQTT_TOPIC_PERCENTAGE_STATE,
                config.MQTT_TOPIC_PERCENTAGE_COMMAND,
        ]:
            self.set_speed(int(msg))
            if topic == config.MQTT_TOPIC_PERCENTAGE_COMMAND:
                self.mqtt_client.publish(config.MQTT_TOPIC_PERCENTAGE_STATE,
                                         msg,
                                         retain=True)
        else:
            print(f"Unhandled topic:msg: {topic}:{msg}")

    def run(self):
        try:
            t_last_print = t_last_ping = t_last_report = 0
            while True:
                self.mqtt_client.check_msg()
                ticks = time.ticks_ms()
                if time.ticks_diff(ticks, t_last_print) > 1000:
                    print("Running...")
                    t_last_print = ticks
                if time.ticks_diff(ticks, t_last_ping) > 10000:
                    print("MQTT ping")
                    self.mqtt_client.ping()
                    t_last_ping = ticks
                if time.ticks_diff(ticks, t_last_report) > 60000:
                    print("MQTT report")
                    self.mqtt_client.publish(config.MQTT_TOPIC_REPORT,
                                             self.get_report(as_string=True))
                    t_last_report = ticks
                time.sleep_ms(100)
        finally:
            # sock.close sends last will - disconnect doesn't
            self.mqtt_client.sock.close()

    def get_speed(self):
        # Duty -> percent
        return int(self.pwm.duty() / 1023 * 100)

    def set_speed(self, pct: int):
        # Percent -> decimal
        dec = pct / 100
        # Decimal -> duty
        duty = int(1023 * dec)
        print(f"Setting speed: {pct}% / {duty}")
        self.pwm.duty(duty)

    def get_power(self):
        return self.power_pin.value() != config.POWER_PIN_INVERTED

    def set_power(self, val: bool):
        val = val != config.POWER_PIN_INVERTED
        print(f"Setting power: {val}")
        self.power_pin.value(val)

    def get_report(self, as_string=False):
        mem_before = gc.mem_free()
        gc.collect()
        mem_after = gc.mem_free()
        report = {
            "power":
            self.get_power(),
            "speed":
            self.get_speed(),
            "mem_before":
            mem_before,
            "mem_after":
            mem_after,
            "uptime":
            int(time.ticks_diff(time.ticks_ms(), self.t_start) / 1000),
            "mqtt_uptime":
            int(time.ticks_diff(time.ticks_ms(), self.t_mqtt_start) / 1000),
        }
        if not as_string:
            return report

        return "\n".join([f"{k}: {v}" for k, v in report.items()])
Example #14
0
class MQTTCommander(Connect2Wifi, ClockUpdate):
    def __init__(self,
                 server,
                 client_id,
                 device_topic,
                 listen_topics,
                 msg_topic=None,
                 static_ip=None,
                 qos=0,
                 user=None,
                 password=None,
                 state_topic=None,
                 avail_topic=None):
        self.server, self.mqtt_client_id = server, client_id
        self.user, self.password, self.qos = user, password, qos
        self.listen_topics, self.msg_topic, self.device_topic = listen_topics, msg_topic, device_topic
        self.mqtt_client, self.arrived_msg = None, None
        self.avail_topic = avail_topic
        self.state_topic = state_topic
        self.last_buttons_state, self.last_ping_time = [], None

        self.boot_time = utime.localtime()

        # ########### Time related Parameters ##################
        clock_update_interval = 2  # [hours]
        self.num_of_fails = 2  # reach broker
        self.minutes_in_emergency_mode = 1  # [min]
        self.keep_alive_interval = 60  # [sec]
        # ######################################################

        # ################ Start Services #################################
        Connect2Wifi.__init__(self, static_ip)
        ClockUpdate.__init__(self,
                             utc_shift=2,
                             update_int=clock_update_interval)
        # #################################################################

        self.startMQTTclient()
        utime.sleep(1)

        self.pub('Boot- broker: [%s], ip: [%s]' %
                 (server, self.sta_if.ifconfig()[0]))
        self.mqtt_wait_loop()

    def startMQTTclient(self):
        self.mqtt_client = MQTTClient(self.mqtt_client_id,
                                      self.server,
                                      self.qos,
                                      user=self.user,
                                      password=self.password,
                                      keepalive=self.keep_alive_interval)
        self.mqtt_client.set_callback(self.on_message)
        self.mqtt_client.set_last_will(topic=self.avail_topic,
                                       msg="offline",
                                       retain=True)

        try:
            self.mqtt_client.connect()
            self.listen_topics.append(self.device_topic)
            for topic in self.listen_topics:
                self.mqtt_client.subscribe(topic)
            self.last_ping_time = utime.ticks_ms()
            # last will msg
            self.mqtt_client.publish(self.avail_topic, "online", retain=True)
            #
            return 1
        except OSError:
            self.notify_error("Error connecting MQTT broker")
            return 0

    def pub(self, msg, topic=None):
        try:
            if topic is not None:
                self.mqtt_client.publish(
                    topic,
                    "%s [%s] %s" % (self.time_stamp(), self.device_topic, msg))
            else:
                self.mqtt_client.publish(
                    self.msg_topic,
                    "%s [%s] %s" % (self.time_stamp(), self.device_topic, msg))
        except OSError:
            self.notify_error("fail to publish to broker")

    def on_message(self, topic, msg):
        self.arrived_msg = msg.decode("UTF-8").strip()
        self.mqtt_commands(topic=topic, msg=self.arrived_msg)

    def mqtt_wait_loop(self):
        fails_counter, off_timer, tot_disconnections = 0, 0, 0
        self.last_buttons_state = self.buttons_state()

        while True:
            # detect button press
            self.check_switch_change()
            #

            self.clock_update()
            self.ping_broker(keep_time=self.keep_alive_interval)

            try:
                # verify existance of MQTT server
                self.mqtt_client.check_msg()
                fails_counter = 0

            except OSError:
                fails_counter += 1

                self.notify_error("Fail Status #%d: Wifi is Connected: %s " %
                                  (fails_counter, self.is_connected()))

                # Check Wifi connectivity
                if self.is_connected() == 0:
                    self.notify_error("Try reconnect wifi #%d" % fails_counter)
                else:
                    # wifi is connected.Try reconnect MQTT client
                    if fails_counter <= self.num_of_fails:
                        # connection failed:
                        if self.startMQTTclient() == 0:
                            utime.sleep(2)
                        else:
                            continue
                    else:
                        # Emeregncy mode- stop looking for MQTT for some time, and comply only to physical switches
                        self.notify_error(
                            "fail reaching MQTT server- %d times, entering emergency mode for %d minutes"
                            % (self.num_of_fails,
                               self.minutes_in_emergency_mode))

                        start_timeout = utime.ticks_ms()
                        time_in_loop = 0
                        while time_in_loop < self.minutes_in_emergency_mode:
                            # accept button switch during this time
                            self.check_switch_change()
                            time_in_loop = (utime.ticks_ms() -
                                            start_timeout) / 1000 / 60
                            utime.sleep(self.switching_delay)
                        fails_counter = 0
                        # exiting emergency
            utime.sleep(self.switching_delay)

    def check_switch_change(self):
        current_buttons_state = self.buttons_state()
        if self.last_buttons_state != current_buttons_state:
            # debounce
            utime.sleep(self.switching_delay)
            # check again
            if self.last_buttons_state != self.buttons_state():
                self.switch_by_button()
                self.last_buttons_state = self.buttons_state()

    @staticmethod
    def time_stamp():
        t_tup = utime.localtime()
        t = "[%d-%02d-%02d %02d:%02d:%02d.%02d]" % (
            t_tup[0], t_tup[1], t_tup[2], t_tup[3], t_tup[4], t_tup[5],
            t_tup[6])
        return t

    def notify_error(self, msg):
        self.append_log(msg)

    def ping_broker(self, keep_time):
        # for keepalive purposes
        if utime.ticks_ms() > self.last_ping_time + keep_time * 1000:
            try:
                self.mqtt_client.ping()
                self.last_ping_time = utime.ticks_ms()
            except OSError:
                # fail
                pass
Example #15
0
class Mqtt:
    """
    Class obtain connecting to mqtt broker and sending data.
    """
    def __init__(self, ip, user="", password="", keepalive=0):
        client_id = ubinascii.hexlify(machine.unique_id())
        self._mqtt = MQTTClient(
            client_id=client_id,
            server=ip,
            user=user,
            password=password,
            keepalive=keepalive,
        )
        self.disconnect()

    def set_last_will(self, topic, msg, retain, qos):
        self._mqtt.set_last_will(topic, msg, retain, qos)

    def is_connected(self):
        """
        :return: Return True if is connection on mqtt broker.
        :rtype: bool
        """
        return self.publish(allow_print=False)

    def disconnect(self):
        try:
            self._mqtt.disconnect()
        except:
            pass

    def connect(self):
        """
        Trying connect to mqqt broker.
        If successfull then return.
        :return: Return True if connecting is OK.
        :rtype: bool
        """
        print("\nMQTT conecting...")
        try:
            _ret = self._mqtt.connect()
            print(_ret)
            if _ret == 0:
                print("\tMQTT connected to broker.")
                return True
            raise OSError
        except:
            print("\tMQTT unable to connect broker.")
            return False

    def publish(self,
                topic="test",
                msg="test",
                allow_print=True,
                retain=False,
                qos=0):
        """
        Sending message data to current topic.
        This function is useful for check connection, too.
        
        :param topic: topic, defaults to ""
        :type topic: str, optional
        :param msg: message to send, defaults to ""
        :type msg: str, optional
        :param allow_print: allow print sending process. In error always print
        :type allow_print: bool, optional
        :type retain: bool, defaults to False
        :type qos: int 0-2, defaults to 0
        :return: Return True if publishing message was successfully.
        :rtype: bool
        """
        try:
            if allow_print:
                print("\tSending message '{}' to topic '{}'".format(
                    msg, topic))
            self._mqtt.publish(topic=topic, msg=msg, retain=retain, qos=qos)
            if allow_print:
                print("\t\tSending OK")
            return True
        except Exception as ex:
            print("\t\tSending ERROR: {}".format(ex))
            return False
class MqttService:
    def __init__(self) -> None:
        """
        MQTT Service for the tlvlp.iot project
        Handles the connection and communication with the server via an MQTT broker

        Currently it is using a blocking MQTT client with asynchronous co-routines. This results in blocking all the
        other coros for the duration of the connection (usually around 2-3s and the timeout is 15s)

        Tested on ESP32 MCUs
        """

        print("MQTT service - Initializing service")
        self.mqtt_client = None
        self.connection_in_progress = False
        self.message_queue_incoming = Queue(config.mqtt_queue_size)
        self.message_queue_outgoing = Queue(config.mqtt_queue_size)
        # Add scheduled tasks
        loop = asyncio.get_event_loop()
        loop.create_task(self.connection_checker_loop())
        loop.create_task(self.incoming_message_checker_loop())
        loop.create_task(self.outgoing_message_sender_loop())
        print("MQTT service - Service initialization complete")

    async def start_service(self) -> None:
        print("MQTT service - Starting service")
        self.connection_in_progress = True
        await self.init_client()
        await self.set_callback()
        await self.set_last_will()
        await self.connect_to_broker()
        await self.subscribe_to_topics()
        shared_flags.mqtt_is_connected = True
        self.connection_in_progress = False
        print("MQTT service - Service is running")

    # Startup methods

    async def init_client(self) -> None:
        print("MQTT service - Initializing client")
        self.mqtt_client = MQTTClient(config.mqtt_unit_id,
                                      config.mqtt_server,
                                      config.mqtt_port,
                                      config.mqtt_user,
                                      config.mqtt_password,
                                      ssl=config.mqtt_use_ssl,
                                      keepalive=config.mqtt_keepalive_sec)
        await asyncio.sleep(0)

    async def set_callback(self) -> None:
        print("MQTT service - Setting callback")
        self.mqtt_client.set_callback(self.callback)
        await asyncio.sleep(0)

    def callback(self, topic_bytes: bytes, payload_bytes: bytes) -> None:
        """ All incoming messages are handled by this method """
        message = MqttMessage(topic_bytes.decode(), payload_bytes.decode())
        asyncio.get_event_loop().create_task(
            self.add_incoming_message_to_queue(message))

    async def set_last_will(self) -> None:
        print("MQTT service - Setting last will")
        self.mqtt_client.set_last_will(config.mqtt_topic_inactive,
                                       config.mqtt_checkout_payload,
                                       qos=config.mqtt_qos)
        await asyncio.sleep(0)

    async def connect_to_broker(self) -> None:
        print("MQTT service - Connecting to broker")
        connected = False
        while not connected:
            try:
                self.mqtt_client.connect()
                connected = True
                print("MQTT service - Connected to broker")
            except OSError:
                if not shared_flags.wifi_is_connected:
                    # If the network connection is lost while trying to connect to the broker
                    machine.reset()
                await asyncio.sleep(0)
        await asyncio.sleep(0)

    async def subscribe_to_topics(self) -> None:
        print("MQTT service - Subscribing to topics")
        for topic in config.mqtt_subscribe_topics:
            self.mqtt_client.subscribe(topic, qos=config.mqtt_qos)
        await asyncio.sleep(0)

    # Interface methods

    async def add_incoming_message_to_queue(self,
                                            message: MqttMessage) -> None:
        """ Takes an MqttMessage and adds it to the queue to be processed """
        if self.message_queue_incoming.full():
            return  # filter out message flood
        await self.message_queue_incoming.put(message)

    async def add_outgoing_message_to_queue(self,
                                            message: MqttMessage) -> None:
        """ Takes an MqttMessage and adds it to the queue to be processed """
        if self.message_queue_outgoing.full():
            return  # prevent message flood
        await self.message_queue_outgoing.put(message)

    # Scheduled loops

    async def connection_checker_loop(self) -> None:
        """ Periodically checks the connection status and reconnects if necessary """
        while True:
            if not shared_flags.mqtt_is_connected and not self.connection_in_progress and shared_flags.wifi_is_connected:
                await self.start_service()
            await asyncio.sleep(config.mqtt_connection_check_interval_sec)

    async def outgoing_message_sender_loop(self) -> None:
        """ Processes the outgoing message queue"""
        while True:
            message = await self.message_queue_outgoing.get()
            topic = message.get_topic()
            payload = message.get_payload()
            try:
                while not shared_flags.mqtt_is_connected:
                    await asyncio.sleep(0)
                self.mqtt_client.publish(topic, payload, qos=config.mqtt_qos)
                print(
                    "MQTT service - Message published to topic:{} with payload: {}"
                    .format(topic, payload))
            except OSError:
                print(
                    "MQTT service - Error in publishing message to topic:{} with payload: {}"
                    .format(topic, payload))
                shared_flags.mqtt_is_connected = False

    async def incoming_message_checker_loop(self) -> None:
        """ Periodically checks for new messages at the broker. Messages will be handled via the callback method """
        while True:
            if shared_flags.mqtt_is_connected:
                try:
                    self.mqtt_client.check_msg()
                except OSError:
                    print(
                        "MQTT service - Error! Messages cannot be retrieved from the MQTT broker. Connection lost."
                    )
                    shared_flags.mqtt_is_connected = False
            await asyncio.sleep_ms(config.mqtt_message_check_interval_ms)
Example #17
0
class HomieDevice:
    """MicroPython implementation of the Homie MQTT convention for IoT."""
    def __init__(self, settings):
        self.errors = 0
        self.settings = settings

        self.nodes = []
        self.node_ids = []
        self.topic_callbacks = {}

        self.start_time = utime.time()
        self.next_update = utime.time()
        self.stats_interval = self.settings.DEVICE_STATS_INTERVAL

        # base topic
        self.topic = b'/'.join(
            (self.settings.MQTT_BASE_TOPIC, self.settings.DEVICE_ID))

        # setup wifi
        utils.setup_network()
        utils.wifi_connect()

        try:
            self._umqtt_connect()
        except:
            print('ERROR: can not connect to MQTT')
            # self.mqtt.publish = lambda topic, payload, retain, qos: None

    def _umqtt_connect(self):
        # mqtt client
        self.mqtt = MQTTClient(self.settings.DEVICE_ID,
                               self.settings.MQTT_BROKER,
                               port=self.settings.MQTT_PORT,
                               user=self.settings.MQTT_USERNAME,
                               password=self.settings.MQTT_PASSWORD,
                               keepalive=self.settings.MQTT_KEEPALIVE,
                               ssl=self.settings.MQTT_SSL,
                               ssl_params=self.settings.MQTT_SSL_PARAMS)

        self.mqtt.DEBUG = True

        # set callback
        self.mqtt.set_callback(self.sub_cb)

        # set last will testament
        self.mqtt.set_last_will(self.topic + b'/$online',
                                b'false',
                                retain=True,
                                qos=1)

        self.mqtt.connect()

        # subscribe to device topics
        self.mqtt.subscribe(self.topic + b'/$stats/interval/set')
        self.mqtt.subscribe(self.topic + b'/$broadcast/#')

    def add_node(self, node):
        """add a node class of HomieNode to this device"""
        self.nodes.append(node)

        # add node_ids
        try:
            self.node_ids.extend(node.get_node_id())
        except NotImplementedError:
            raise
        except Exception:
            print('ERROR: getting Node')

        # subscribe node topics
        for topic in node.subscribe:
            topic = b'/'.join((self.topic, topic))
            self.mqtt.subscribe(topic)
            self.topic_callbacks[topic] = node.callback

    def sub_cb(self, topic, message):
        # device callbacks
        print('MQTT SUBSCRIBE: {} --> {}'.format(topic, message))

        if b'$stats/interval/set' in topic:
            self.stats_interval = int(message.decode())
            self.publish(b'$stats/interval', self.stats_interval, True)
            self.next_update = utime.time() + self.stats_interval
        elif b'$broadcast/#' in topic:
            for node in self.nodes:
                node.broadcast(topic, message)
        else:
            # node property callbacks
            if topic in self.topic_callbacks:
                self.topic_callbacks[topic](topic, message)

    def publish(self, topic, payload, retain=True, qos=1):
        # try wifi reconnect in case it lost connection
        utils.wifi_connect()

        if not isinstance(payload, bytes):
            payload = bytes(str(payload), 'utf-8')
        t = b'/'.join((self.topic, topic))
        done = False
        while not done:
            try:
                print('MQTT PUBLISH: {} --> {}'.format(t, payload))
                self.mqtt.publish(t, payload, retain=retain, qos=qos)
                done = True
            except Exception as e:
                # some error during publishing
                done = False
                done_reconnect = False
                utime.sleep(RETRY_DELAY)
                # tries to reconnect
                while not done_reconnect:
                    try:
                        self._umqtt_connect()
                        self.publish_properties()  # re-publish
                        done_reconnect = True
                    except Exception as e:
                        done_reconnect = False
                        print('ERROR: cannot connect, {}'.format(str(e)))
                        utime.sleep(RETRY_DELAY)

    def publish_properties(self):
        """publish device and node properties"""
        # node properties
        properties = (Property(b'$homie', b'2.1.0',
                               True), Property(b'$online', b'true', True),
                      Property(b'$name', self.settings.DEVICE_NAME, True),
                      Property(b'$fw/name', self.settings.DEVICE_FW_NAME,
                               True),
                      Property(b'$fw/version', __version__, True),
                      Property(b'$implementation',
                               bytes(sys.platform, 'utf-8'), True),
                      Property(b'$localip', utils.get_local_ip(), True),
                      Property(b'$mac', utils.get_local_mac(), True),
                      Property(b'$stats/interval', self.stats_interval, True),
                      Property(b'$nodes', b','.join(self.node_ids), True))

        # publish all properties
        for prop in properties:
            self.publish(*prop)

        # device properties
        for node in self.nodes:
            try:
                for prop in node.get_properties():
                    self.publish(*prop)
            except NotImplementedError:
                raise
            except Exception as error:
                self.node_error(node, error)

    def publish_data(self):
        """publish node data if node has updates"""
        self.publish_device_stats()
        # node data
        for node in self.nodes:
            try:
                if node.has_update():
                    for prop in node.get_data():
                        self.publish(*prop)
            except NotImplementedError:
                raise
            except Exception as error:
                self.node_error(node, error)

    def publish_device_stats(self):
        if utime.time() > self.next_update:
            # uptime
            uptime = utime.time() - self.start_time
            self.publish(b'$stats/uptime', uptime, True)
            # set next update
            self.next_update = utime.time() + self.stats_interval

    def node_error(self, node, error):
        self.errors += 1
        print('ERROR: during publish_data for node: {}'.format(node))
        print(error)
Example #18
0
class HomieDevice:
    """ MicroPython implementation of the homie v2 convention. """
    def __init__(self, cfg=None):
        self.nodes = []
        self.node_ids = []
        self.topic_callbacks = {}

        # update config
        if cfg is not None:
            if 'mqtt' in cfg:
                CONFIG['mqtt'].update(cfg['mqtt'])
            if 'device' in cfg:
                CONFIG['device'].update(cfg['device'])

        self.start_time = utime.time()
        self.next_update = utime.time()
        self.stats_interval = CONFIG['device']['stats_interval']

        # base topic
        self.topic = b'/'.join(
            (CONFIG['mqtt']['base_topic'], CONFIG['device']['id']))

        self._umqtt_connect()

    def _umqtt_connect(self):
        # mqtt client
        self.mqtt = MQTTClient(CONFIG['device']['id'],
                               CONFIG['mqtt']['broker'],
                               port=CONFIG['mqtt']['port'],
                               user=CONFIG['mqtt']['user'],
                               password=CONFIG['mqtt']['pass'],
                               keepalive=CONFIG['mqtt']['keepalive'],
                               ssl=CONFIG['mqtt']['ssl'],
                               ssl_params=CONFIG['mqtt']['ssl_params'])

        # set callback
        self.mqtt.set_callback(self.sub_cb)

        # set last will testament
        self.mqtt.set_last_will(self.topic + b'/$online',
                                b'false',
                                retain=True,
                                qos=1)

        self.mqtt.connect()

        # subscribe to device topics
        self.mqtt.subscribe(self.topic + b'/$stats/interval/set')
        self.mqtt.subscribe(self.topic + b'/$broadcast/#')

    def add_node(self, node):
        """add a node class of HomieNode to this device"""
        self.nodes.append(node)

        # add node_ids
        self.node_ids.extend(node.get_node_id())

        # subscribe node topics
        for topic in node.subscribe:
            topic = b'/'.join((self.topic, topic))
            self.mqtt.subscribe(topic)
            self.topic_callbacks[topic] = node.callback

    def sub_cb(self, topic, message):
        # device callbacks
        if b'$stats/interval/set' in topic:
            self.stats_interval = int(message.decode())
            self.publish(b'$stats/interval', self.stats_interval, True)
            self.next_update = utime.time() + self.stats_interval
        elif b'$broadcast/#' in topic:
            for node in self.nodes:
                node.broadcast(topic, message)
        else:
            # node property callbacks
            if topic in self.topic_callbacks:
                self.topic_callbacks[topic](topic, message)

    def publish(self, topic, payload, retain=True, qos=1):
        if not isinstance(payload, bytes):
            payload = bytes(str(payload), 'utf-8')
        t = b'/'.join((self.topic, topic))
        done = False
        while not done:
            try:
                self.mqtt.publish(t, payload, retain=retain, qos=qos)
                done = True
            except Exception as e:
                # some error during publishing
                done = False
                done_reconnect = False

                # tries to reconnect
                while not done_reconnect:
                    try:
                        self._umqtt_connect()
                        done_reconnect = True
                    except Exception as e:
                        done_reconnect = False
                        print(str(e))
                        utime.sleep(2)

    def publish_properties(self):
        """publish device and node properties"""
        # node properties
        properties = ((b'$homie', b'2.1.0', True), (b'$online', b'true', True),
                      (b'$fw/name', CONFIG['device']['fwname'], True),
                      (b'$fw/version', CONFIG['device']['fwversion'], True),
                      (b'$implementation', CONFIG['device']['platform'],
                       True), (b'$localip', CONFIG['device']['localip'],
                               True), (b'$mac', CONFIG['device']['mac'], True),
                      (b'$stats/interval', self.stats_interval,
                       True), (b'$nodes', b','.join(self.node_ids), True))

        # publish all properties
        for prop in properties:
            self.publish(*prop)

        # device properties
        for node in self.nodes:
            for prop in node.get_properties():
                self.publish(*prop)

    def publish_data(self):
        """publish node data if node has updates"""
        self.publish_device_stats()
        # node data
        for node in self.nodes:
            if node.has_update():
                for prop in node.get_data():
                    self.publish(*prop)

    def publish_device_stats(self):
        if utime.time() > self.next_update:
            # uptime
            uptime = utime.time() - self.start_time
            self.publish(b'$stats/uptime', uptime, True)
            # set next update
            self.next_update = utime.time() + self.stats_interval
Example #19
0
if not inp():
    try:
        info = meassure()
        message = json.dumps(info).encode()
        topic = b"weather/outside"
    except:
        message = b"Error cargando BME280 en Terraza"
        topic = b"ERRORS"
    print(message)

    try:
        print("Connecting Client")
        KEEP_ALIVE = int(2.2 * WAIT_TIME / 1000)
        c = MQTTClient("umqtt_client",
                       "192.168.1.85",
                       user="******",
                       password="******",
                       keepalive=KEEP_ALIVE)
        c.set_last_will(b"ERRORS", b"Sensor BME280 en terraza desconectado")
        c.connect()
        c.publish(topic, message)
        time.sleep(2)
        c.disconnect()
        print("Disconeecting Client")
    except:
        print("Error in Conexion")
        time.sleep(2)
else:
    print("Charging")
machine.deepsleep(WAIT_TIME)
class Client:
    def __init__(self, client_id, broker_address):
        """
        Initialises the MQTT Client
        :param client_id: The unique client id used to initiate an MQTTClient class
        :param broker_address: A string holding domain name or IP address of the broker to connect to, to send and
                            receive data.
        """
        self.keep_alive_interval = 30
        self.client = MQTTClient(client_id, broker_address, keepalive=self.keep_alive_interval)
        self.mqtt_broker = broker_address
        self.connected = False

    def set_last_will(self, topic, msg):
        """
        Sets the last will and testament message for the client.
        :param will_topic: The topic to send a last will msg on
        :param will_msg: The msg to send on the will_topic when the client disconnects
        """
        self.client.set_last_will(topic, self._to_bytes_literal(msg), retain=True)

    async def connect_and_subscribe(self, topics_to_subscribe, callback_func):
        """
        Connects to the MQTT broker and subscribes to each topic in 'topics_to_subscribe' using QoS = 1
        :param topics_to_subscribe: An array of topics to subscribe to.
                                    Each element must be a string or byte literal (the latter is preferred)
        :param callback_func: The function to be called whenever a message from the subscribed topic is received.
        """
        self.client.set_callback(callback_func)

        # Connect to MQTT broker
        while not self.connected:
            try:
                print(
                    "Attempting connection to MQTT broker at {}...".format(
                        self.mqtt_broker
                    )
                )
                self.client.connect()
                self.connected = True
            except (OSError, MQTTException) as e:
                print("Failed to connect! {}: {}".format(type(e), e))
                print("Reattempting in 5 seconds.")
                await asyncio.sleep(5)

        print("Connected to {}".format(self.mqtt_broker))
        self.connected = True

        # Subscribe to each topic
        for topic in topics_to_subscribe:
            self.client.subscribe(topic, qos=1)
            print("Subscribed to {} topic".format(topic))

        # Start pingreq loop
        asyncio.create_task(self.start_ping_loop())

        return True

    async def start_ping_loop(self):
        """
        Sends a PINGREQ message to the broker at a regular interval so it knows we're
        still connected. The server's response is handled by umqtt automatically.
        """
        while True:
            if self.connected:
                self.client.ping()
            await asyncio.sleep(self.keep_alive_interval)


    def _to_bytes_literal(self, data):
        """
        Converts data into a form MQTT can read
        :param data: A string of data to convert to bytes literal
        :return: The bytes literal version of the 'data'
        """
        str_data = str(data)
        return str.encode(str_data)

    def publish(self, topic, data="", retain=False):
        """
        This function takes care of all of the formatting and publishes 'data' on the given topic. Also checks for any
        incoming messages
        :param topic: A string representing the topic to send 'data' to.
        :param data: A string of data to send/publish
        :param retain:
        """
        msg = self._to_bytes_literal(data)
        self.client.publish(topic, msg, retain=retain)

        self.check_for_message()

    def check_for_message(self):
        """
        Checks whether an incoming message from the MQTT broker on the subscribed topics is pending.
        """
        self.client.check_msg()

    def wait_for_message(self):
        """
        This function blocks until a message is received on one of the subscribed topics
        """
        self.client.wait_msg()

    def disconnect(self):
        """
        Disconnect from the broker
        """
        self.connected = False
        self.client.disconnect()
Example #21
0
        if msg == b'blue':
            cardstate = 124
        elif msg == b'green':
            cardstate = 224
        elif msg == b'red':
            cardstate = 324
        else:
            cardstate = 23


tstatus = b'eos/rfid/status'
mqttid = ubinascii.hexlify(machine.unique_id())
mqtt = MQTTClient(client_id=mqttid, server='192.168.1.58')
mqtt.set_callback(mqtt_rec)
mqtt.set_last_will(tstatus,
                   b'{"battery":0.0,"connected":false}',
                   retain=True,
                   qos=1)
try:
    mqtt.connect()
    mqtt.subscribe(b'eos/rfid/color')
except:
    pass

adc = machine.ADC(0)
cnt = 1500
while True:
    ct = ticks_add(ticks_ms(), 40)
    try:
        pn.mainloop()
    except:
        sleep_ms(100)
Example #22
0
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect("Dicey 2", "84735peter")

sleep(5)

broker_address = '192.168.0.81'

# client id can be esp32, doesnt need the last bit
client_id = 'esp32_{}'.format(ubinascii.hexlify(machine.unique_id()))
topic = b'temp_humidity'
client = MQTTClient(client_id, broker_address)

# last will is when it dies, this is the last thing that is sent, i think
# basically you can subscribe to the dead topic and get the logs
client.set_last_will(topic, b'dead')

client.connect()
print("connected to broker")

# ignore, this is for my sensor
sensor = DHT11(Pin(5))

while True:
    try:
        # measure sensor
        sensor.measure()

        # store sensor values
        t = sensor.temperature()
        h = sensor.humidity()
Example #23
0
class SmartLight():
    def __init__(self):
        self.wdt = WDT()
        self.adc = ADC(0)
        self.auto_tim = Timer(1)
        self.publish_tim = Timer(2)
        self.ping_fail = 0
        self.ping_mqtt = 0
        self.light_state = 0
        self.light_intensity = 0
        self.sensor_interrupt = 0
        self.button_interrupt = 0
        self.current_color = [255, 255, 255]
        self.auto_human = config.AUTO_HUMAN
        self.auto_sound = config.AUTO_SOUND
        self.auto_light = config.AUTO_LIGHT
        self.light_status = {
            "state": "OFF",
            "brightness": 100,
            "color": {
                "r": 255,
                "g": 255,
                "b": 255
            },
            "effetc": ""
        }

        self.np = NeoPixel(Pin(config.WS2812_PIN, Pin.OUT), config.WS2812_BIT)

        self.mqtt_client = MQTTClient(client_id=config.DEVICE_NAME,
                                      server=config.MQTT_SERVER,
                                      port=config.MQTT_PORT,
                                      user=config.MQTT_USER,
                                      password=config.MQTT_PASSWD,
                                      keepalive=60)
        self.mqtt_client.set_callback(self.sub_callback)
        self.mqtt_client.set_last_will(config.AVAILABILITY_TOPIC, "offline")

        self.human_sensor_1 = Pin(config.HUMAN_SENSOR_PIN_1, Pin.IN,
                                  Pin.PULL_UP)
        self.human_sensor_2 = Pin(config.HUMAN_SENSOR_PIN_2, Pin.IN,
                                  Pin.PULL_UP)
        self.human_sensor_3 = Pin(config.HUMAN_SENSOR_PIN_3, Pin.IN,
                                  Pin.PULL_UP)
        self.sound_sensor = Pin(config.SOUND_SENSOR_PIN, Pin.IN, Pin.PULL_UP)
        self.button = Pin(config.BUTTON_PIN, Pin.IN, Pin.PULL_UP)

    def mqtt_connect(self):
        try:
            self.mqtt_client.connect()
            for topic in [
                    config.DEVICE_SET_TOPIC, config.MQTT_CHECK_TOPIC,
                    config.HUMAN_SET_TOPIC, config.LIGHT_SET_TOPIC,
                    config.SOUND_SET_TOPIC
            ]:
                self.mqtt_client.subscribe(topic)
            self.mqtt_client.publish(config.AVAILABILITY_TOPIC, "online")
            self.mqtt_client.publish(config.DEVICE_STATE_TOPIC,
                                     json.dumps(self.light_status))
            self.mqtt_client.publish(config.HUMAN_STATE_TOPIC, self.auto_human)
            self.mqtt_client.publish(config.LIGHT_STATE_TOPIC, self.auto_light)
            self.mqtt_client.publish(config.SOUND_STATE_TOPIC, self.auto_sound)
        except Exception as e:
            print("mqtt connect faild", e)

    def set_color(self, color):
        if isinstance(color, dict):
            r, g, b = color.values()
        elif isinstance(color, list):
            r, g, b = color
        for i in range(config.WS2812_BIT):
            self.np[i] = (b, g, r)
        self.np.write()

    def show_effects(self, effect):
        print(effect)

    def sub_callback(self, topic, msg):
        topic = topic.decode('utf-8')
        msg = msg.decode('utf-8')
        if topic == config.DEVICE_SET_TOPIC:
            msg = json.loads(msg)
            state = msg.get('state', '')
            brightness = msg.get('brightness', '')
            color = msg.get('color', {})
            effect = msg.get('effect', '')
            self.light_control(state, brightness, color, effect)
            self.mqtt_client.publish(config.DEVICE_STATE_TOPIC,
                                     json.dumps(self.light_status))
        elif topic == config.MQTT_CHECK_TOPIC:
            if int(msg) == self.ping_mqtt:
                # print("MQTT is OK")
                self.ping_fail = 0
        elif topic == config.HUMAN_SET_TOPIC:
            if msg == "ON":
                self.auto_human = 1
                self.mqtt_client.publish(config.HUMAN_STA_TOPIC, "ON")
            elif msg == "OFF":
                self.auto_human = 0
                self.mqtt_client.publish(config.HUMAN_STATE_TOPIC, "OFF")
        elif topic == config.LIGHT_SET_TOPIC:
            if msg == "ON":
                self.auto_light = 1
                self.mqtt_client.publish(config.LIGHT_STATE_TOPIC, "ON")
            elif msg == "OFF":
                self.auto_light = 0
                self.mqtt_client.publish(config.LIGHT_STATE_TOPIC, "OFF")
        elif topic == config.SOUND_SET_TOPIC:
            if msg == "ON":
                self.auto_sound = 1
                self.mqtt_client.publish(config.SOUND_STATE_TOPIC, "ON")
            elif msg == "OFF":
                self.auto_sound = 0
                self.mqtt_client.publish(config.SOUND_STATE_TOPIC, "OFF")

    def light_control(self, state, brightness, color, effect):
        # TODO:当灯处于关闭状态时调节亮度无效的
        if color:
            self.set_color(color)
            self.light_state = 2
            self.light_status["state"] = "ON"
            self.light_status['color'] = color
            self.light_status['brightness'] = int(
                max(color.values()) / 255 * 100)
        if type(brightness) == int:
            if brightness == 0:
                # print("turn off")
                self.set_color(config.DEFAULT_OFF_COLOR)
                self.light_state = 0
            else:
                scale = max(self.light_status["color"].values()) / int(
                    brightness / 100 * 255)
                for c in ['r', 'g', 'b']:
                    self.light_status["color"][c] = int(
                        self.light_status["color"][c] / scale)
                self.set_color(self.light_status["color"])
                self.light_state = 2
            self.light_status["brightness"] = brightness
        if effect:
            self.show_effects(effect)
        if state == "OFF":
            self.light_status["state"] = "OFF"
            self.set_color(config.DEFAULT_OFF_COLOR)
            self.light_state = 0
        if state == "ON":
            if any([color, type(brightness) == int, effect]):
                pass
            else:
                self.set_color(config.DEFAULT_COLOR)
                self.light_status["state"] = "ON"
                self.light_state = 2

    def sensor_action(self, pin):
        self.sensor_interrupt = self.sensor_interrupt + 1

    def button_action(self, pin):
        self.button_interrupt = self.button_action + 1
        if self.light_state == 0:
            self.set_color(config.DEFAULT_COLOR)
            self.light_state = 1
            self.light_status["state"] = "ON"
        elif self.light_state == 1:
            self.set_color(config.DEFAULT_OFF_COLOR)
            self.light_state = 0
            self.light_status["state"] = "OFF"
        self.publish_tim.init(period=1000,
                              mode=Timer.ONE_SHOT,
                              callback=self.publish_light_status)

    def get_light_intensity(self):
        li = self.adc.read()
        return 1 if li > 512 else 0

    def publish_light_status(self):
        if self.ping_fail == 0:
            self.mqtt_client.publish(config.STATUS_TOPIC,
                                     json.dumps(self.light_status))

    def internet_connected(self):
        return True

    async def check_interrupt(self, pin):
        while True:
            await asyncio.slepp(0.5)
            if self.sensor_interrupt > 0:
                if self.auto_light:
                    self.light_intensity = self.get_light_intensity()
                else:
                    self.light_intensity = 0

                if pin == config.SOUND_SENSOR_PIN:
                    code = "{}{}{}{}".format(self.auto_sound, self.auto_light,
                                             self.light_intensity,
                                             self.light_state)
                else:
                    code = "{}{}{}{}".format(self.auto_human, self.auto_light,
                                             self.light_intensity,
                                             self.light_state)
                are_light = code_table[code]
                if are_light == 1:
                    self.set_color(config.DEFAULT_COLOR)
                    self.auto_tim.init(period=config.DELAY_TIME * 1000,
                                       mode=Timer.ONE_SHOT,
                                       callback=lambda t: self.set_color(
                                           config.DEFAULT_OFF_COLOR))
                    self.light_state = 1
                    print("Turn off the lights after {} s".format(
                        config.DELAY_TIME))
                else:
                    pass
                self.sensor_interrupt = 0

    async def keep_mqtt(self):
        while True:
            await asyncio.sleep(10)
            self.ping_mqtt = time.time()
            self.mqtt_client.publish(config.MQTT_CHECK_TOPIC,
                                     "%s" % self.ping_mqtt)
            # print("Send MQTT ping (%i)" % self.ping_mqtt)
            self.ping_fail += 1

            if self.ping_fail > 10:
                # print("MQTT ping false... reset (%i)" % self.ping_fail)
                machine.reset()

            if self.ping_fail > 3:
                # print("MQTT ping false... reconnect (%i)" % self.ping_fail)
                self.mqtt_client.disconnect()
                self.mqtt_connect()

    async def check_message(self):
        while True:
            self.wdt.feed()
            await asyncio.sleep(0.2)
            try:
                self.mqtt_client.check_msg()
            except:
                self.mqtt_connect()

    def run(self):
        self.sound_sensor.irq(trigger=Pin.IRQ_FALLING,
                              handler=self.sensor_action)
        self.human_sensor_1.irq(trigger=Pin.IRQ_FALLING,
                                handler=self.sensor_action)
        self.human_sensor_2.irq(trigger=Pin.IRQ_FALLING,
                                handler=self.sensor_action)
        self.human_sensor_3.irq(trigger=Pin.IRQ_FALLING,
                                handler=self.sensor_action)
        self.button.irq(trigger=Pin.IRQ_FALLING, handler=self.button_action)

        try:
            loop = asyncio.get_event_loop()
            loop.create_task(self.check_message())
            loop.create_task(self.check_interrupt())
            loop.create_task(self.keep_mqtt())
            loop.run_forever()
        except Exception as e:
            print(e)
Example #24
0
if runapp.value() != 1:
	from sys import exit
	exit(0)

led.value( 0 ) # allumer

# --- Programme Pincipal ---
from umqtt.simple import MQTTClient
try:
	if os.uname().nodename != 'esp32':
		raise Exception( "ESP32 only project (3.3V Analog required)")

	q = MQTTClient( client_id = CLIENT_ID, server = MQTT_SERVER, user = MQTT_USER, password = MQTT_PSWD )
	sMac = hexlify( WLAN().config( 'mac' ) ).decode()
	q.set_last_will( topic="disconnect/%s" % CLIENT_ID , msg=sMac )

	if q.connect() != 0:
		led_error( step=1 )

except Exception as e:
	print( e )
	# check MQTT_SERVER, MQTT_USER, MQTT_PSWD
	led_error( step=2 )

# chargement des bibliotheques
try:
	from machine import Pin
except Exception as e:
	print( e )
	led_error( step=3 )
Example #25
0
class MQTTService(object):
    def __init__(self, sub_cb=None):
        self.__client = None
        self.__sub_cb = sub_cb
        self.__heartbeat_timer = Timer(0)
        self.__heartbeat_counter = 0

        self.__client = MQTTClient(
            Settings.MQTT_CLIENT_ID,
            Settings.MQTT_HOST,
            Settings.MQTT_PORT,
            Settings.MQTT_USERNAME,
            Settings.MQTT_PASSWORD,
            Settings.MQTT_KEEPALIVE,
        )

    def __heartbeat_cb(self, timer):
        self.__heartbeat_counter += 1

        if self.__heartbeat_counter >= Settings.MQTT_KEEPALIVE:
            try:
                self.__client.publish(
                    b'{}/ping'.format(Settings.MQTT_USERNAME), b'ping')
                self.__heartbeat_counter = 0
            except OSError as ose:
                err_msg = str(ose)

                print("err time:", time())
                print(err_msg)

                if err_msg in ("[Errno 104] ECONNRESET", "-1"):
                    try:
                        self.__client.disconnect()
                    except OSError:
                        pass
                    finally:
                        self.__client.connect()
                elif err_msg == "[Errno 113] EHOSTUNREACH":
                    Utilities.hard_reset()

        gc.collect()

    def deinit(self):
        self.__client.disconnect()
        self.__heartbeat_timer.deinit()

        self.__client = None
        self.__heartbeat_timer = None

    def connect(self, clean_session=True):
        # mqtt_client.set_last_will(b'walkline/last_will', b'offline')
        self.__client.set_callback(self.__sub_cb)
        self.__client.connect(clean_session=clean_session)

        self.__heartbeat_timer.init(mode=Timer.PERIODIC,
                                    period=1000,
                                    callback=self.__heartbeat_cb)

        print("mqtt forever loop")
        print("now:", time())

        username = Settings.MQTT_BIGIOT_USERNAME if bool(
            Settings.MQTT_IS_BIGIOT) else Settings.MQTT_CLIENT_ID

        self.__client.subscribe(b'{}/{}'.format(username,
                                                Settings.MQTT_CLIENT_ID))

    def disconnect(self):
        self.__client.disconnect()

    def set_callback(self, f):
        self.__sub_cb = f
        self.__client.set_callback(self.__sub_cb)

    def set_last_will(self, topic, msg, retain=False, qos=0):
        self.__client.set_last_will(topic, msg, retain=retain, qos=qos)

    def ping(self):
        self.__client.ping()

    def publish(self, topic, msg, retain=False, qos=0):
        self.__client.publish(topic, msg, retain=retain, qos=qos)

    def subscribe(self, topic, qos=0):
        self.__client.subscribe(topic, qos=qos)

    def wait_msg(self):
        self.__client.wait_msg()

    def check_msg(self):
        self.__client.check_msg()
Example #26
0
def transmit(switch_cntrl,
             light1,
             light2,
             sw,
             topic,
             name="outlet_default",
             server="192.168.1.90",
             err_slp=100,
             err_rst=150):
    print("Starting MQTT transmitter...")

    #save the start time
    (syear, smonth, smday, shour, sminute, ssecond, sweekday,
     syearday) = utime.localtime()

    #configure switch pins
    outlet_switch = machine.Pin(sw, machine.Pin.OUT)
    outlet_light1 = machine.Pin(light1, machine.Pin.OUT)
    outlet_light2 = machine.Pin(light2, machine.Pin.OUT)
    outlet_cntrl = machine.Pin(switch_cntrl, machine.Pin.IN,
                               machine.Pin.PULL_UP)

    #set the outlet to the default state
    outlet_switch.off()
    outlet_light1.off()

    #flash the blue light so user has indication that outlet is working
    outlet_light2.on()
    time.sleep(.25)
    blink1()
    blink1()
    outlet_light1.on()

    #define the channels
    btopic = bytes(topic, 'utf-8')
    state_channel = btopic
    command_channel = btopic + b'/set'
    availability_channel = btopic + b'/available'
    debug_channel = 'debug'

    #set up udp socket
    c = MQTTClient(name, server)
    c.set_last_will(topic=availability_channel,
                    msg=b'offline',
                    retain=False,
                    qos=0)
    c.connect()
    print("Started!")

    #notify that you're available
    c.publish(availability_channel, b'online')

    def dbg_msg(name, msg):
        #debug messages
        payload = {}
        payload["outlet_name"] = name
        payload["message"] = msg
        a = ujson.dumps(payload)
        c.publish(debug_channel, a)

    dbg_msg(name, 'switch boot up')

    #status
    def status():
        (year, month, mday, hour, minute, second, weekday,
         yearday) = utime.localtime()

        print("")
        print("")
        print("Outlet v.0.5.0")
        print("{}/{}/{} {}:{}:{} | boot: {}/{}/{} {}:{}:{}".format(
            month, mday, year, hour, minute, second, smonth, smday, syear,
            shour, sminute, ssecond))
        print("Error Count: {}".format(str(error_cnt)))
        print("")
        print("Outlet status: " + str(outlet_switch.value()))
        print("Outlet name: " + name)
        print("Outlet topic: " + topic)

        dbg_msg(name, "Outlet status: " + str(outlet_switch.value()))

    #mqtt callback
    def monitor_cmds(topic, msg):
        if msg == b"ON":
            outlet_switch.on()
            try:
                c.publish(state_channel, b'ON')
                dbg_msg(name, 'switch commanded on')

            except:
                print("Error - Publish On!")
                rst_comm()
                error_cnt += 1
            outlet_light1.off()
            outlet_light2.on()

        elif msg == b"OFF":
            outlet_switch.off()
            try:
                c.publish(state_channel, b'OFF')
                dbg_msg(name, 'switch commanded off')
            except:
                print("Error - Publish Off!")
                rst_comm()
                error_cnt += 1
            outlet_light1.on()
            outlet_light2.on()

        #elif msg == b"schedule update":
        #elif msg == b"request schedule":
        #elif msg == b"schedule message":
        #elif msg == b"control selection":
        #elif msg == b"reboot":

    #phyisical button
    def btn_cntrl(p):
        time.sleep(1)
        if outlet_cntrl.value() == 0:
            if outlet_switch.value() == 0:
                monitor_cmds('', b'ON')
            else:
                monitor_cmds('', b'OFF')

        #debug messages
        dbg_msg(name, 'physical button pressed')

    def rst_comm():
        c.disconnect()
        c.connect()
        c.subscribe(command_channel)
        dbg_msg(name, 'device reset')

    #set interrupts
    c.set_callback(monitor_cmds)
    outlet_cntrl.irq(handler=btn_cntrl, trigger=outlet_cntrl.IRQ_FALLING)

    #subscribe to the command channel
    c.subscribe(command_channel)

    #wait
    error_cnt = 0
    while True:
        try:
            #check the command channel
            c.check_msg()
        except:
            print("Error - Check Message!")

            #reboot the connection
            rst_comm()
            error_cnt += 1

        #print status to the repl
        try:
            status()
        except:
            print("Error - Status")
            error_cnt += 1

        #watch error count, reset if limit exceeded
        if error_cnt == err_slp:
            time.sleep(15)
        elif error_cnt > err_rst:
            machine.reset()

        #Wait for a second
        time.sleep(1)

    c.disconnect()
    print('exiting...')
Example #27
0
from mqtt_config import config

MQTT_BROKER = config['broker']
MQTT_SUB = config['topic_sub']
MQTT_PUB = config['topic_pub']

client = MQTTClient(utils.get_mac(), MQTT_BROKER)


def rcv(topic, msg):
    print("{}: {}".format(topic.decode("utf-8"), msg.decode("utf-8")))
    client.publish(MQTT_PUB, '{"rcv":"' + msg.decode("utf-8") + '"}')


client.set_callback(rcv)
client.set_last_will('test/admin', 'OOPS - ' + utils.get_mac() + ' crashed!')
client.connect()
client.subscribe(MQTT_SUB)


def start_loop():
    try:
        while True:
            client.check_msg()
            sleep(1)
    except KeyboardInterrupt:
        pass
    finally:
        client.disconnect()