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()
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")
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()
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()
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
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()
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)
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
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)
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))
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
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()
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()])
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
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)
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)
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
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()
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)
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()
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)
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 )
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()
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...')
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()