如何通过mqtt实现一个"mailbox"服务?
How to implement a "mailbox" service through mqtt?
我是所有 mqtt 的新手,作为第一个练习,我想通过持久的 mqtt 会话创建一个“邮箱”服务。奖励是一个低功耗 ESP8266 设备,它大部分时间都处于睡眠状态,并定期唤醒并检查是否有任何待处理的命令。
我尝试通过我的 Linux 主机上的发送者和接收者使用 python 和 paho mqtt 来实现这一点。 Mosquitto 作为经纪人在后台 运行。
这里首先是“mbox”发件人,每次按下 Enter 时它都会发送另一条消息。
import paho.mqtt.client as mqtt
broker_address='127.0.0.1'
client = mqtt.Client('MBoxClient')
client.connect(broker_address)
counter = 1
while True:
print('Press Enter to send msg #'+str(counter)+': ', end='')
if input().startswith('q'):
break
client.publish("mbox/mail","Hello "+str(counter), qos=1)
counter += 1
client.disconnect()
print('done!')
这是我的 mbox 接收器:
import paho.mqtt.client as mqtt
import time
def on_message(client, userdata, message):
print("message:", message.topic + ': ' + str(message.payload.decode("utf-8")))
print('I\'m listening for mbox messages!')
broker_address="127.0.0.1"
client_name='mbox'
is_first=True
while 1:
client = mqtt.Client(client_name, clean_session=is_first)
is_first=False
print("polling")
client.on_message=on_message
client.connect(broker_address)
client.subscribe('mbox/#',qos=1)
client.loop_start()
time.sleep(0.1) # How long should this time be?
client.loop_stop()
# client.loop(0.1) # why doesn't this do the same action as the previous three lines?
client.disconnect()
time.sleep(5)
尽管这可行,但我觉得我的解决方案非常老套。 client.loop_start()
和 client.loop_stop()
创建另一个线程。但是当我尝试做 client.loop(0.1)
而不是它时。
所以我的问题是:
- 是否有直接轮询消息的方法,而不是使用
loop_start();…;loop_stop()
的间接方法?
- 如果使用
loop_start();time.sleep(t);loop_end()
是惯用的,我怎么知道要睡多久?
- 为什么我做
loop(0.1); instead of
loop_start()时接收器不工作;睡眠(0.1); loop_stop()`?有什么区别?
- 接收方是否保证收到所有消息?
- 有没有更好的方法来实现这个模式?
问题按顺序回答。
- 不,轮询完全违背了像 MQTT
这样的 pub/sub 协议的意义
- 你真的应该在循环中调用
client.loop()
,它默认只在提供的超时期限内处理 1 个数据包。 QOS1需要多个数据包才能完成投递。
- 调用
client.loop(0.1)
将阻塞 0.1 秒等待传入消息,然后 return。如果消息在 0.1 秒后到达,它将位于 OS TCP/IP 堆栈中,直到您再次调用 client.loop()
。如果您没有定期调用它,那么代理将启动客户端,因为 KeepAlive 测试将失败。客户端循环还处理发送所有订阅消息。
- 假设消息在 QOS > 0 发布并且您在 QOS > 0 订阅并且客户端 ID 保持不变并且干净的会话为 false 经纪人应该交付并且订阅者离线时发布的消息
- 如前所述,您需要为每条消息多次调用
client.loop()
,因为每个唤醒周期您只调用一次。启动后台线程将在您设置的时间长度内处理所有必需的消息 运行 for.
我是所有 mqtt 的新手,作为第一个练习,我想通过持久的 mqtt 会话创建一个“邮箱”服务。奖励是一个低功耗 ESP8266 设备,它大部分时间都处于睡眠状态,并定期唤醒并检查是否有任何待处理的命令。
我尝试通过我的 Linux 主机上的发送者和接收者使用 python 和 paho mqtt 来实现这一点。 Mosquitto 作为经纪人在后台 运行。
这里首先是“mbox”发件人,每次按下 Enter 时它都会发送另一条消息。
import paho.mqtt.client as mqtt
broker_address='127.0.0.1'
client = mqtt.Client('MBoxClient')
client.connect(broker_address)
counter = 1
while True:
print('Press Enter to send msg #'+str(counter)+': ', end='')
if input().startswith('q'):
break
client.publish("mbox/mail","Hello "+str(counter), qos=1)
counter += 1
client.disconnect()
print('done!')
这是我的 mbox 接收器:
import paho.mqtt.client as mqtt
import time
def on_message(client, userdata, message):
print("message:", message.topic + ': ' + str(message.payload.decode("utf-8")))
print('I\'m listening for mbox messages!')
broker_address="127.0.0.1"
client_name='mbox'
is_first=True
while 1:
client = mqtt.Client(client_name, clean_session=is_first)
is_first=False
print("polling")
client.on_message=on_message
client.connect(broker_address)
client.subscribe('mbox/#',qos=1)
client.loop_start()
time.sleep(0.1) # How long should this time be?
client.loop_stop()
# client.loop(0.1) # why doesn't this do the same action as the previous three lines?
client.disconnect()
time.sleep(5)
尽管这可行,但我觉得我的解决方案非常老套。 client.loop_start()
和 client.loop_stop()
创建另一个线程。但是当我尝试做 client.loop(0.1)
而不是它时。
所以我的问题是:
- 是否有直接轮询消息的方法,而不是使用
loop_start();…;loop_stop()
的间接方法? - 如果使用
loop_start();time.sleep(t);loop_end()
是惯用的,我怎么知道要睡多久? - 为什么我做
loop(0.1); instead of
loop_start()时接收器不工作;睡眠(0.1); loop_stop()`?有什么区别? - 接收方是否保证收到所有消息?
- 有没有更好的方法来实现这个模式?
问题按顺序回答。
- 不,轮询完全违背了像 MQTT 这样的 pub/sub 协议的意义
- 你真的应该在循环中调用
client.loop()
,它默认只在提供的超时期限内处理 1 个数据包。 QOS1需要多个数据包才能完成投递。 - 调用
client.loop(0.1)
将阻塞 0.1 秒等待传入消息,然后 return。如果消息在 0.1 秒后到达,它将位于 OS TCP/IP 堆栈中,直到您再次调用client.loop()
。如果您没有定期调用它,那么代理将启动客户端,因为 KeepAlive 测试将失败。客户端循环还处理发送所有订阅消息。 - 假设消息在 QOS > 0 发布并且您在 QOS > 0 订阅并且客户端 ID 保持不变并且干净的会话为 false 经纪人应该交付并且订阅者离线时发布的消息
- 如前所述,您需要为每条消息多次调用
client.loop()
,因为每个唤醒周期您只调用一次。启动后台线程将在您设置的时间长度内处理所有必需的消息 运行 for.