Skip to content

ThingsBoard 自定义创建设备的规则节点 ​

正文、配图与代码来自原稿。在规则链中按配置创建设备(已存在则更新),适合自动开户、批量接入场景。

1、定义 TbCreateDeviceNode ​

java
package org.thingsboard.rule.engine.custom.createDevice;

import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.api.*;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;

import java.util.UUID;

import static org.thingsboard.common.util.DonAsynchron.withCallback;

@RuleNode(
        type = ComponentType.ACTION,
        name = "create device",
        configClazz = TbCreateDeviceNodeConfiguration.class,
        nodeDescription = "Create device",
        nodeDetails = "Create device",
        uiResources = {"static/rulenode/rulenode-core-config.js"},
        icon = "add_circle")
@Slf4j
public class TbCreateDeviceNode implements TbNode {

    private TbCreateDeviceNodeConfiguration config;

    @Override
    public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
        this.config = TbNodeUtils.convert(configuration, TbCreateDeviceNodeConfiguration.class);
    }

    @Override
    public void onMsg(TbContext ctx, TbMsg msg) {
        try {
            withCallback(createDevice(ctx),
                    saveDevice -> ctx.tellSuccess(msg),
                    t -> ctx.tellFailure(msg, t), ctx.getDbCallbackExecutor());
        } catch (Exception e) {
            ctx.tellFailure(msg, e);
        }
    }

    private ListenableFuture<Device> createDevice(TbContext ctx) {
        log.info("config:" + config);
        if (ObjectUtils.isEmpty(config.getName())) {
            throw new RuntimeException("设备名称不能为空");
        }
        if (ObjectUtils.isEmpty(config.getDeviceProfileId())) {
            throw new RuntimeException("设备配置ID不能为空");
        }
        if (ObjectUtils.isEmpty(config.getCustomerId())) {
            // 未指定客户时挂到 Public / 默认客户 UUID(按你环境调整)
            config.setCustomerId("13814000-1dd2-11b2-8080-808080808080");
        }
        Device oldDevice = ctx.getDeviceService()
                .findDeviceByTenantIdAndName(ctx.getTenantId(), config.getName());
        if (!ObjectUtils.isEmpty(oldDevice)) {
            oldDevice.setName(config.getName());
            oldDevice.setLabel(config.getLabel());
            oldDevice.setTenantId(ctx.getTenantId());
            oldDevice.setDeviceProfileId(DeviceProfileId.fromString(config.getDeviceProfileId()));
            oldDevice.setAdditionalInfo(JacksonUtil.valueToTree(config.getAdditionalInfo()));
            oldDevice.setCustomerId(new CustomerId(UUID.fromString(config.getCustomerId())));
            return Futures.immediateFuture(ctx.getDeviceService().saveDevice(oldDevice));
        }
        Device device = new Device();
        device.setName(config.getName());
        device.setLabel(config.getLabel());
        device.setTenantId(ctx.getTenantId());
        device.setDeviceProfileId(DeviceProfileId.fromString(config.getDeviceProfileId()));
        device.setAdditionalInfo(JacksonUtil.valueToTree(config.getAdditionalInfo()));
        device.setCustomerId(new CustomerId(UUID.fromString(config.getCustomerId())));
        return Futures.immediateFuture(ctx.getDeviceService().saveDevice(device));
    }
}

2、定义 TbCreateDeviceNodeConfiguration ​

java
package org.thingsboard.rule.engine.custom.createDevice;

import lombok.Data;
import org.thingsboard.rule.engine.api.NodeConfiguration;

@Data
public class TbCreateDeviceNodeConfiguration
        implements NodeConfiguration<TbCreateDeviceNodeConfiguration> {

    private String name;
    private String label;
    private String deviceProfileId;
    private AdditionalInfo additionalInfo;
    private String customerId;

    @Override
    public TbCreateDeviceNodeConfiguration defaultConfiguration() {
        TbCreateDeviceNodeConfiguration configuration = new TbCreateDeviceNodeConfiguration();
        configuration.setName("");
        configuration.setLabel("");
        configuration.setDeviceProfileId("");
        configuration.setAdditionalInfo(new AdditionalInfo());
        configuration.setCustomerId("");
        return configuration;
    }
}

配置 JSON 示意(UI 里设备配置常以实体对象形式出现,落地时取 id 字符串即可):

json
{
  "name": "test1",
  "label": "",
  "deviceProfileId": "53562990-7fc3-11ee-b35b-ab3138b75231",
  "additionalInfo": {
    "gateway": false,
    "overwriteActivityTime": false,
    "description": ""
  },
  "customerId": null
}

3、定义 AdditionalInfo ​

java
package org.thingsboard.rule.engine.custom.createDevice;

import lombok.Data;

@Data
public class AdditionalInfo {
    private Boolean gateway = false;
    private Boolean overwriteActivityTime = false;
    private String description = "";
}

4、项目结构 ​

项目结构

5、小结 ​

  • 同名设备走 更新,否则 新建。
  • deviceProfileId、客户 ID 必填策略按业务调整;生产环境勿写死客户 UUID。
  • 名称、标签等可用模板从消息注入(见 模板化)。