示例#1
0
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()
示例#2
0
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()
示例#3
0
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()
示例#4
0
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()
示例#5
0
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()
示例#6
0
class FanController:
    def __init__(self):
        self.t_start = time.ticks_ms()

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.boot_time = utime.localtime()

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

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

        self.startMQTTclient()
        utime.sleep(1)

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

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

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

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

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

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

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

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

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

            except OSError:
                fails_counter += 1

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

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

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

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

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

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

    def ping_broker(self, keep_time):
        # for keepalive purposes
        if utime.ticks_ms() > self.last_ping_time + keep_time * 1000:
            try:
                self.mqtt_client.ping()
                self.last_ping_time = utime.ticks_ms()
            except OSError:
                # fail
                pass
示例#8
0
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
示例#9
0
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())
示例#10
0
        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:
示例#11
0
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
示例#12
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())
示例#13
0
class Sensor:
    def __init__(self, name, server, port, keyfile, certfile, root_topic):

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

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

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

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

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

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

        self.publish_status(b'online')

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

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

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

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

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

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

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

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

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

            if self.on_repl_disabled:
                if prev and not self.repl:
                    self.on_repl_disabled()
示例#14
0
class MQTTService(object):
    def __init__(self, sub_cb=None):
        self.__client = None
        self.__sub_cb = sub_cb
        self.__heartbeat_timer = Timer(0)
        self.__heartbeat_counter = 0

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

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

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

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

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

        gc.collect()

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

        self.__client = None
        self.__heartbeat_timer = None

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

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

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

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

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

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

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

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

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

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

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

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

    def check_msg(self):
        self.__client.check_msg()
示例#15
0
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))
示例#17
0
文件: main.py 项目: PinkInk/upylib
    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")
  
示例#20
0
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
示例#21
0
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()
示例#22
0
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()