4

我正在使用 Mosquitto 和 Paho 的 Python 实现来尝试交流几个程序。当我使用最后一个意志功能时,我遇到了一些麻烦。我的代码是这样的:

订阅者:

import paho.mqtt.client as mqtt
def on_message(client, userdata, msg):
    print 'Received: ' + msg.payload

client = mqtt.Client()
client.on_message = on_message

client.connect('localhost', 1883)
client.subscribe('hello/#')

client.loop_forever()

出版商:

import paho.mqtt.client as mqtt

client = mqtt.Client()

client.will_set('hello/will', 'Last will', 0, False)
client.connect('localhost', 1883)

client.publish('hello/world', 'Regular msg', 0, False)
client.disconnect()

输出:

Received: Last will

我应该只收到常规消息,因为我client.disconnect()用来关闭连接。如果我评论该will_set行,我会收到常规消息。我也尝试在同一主题上发布两者,但它不起作用。

4

3 回答 3

11

如何设置 MQTT last 将正确发送消息

最后遗嘱和遗嘱功能需要遵循一些规则。

client.will_set连接前先打电话

打电话给will_set之前client.connect

client = mqtt.Client()
client.will_set("stack/clientstatus", "LOST_CONNECTION", 0, False)
client.connect(host, port, timeout)

连接后调用will_set对我不起作用。

只有最后一个client.will_set计数

可以尝试will_set多次使用,但只有最后一个有效,之前的将被忽略。

client.disconnect完成

client.disconnect实际上是向代理发送“DISCONNECT”消息的请求。

由于消息是异步发送的,因此您的程序可能会更快结束,然后“DISCONNECT”消息就完成了。

client.loop_*()之后使用client.disconnect 这将允许客户端完成发送“DISCONNECT”消息的过程。

以下组合对我有用:

  • loop_start()->loop_stop()
  • loop_start()-> loop_forever()(发送 DISCONNECT 消息后完成)

我没有尝试其他组合。

从这些选项中,第一个对我来说似乎更好(与 保持loop_start配对loop_stop)。第二个选项可能完全是错误的。

我的工作代码:

import paho.mqtt.client as mqtt

host = "test.mosquitto.org"
port = 1883
timeout = 10

client = mqtt.Client()
client.will_set("stack/clientstatus", "LOST_CONNECTION", 0, False)
client.connect(host, port, timeout)

client.publish("stack/clientstatus", "ON-LINE")

client.loop_start()
for msg in ["msg1", "msg2", "msg3"]:
    client.publish("stack/message", msg)
    print msg

client.publish("stack/clientstatus", "OFF-LINE")
client.disconnect()
client.loop_stop()  # waits, until DISCONNECT message is sent out
print "Now I am done."

不可靠的方法 ( sleep, 添加on_disconnect)

添加time.sleep可能会有所帮助,但在其他情况下(不可靠的连接)可能会失败。

在我的情况下,添加client.on_disconnect = on_disconnect似乎没有帮助,这个回调是异步处理的,不会阻塞client.disconnect调用。

于 2016-01-10T18:59:13.253 回答
3

disconnect()必须向经纪人发送DISCONNECT命令,这就是经纪人知道不发送遗嘱的方式。如果您只是打电话disconnect(),则不能保证这已经发生。您需要调用loop*()以处理传出的网络流量。您可以通过检查on_disconnect()正在调用的回调来确定已发送 DISCONNECT 消息。您也可以调用loop_forever()after disconnect()which 将工作相同。

import paho.mqtt.client as mqtt

client = mqtt.Client()

client.will_set('hello/will', 'Last will', 0, False)
client.connect('localhost', 1883)

client.publish('hello/world', 'Regular msg', 0, False)
client.disconnect()
client.loop_forever()

或者paho.mqtt.publish.single()按照@hardillb 的建议使用。

于 2015-02-20T16:57:55.007 回答
2

您可以尝试使用单一方法仅发布一条消息,如下所示:

import paho.mqtt.publish as publish

publish.single('hello/world', 'Regular msg', 0, False, 'localhost' , 1883, 'publisher', 10, {'topic': 'hello/will', 'payload': 'Will msg', 'qos': 0, 'retain': False})

https://pypi.python.org/pypi/paho-mqtt#single

我猜问题是您在发布实际完成之前断开连接,这可能是您看到遗嘱消息的原因。

编辑 - 当我使用 mosquitto_sub -v -t 'hello/#' 运行您的代码时,我看到了正常消息和正在传递的遗嘱。

编辑2 -

这对我来说很好:

import paho.mqtt.client as mqtt

client = mqtt.Client()

client.will_set('hello/will', 'Last will', 0, False)
client.connect('localhost', 1883)

client.publish('hello/world', 'Regular msg', 0, False)
client.loop();
client.disconnect()
client.loop();
于 2015-02-19T22:21:20.917 回答