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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 10:39:51