def mqtt_send(values): """Send key/value pairs over mqtt.""" device_name = rom_to_hex(bytearray(machine.unique_id())) mqtt = MQTTClient(device_name, MQTT_SERVER) mqtt.connect() # do mqtt ping/pong to ensure communication with broker is ok for x in range(CONNECT_WAIT): mqtt.ping() mqtt.sock.setblocking(False) res = mqtt.sock.read(1) if res == b"\xd0": sz = mqtt.sock.read(1)[0] if sz == 0: break time.sleep(1) else: return False for name, raw_value in values.items(): if isinstance(raw_value, float): value = b"{:4.3f}".format(raw_value) elif isinstance(raw_value, int): value = b"{:d}".format(raw_value) elif isinstance(raw_value, str): value = bytes(raw_value, 'utf8') mqtt.publish(b"templog/{}/{}".format(device_name, name), value) mqtt.disconnect()
def init(client_id, hostname='alpcer0.local', sub_topic='kybIntcpt', callback=simple_sub_cb): global mqtt_client mqtt_client = MQTTClient(client_id, hostname) mqtt_client.set_callback(callback) mqtt_client.connect() mqtt_client.subscribe(sub_topic) mqtt_client.ping() mqtt_client.wait_msg()
class Mqtt: def __init__(self, client_name, server): self.__c = MQTTClient(client_name, server) self.__connected = False def is_connected(self): try: logger.print_cmd('Send MQTT ping') self.__c.ping() self.__connected = True logger.print_info('Connected from MQTT Broker') except: self.disconnect(False) return self.__connected def connect(self): logger.print_cmd('Connect to MQTT Broker') self.__c.connect() self.is_connected() def disconnect(self, force=False): if self.__connected or force: logger.print_cmd('Disconnected from MQTT Broker') self.__connected = False self.__c.disconnect() def publish(self, topic, msg): logger.print_cmd('Publish data vi MQTT') self.__c.publish(topic, msg) def subscribe(self, topic, message_func): logger.print_cmd('Subscribe data vi MQTT') self.__c.set_callback(message_func) self.__c.subscribe(topic) def wait_msg(self): try: while 1: self.__c.wait_msg() finally: self.__c.disconnect()
def mqtt_drive(server="localhost", robot_name='another robot', mqtt_user='******', mqtt_password='******'): global time_to_stop intro() motor.motor_a.stop() motor.motor_b.stop() print("I'm %s" % topic) time_to_announce = ticks_ms() + 15 * 1000 c = MQTTClient(b"umqtt_client/%s" % robot_id, server, 1883, mqtt_user, mqtt_password) c.set_callback(msg_callback) # c.set_last_will(topic + "/$online$", "0", retain=1) c.connect() c.publish(topic + "/$online$", '1') c.publish(topic + "/$name$", robot_name, retain=1) c.subscribe(topic + '/#') while True: c.check_msg() if ticks_ms() > time_to_stop: motor.motor_a.stop() motor.motor_b.stop() c.ping() time_to_stop = ticks_ms() + 10 * TIMEOUT if ticks_ms() > time_to_announce: c.publish(topic + "/$online$", '1') time_to_announce = ticks_ms() + 16 * 1000 # Then need to sleep to avoid 100% CPU usage (in a real # app other useful actions would be performed instead) time.sleep(0.005) c.disconnect()
def main(server=SERVER): #端口号为:6002 c = MQTTClient(CLIENT_ID, server, 6002, username, password, keepalive=10) # 保持连接时间间隔设置10秒 c.set_callback(sub_cb) c.connect() tim1 = Timer(1) #创建定时器1 tim1.init(period=2000, mode=Timer.PERIODIC, callback=lambda n: c.ping()) # 发送心跳包 ,保持连接 print("Connected to %s" % server) try: while 1: c.wait_msg() finally: c.disconnect()
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 Gateway: id = None # description = None # gateway_type = None class MQTTServer: # server = "192.168.1.123" # port = 1883 # keep_alive = 60 # username = "******" # password = "******" wait_to_reconnect = 5 mqtt_server = MQTTServer() def __init__(self, config, start=True): self.configure(config) if start: self.start() def configure(self, config): from kiota.Configurator import Configurator Configurator.apply(self, config["gateway"]) # if self.id is None: # try: # import ubinascii # except ImportError: # import binascii as ubinascii # try: # import uhashlib # except ImportError: # import hashlib as uhashlib # self.id = ubinascii.hexlify(uhashlib.sha256(machine.unique_id()).digest()).decode() self.topic = "/kiota/{}".format(self.id) self.last_ping = 0 self.client = MQTTClient(self.topic, self.mqtt_server.server, self.mqtt_server.port, self.mqtt_server.username, self.mqtt_server.password, self.mqtt_server.keep_alive) self.client.set_callback(self.do_message_callback) self.exit_topic = "{}/exit".format(self.topic) self.devices = [] for d in config["devices"]: try: class_name = d["type"] module_name = class_name try: module_name = d["module"] except (KeyError): pass package_name = "kiota" try: package_name = d["package"] except (KeyError): pass package = __import__("{}.{}".format(package_name, module_name), class_name) # print(package) module = getattr(package, module_name) # print(module) klass = getattr(module, class_name) # print(klass) device = klass(d) self.devices.append(device) except ImportError as e: Util.log(self, "error: '{}' config: '{}'".format(e, d)) def connect(self): self.client.connect() Util.log( self, "connect to MQTT server on {}:{} as {}".format( self.mqtt_server.server, self.mqtt_server.port, self.mqtt_server.username)) self.subscribe(self.exit_topic) for device in self.devices: device.connect(self) def subscribe(self, topic): self.client.subscribe(topic.encode()) def publish(self, topic, payload): Util.log(self, "sent: topic '{}' payload: '{}'".format(topic, payload)) # self.client.publish(topic.encode('utf-8'), payload) self.client.publish(topic.encode(), payload) def start(self): while True: try: self.connect() while True: #time.sleep(0.01) # attempt to reduce number of OSError: [Errno 104] ECONNRESET self.client.check_msg() #time.sleep(0.01) # attempt to reduce number of OSError: [Errno 104] ECONNRESET self.push() time.sleep(0.01) except OSError as e: Util.log(self, "failed to connect, retrying....", e) time.sleep(self.mqtt_server.wait_to_reconnect) except IndexError as e: Util.log(self, "failed to connect, retrying....", e) time.sleep(self.mqtt_server.wait_to_reconnect) self.client.disconnect() def push(self): if time.time() > self.last_ping + self.mqtt_server.keep_alive / 3: self.last_ping = time.time() self.client.ping() for device in self.devices: device.push() def do_message_callback(self, b_topic, payload): topic = b_topic.decode() #convert to string import gc, micropython gc.collect() gc.threshold(gc.mem_free() // 4 + gc.mem_alloc()) micropython.mem_info() Util.log(self, "received: topic '{}' payload: '{}'".format(topic, payload)) if topic == self.exit_topic: raise ExitGatewayException() for device in self.devices: if device.do_message(topic, payload): # Util.log(self,"consumed: topic '{}' payload: '{}' by device {}".format(topic,payload,json.dumps(device.config))) # break return
class Mqtt(ConfigOp, Consumer): def __init__(self, opc): ConfigOp.__init__(self, 'mqtt', CONFIG_NAME) Consumer.__init__(self) self.add_command(self.__get_info, GET) self.__client = None self.__pub_queue = queue.Queue(10) self.__connected = False self.__last_ping_tm = 0 self.__valid_config = False self.__with_auth = False self.__opc = opc self.__topic = set() self.__sub_cb = None self.add_command(self.__reconnect, SET, 'reconnect') async def consume(self, data): if ENCRYPTED_OUTPUT: st = Sec() self.publish(st.enc_paylaod(data)) else: self.publish(data) sleep(0) async def __get_info(self, _): v = self.get_info() await sleep(0) return result(200, None, v) def config_item(self, name, def_val = None): if self.__config is None or name not in self.__config: return def_val return self.__config[name] def get_info(self): return { ENABLED: self.config_item(ENABLED, False), 'connected': self.is_connected(), 'config_valid': self.__valid_config, 'with_auth': self.__with_auth, 'client-id': DEVICE_NAME, HOST: self.config_item(HOST), PORT: self.config_item(PORT, 1883), USER: self.config_item(USER), PASSWORD: self.config_item(PASSWORD), 'sensor-topic': self.config_item(TOPIC), 'command-topic': CMD_TOPIC } async def __reload_config(self): # NOSONAR delayed_task(5000, self.connect, (True, True)) return result(200, None, RECONNECT_MSG) async def __reconnect(self, _): delayed_task(5000, self.connect, (True)) return result(200, None, RECONNECT_MSG) def __check_config(self): if self.config_item(HOST) is None or self.config_item(TOPIC) is None: self.__valid_config = False self.__with_auth = False else: self.__valid_config = True self.__with_auth = (self.config_item(USER) is not None and self.config_item(PASSWORD) is not None) def is_connected(self): return self.__client is not None and self.__connected def connect(self, force = False, reload = False): try: return self.__connect(force, reload) except BaseException as e: log.warning("Mqtt connection exception: %r", e) return False def __connect(self, force = False, reload = False): if self.is_connected() and not force and not reload: return True self.disconnect() self.load(reload) self.__check_config() if self.__valid_config: if self.config_item(ENABLED, False): if self.__with_auth: self.__client = MQTTClient( DEVICE_NAME, self.config_item(HOST), self.config_item(PORT), self.config_item(USER), self.config_item(PASSWORD), 0, SSL) else: self.__client = MQTTClient( DEVICE_NAME, self.config_item(HOST), self.config_item(PORT), None, None, 0, SSL) else: log.info("MQTT disabled") return False else: log.error("Invalid mqtt config") return False self.__client.connect() self.__client.DEBUG = DEBUG self.__client.set_callback(self.__sub_callback) self.__client.subscribe(bytes(CMD_TOPIC, 'utf-8')) self.__connected = True log.debug("Mqtt broker connected") return True def disconnect(self): log.debug("Disconnect mqtt") self.__connected = False if self.__client is None: return try: self.__client.disconnect() except: #pylint: disable=bare-except pass self.__client = None def publish_op_log(self, p, c, ret): x = {'p': p, 'c': c, 'r': ret, 'tm': time_stamp()} if ENCRYPTED_OUTPUT: st = Sec() x = st.enc_paylaod(x) return self.publish(x, topic = OP_LOG_TOPIC) def __sub_callback(self, topic, pay): s = pay.decode("utf-8") log.info('Received %s: %s' , topic.decode("utf-8"), s) try: json = loads(s) if ENCRYPTED_INPUT: # 处理加密 st = Sec() json = st.dec_payload(json) create_task(self.__opc.op_request(json)) except BaseException as e: m = "Process message failed: %r" % e log.error(m) self.publish_op_log(None, None, result(500, m)) def publish(self, ret, retain = False, qos = 0, topic = None): t = None try: ret['i'] = DEVICE_NAME if topic is None: t = self.config_item(TOPIC) else: t = topic if t is None: log.debug("None topic, ignored") return log.debug("Add msg to pub queue: topic: %s, %r ", t, ret) l = {'t': bytes(t, 'utf-8'), 'm': bytes(dumps(ret), 'utf-8'), 'r': retain, 'q': qos} self.__pub_queue.put_nowait(l) except BaseException as e: log.error("Publish to topic %s failed: %r", t, e) def __next(self, o): if o is not None: return o try: try: return self.__pub_queue.get_nowait() except: #pylint: disable=bare-except return None except: #pylint: disable=bare-except return None async def __int_pub(self, o): '''从旧消息或队列里读取,如果qos大于0,且失败,返回未发送得消息''' while True: m = self.__next(o) if m is None: return None qos = 0 try: qos = m['q'] if self.is_connected(): log.debug("Publish msg %r", m) self.__client.publish(m['t'], m['m'], m['r']) self.__last_ping_tm = time() return None except BaseException as e: log.debug("Publish error: %r", e) self.__connected = False if qos > 0: return m return None def __keep_alive(self): if time() > self.__last_ping_tm + KEEP_ALIVE: try: if self.is_connected(): log.debug("Mqtt ping") self.__client.ping() self.__last_ping_tm = time() except: #pylint: disable=bare-except self.__connected = False def __int_sub(self): try: if self.is_connected(): log.debug("mqtt sub-check") self.__client.check_msg() self.__last_ping_tm = time() except: #pylint: disable=bare-except self.__connected = False async def __loop(self): old_msg = None log.debug("Start mqtt loop") while True: try: if self.is_connected(): old_msg = await self.__int_pub(old_msg) self.__int_sub() self.__keep_alive() else: while not self.is_connected(): self.connect() await sleep(RECONNECT_INTERVAL) except: #pylint: disable=bare-except self.__connected = False # 指示连接错误 await sleep(SLEEP_INTERVAL) def setup(self): self.connect() create_task(self.__loop())
last_publish = 0 last_ping = ticks_ms() print('Connected') print('Subscribing to topic %s...' % topic) client.subscribe(topic) print('Subscribed') else: # Periodically ping the broker consistently with the "keepalive" # argument used when connecting. If this isn't done, the broker will # disconnect when the client has been idle for 1.5x the keepalive # time. if ticks_ms() - last_ping >= keepalive * 1000: client.ping() last_ping = ticks_ms() # Every two minutes publish a message for fun. if ticks_ms() - last_publish >= 2 * 60 * 1000: message = b'ticks_ms() = %d' % ticks_ms() print('Publishing to topic %s message %s...' % (topic, message)) client.publish(topic, message) last_publish = ticks_ms() print('Published') # Receive the next message if one is available, and handle the case that # the broker has disconnected. try: client.check_msg() except OSError as e:
try: connectWifi(SSID, PASSWORD) server = SERVER c = MQTTClient(CLIENT_ID, server, 0, username, password) c.set_callback(sub_cb) c.connect() c.subscribe(TOPIC) c.subscribe(TOPIC_DOOR) key_of_door = str(random.randint(10000, 99999)) c.publish(TOPIC2, key_of_door, retain=True) c.publish(topic_check, check_sentence, retain=True) keepalive = Timer(2) keepalive.init(period=120000, mode=Timer.PERIODIC, callback=lambda t: c.ping()) #保持存活 print('Connected to %s, subscribed to %s topic' % (server, TOPIC)) while True: if check_p == 1: check_p = 0 key_of_door_r = str(random.randint(1, 99999)) m = 5 - len(key_of_door) key_of_door = '0' * m + key_of_door_r print(key_of_door) c.publish(TOPIC2, key_of_door, retain=True) elif state == 1: c.publish(TOPIC_R, "wrong password", retain=True) state = 0
class MqttClient: # User App of Hub SDK, subscribe and publish MQTT messages # http://www.hivemq.com/demos/websocket-client/ MQTT_HOST = "broker.mqttdashboard.com" MQTT_PORT = 1883 UNIQUE_ID = 'MC30AEA4CC1A40' DEFAULT_KEEPALIVE = const(60) KEEP_ALIVE_THRESHOLD = const(5) def __init__(self, callback=None): self.subscribeCallback = callback self.sn = self.UNIQUE_ID self.client = None self.topicSubOperation = "%s/operation" % ( self.sn) # same as: MC30AEA4CC1A40/operation self.topicPubUpdate = "%s/update" % ( self.sn) # same as: MC30AEA4CC1A40/update self.mqttLive = False log.info('MQTT init') def _clientInit(self): self.client = MQTTClient(client_id=self.sn, server=self.MQTT_HOST, port=self.MQTT_PORT, keepalive=DEFAULT_KEEPALIVE) def _clientConnect(self): log.debug('MQTT connecting...') try: self.client.connect() log.info('MQTT live!') self.mqttLive = True return True except Exception as e: log.exception(e, 'could not establish MQTT connection') return False def _subscribeTopic(self): try: self.client.set_callback(self._msgReceivedCallback ) # set a handler for incoming messages self.client.subscribe(topic=self.topicSubOperation, qos=0) log.info('subscribe [%s]', self.topicSubOperation) except Exception as e: log.exception(e, 'subscribe fail') def _resetPingTimer(self): self.pingCountdown = DEFAULT_KEEPALIVE def _ping(self): ''' do a MQTT ping before keepalive period expires ''' self.pingCountdown -= 1 if self.pingCountdown < KEEP_ALIVE_THRESHOLD: log.debug('mqtt ping...') self.client.ping() self._resetPingTimer() def _connectAttempt(self): if self._clientConnect(): self._subscribeTopic() self._resetPingTimer() return True else: return False def _msgReceivedCallback(self, topic, msg): if self.subscribeCallback is not None: self.subscribeCallback(topic, msg) def mqttIsLive(self): return self.mqttLive def publishMsg(self, msg): try: topic = self.topicPubUpdate log.info("publish: topic[%s] msg[%s]", topic, msg) self.client.publish(topic=topic, msg=msg, qos=0) except Exception as e: log.exception(e, 'publish fail') async def taskMqttWorker(self): reconnectAttemptBackoff = 1 # don't try too hard, use backoff self._connectAttempt() while True: try: self.client.check_msg( ) # if there is a message, _msgReceivedCallback will be called self._ping() reconnectAttemptBackoff = 1 await asyncio.sleep(1) except Exception as e: log.exception(e, 'MQTT check message problem') self.mqttLive = False if not self._connectAttempt(): reconnectAttemptBackoff *= 2 # don't retry too fast, this will abuse the server if reconnectAttemptBackoff > 64: reconnectAttemptBackoff = 64 log.debug('reconnect attempt backoff: %ds', reconnectAttemptBackoff) await asyncio.sleep(reconnectAttemptBackoff) def start(self): self._clientInit() asyncio.create_task(self.taskMqttWorker())
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 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()
class Controller(controller.ControllerProto): CONTROLLER_ID = 2 CONTROLLER_NAME = "Domoticz MQTT" def __init__(self, controllerindex): controller.ControllerProto.__init__(self, controllerindex) self.usesID = True self.onmsgcallbacksupported = True self.controllerport = 1883 self.inchannel = "domoticz/in" self.outchannel = "domoticz/out" # webformload? self._mqttclient = None self.lastreconnect = 0 self.usesAccount = True self.usesPassword = True self.usesMQTT = True self.authmode = 0 self.certfile = "" self.laststatus = -1 self.keepalive = 60 self._connected = False def controller_init(self, enablecontroller=None): if enablecontroller != None: self.enabled = enablecontroller self.connectinprogress = 0 try: ls = self.laststatus except: self.laststatus = -1 if self.controllerpassword == "*****": self.controllerpassword = "" self.initialized = True if self.enabled: try: if self._connected: pass except: self._connected = False try: if self._connected == False: misc.addLog(pglobals.LOG_LEVEL_DEBUG, "MQTT: Try to connect") self.connect() except: self._connected = False else: self.disconnect() return True def connect(self): if self.enabled and self.initialized: if self._connected: misc.addLog(pglobals.LOG_LEVEL_DEBUG, "Already connected force disconnect!") self.disconnect() self.connectinprogress = 1 self.lastreconnect = utime.time() try: am = self.authmode except: am = 0 cname = settings.Settings["Name"] + str(utime.time()) mna = self.controlleruser if mna.strip() == "": mna = None mpw = self.controllerpassword if mpw.strip() == "": mpw = None try: self._mqttclient = MQTTClient(cname, self.controllerip, port=int(self.controllerport), user=mna, password=mpw, keepalive=self.keepalive, ssl=(am != 0)) self._mqttclient.set_callback(self.on_message) self._mqttclient.connect() self._connected = self.isconnected() self._mqttclient.subscribe(self.outchannel.encode()) except Exception as e: misc.addLog( pglobals.LOG_LEVEL_ERROR, "MQTT controller: " + self.controllerip + ":" + str(self.controllerport) + " connection failed " + str(e)) self._connected = False self.laststatus = 0 else: self._connected = False self.laststatus = 0 return self._connected def disconnect(self): try: self._mqttclient.disconnect() except: pass self._connected = False self.laststatus = 0 try: commands.rulesProcessing("DomoMQTT#Disconnected", pglobals.RULE_SYSTEM) except: pass def isconnected(self, ForceCheck=True): res = -1 if self.enabled and self.initialized: if ForceCheck == False: return self._connected if self._mqttclient is not None: try: self._mqttclient.ping() res = 1 except: res = 0 if res != self.laststatus: if res == 0: commands.rulesProcessing("DomoMQTT#Disconnected", pglobals.RULE_SYSTEM) else: commands.rulesProcessing("DomoMQTT#Connected", pglobals.RULE_SYSTEM) self.laststatus = res if res == 1 and self.connectinprogress == 1: self.connectinprogress = 0 return res def webform_load(self): # create html page for settings ws.addFormTextBox("Controller Publish", "inchannel", self.inchannel, 255) ws.addFormTextBox("Controller Subscribe", "outchannel", self.outchannel, 255) try: kp = self.keepalive except: kp = 60 ws.addFormNumericBox("Keepalive time", "keepalive", kp, 2, 600) ws.addUnit("s") try: am = self.authmode fname = self.certfile except: am = 0 fname = "" options = ["MQTT", "MQTTS"] optionvalues = [0, 1] ws.addFormSelector("Mode", "c002_mode", len(optionvalues), options, optionvalues, None, int(am)) return True def webform_save(self, params): # process settings post reply pchange = False pval = self.inchannel self.inchannel = ws.arg("inchannel", params) if pval != self.inchannel: pchange = True pval = self.outchannel self.outchannel = ws.arg("outchannel", params) if pval != self.outchannel: pchange = True try: p1 = self.authmode self.authmode = int(ws.arg("c002_mode", params)) if p1 != self.authmode: pchange = True except: self.authmode = 0 pval = self.keepalive try: self.keepalive = int(ws.arg("keepalive", params)) except: self.keepalive = 60 if pval != self.keepalive: pchange = True if pchange and self.enabled: self.disconnect() utime.sleep(0.1) self.connect() return True def on_message(self, topic, msg): if self.enabled: msg2 = msg.decode('utf-8') mlist = [] if ('{' in msg2): try: mlist = ujson.loads(msg2) except Exception as e: misc.addLog(pglobals.LOG_LEVEL_ERROR, "JSON decode error:" + str(e) + str(msg2)) mlist = [] if (mlist) and (len(mlist) > 0): try: if mlist['Type'] == "Scene": # not interested in scenes.. return False except: pass devidx = -1 nvalue = "0" svalue = "" decodeerr = False tval = [-1, -1, -1, -1] try: devidx = str(mlist['idx']).strip() except: devidx = -1 decodeerr = True try: nvalue = str(mlist['nvalue']).strip() except: nvalue = "0" decodeerr = True try: svalue = str(mlist['svalue']).strip() except: svalue = "" if (';' in svalue): tval = svalue.split(';') tval2 = [] for x in range(1, 4): sval = "" try: sval = str(mlist['svalue' + str(x)]).strip() except: sval = "" if sval != "": tval2.append(sval) if len(tval2) == 1 and svalue == "": svalue = tval2[0] else: for y in range(len(tval2)): matches = misc.findall('[0-9]', tval2[y]) if len(matches) > 0: tval[y] = tval2[y] forcesval1 = False try: if ("Selector" in mlist['switchType']) or ( "Dimmer" in mlist['switchType']): forcesval1 = True except: forcesval1 = False if (tval[0] == -1) or (tval[0] == ""): if (float(nvalue) == 0 and svalue.lower() != "off" and svalue != "") or (forcesval1): tval[0] = str(svalue) else: tval[0] = str(nvalue) if decodeerr: misc.addLog(pglobals.LOG_LEVEL_ERROR, "JSON decode error: " + msg2) else: self._onmsgcallbackfunc(self.controllerindex, devidx, tval) def senddata(self, idx, taskobj, changedvalue=-1): if self.enabled: mStates = ["Off", "On"] # domomsg = '{{ "idx": {0}, "nvalue": {1:0.2f}, "svalue": "{2}" }}' domomsgw = '{{ "idx": {0}, "nvalue": {1:0.2f}, "svalue": "{2}", "RSSI": {3} }}' domomsgwb = '{{ "idx": {0}, "nvalue": {1:0.2f}, "svalue": "{2}", "RSSI": {3}, "Battery": {4} }}' domosmsgw = '{{"command": "switchlight", "idx": {0}, "switchcmd": "Set Level", "level":"{1}", "RSSI": {2} }}' domosmsgwb = '{{"command": "switchlight", "idx": {0}, "switchcmd": "Set Level", "level":"{1}", "RSSI": {2}, "Battery": {3} }}' if self._connected: try: usebattery = float(str(taskobj.battery).strip()) except Exception as e: usebattery = -1 if int(idx) > 0: if usebattery != -1 and usebattery != 255: bval = int(usebattery) else: bval = int(misc.get_battery_value()) msg = "" if (int(taskobj.vtype) == pglobals.SENSOR_TYPE_SWITCH): try: stateid = round(float(taskobj.uservar[0])) except: stateid = 0 if stateid < 0: stateid = 0 if stateid > 1: stateid = 1 msg = domomsgwb.format(str(idx), int(stateid), mStates[stateid], mapRSSItoDomoticz(taskobj.rssi), str(bval)) elif (int(taskobj.vtype) == pglobals.SENSOR_TYPE_DIMMER): msg = domosmsgwb.format( str(idx), str(taskobj.uservar[0]), mapRSSItoDomoticz(taskobj.rssi), str(bval)) else: msg = domomsgwb.format( str(idx), 0, formatDomoticzSensorType(taskobj.vtype, taskobj.uservar), mapRSSItoDomoticz(taskobj.rssi), str(bval)) try: self._mqttclient.publish(self.inchannel.encode(), msg.encode()) except: self._connected = False else: misc.addLog(pglobals.LOG_LEVEL_ERROR, "MQTT idx error, sending failed.") else: misc.addLog(pglobals.LOG_LEVEL_ERROR, "MQTT not connected, sending failed.") if ((utime.time() - self.lastreconnect) > 30): # if ((time.time()-self.lastreconnect)>30) and (self.connectinprogress==0): self.connect() def periodic_check(self): if self.enabled: try: if self._connected: self._mqttclient.check_msg() except: pass return self.onmsgcallbacksupported
co2 = None co2_show = None co2_show_accum = [] co2_show_accum_max_len = 4 climate = (0, 0, 0) ui = UI() while True: time_synced = utime.localtime()[0] >= 2020 if not wifi.status(): _ = wifi.connect() if not time_synced and wifi.status(): _ = wifi.ntp() if wifi.status(): try: mqtt.ping() except: mqtt.connect() if mhz19 is None: mhz19 = MHZ19(rx_pin=17, tx_pin=16) try: co2 = mhz19.gas_concentration() print('co2: %d' % co2) except Exception as err: print(err) mhz19.close() mhz19 = None continue try: mqtt.publish('%s/%s/co2_ppm' % (mqtt_prefix, nickname), str(co2))
payload_t["t"] = sum(payload_t["raw_t"]) / len(payload_t["raw_t"]) payload_h["h"] = sum(payload_h["raw_h"]) / len(payload_h["raw_h"]) except: pass c = MQTTClient(client, broker, port=broker_port) for _ in range(5): try: print("MQTT: CONNECTING ...") c.connect() print("MQTT: CONNECTION SUCCEEDED") break except: print("MQTT: CONNECTION FAILED") time.sleep(2) try: c.ping() c.publish(topic, json.dumps(payload_t)) c.publish(topic, json.dumps(payload_h)) print("MQTT: MESSAGE SENT") c.disconnect() except: print("MQTT: MESSAGE FAILED") print("SLEEP") rtc = machine.RTC() rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP) rtc.alarm(rtc.ALARM0, sleepfor * 1000) machine.deepsleep()
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()
zv1 = 9999 ztm1 = 0.0 while True: v1 = t1.read() print("adc0=",v1) if v1>999: # Touch value is over 1000 as 1000, not as 0. v1=1000 # Update for Your machine value. else: # v1=0 # if v1 != zv1: # value change ON or OFF only event pushing. msg = '{"d":{"value":' + str(v1) + ', "dummyD":1, "dummyC": "A"}}' c.publish(TOPIC, msg, 0, True) zv1 = v1 tm1 = time.time() #Ping per 1200sec. if (tm1-ztm1) > 1200.0: # ibmcloud mqtt time out is 3600sec. c.ping() # ztm1 = tm1 # time.sleep(0.1) #wait 100msec finally: #error or Ctrl+c if(c is not None): c.disconnect() wlan.disconnect() wlan.active(False) print("ended")
class Controller(controller.ControllerProto): CONTROLLER_ID = 14 CONTROLLER_NAME = "Generic MQTT" def __init__(self, controllerindex): controller.ControllerProto.__init__(self, controllerindex) self.usesID = False self.onmsgcallbacksupported = True self.controllerport = 1883 self.inchannel = "%sysname%/#/state" self.outchannel = "%sysname%/#/set" # webformload? self._mqttclient = None self.lastreconnect = 0 self.usesAccount = True self.usesPassword = True self.usesMQTT = True self.authmode = 0 self.certfile = "" self.laststatus = -1 self.keepalive = 60 self._connected = False self._inch = "" self._outch = "" def controller_init(self, enablecontroller=None): if enablecontroller != None: self.enabled = enablecontroller self.connectinprogress = 0 self._inch, state = commands.parseruleline( self.inchannel) # replace global variables self._outch, state = commands.parseruleline(self.outchannel) state = self._outch.find('#') if state > -1: self._outch = self._outch[:(state + 1)] else: state = self._outch.find('%tskname%') if state < 0: state = self._outch.find('%tskid%') if state > -1: self._outch = self._outch[:(state)] + "/#" else: state = self._outch.find('%valname%') if state > -1: self._outch = self._outch[:(state)] + "/#" self._outch = self._outch.replace('//', '/').strip() if self._outch == "" or self._outch == "/" or self._outch == "/#" or self._outch == "%/#": self._outch = "#" try: ls = self.laststatus except: self.laststatus = -1 if self.controllerpassword == "*****": self.controllerpassword = "" self.initialized = True if self.enabled: try: if self._connected: pass except: self._connected = False try: if self._connected == False: misc.addLog(pglobals.LOG_LEVEL_DEBUG, "MQTT: Try to connect") self.connect() except: self._connected = False else: self.disconnect() return True def connect(self): if self.enabled and self.initialized: if self._connected: misc.addLog(pglobals.LOG_LEVEL_DEBUG, "Already connected force disconnect!") self.disconnect() self.connectinprogress = 1 self.lastreconnect = utime.time() try: am = self.authmode except: am = 0 cname = settings.Settings["Name"] + str(utime.time()) mna = self.controlleruser if mna.strip() == "": mna = None mpw = self.controllerpassword if mpw.strip() == "": mpw = None try: self._mqttclient = MQTTClient(cname, self.controllerip, port=int(self.controllerport), user=mna, password=mpw, keepalive=self.keepalive, ssl=(am != 0)) self._mqttclient.set_callback(self.on_message) self._mqttclient.connect() self._connected = self.isconnected() self._mqttclient.subscribe(self._outch.encode()) # self.laststatus = 1 # commands.rulesProcessing("DomoMQTT#Connected",pglobals.RULE_SYSTEM) except Exception as e: misc.addLog( pglobals.LOG_LEVEL_ERROR, "MQTT controller: " + self.controllerip + ":" + str(self.controllerport) + " connection failed " + str(e)) self._connected = False self.laststatus = 0 else: self._connected = False self.laststatus = 0 return self._connected def disconnect(self): try: self._mqttclient.disconnect() except: pass self._connected = False self.laststatus = 0 try: commands.rulesProcessing("GenMQTT#Disconnected", pglobals.RULE_SYSTEM) except: pass def isconnected(self, ForceCheck=True): res = -1 if self.enabled and self.initialized: if ForceCheck == False: return self._connected if self._mqttclient is not None: try: self._mqttclient.ping() res = 1 except: res = 0 if res != self.laststatus: if res == 0: commands.rulesProcessing("GenMQTT#Disconnected", pglobals.RULE_SYSTEM) else: commands.rulesProcessing("GenMQTT#Connected", pglobals.RULE_SYSTEM) self.laststatus = res if res == 1 and self.connectinprogress == 1: self.connectinprogress = 0 return res def webform_load(self): # create html page for settings ws.addFormTextBox("Report topic", "inchannel", self.inchannel, 255) ws.addFormTextBox("Command topic", "outchannel", self.outchannel, 255) try: kp = self.keepalive except: kp = 60 ws.addFormNumericBox("Keepalive time", "keepalive", kp, 2, 600) ws.addUnit("s") try: am = self.authmode fname = self.certfile except: am = 0 fname = "" options = ["MQTT", "MQTTS"] optionvalues = [0, 1] ws.addFormSelector("Mode", "c014_mode", len(optionvalues), options, optionvalues, None, int(am)) return True def webform_save(self, params): # process settings post reply pchange = False pval = self.inchannel self.inchannel = ws.arg("inchannel", params) if pval != self.inchannel: pchange = True pval = self.outchannel self.outchannel = ws.arg("outchannel", params) if self.inchannel == self.outchannel: self.outchannel = self.outchannel + "/set" if pval != self.outchannel: pchange = True try: p1 = self.authmode self.authmode = int(ws.arg("c014_mode", params)) if p1 != self.authmode: pchange = True except: self.authmode = 0 pval = self.keepalive try: self.keepalive = int(ws.arg("keepalive", params)) except: self.keepalive = 60 if pval != self.keepalive: pchange = True if pchange and self.enabled: self.disconnect() utime.sleep(0.1) self.connect() return True def on_message(self, topic, msg): if self.enabled == False: return False success = False tstart = self._outch[:len(self._outch) - 1] try: topic2 = topic.decode('utf-8') except: topic2 = str(topic) if topic2.startswith(tstart) or self._outch == "#": try: msg2 = msg.decode('utf-8') except: msg2 = str(msg) if (topic2 == tstart + "cmd") and ( self._outch != "#"): # global command arrived, execute commands.doExecuteCommand(msg2, True) success = True else: try: # tend = msg.topic[len(self.outch)-1:] dnames = topic2.split("/") dnames2 = self.outchannel.split("/") except: dnames = [] if len(dnames) > 1: v1 = -1 v2 = -1 if self.outchannel.endswith( "/" + dnames[len(dnames) - 1] ): # set command arrived, forward it to the Task ttaskname = "" try: v1 = dnames2.index("#") v2 = v1 + 1 except: v1 = -1 if v1 == -1: try: v1 = dnames2.index("%tskname%") except: v1 = -1 try: v2 = dnames2.index("%valname%") except: v2 = -1 try: v3 = dnames2.index("%tskid%") except: v3 = -1 if v3 > -1: try: t = int(dnames[v3]) - 1 if settings.Tasks[t] and type( settings.Tasks[t]) is not bool: ttaskname = settings.Tasks[ t].gettaskname().strip() except: pass elif v1 == -1 and v2 > -1: try: for x in range(len(settings.Tasks)): if settings.Tasks[x] and type( settings.Tasks[x]) is not bool: for u in range(settings.Tasks[x]. valuecount): if settings.Tasks[ x].valuenames[ u] == dnames[v2]: ttaskname = settings.Tasks[ x].gettaskname().strip( ) break if ttaskname != "": break except: pass if ttaskname == "" and v1 > -1: ttaskname = dnames[v1] # print(v1,v2,ttaskname,dnames) #debug if ttaskname != "" and v2 > -1 and v2 < len(dnames): self._onmsgcallbackfunc( self.controllerindex, -1, msg2, taskname=ttaskname, valuename=dnames[v2] ) #-> Settings.callback_from_controllers() success = True def senddata(self, idx, taskobj, changedvalue=-1): if self.enabled: success = False if self.isconnected(False): tasknum = taskobj.taskindex if tasknum > -1: tname = taskobj.gettaskname() if changedvalue == -1: for u in range(taskobj.valuecount): vname = taskobj.valuenames[u] if vname != "": if ('%t' in self._inch) or ('%v' in self._inch): gtopic = self._inch.replace('#/', '') gtopic = gtopic.replace('#', '') gtopic = gtopic.replace('%tskname%', tname) gtopic = gtopic.replace( '%tskid%', str(tasknum + 1)) gtopic = gtopic.replace('%valname%', vname) else: gtopic = self._inch.replace( '#', tname + "/" + vname) gval = str(taskobj.uservar[u]) if gval == "": gval = "0" try: self._mqttclient.publish( gtopic.encode(), gval.encode()) except: self._connected = False else: vname = taskobj.valuenames[changedvalue - 1] if ('%t' in self._inch) or ('%v' in self._inch): gtopic = self._inch.replace('#/', '') gtopic = gtopic.replace('#', '') gtopic = gtopic.replace('%tskname%', tname) gtopic = gtopic.replace('%tskid%', str(tasknum + 1)) gtopic = gtopic.replace('%valname%', vname) else: gtopic = self._inch.replace( '#', tname + "/" + vname) if vname != "": gval = str(taskobj.uservar[changedvalue - 1]) if gval == "": gval = "0" try: self._mqttclient.publish( gtopic.encode(), gval.encode()) except: self._connected = False else: misc.addLog(pglobals.LOG_LEVEL_ERROR, "MQTT taskname error, sending failed.") else: misc.addLog(pglobals.LOG_LEVEL_ERROR, "MQTT not connected, sending failed.") if (utime.time() - self.lastreconnect) > 30: self.connect() def periodic_check(self): if self.enabled: try: if self._connected: self._mqttclient.check_msg() except: pass return self.onmsgcallbacksupported
class MQTTClientWrapper: def __init__(self, config): self.server = config.MQTT_SERVER self.port = config.MQTT_PORT self.mqtt_client = MQTTClient( client_id=config.MQTT_CLIENT_ID, server=self.server, port=self.port, user=config.MQTT_USER, password=config.MQTT_PASSWORD, keepalive=config.MQTT_KEEPALIVE, ssl=config.MQTT_SSL, ssl_params=config.MQTT_SSL_PARAMS, ) self.mqtt_client.set_callback(self._process_incoming_msgs) self.callbacks = {} self.connected = False self.max_retries = MQTT_MAX_RETRIES def connect(self): attempt = 1 while attempt <= self.max_retries: print('connecting to mosquitto server "{}:{}" (attempt {})...' .format(self.server, self.port, attempt), end='') try: res = self.mqtt_client.connect() if res == 0: print('done') break else: print('error {}'.format(res)) attempt += 1 except OSError: print('error') attempt += 1 else: self.connected = False raise MQTTConnectionError() self.connected = True def disconnect(self): self.mqtt_client.disconnect() def publish(self, topic, msg, qos=0, retain=False): print('publishing topic {}: {}...'.format(topic, msg), end='') self.mqtt_client.publish(topic, msg, qos, retain) print('done') def subscribe(self, topic, callback): self.callbacks[topic] = callback self.mqtt_client.subscribe(topic) def _process_incoming_msgs(self, topic, msg): topic = topic.decode() msg = msg.decode() callback = self.callbacks.get(topic) if callback is not None: callback(topic, msg) def wait_msg(self): return self.mqtt_client.wait_msg() def check_msg(self): return self.mqtt_client.check_msg() def ping(self): return self.mqtt_client.ping()
class AwsClient: def __init__(self, configurator: SprinklerConfiguration, zone_scheduler: ZoneScheduler): self.configurator = configurator self.zone_scheduler = zone_scheduler self.client_id = None self.client = None self.connected = False self.reconnect_scheduler = WorkScheduler() self.reconnect_scheduler.schedule_work() def setup(self): try: config = get_config() self.client_id = config["client_id"] server = config["server"] del config["client_id"] del config["server"] self.client = MQTTClient(self.client_id, server, **config) self.client.set_callback( lambda t, m: self.sub_cb(t.decode('utf-8'), m.decode('utf-8'))) except Exception as e: sys.print_exception(e) def get_stop_zones_topic(self): return 'sprinkler/{}/zones/stop'.format(self.client_id) def get_queue_zones_topic(self): return 'sprinkler/{}/zones/queue'.format(self.client_id) def get_status_requested_topic(self): return 'sprinkler/{}/status/request'.format(self.client_id) def get_report_status_topic(self): return 'sprinkler/{}/status/report'.format(self.client_id) def get_desired_config_received_topic(self): return 'sprinkler/{}/config/desired'.format(self.client_id) def get_report_config_topic(self): return '$aws/things/{}/shadow/update'.format(self.client_id) def sub_cb(self, topic, message): try: print('MQTT Message: {}'.format((topic, message))) if topic == self.get_stop_zones_topic(): zones = json.loads(message) if len(message) > 0 else [] self.zone_scheduler.stop_zones(zones) self.report_status() if topic == self.get_queue_zones_topic(): duration_by_zone = json.loads(message) self.zone_scheduler.queue_zones(duration_by_zone) self.report_status() if topic == self.get_desired_config_received_topic(): shadow = json.loads(message) self.configurator.save_config(shadow) self.report_config() if topic == self.get_status_requested_topic(): self.report_status() except Exception as e: sys.print_exception(e) def publish(self, topic, message): self.client.publish(bytes(topic, 'UTF-8'), bytes(message, 'UTF-8')) def subscribe(self, topic): self.client.subscribe(bytes(topic, 'UTF-8')) def report_config(self): raw_config = self.configurator.read_config() self.publish(self.get_report_config_topic(), json.dumps({"state": { "reported": raw_config }})) def report_status(self): queue = self.zone_scheduler.queue now = utime.time() self.publish( self.get_report_status_topic(), json.dumps({ 'active': [(i[0], i[1] - now) for i in queue.active], 'pending': queue.pending, })) def check_connection(self): try: if not self.client: return if not wifiConnect.getStatus()['active']: self.connected = False return if self.client.sock is not None: try: self.client.ping() self.client.ping() except Exception: self.connected = False if not self.connected: print('aws: connecting') self.client.connect() print('aws: subscribing') self.subscribe(self.get_stop_zones_topic()) self.subscribe(self.get_queue_zones_topic()) self.subscribe(self.get_status_requested_topic()) self.subscribe(self.get_desired_config_received_topic()) print('aws: subscribed') self.report_config() self.report_status() self.connected = True except Exception as e: self.connected = False try: self.client.disconnect() except Exception: pass sys.print_exception(e) def do_tasks(self): if self.reconnect_scheduler.work_pending(10000): self.check_connection() if self.connected: self.client.check_msg()