我目前正在使用运行 Ubuntu 18.04 的 NVIDIA Jetson 开发 MQTT 项目。我已安装 mosquitto(版本 2.0.15)作为我的 MQTT 代理,并为我的 Python MQTT 客户端安装 paho-mqtt(版本 1.6.1)。
我遇到一个问题,在尝试向 MQTT 代理发布消息时,我始终收到“mid”(消息标识符)代码为 1 的“协议版本无效”错误。我已经仔细检查了我的代码和配置,并且我相信我在 Python MQTT 客户端中指定了正确的协议版本 (MQTTv5),因为 mosquitto v2.0.15 支持 MQTTv5 和 MQTTv3.1。
代理服务器和发布客户端在同一设备/网络上运行。
MQTT 代理确实正在运行:
gabe@gabe-desktop:~$ systemctl status mosquitto
mosquitto.service - Mosquitto MQTT Broker
Loaded: loaded (/lib/systemd/system/mosquitto.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2024-01-06 19:10:01 CET; 1h 35min ago
Docs: man:mosquitto.conf(5)
man:mosquitto(8)
Main PID: 22604 (mosquitto)
Tasks: 1 (limit: 4180)
CGroup: /system.slice/mosquitto.service
└─22604 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
Jan 06 19:10:01 gabe-desktop systemd[1]: Starting Mosquitto MQTT Broker...
Jan 06 19:10:01 gabe-desktop systemd[1]: Started Mosquitto MQTT Broker.
并且端口 1883 正在侦听地址:
localhost:1883
和 ip6-localhost:1883
。
gabe@gabe-desktop:~$ netstat -at
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:sunrpc 0.0.0.0:* LISTEN
tcp 0 0 localhost:domain 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN
tcp 0 0 localhost:1883 0.0.0.0:* LISTEN
tcp 0 0 localhost:40283 0.0.0.0:* LISTEN
tcp 0 0 localhost:42269 0.0.0.0:* LISTEN
tcp 0 0 localhost:34941 0.0.0.0:* LISTEN
tcp 0 0 localhost:40451 0.0.0.0:* LISTEN
tcp 0 0 localhost:gpsd 0.0.0.0:* LISTEN
tcp 0 0 localhost:40283 localhost:47786 ESTABLISHED
tcp 0 0 gabe-desktop:35130 13.107.5.93:https ESTABLISHED
tcp 0 108 gabe-desktop:ssh Gabes-MBP:53006 ESTABLISHED
tcp 0 0 gabe-desktop:35140 13.107.5.93:https ESTABLISHED
tcp 0 0 localhost:40283 localhost:47788 ESTABLISHED
tcp 0 0 localhost:47786 localhost:40283 ESTABLISHED
tcp 0 0 localhost:47788 localhost:40283 ESTABLISHED
tcp 0 0 localhost:40283 localhost:47272 CLOSE_WAIT
tcp6 0 0 [::]:sunrpc [::]:* LISTEN
tcp6 0 0 [::]:ssh [::]:* LISTEN
tcp6 0 0 ip6-localhost:1883 [::]:* LISTEN
tcp6 0 0 ip6-localhost:gpsd [::]:* LISTEN
以下是尝试创建发布连接时的 Python 代码和错误:
import paho.mqtt.client as mqtt
# MQTT broker information
BROKER_ADDRESS = "localhost"
PORT = 1883
TOPIC = "testing"
RESPONSE = {
0: "connection succeeded",
1: "connection failed - incorrect protocol version",
2: "connection failed - invalid client identifier",
3: "connection failed - the broker is not available",
4: "connection failed - wrong username or password",
5: "connection failed - unauthorized"
}
def on_publish(client, data, mid):
print(f"Connected to broker with status: {mid}: {RESPONSE.get(mid, 'Unknown')}")
def main():
client = mqtt.Client(client_id="jetson", protocol=mqtt.MQTTv5)
# Set the callback function for when the publisher connects to the broker
client.on_publish = on_publish
# Connect to the broker
client.connect(BROKER_ADDRESS, PORT)
# Publish a message to the "testing" topic
message = "Hello, world!"
client.publish(TOPIC, message)
# Keep client running "forever"
client.loop_forever()
if __name__ == '__main__':
main()
Connected to broker with status: 1: connection failed - incorrect protocol version
我也尝试了协议版本
mqtt.MQTTv31
并收到了相同的错误。
所有在线资源都必须确保正确配置 mosquitto 配置文件。不过,我仔细检查过,情况似乎确实如此。
为了确保 MQTT 代理服务器确实正确运行,我在两个单独的终端中执行了以下测试
1号航站楼:
gabe@gabe-desktop:~$ mosquitto_sub -h localhost -t test
2号航站楼:
gabe@gabe-desktop:~$ mosquitto_pub -h localhost -t test -m "hello world"
我在终端 1 中得到“hello world”输出。
def on_publish(client, data, mid):
print(f"Connected to broker with status: {mid}: {RESPONSE.get(mid, 'Unknown')}")
on_publish
是“当要使用
publish() 调用已完成向代理的传输。”并且已通过:
client:此回调的客户端实例
userdata:在Client()或userdata_set()中设置的私有用户数据
mid:匹配从相应的publish()调用返回的mid变量,以允许跟踪传出消息。
您似乎假设
mid
指示连接是否成功(根据上面复制的文档;事实并非如此)。 .
所以发生的事情(好吧,当我测试你的代码时会发生什么)是你成功连接到代理,然后成功发布消息。然而,一旦消息被传输,您的
on_publish
就会被调用(这会错误地打印错误消息)。
我认为你的意图是这样的:
def on_connect(client, userdata, flags, reasonCode, properties):
print(f"Connected to broker with status: {reasonCode}")
def on_publish(client, data, mid):
print(f"Publish completed: {mid}")
def main():
client = mqtt.Client(client_id="jetson", protocol=mqtt.MQTTv5)
# Set the callback function for when the publisher connects to the broker
client.on_connect = on_connect
client.on_publish = on_publish
...