RevPi与Windows PC通过WebSockets交互输入事件异常排查
问题:RevPi服务端输入变更事件无法被Windows客户端接收
场景说明
尝试通过WebSockets实现RevPi(服务端)与Windows PC(客户端)的输入事件交互。客户端能正常接收初始值,但RevPi输入值变更后,服务端日志显示已发送消息,客户端却无法接收并处理后续变更。
服务端代码
@app.route('/init', methods=['GET']) def initialize(): rpi.io.O_Unlock.value = False rpi.mainloop(blocking=False) sio.emit("initialValues", { "I_Slot1": rpi.io.I_Slot1.value, "I_Slot2": rpi.io.I_Slot2.value, "I_Lock": rpi.io.I_Lock.value }) rpi.io.I_Slot1.reg_event(slot_master_handler) rpi.io.I_Slot2.reg_event(slot_slave_handler) rpi.io.I_Lock.reg_event(lock_event_handler) return jsonify({"message": "RevPi initialized and event system running."}) def slot_master_handler(name, I_Slot1): print(f"{name} = {I_Slot1}") sio.emit("master", {name: I_Slot1}) def slot_slave_handler(name, I_Slot2): print(f"{name} = {I_Slot2}") sio.emit("slave", {name: I_Slot2})
客户端代码
def __init__(self, procImage): ... # register events self.sio = socketio.Client() self.register() self.start() self._send_request("init") def register(self): """Initialize the Socket.IO client and register event handlers.""" @self.sio.event def connect(): print("Connected to WebSocket server") @self.sio.event def disconnect(): print("Disconnected from WebSocket server") @self.sio.on("initialValues") def on_initial_values(data): # Handle initial values using the same event methods print(f"received value = {data}") self._slotMasterEvent("I_Slot1", data["I_Slot1"]) self._slotSlaveEvent("I_Slot2", data["I_Slot2"]) self._lockEvent("I_Lock", data["I_Lock"]) @self.sio.on("master") def on_master(data): print(f"[Client] Master button: {data}") self._slotMasterEvent("I_Slot1", data["I_Slot1"]) @self.sio.on("slave") def on_slave(data): print(f"[Client] Slave button: {data}") self._slotSlaveEvent("I_Slot2", data["I_Slot2"]) @self.sio.on("lock") def on_lock(data): print(f"[Client] Lock event: {data}") self._lockEvent("I_Lock", data["I_Lock"])
服务端日志
emitting event "initialValues" to all [/] anWfkgucTrjUfcgIAAAA: Sending packet MESSAGE data 2["initialValues",{"I_Slot1":false,"I_Slot2":false,"I_Lock":false}] 192.168.4.101 - - [11/Apr/2025 16:09:59] "GET /init HTTP/1.1" 200 195 0.006046 I_Slot1 = True emitting event "master" to all [/] anWfkgucTrjUfcgIAAAA: Sending packet MESSAGE data 2["master",{"I_Slot1":true}] I_Slot1 = False emitting event "master" to all [/] anWfkgucTrjUfcgIAAAA: Sending packet MESSAGE data 2["master",{"I_Slot1":false}] I_Slot1 = True emitting event "master" to all [/] anWfkgucTrjUfcgIAAAA: Sending packet MESSAGE data 2["master",{"I_Slot1":true}]
客户端日志
received value = {'I_Slot1': True, 'I_Slot2': False, 'I_Lock': False} I_Slot1=True I_Slot2=False I_Lock=False #### The change should show here ####
排查思路与解决方案
1. 确保Socket.IO客户端事件循环正常运行
客户端使用socketio.Client()时,若在GUI或多线程环境中,需维护事件循环才能持续监听消息。如果self.start()仅执行连接操作,未启动事件循环,会导致后续消息无法接收。
- 修复方案:在
start()方法中添加事件循环维护逻辑,例如:def start(self): self.sio.connect("http://你的RevPiIP:端口") # 多线程环境下启动守护线程维持事件循环 import threading threading.Thread(target=self.sio.wait, daemon=True).start()
2. 捕获事件处理异常,避免静默失败
客户端事件处理函数若因数据解析错误抛出异常,可能导致后续事件监听中断,且无日志提示。
- 修复方案:在事件处理函数中添加异常捕获:
@self.sio.on("master") def on_master(data): try: print(f"[Client] Master button: {data}") self._slotMasterEvent("I_Slot1", data["I_Slot1"]) except Exception as e: print(f"处理master事件出错: {e}, 数据: {data}")
3. 检查Socket.IO版本兼容性
服务端与客户端的python-socketio版本需匹配,不同版本的协议可能存在差异,导致消息无法被正确解析。
- 修复方案:统一两端版本,执行
pip install python-socketio==<对应版本>(例如服务端用v4,客户端也安装v4)。
4. 验证连接状态稳定性
虽然服务端日志显示连接未断开,但客户端可能因网络波动或未正确维持连接导致消息丢失。
- 排查方案:添加连接错误监听:
@self.sio.event def connect_error(data): print(f"连接错误: {data}")
5. 确认RevPi事件注册逻辑
服务端在initialize()中先发送初始值再注册事件,逻辑无误,但需确认rpi.mainloop(blocking=False)是否正确启动了输入事件监听循环,确保输入变更能触发回调函数。
内容的提问来源于stack exchange,提问作者Ahmad Ali
相关产品推荐
相关产品推荐

