Node-RED流中检测Webservice连接失败并触发对应节点的方案咨询
我使用Node-RED V1.3.7通过WebSocket与ESP32通信,ESP32对接3路调光器控制3盏灯具,同时连接8路继电器板用于选择3路调光器中的一路输出到对应灯具,还搭载了红外(IR)编解码器。WebSocket用于向ESP32发送引脚开关指令,ESP32也会通过该通道向流上报事件和自身状态。目前ESP32存在内存泄漏问题,我暂不修复该问题,以此模拟ESP32崩溃场景,验证流的优雅恢复能力。
我需要在WebSocket断开连接时触发function节点或其他对应逻辑,但目前仅能通过webservice组件的状态图标看到ESP32崩溃后显示断开,无法通过连接断开事件触发节点,添加的catch节点也无法被触发,原生webservice节点不会在连接失败/断开时输出消息。
流说明
该流包含以下输入源:
- 来自ESP32的WebSocket,用于上报事件(收到IR信号)和状态更新。
- 对接Firestick的自定义节点,运行adb logcat检测媒体播放状态。
- 对接WiFi路由器的自定义节点,解析DHCP事件,通过手机网络存在状态判断人员进出房屋。
因此灯光和调光器选择会受ESP32 IR接收器捕获的特定IR码、手机进出网络、Firestick播放状态三个因素影响。
流将ESP32引脚状态存储在流变量中,我的需求是:当检测到表明ESP32已重启的WebSocket错误时,向ESP32重发所有受控引脚的配置消息,将其恢复到重启前的流存储状态。
流中所有逻辑最终都会向Pins节点发送消息,该节点检测到引脚状态变化时(去重过滤)会生成消息发送给lrelay节点。lrelay发送引脚变更消息后,ESP32返回的响应会包含引脚变更后的状态,随后save state节点会将该引脚状态存入流变量用于后续去重。
错误恢复逻辑设计如下:GET/salon/lumiere endpoint返回ESP32所有受控引脚及其状态的JSON数据:
[{"name":"D1O2","state":0},{"name":"D12O3","state":0},{"name":"D123OH","state":1},{"name":"entree","state":0},{"name":"salon","state":1},{"name":"cuisine","state":0}]
引脚/继电器对应关系:
D1O2: 选择调光器1或2
D12O3: 选择D1O2输出或调光器3输出
D123OH: 选择D12O3输出或全120V市电(H代表高电压)
salon: 客厅灯光开关
entree: 入口灯光开关
cuisine: 厨房灯光开关
Connect节点每秒左右向ESP32发送一条"Connect" WebSocket消息,触发ESP32注册Node-RED的WebSocket并建立连接,只有第一条消息会被ESP32处理,其余消息相当于心跳包。
每次发送Connect消息时,getstate节点会调用上述JSON接口获取所有引脚状态并发送给Pins节点,默认情况下Pins节点会忽略这些请求,仅在检测到状态变更时才会向ESP32发送引脚变更消息,因此这种状态重放默认不会触发任何操作。
我提出的实现方案
检测到WebSocket错误时设置一个流变量,Pins节点检测到该变量被设置时,暂时关闭去重逻辑,允许引脚变更消息重放,待ESP32返回状态响应触发save state节点时再重置该错误流变量。
我正在考虑但不倾向的备选方案
按偏好排序,将原生WebSocket节点替换为以下方案:
- 自定义WebSocket节点,实现完善的错误处理,支持触发catch节点。
- 使用tcp请求节点实现WebSocket通信,捕获连接错误,替代原生WebSocket能力。
我希望避免的方案
我可以在ESP32端修复该问题,让其启动时请求/salon/lumiere接口初始化引脚状态,但我不希望在架构上将ESP32代码与Node-RED绑定,尤其是绑定到特定Node-RED流暴露的特定端点。我也可以在ESP32中添加"初始化URL"参数实现解耦,但我目前更倾向于在Node-RED端而非ESP32端解决该问题。
内容的提问来源于stack exchange,提问作者Louis Riel

