
上周在创客交流群蹲了一晚上,见着三个刚玩物联网的朋友卡在用Python读ESP32上传的MQTT数据上,报错都不带重样的,把问得最多的几个问题整理出来,省得大家挨个搜旧教程踩坑。
大家问得最集中的三个问题是:
- 明明用MQTT.fx客户端能正常连上MQTT服务器,换成Python脚本就一直报连接超时
- 脚本打印了连接成功,但等很久都收不到ESP32发上来的消息
- 偶尔能蹦出来一两条消息,但是内容全是乱码,根本读不出来传感器数值
脚本连不上服务器的排查步骤
说白了这个问题八成是paho-mqtt版本闹的,现在直接pip安装默认拉的是2.x版本,和网上1.x版本的老教程写法不兼容,剩下两成是端口填错、开了系统代理截了流量。排查按这个顺序走就行:
- 先在终端跑命令确认安装的版本:
如果版本在2.0.0以上,初始化客户端的时候必须显式指定回调API版本,不然连接逻辑会出莫名问题,正确初始化写法:pip show paho-mqttimport paho.mqtt.client as mqtt # 2.x版本必填VERSION2参数,缺省容易出现连接异常 client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="py_test_client_001") # 注意端口别混,TCP默认1883,WebSocket端口一般是8083 client.connect("你的MQTT服务器地址", 1883, keepalive=60) - 跑脚本的时候暂时关一下系统全局代理,不少代理规则默认会拦截1883端口的TCP流量,表现就是第三方客户端能连,Python脚本连不上。
连接成功但收不到消息怎么查
这个问题我自己刚接触的时候也卡过,大部分时候是订阅代码写的位置不对,或者主题名匹配不上。
- 别把订阅主题的代码写在connect()方法后面,一定要放在on_connect连接成功的回调函数里,这样断线重连之后也会自动重新订阅,不会出现刚连上还没来得及订阅就错过消息的情况,参考写法:
def on_connect(client, userdata, flags, reason_code, properties): print(f"连接返回码:{reason_code}") # 连接成功第一时间订阅主题 client.subscribe("esp32/sensor/data") def on_message(client, userdata, msg): print(f"收到{msg.topic}的消息") client.on_connect = on_connect client.on_message = on_message # 启动后台监听循环 client.loop_start() - 先做个对照测试:用MQTT.fx往"test/debug"主题发个简单字符串,Python脚本也订阅这个主题,如果能收到,就逐字符核对ESP32端写的主题名,大小写、斜杠、无意中多打的空格都会导致匹配不上,别嫌麻烦。
收到乱码的处理方法
这个基本都是编码没对上的问题,别一上来就硬转字符串。
- 先在on_message回调里打印msg.payload的原始字节内容,看看是不是有多余的BOM头,或者根本不是UTF-8编码的文本,正常文本转码的时候加个错误忽略参数就行:
payload_text = msg.payload.decode('utf-8', errors='ignore') - 如果ESP32端发的是二进制格式的传感器原始值,就别硬转字符串,用struct模块对应字节长度解析成数值就行。
小提示:要是用的是公共免费MQTT服务器,自己的主题前面最好加个唯一标识,比如你的昵称缩写,不然很容易收到其他陌生人发的无关消息,调试的时候能少走不少弯路。
反正我当初因为主题名多写了一个末尾的斜杠,硬生生卡了快一节课的时间,说出来也不丢啥人。
评论一下?