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

如何在Node-RED中实现适配Puck.js按钮的可取消触发状态机

基于Node-RED实现Puck.js按键触发延迟告警的状态机方案

方案1:原生节点实现零额外代码状态机(推荐)

完全使用Node-RED自带节点实现,无需编写自定义函数,维护成本最低:

  • 先定义2个流上下文变量:is_counting(布尔值,标记当前是否处于30秒倒计时等待取消状态)
  • 流结构按以下顺序搭建:
    1. 入口为mqtt in节点,对接Puck.js发送的按键事件topic
    2. 接switch节点,判断flow.is_counting的状态:
      • 分支1:flow.is_counting为false(空闲状态)
        • 第一步:接LED控制节点,触发闪烁
        • 第二步:接change节点,将flow.is_counting设为true
        • 第三步:接trigger节点,配置规则为「收到消息后等待30秒发送消息,期间收到新消息则取消待发任务」
        • trigger节点后续接两个动作:先触发LED停止闪烁,再调用SMS发送节点
        • 最后接change节点,将flow.is_counting重置为false
      • 分支2:flow.is_counting为true(倒计时状态)
        • 第一步:接LED控制节点,停止闪烁
        • 第二步:接change节点,将flow.is_counting重置为false,无后续动作直接回到空闲状态

方案2:轻量自定义函数实现可扩展状态机

如果后续需要扩展更多状态(比如区分长短按、多按键逻辑),可以用单个function节点实现,核心代码不到20行:

// 读取流上下文存储的状态,默认空闲
const currentState = flow.get("puck_state") || "idle";

switch (currentState) {
  case "idle":
    // 空闲状态收到按键进入倒计时
    node.send([{ payload: "blink" }, null]);
    flow.set("puck_state", "counting");
    // 存储定时器ID用于后续取消
    const timer = setTimeout(() => {
      node.send([{ payload: "stop_blink" }, { payload: "send_sms" }]);
      flow.set("puck_state", "idle");
    }, 30000);
    flow.set("current_timer", timer);
    break;
  case "counting":
    // 倒计时状态收到按键直接取消请求
    clearTimeout(flow.get("current_timer"));
    node.send([{ payload: "stop_blink" }, null]);
    flow.set("puck_state", "idle");
    break;
}
return null;

function节点设置2个出口,第一个出口对接LED控制节点,第二个出口对接SMS发送节点即可,后续新增状态直接在switch语句中加分支即可。

注意事项

  • 状态变量优先用流上下文存储,不要用全局上下文,避免和其他流的变量冲突
  • 调试时可以在状态变更节点后加debug节点,打印当前状态值快速排查问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:54:04