You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python paho-mqtt交替连接断开循环仅执行一次问题排查

问题根因

代码仅能运行单轮的核心问题如下:

  • 循环结构错误:两个while块为顺序执行关系,第一个MQTT连接循环跑完一次、将latch置为1后就会永久退出,后续计算逻辑把latch改回0后,没有逻辑能跳转回第一个循环,程序直接终止。
  • 回调注册顺序错误:先启动client.loop_start()网络线程,之后才绑定on_connect、on_message回调,存在事件触发时回调未注册的概率,导致订阅失败、消息丢失。
  • 接收逻辑不可靠:固定休眠5秒就断开连接,没有校验三个主题的消息是否全部接收完成,一旦某个节点上报延迟,三边计算会直接触发未定义变量错误。
  • 重连逻辑有缺陷:每次循环新建客户端且使用固定Client ID,前一个连接未被broker及时清理时,新连接会被服务端强制踢下线。
修正实现

将MQTT连接、消息接收、业务计算合并到同一个主循环中,增加消息收齐判断,调整回调注册顺序,修正后代码如下:

import paho.mqtt.client as mqtt
import time

# 全局存储三个锚点的测距值
ESP1 = None
ESP2 = None
ESP3 = None

def on_connect(client, userdata, flags, rc):
    print(f"Connected with result code {rc}")
    # 连接成功后订阅目标主题
    client.subscribe("trilaterasi/ESP1")
    client.subscribe("trilaterasi/ESP2")
    client.subscribe("trilaterasi/ESP3")

def on_message(client, userdata, msg):
    global ESP1, ESP2, ESP3
    if msg.topic == 'trilaterasi/ESP1':
        ESP1 = float(msg.payload)
        print(f"Msg rcvd {msg.topic} {ESP1}")
    elif msg.topic == 'trilaterasi/ESP2':
        ESP2 = float(msg.payload)
        print(f"Msg rcvd {msg.topic} {ESP2}")
    elif msg.topic == 'trilaterasi/ESP3':
        ESP3 = float(msg.payload)
        print(f"Msg rcvd {msg.topic} {ESP3}")
    
    # 三个主题消息全部收齐后主动断开,进入计算环节
    if None not in (ESP1, ESP2, ESP3):
        client.disconnect()

if __name__ == "__main__":
    broker = "ipaddress"
    # 锚点固定坐标
    ESP1x, ESP1y = 300, 0
    ESP2x, ESP2y = 0, 130
    ESP3x, ESP3y = 150, 260

    while True:
        # 每轮开始重置测距值,避免旧数据干扰
        ESP1 = ESP2 = ESP3 = None

        # 先注册回调再连接,Client ID拼接时间戳避免重连冲突
        client = mqtt.Client(f"Python_{int(time.time())}")
        client.on_connect = on_connect
        client.on_message = on_message
        client.connect(broker, keepalive=10)
        
        # 阻塞运行网络循环,断开连接后自动往下执行
        client.loop_forever()

        # 执行三边测量计算
        a = 2 * (-ESP1x + ESP2x)
        b = 2 * (-ESP1y + ESP2y)
        c = ESP1**2 - ESP2**2 - ESP1x**2 + ESP2x**2 - ESP1y**2 + ESP2y**2
        d = 2 * (-ESP2x + ESP3x)
        e = 2 * (-ESP2y + ESP3y)
        f = ESP2**2 - ESP3**2 - ESP2x**2 + ESP3x**2 - ESP2y**2 + ESP3y**2
        
        x = (c*e - f*b) / (e*a - b*d)
        y = (c*d - a*f) / (b*d - a*e)
        print(f"定位结果 x: {x:.2f}, y: {y:.2f}")

        # 计算完成后加短延时,避免重连过于频繁
        time.sleep(0.5)
补充说明
  • 用loop_forever()替代原有的loop_start()+固定休眠逻辑,阻塞等待消息收齐后再断开,不需要冗余等待时间,响应更快。
  • 每轮重置测距值为None,确保不会用上一轮的旧数据计算。
  • 如果需要增加超时机制(比如某路ESP离线时避免永久卡住),可以加定时器判断超时后主动断开连接,进入下一轮重连。

内容的提问来源于stack exchange,提问作者Natriz Kiandral

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 10:01:47