class MQTTDevice: def __init__(self, topic_online, true_message="true", false_message="false"): self.true_message = true_message self.false_message = false_message self.client = MQTTClient(MQTT_CLIENT_ID_RANDOM, MQTT_BROKER_ADDRESS, port=MQTT_PORT, keepalive=KEEP_ALIVE_TIME_SEC) self.next_scheduled_ping_time = 0 self._client_setup(topic_online) def _client_setup(self, topic_online): self.client.set_last_will(topic_online, self.false_message) self.client.connect() self.client.publish(topic_online, self.true_message) self.setup_subscriptions() # override this method in subclass # set callback and subscriptions def setup_subscriptions(self): pass def _ping(self): if (self.next_scheduled_ping_time < utime.time()): self.client.ping() self.next_scheduled_ping_time = utime.time() + PING_EVERY_SEC #run method has to be called every execution cycle def run(self): self._ping() self.client.check_msg()
class Device(object): def __init__(self, device_token): self.__device_token = bytes(device_token, 'utf-8') self.__variables = None self.__diag_variables = None self.__mqtt = None self.__bindings = dict() self.next_ping_time = time() def __publish(self, topic, payload=None): if payload is None: return msg = json.dumps({'payload': payload}) self.__mqtt.publish(C4R_TOPIC_FORMAT % (self.__device_token, topic), msg, qos=1) print(topic, "<--", msg) self.mqtt_ping_reset() def __on_message(self, topic, msg): print(topic.decode().rsplit('/')[-1], "-->", msg.decode()) data = json.loads(msg) for var_name, callback in self.__bindings.items(): if var_name in data.keys(): ret = callback(data[var_name]) self.__variables[var_name]['value'] = ret self.__publish('data', {var_name: ret}) def connect(self): self.__mqtt = MQTTClient(client_id=self.__device_token, server=C4R_BROKER_HOST, port=C4R_BROKER_PORT) self.__mqtt.set_callback(self.__on_message) try: self.__mqtt.connect() self.__mqtt.subscribe(C4R_TOPIC_FORMAT % (self.__device_token, 'commands'), qos=1) except Exception as e: print("[Exception] %s: %s" % (type(e).__name__, e)) return False self.mqtt_ping_reset() return True def ping(self): self.__mqtt.ping() self.mqtt_ping_reset() def mqtt_ping_reset(self): self.next_ping_time = time() + PING_INTERVAL print("Next MQTT ping at", self.next_ping_time) def declare(self, variables): self.__variables = variables def declare_diag(self, diag_variables): self.__diag_variables = diag_variables def publish_config(self): cfg = [] for var_name, var_config in self.__variables.items(): cfg.append({'name': var_name, 'type': var_config['type']}) self.__bindings[var_name] = var_config['bind'] self.__publish('config', cfg) def publish_diag(self): self.__publish('diagnostics', self.__diag_variables) def publish_data(self): for var_name, callback in self.__bindings.items(): self.__variables[var_name]['value'] = \ callback(self.__variables[var_name]['value']) cfg = {var_name: var_config['value'] for var_name, var_config in self.__variables.items()} self.__publish('data', cfg) def check_commands(self): """Call me at least once per 55s""" self.__mqtt.check_msg() if time() >= self.next_ping_time: print("MQTT ping at", time()) self.ping()
client.publish(topic=LOG_TOPIC, msg=id + b' is up') last_message = time.time() while True: client.check_msg() if button_changed == True: button_changed = False if button() == 0: msg = "ON" else: msg = "OFF" last_message = time.time() # Note: The retain flag is not supported by Adafruit IO! # https://io.adafruit.com/blog/#mqtt-get-and-the-case-of-the-missing-retain-flag client.publish(topic=LED_STATE_TOPIC, msg=msg.encode(), retain=True, qos=MQTT_QoS.AT_LEASE_ONCE) time.sleep(.1) if time.time() > last_message + keepalive / 2: last_message = time.time() client.ping()
debug("slave: ampsMax=%2.2f, ampsActual=%2.2f" % (ourSlave['ampsMax'], ourSlave['ampsActual']), 1) else: rgbled(0xFF, 0x00, 0x00) debug("recv: unknown message type %d:%d" % (slaveMsg[0], slaveMsg[1]), 1) except InvalidMessage as e: rgbled(0xFF, 0x00, 0x00) debug("slave message failed checks: %s" % e, 0) except ValueError as e: rgbled(0xFF, 0x00, 0x00) debug("recv: garbled message: %s" % e, 0) ERRORS += 1 if (time.time() > PING): rgbled(0x0F, 0x0F, 0x00) try: mqtt_client.ping() except: debug("mqtt ping failure", 0) time.sleep(1) machine.reset() PING = time.time() + 30 # If we have a slave talk to it every second if (time.time() >= HEARTBEAT): HEARTBEAT = time.time() + 1 rgbled(0x0F, 0x00, 0x0F) debug("mem_free: %d" % gc.mem_free(), 1) if (ourSlave['twcid'] != None): send_master_heartbeat("limit", ourSlave['charge_rate']) # send_master_heartbeat("limit", 15)