
物联网后端数据可视化消息队列【免费下载链接】thingsboardAll-in-one IoT Platform - Device management, data collection, processing and visualization.项目地址https://gitcode.com/GitHub_Trending/th/thingsboard点击查看免费下载导读在 ThingsBoard 规则引擎中Create Alarm创建告警节点允许你通过一段 TBELThingsBoard Expression Language脚本自定义存入告警Alarm实体的附加详情Alarm Details例如把入站消息 payload 中的temperature属性、元数据中的设备名称等保存到告警中。本文将围绕 create_alarm_node_script_fn.md 中定义的Details(msg, metadata, msgType)构建函数讲解它的签名、参数、返回值约定以及如何通过metadata.prevAlarmDetails读取并合并历史告警详情实现告警次数的累计计数。读完本文你将能够在 ThingsBoard 中独立编写、配置并调试这段 TBEL 脚本。Details 函数Create Alarm 节点如何生成 Alarm DetailsCreate Alarm 节点在创建或更新告警时会调用一段用户编写的脚本函数来生成Alarm Details对象。该对象最终作为告警实体的details字段存储用于承载告警之外的附加业务参数。函数的完整声明如下function Details(msg, metadata, msgType): any这段脚本属于 TBEL 语言ThingsBoard 基于 JavaScript 语法的表达式语言配置位置在 Create Alarm 节点的Alarm details配置项中脚本的返回值被序列化为 JSON作为告警的Alarm Details存储常见用法是从原始消息Original Message的 payload 或 metadata中挑选出若干键值对保存到告警详情里便于后续规则链节点或仪表板直接使用。参数说明参数类型含义msg{[key: string]: any}消息 payload 的键值对象值可以是任意类型数字、字符串、布尔、嵌套对象等metadata{[key: string]: string}消息元数据键值映射键和值都必须是字符串msgTypestring消息类型字符串对应规则引擎中常见的MessageType枚举值如POST_TELEMETRY_REQUEST、ENTITY_CREATED等关于三个参数的完整定义可参见 common_node_script_args.md。其中metadata强调键值均为字符串因此从msg中取值可以保留数字类型而从metadata中取出的任何值本质上都是字符串需要时记得自行转换。返回值约定函数必须返回一个对象object该对象即告警的 Alarm Details。返回{}空对象也是合法的此时告警详情为空。如果返回null或抛出异常将导致该节点的消息处理失败节点会走 Failure 链路这一点在源码测试中也有明确验证见下文“源码级验证”部分。通过 metadata.prevAlarmDetails 读取历史告警详情这是本函数最有价值、也最容易踩坑的一个点。当规则链中有多个消息持续触发同一告警例如同一设备连续上报超温数据时Create Alarm 节点可能会更新已存在的告警。此时TBEL 引擎会把上一次保存的 Alarm Details 以原始字符串形式注入到本次脚本的metadata.prevAlarmDetails字段中供你读取、合并。需要特别注意仅在存在上一次告警详情时才存在该字段如果这是第一次创建该告警metadata.prevAlarmDetails不会出现在 metadata 中metadata.prevAlarmDetails是raw String原始字符串不是对象必须先用JSON.parse(...)反序列化后才能访问其中的属性解析完成后建议立即用delete metadata.prevAlarmDetailsTBEL 写法把它从 metadata 中移除避免该字段被后续规则节点继续携带。标准解析模板var details {}; if (metadata.prevAlarmDetails) { // remove prevAlarmDetails from metadata delete metadata.prevAlarmDetails; details JSON.parse(metadata.prevAlarmDetails); }这段代码的语义是优先继承上一次告警的全部详情字段作为本次详情的基础对象然后再在上面叠加本次消息带来的新数据。从源码看该字段的注入发生在 TbAbstractAlarmNode.java 的buildAlarmDetails方法中static final String PREV_ALARM_DETAILS prevAlarmDetails; ... protected ListenableFutureJsonNode buildAlarmDetails(TbMsg msg, JsonNode previousDetails) { try { TbMsg dummyMsg msg; if (previousDetails ! null) { TbMsgMetaData metaData msg.getMetaData().copy(); metaData.putValue(PREV_ALARM_DETAILS, JacksonUtil.toString(previousDetails)); dummyMsg msg.transform().metaData(metaData).build(); } return scriptEngine.executeJsonAsync(dummyMsg); } ... }可以看到当存在历史详情previousDetails ! null时节点会把历史详情序列化成字符串写入prevAlarmDetails元数据再交给 TBEL 脚本引擎执行。这正解释了为什么脚本中拿到的metadata.prevAlarmDetails是一个需要JSON.parse的字符串。实战示例计数累加 温度属性入库文档中给出的完整示例覆盖了最常见的两类操作从历史详情中读取计数并累加、从入站消息 payload 中取属性写入详情。var details {temperature: msg.temperature, count: 1}; if (metadata.prevAlarmDetails) { var prevDetails JSON.parse(metadata.prevAlarmDetails); // remove prevAlarmDetails from metadata delete metadata.prevAlarmDetails; if (prevDetails.count) { details.count prevDetails.count 1; } } return details;逐行解读初始化新详情var details {temperature: msg.temperature, count: 1};直接把入站消息 payload 中的temperature属性存入详情count初始为1代表这是第一次告警或首次检测到的次数。合并历史详情如果存在metadata.prevAlarmDetails先JSON.parse得到上一次的详情对象prevDetails。清理 metadatadelete metadata.prevAlarmDetails保证向下游节点传递的 metadata 与进入本节点时一致。递增计数如果上一次详情里已有count字段则在其基础上1实现“该告警累计触发次数”的持久化统计。返回return details;最终count会变成历史次数 1temperature则是本次消息的最新值。这一“历史计数 实时属性”的组合在实际中非常有用例如统计某设备连续超温的告警次数同时保留最近一次的超温温度值。与 Clear Alarm 节点的关联类似地Clear Alarm清除告警节点 也使用同样的Details函数形态来生成更新后的详情对象同样依赖metadata.prevAlarmDetails读取当前告警详情并通过metadata.remove(prevAlarmDetails)清理元数据。两者的写法可以相互借鉴。源码级验证默认模板、脚本语言选择与测试覆盖两种脚本语言的默认模板Create Alarm 节点同时支持TBEL和JS两种脚本语言对应源码中的两个默认模板见 TbAbstractAlarmNodeConfiguration.javaJS 模板ALARM_DETAILS_BUILD_JS_TEMPLATE使用if (metadata.prevAlarmDetails)判断并用delete metadata.prevAlarmDetails清理TBEL 模板ALARM_DETAILS_BUILD_TBEL_TEMPLATE使用if (metadata.prevAlarmDetails ! null)判断并用metadata.remove(prevAlarmDetails)清理。两者的判断条件与清理方式略有差异但语义一致。TBEL 更推荐使用! null判断与metadata.remove(...)写法本文沿用原文档的 TBEL 风格。脚本语言的实际选择发生在 TbAbstractAlarmNode.java 的init方法中scriptEngine ctx.createScriptEngine(config.getScriptLang(), ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getAlarmDetailsBuildTbel() : config.getAlarmDetailsBuildJs());即当scriptLang为TBEL时执行的是alarmDetailsBuildTbel字段中的脚本否则执行alarmDetailsBuildJs中的脚本。测试用例验证的行为仓库中的单元测试 TbCreateAlarmNodeTest.java 对这一机制做了完整验证可以佐证以下几点默认配置下alarmDetailsBuildJs与alarmDetailsBuildTbel分别等于上文两套默认模板测试第 106–129 行当存在历史告警时脚本执行前会被注入一个带有prevAlarmDetails元数据的 dummy 消息测试第 625 行断言actualDummyMsg.getMetaData().getData()包含prevAlarmDetails键当overwriteAlarmDetails为false时历史详情会被读取并合并进新详情当其为true时则直接用新详情覆盖测试第 856–1000 行分别覆盖了两种分支当告警详情脚本抛出异常时消息会走失败链路且不会执行其他动作测试第 1224–1243 行的whenAlarmDetailsScriptThrowsException用例。这些测试同时印证了一个重要行为告警详情的写入是否覆盖历史数据还取决于节点配置中的 “Overwrite alarm details” 选项而不仅仅是脚本逻辑本身。调试与验证在 ThingsBoard 界面配置该节点时在规则链编辑器中打开Create Alarm节点在Script language中选择TBEL在Alarm details文本框中粘贴上述脚本此为该函数对应的配置项开启节点的 Debug 模式即可在规则链的调试面板中近乎实时地查看每次经过该节点的消息含入站消息与经过脚本处理后出站的消息确认生成的 Alarm Details 是否符合预期。Debug 模式的详细使用方法可参考仓库中 common_node_script_args.md 中的指引。延伸阅读告警Alarm实体的整体模型、生命周期与告警规则配置可进一步查阅仓库内ui-ngx/src/assets/help中关于告警的教程类文档结合 create_alarm_node_script_fn.md 同目录下的其他节点脚本文档如 filter_node_script_fn.md、transformation_node_script_fn.md可以系统掌握 TBEL 在规则引擎各节点中的通用写法若要实际演练“创建与清除告警”的完整规则链配置步骤可参考官方针对 Create and Clear Alarms 场景的逐步教程。赞分享物联网后端数据可视化消息队列【免费下载链接】thingsboardAll-in-one IoT Platform - Device management, data collection, processing and visualization.项目地址https://gitcode.com/GitHub_Trending/th/thingsboard点击查看免费下载相关推荐ThingsBoard 规则引擎Clear Alarm 节点 Alarm Details 构建函数clear_alarm_node_script_fn完全指南ThingsBoard 规则引擎Clear Alarm 节点 Alarm Details 构建函数clear_alarm_node_script_fn完全物联网后端数据可视化消息队列巴菲特《错误的25年》精读机构惯性、卓越公司与工程管理的稳健决策巴菲特《错误的25年》精读机构惯性、卓越公司与工程管理的稳健决策 本文是对工程管理资源库 engineering management https://lin物联网后端数据可视化消息队列ThingsBoard AI 请求节点提示词设置实战基于 Telemetry 与 Alarm 的提示模板与 JSON 结构化输出ThingsBoard AI 请求节点提示词设置实战基于 Telemetry 与 Alarm 的提示模板与 JSON 结构化输出 AI 请求节点AI req物联网后端数据可视化消息队列上一篇Wand-Enhancer终极指南免费解锁WeMod Pro会员功能下一篇ComfyUI-VideoHelperSuite5分钟掌握AI视频创作的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考