ThingsBoard—自定义规则节点

2023-05-16

一般的功能,可以使用现有的节点来完成。但如果有比较复杂,或有自己特殊业务需求的,可能就需要自定义了。按官方教程来基本就可以入门,如果需要深入,可以参考ThingsBoard自有节点的实现,见源码

一、编译example

这里以docker为例。先下载example源码,然后编译好放入到TB中

# 下载源码
$ git clone https://github.com/thingsboard/rule-node-examples

# 编译成jar包(target/rule-engine-1.0.0-custom-nodes.jar)
$ mvn clean install

# 默认是没有extensions目录的,需要到docker(mytb)中创建extensions文件夹
$ docker exec -it mytb bash
$ cd /usr/share/thingsboard
$ mkdir extensions

# 拷贝jar包到docker中
$ docker cp target/rule-engine-1.0.0-custom-nodes.jar mytb:/usr/share/thingsboard/extensions/

# 重启docker。不行,就依次执行stop和start
$ docker restart mytb

如果编译时报错:

[ERROR] Failed to execute goal com.mycila:license-maven-plugin:3.0:check (default) on project rule-engine: Some files do not have the expected license header -> [Help 1]

因为检查了头部的license注释,可以换成:

$ mvn -Dlicense.skip=true clean install

重启后,在TB后台刷新,就可以看到新的节点了。这里就不放图了

二、文件结构

核心就这四块:

  • 第1个是打包时的配置,在pom.xml中配置
  • 第2个是源码,一个节点,基本包括两个java文件,一个是节点,一个是节点配置数据
  • 第3个是节点UI对应的js文件
  • 第4个是pom.xml

三、自定义节点步骤

  1. 实现TbNode接口
  2. 添加@RuleNode注解,并添加对应的名称、关联类型、说明、UI文件、及UI的selector模块名(驼峰命名法,对应着js的短横线命名法)等
  3. init()中初始化,主要获取用户配置的数据
  4. onMsg()中处理业务逻辑
  5. 通过ctx.tellSuccess()ctx.tellNext()ctx.tellFailure()把结果传递给下一个节点

    如果在子线程处理,也必须通过上面三个方法来处理结果

  6. 【可选】如果修改了原包名(org.thingsboard.rule.engine),需要把新包名(eg:com.test.rule.engine)添加到thingsboard.yml文件中:
       # Plugins configuration parameters
       plugins:
         # Comma separated package list used during classpath scanning for plugins
         scan_packages: "$PLUGINS_SCAN_PACKAGES:org.thingsboard.server.extensions,org.thingsboard.rule.engine,com.test.rule.engine"
    

    如果不是源码,而是docker,在这修改:/usr/share/thingsboard/bin/thingsboard.yml

  7. 打包

四、demo参考

这里写了个demo,主要用于展示如何获取、修改msgmetadata的数据

4.1 源码

TbTestNode.java

/**
 * @author ralap
 * @date 2022/3/6
 */
@RuleNode(
        type = ComponentType.ENRICHMENT,
        name = "convert m/s to km/h",
        configClazz = TbTestConfiguration.class,
        nodeDescription = "获取msg中的速度数据,并修改",
        nodeDetails = "获取msg的速度数据,速度对应的key为输入框<code>speedKey</code>对应的值,并把它转换成km/h。metadata中增加是否转换成功的结果<code>metadata.cvtResult</code>"
//        uiResources = "static/rulenode/custom-nodes-config.js",
//        configDirective = "tbEnrichmentNodeSumIntoMetadataConfig")
)
@Slf4j
public class TbTestNode implements TbNode

    private static final ObjectMapper mapper = new ObjectMapper();
    private TbTestConfiguration config;
    private String speedKey;

    @Override
    public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException 
        this.config = TbNodeUtils.convert(configuration, TbTestConfiguration.class);
        this.speedKey = this.config.getSpeedKey();
    

    @Override
    public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException 
        // 获取msg数据
        String msgData = msg.getData();
        log.info("onMsg.data=" + msgData);

        // 获取metadata数据
        TbMsgMetaData metaData = msg.getMetaData();
        metaData.getData().forEach((key, val) ->
            log.info("onMsg.metadata: " + key + "=" + val)
        );

        try 
            // 找speedKey
            JsonNode dataNode = mapper.readTree(msgData);
            JsonNode speedNode = dataNode.get(speedKey);
            int speed = speedNode.asInt();
            double newSpeed = speed * 3.6;
            ObjectNode node = mapper.createObjectNode();
            node.put("newSpeed", newSpeed);
            log.info("onMsg.newNode=" + mapper.writeValueAsString(node));

            // 增加metaData结果
            msg.getMetaData().putValue("cvtResult", "True");

            // 重新生成msg
            TbMsg newMsg = TbMsg.transformMsg(msg, msg.getType(), msg.getOriginator(), msg.getMetaData(), mapper.writeValueAsString(node));
            ctx.tellSuccess(newMsg);
         catch (JsonProcessingException e) 
            e.printStackTrace();
            msg.getMetaData().putValue("cvtResult", "False");
            ctx.tellFailure(msg, e);
        
    

    @Override
    public void destroy()  

说明一下:
这里@RuleNode注解中,把最后两行注释掉了,代表没有用自定义的UI(即resources下的custom-nodes-config.js),使用的是默认UI(ThingsBoard自带的rulenode-core-config.js)。因为自定义UI编译出来的js,放到tb中会报错:加载配置UI资源失败。暂时没解决,可以自己去试试看

TbTestConfiguration.java

@Data
public class TbTestConfiguration implements NodeConfiguration<TbTestConfiguration> 

    private String speedKey;

    @Override
    public TbTestConfiguration defaultConfiguration() 
        TbTestConfiguration configuration = new TbTestConfiguration();
        configuration.setSpeedKey("speed");
        return configuration;
    

4.2 结果展示

规则链中,通过generator节点来模拟设备的数据,这样就需要等外部设备的数据,保存时就能触发数据

generator的节点配置

var msg =  speed: 100;
var metadata =  car: "Maybach" ;
var msgType = "POST_TELEMETRY_REQUEST";

return  msg: msg, metadata: metadata, msgType: msgType ;

自定义节点展示

配置内容

打开调试模式后,查看输出的msg结果

输出的metadata数据:

控制台打印的日志:

以上是关于ThingsBoard——自定义规则节点的主要内容,如果未能解决你的问题,请参考以下文章

串线篇SQL映射文件-resultMap自定义封装

Java语言的常见命名规则——驼峰命名法

Java语言的常见命名规则——驼峰命名法

Vue.js---自定义指令

03Vue.js---自定义指令

ThingsBoard——Android APP安装

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ThingsBoard—自定义规则节点 的相关文章

随机推荐

  • 线性探测再散列

    哈希表又称散列表 哈希表存储的基本思想是 xff1a 以数据表中的每个记录的关键字 k为自变量 xff0c 通过一种函数H k 计算出函数值 把这个值解释为一块连续存储空间 xff08 即数组空间 xff09 的单元地址 xff08 即下标
  • 特征选择的几种方法

    目录 1 过滤法 xff08 Filter xff09 1 1 方差选择法 1 2 相关系数法 1 3 卡方检验 1 4 互信息法 1 5 relief算法 2 包裹法 xff08 Wrapper xff09 2 1 递归特征消除法 2 2
  • Excel调用有道词典实现批量翻译

    如图所示 xff0c 我们在B2单元格中写入公式 xff1a 61 FILTERXML WEBSERVICE 34 http fanyi youdao com translate amp i 61 34 amp A2 amp 34 amp
  • Python的使用技巧:any all的短路

    注意迭代类型和list的结果是不一样的 xff1a if name 61 61 39 main 39 a 61 1 2 3 if any print i is None for i in a print 6666666666 1 2 3 6
  • curl升级到7.87(centos7和TencentOS2.4 tk)

    centos7升级curl到7 8 7 按照之前写过的一篇文章 大致按描述操作即可 只不过需要做一点点修正 CentOS 7升级curl 乐大师的博客 CSDN博客 centos7 curl升级 更新操作中会报错安装失败 提示如下 nbsp
  • Python中raise…from用法

    本来这几天是计划阅读string模块的源码 xff0c 恰好其中一段异常处理的代码我觉得很新奇 xff0c 也就是raise from的用法 xff0c raise的用法大家都知道 因为我之前没遇到过 xff0c 所以就去网上查了相关的资料
  • AI模型隐私风险及防护技术

    一 背景 随着AI成为新一代关键技术趋势 xff0c 围绕着AI的服务也越来越普及 特别是结合了云计算以后 xff0c 机器学习数据的标注 模型训练及预测等服务纷纷上云 xff0c 为用户提供了强大的算力和优秀的算法 xff0c 极大方便了
  • 汉诺塔的图解递归算法

    一 xff0e 起源 xff1a 汉诺塔 xff08 又称河内塔 xff09 问题是源于印度一个古老传说的益智玩具 大梵天创造世界的时候做了三根金刚石柱子 xff0c 在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘 大梵天命令婆罗门把圆
  • 推荐系统中的矩阵分解总结

    最近学习矩阵分解 xff0c 但是学了好多种类 xff0c 都乱了 xff0c 看了这篇文章 xff0c 系统性的总结了矩阵分解 xff0c 感觉很棒 xff0c 故分享如下 前言 推荐系统中最为主流与经典的技术之一是协同过滤技术 xff0
  • 几种常见的离群点检验方法

    在一组平行测定中 xff0c 若有个别数据与平均值差别较大 xff0c 则把此数据视为可疑值 xff0c 也称离群值 如果统计学上认为应该舍弃的数据留用了 xff0c 势必会影响其平均值的可靠性 相反 xff0c 本应该留用的数 据被舍弃
  • Spring框架介绍及使用(一)

    文章目录 概念为什么要用 xff1f Spring的体系结构Spring框架之控制反转 xff08 IOC xff09 概念Spring文件包解释入门程序入门程序需要的jar包配置文件入门程序的建立ApplicationContext与Be
  • SpringMVC 相关配置

    SpringMVC 相关配置 打印请求与响应日志 打印 64 RequestBody 64 Response日志 https blog csdn net ww 1997 article details 116006445 https www
  • 普通表到分区表转换

    A 通过 Export import 方法 B 通过 Insert with a subquery 方法 C 通过 Partition Exchange 方法 D 通过 DBMS REDEFINITION 方法 比如把test用户下的普通表
  • Ubuntu 20.04 上安装 Node.js 和 npm 的三种方法

    主要介绍三种在 Ubuntu 20 04 上安装 Node js 和 npm 的方法 xff1a 通过Ubuntu标准软件库 这是最简单的安装方法 xff0c 并且适用大多数场景 但是标准软件库中最高版本只有 v10 19 0 root 6
  • android databinding 数据绑定错误 错误:任务':app:compileDebugJavaWithJavac' 的执行失败

    今天到公司照常打开项目 xff0c 突然运行不了显示databinding错误 Error Execution failed for task 39 app compileDebugJavaWithJavac 39 gt android d
  • 解决idea新建Module的奇怪路径问题

    问题由来 xff1a 在部署SpringCloud的时候想新建一个module来快速创建 xff0c 结果被创建出来的目录结构搞得一脸懵逼 xff0c 新建的module的根目录跑到了 xff0c 项目的src目录下 xff0c 整个看起来
  • ThingsBoard源码解析-数据订阅与规则链数据处理

    前言 结合本篇对规则链的执行过程进行探讨 根据之前对MQTT源码的学习 xff0c 我们由消息的处理入手 org thingsboard server transport mqtt MqttTransportHandler void pro
  • Thingsboard使用gateway网关

    简介 xff1a 本次是想测试一下thingsboard网关的使用 xff0c 实现通过网关 43 mqtt 43 thingsboard 43 emqx 实现间接设备创建和数据传输 前期准备 xff1a thingsboard平台 thi
  • Thingsboard(2.4 postgresql版)数据库表结构说明

    本文描述的表结构是根据thingsboard2 4 xff08 postgresql版 xff09 数据库中整理出来的 xff0c 不一定完整 xff0c 后续有新的发现再补充文档 一 数据库E R关系 Thingsboard2 4社区版共
  • ThingsBoard—自定义规则节点

    一般的功能 xff0c 可以使用现有的节点来完成 但如果有比较复杂 xff0c 或有自己特殊业务需求的 xff0c 可能就需要自定义了 按官方教程来基本就可以入门 xff0c 如果需要深入 xff0c 可以参考ThingsBoard自有节点