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

树莓派Python脚本中Paho MQTT回调函数未触发问题求助

MQTT回调函数未触发问题排查(树莓派4 + GrovePi + Python 2.7)

我在树莓派4上运行Python 2.7脚本,搭配GrovePi扩展板,连接了按钮和LCD显示屏。使用Paho MQTT库时,on_message和on_intrusion两个回调函数始终未被调用,但发布功能正常。已通过sudo mosquitto_sub -h <broker_ip> -t 'MyTopic' -q 0验证树莓派可访问Broker,LCD和按钮单独测试正常,主题路径也反复核对过。

当前代码

import time
import LCDDisplay
import paho.mqtt.client as paho
import grovepi
import threading

broker_ip = '192.168.1.23'
broker_port = 1883
turn_on_topic = 'GreenHouse/Security/TurnOn'
intrusion_topic = 'GreenHouse/Security/IntrusionDetected'
message_topic = 'GreenHouse/Message'
message_display_duration = 5.0

button_port = 3
last_message = 'Initial display'

def display_last_message():
    print('Timer starting')
    LCDDisplay.setText(last_message)
    LCDDisplay.setRGB(160,240,70)

message_timer = threading.Timer(message_display_duration, display_last_message)

def on_message(client, userdata, msg):
    print('Message received')
    LCDDisplay.setText('Message received')
    LCDDisplay.setRGB(60,190,250)
    if message_timer.is_alive():
        message_timer.cancel()
        message_timer = threading.Timer(message_display_duration, display_last_message)
    message_timer.start()

def on_intrusion(client, userdata, msg):
    LCDDisplay.setText('ALERT - INTRUSION DETECTED')
    LCDDisplay.setRGB(240,65,65)

if __name__=="__main__":
    display_last_message()
    print('Connecting to broker...')
    mqttClient = paho.Client('Button_LCD_Main')
    mqttClient.message_callback_add(message_topic, on_message)
    mqttClient.message_callback_add(intrusion_topic, on_intrusion)
    mqttClient.connect(broker_ip, broker_port, 60)

    print('Starting loop and button check')
    mqttClient.loop_start()
    grovepi.pinMode(button_port,"INPUT")
    time.sleep(2) # Wait for button to initialize
    try:
        while True:
            button_output = grovepi.digitalRead(button_port)
            if button_output == 1:
                print('Button activated')
                mqttClient.publish(turn_on_topic)
                time.sleep(1)
            else:
                time.sleep(0.2)
    finally:
        mqttClient.loop_stop()
        mqttClient.disconnect()

程序启动后输出

Timer starting
Connecting to broker...
Starting loop and button check

问题排查与修复方案

1. 核心问题:未订阅目标主题

Paho MQTT客户端仅添加回调映射是不够的,必须显式调用subscribe()方法订阅对应主题,否则客户端不会接收该主题的消息。在connect()之后、loop_start()之前添加订阅代码:

# 订阅消息主题和入侵告警主题
mqttClient.subscribe(message_topic, qos=0)
mqttClient.subscribe(intrusion_topic, qos=0)

2. 修复Timer变量作用域问题

在on_message函数中重新赋值message_timer时,会创建局部变量覆盖全局变量,导致后续Timer操作异常。需要在函数开头声明global message_timer:

def on_message(client, userdata, msg):
    global message_timer  # 声明使用全局变量
    print('Message received')
    LCDDisplay.setText('Message received')
    LCDDisplay.setRGB(60,190,250)
    if message_timer.is_alive():
        message_timer.cancel()
        message_timer = threading.Timer(message_display_duration, display_last_message)
    message_timer.start()

3. 添加异常捕获避免回调静默失败

Paho的后台loop线程会屏蔽回调函数中的异常,若LCD操作抛出异常,会导致回调直接终止且无日志。建议在回调中添加异常捕获:

def on_intrusion(client, userdata, msg):
    try:
        LCDDisplay.setText('ALERT - INTRUSION DETECTED')
        LCDDisplay.setRGB(240,65,65)
    except Exception as e:
        print(f"Intrusion callback error: {str(e)}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:43:28