【问题标题】:python paho-mqtt loops & persistan connection to brokerpython paho-mqtt 循环和持久连接到代理
【发布时间】:2017-03-16 15:23:05
【问题描述】:

我已经编写了一些python3代码来依次执行以下操作;

  1. 检查网络是否正常
  2. 如果互联网连接到 MQTT 代理
  3. 每 30 分钟向 pub_topic 发布消息
  4. 然后循环到第一步并重复

另外,我希望 MQTT 连接是持久的,以便可以接收传入的消息。

实际情况是,经过几次迭代后,MQTT 连接断开,最终程序崩溃。

下面是我的while循环代码sn-p;

while True:
        try:
                if not internet_up():
                        time.sleep(20)

                client = mqtt.Client()
                client.on_connect = on_connect
                client.on_message = on_message
                client.connect(broker, 1883, 60)
                client.loop_start()


                if internet_up():
                        print(read_temp())
                        client.publish(pub_topic, read_temp())
                        time.sleep(60*30)


        except Exception as err:
                logging.info(err)
                pass

A.这里有明显的错误吗?

B.我觉得这不是最佳的,如何才能使这更有效、pyhonic 或纠正?

C.另外,loop_start()loop_forever() 之间有什么区别?我已经阅读了文档,但对我来说并不明显。

【问题讨论】:

  • loop_start 启动后台线程运行事件循环,loop_forever 阻止在当前线程上运行事件循环
  • 狡猾的逻辑:如果在 time.sleep(60*30) 期间互联网中断了足够长的时间以中断代理连接,但在 30 分钟结束之前又恢复了 - 那么你的代码会看到'伟大的互联网此时已启动,所以过去 30 分钟肯定没问题',并假设连接仍然存在,并在代理连接不存在时尝试发布读数。最好连接到 on_disconnect() 并使用它来打破“每 30 分钟发布一次”循环。或者可能总是在 client.publish() 工作之前执行 client.reconnect(),不确定
  • @barny 感谢您的评论。我绝不是这里的专家,您可以添加您提到的 on_connect() 和 client.reconnect() 代码吗?我假设 loop_start() 和 client.connect() 的组合会保持与代理的 MQTT 连接,但似乎没有。 Paho 文档并不完全友好。
  • @hardillb 感谢您的评论。你能解释一下事件循环吗?我觉得文档很难理解。
  • loop_start() 意味着您的客户端将尝试通过发送后台保持唤醒消息来保持连接处于活动状态,并检查它们是否从代理接收,但如果它不会恢复连接坏了,这取决于您的客户端代码。如果您提供 on_disconnect 函数,它将被调用,我想您需要提供代码以至少设置一个标志以记录客户端已断开连接,以便您的 30 分钟睡眠循环知道它必须返回连接步骤.

标签: python-3.x raspberry-pi mqtt paho


【解决方案1】:

根据 barny 的评论,我怀疑这里的问题是您重复调用 client.loop_start() 而没有调用 client.loop_stop() 或 client.disconnect()。

为了对此进行测试,我使用 mosquitto 测试服务器编写了一个测试脚本:

from time import sleep

import paho.mqtt.client as mqtt


def on_connect(client, userdata, flags, rc):
   client.subscribe('$SYS/broker/load/messages/received/1min')


def messages_received(client, userdata, message):
   print(message.payload)


while True:
   client = mqtt.Client()
   client.loop_start()
   client.message_callback_add('$SYS/broker/load/messages/received/1min', messages_received)
   client.on_connect = on_connect
   client.connect("test.mosquitto.org", 1883, 60)
   sleep(13)

此脚本在几分钟内失败。但是,如果我将最后一部分更改为包含 client.loop_stop() 和 client.disconnect() ,如下所示:

while True:
  client = mqtt.Client()
  client.loop_start()
  client.message_callback_add('$SYS/broker/load/messages/received/1min', messages_received)
  client.on_connect = on_connect
  client.connect("test.mosquitto.org", 1883, 60)
  sleep(3)
  client.disconnect()
  client.loop_stop()
  sleep(10)

它无限期地运行。我是 python 和 paho 的新手,所以这里可能还有另一个问题......我只用 test.mosquitto.org 测试了这个,所以可能存在特定于代理的问题......但是为了让你现有的代码工作我会至少尝试在循环中添加 client.loop_stop 。

但是,由于您希望连接是持久的,您可能需要考虑使用 client.loop_forever() 并将您的 while 循环放入 on_connect 回调或类似的东西中。

希望对您有所帮助!

【讨论】:

  • 在连接之前调用循环开始,有一些已知和记录的问题,如客户端的 github 问题列表中所述。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-19
  • 1970-01-01
  • 2023-03-22
  • 2020-01-18
  • 2017-07-16
相关资源
最近更新 更多