树莓派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
相关产品推荐
相关产品推荐

