自定义获取发起者配置类型节点
正文、配图与代码来自原稿。TB 没有现成「取设备/资产配置(Profile)字段」节点时,可自定义 originator profile fields。
1、需求
需要获取设备或资产的配置(Profile)信息,官方没有对应节点,于是自定义一个 Enrichment 节点来实现。
节点名称:originator profile fields。
2、案例实操
2.1、TbGetOriginatorProfileFieldsNode
java
package org.thingsboard.rule.engine.custom;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.rule.engine.api.*;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.EntityFieldsData;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
import java.util.function.Function;
import static org.thingsboard.common.util.DonAsynchron.withCallback;
@Slf4j
@RuleNode(
type = ComponentType.ENRICHMENT,
name = "originator profile fields",
configClazz = TbGetOriginatorProfileFieldsConfiguration.class,
nodeDescription = "Add Message Originator profile fields values into Message Metadata",
nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeOriginatorFieldsConfig"
)
public class TbGetOriginatorProfileFieldsNode implements TbNode {
private TbGetOriginatorProfileFieldsConfiguration config;
private boolean ignoreNullStrings;
@Override
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
config = TbNodeUtils.convert(configuration, TbGetOriginatorProfileFieldsConfiguration.class);
ignoreNullStrings = config.isIgnoreNullStrings();
}
@Override
public void onMsg(TbContext ctx, TbMsg msg) {
try {
withCallback(putEntityFields(ctx, msg),
i -> ctx.tellSuccess(msg),
t -> ctx.tellFailure(msg, t),
ctx.getDbCallbackExecutor());
} catch (Throwable th) {
ctx.tellFailure(msg, th);
}
}
private ListenableFuture<Void> putEntityFields(TbContext ctx, TbMsg msg) {
if (config.getFieldsMapping().isEmpty()) {
return Futures.immediateFuture(null);
} else {
return Futures.transform(
findAsync(ctx, msg.getMetaData().getValue("deviceType")),
data -> {
config.getFieldsMapping().forEach((field, metaKey) -> {
String val = data.getFieldValue(field, ignoreNullStrings);
if (val != null) {
msg.getMetaData().putValue(metaKey, val);
}
});
return null;
},
MoreExecutors.directExecutor()
);
}
}
private static ListenableFuture<EntityFieldsData> findAsync(TbContext ctx, String profileName) {
return getAsync(
Futures.immediateFuture(
ctx.getDeviceProfileService()
.findDeviceProfileByName(ctx.getTenantId(), profileName)
),
EntityFieldsData::new
);
}
private static <T extends BaseData> ListenableFuture<EntityFieldsData> getAsync(
ListenableFuture<T> future, Function<T, EntityFieldsData> converter) {
return Futures.transformAsync(future, in -> in != null
? Futures.immediateFuture(converter.apply(in))
: Futures.immediateFailedFuture(new RuntimeException("Entity not found!")),
MoreExecutors.directExecutor());
}
}逻辑要点:
- 从 metadata 读取
deviceType(设备配置名称) DeviceProfileService.findDeviceProfileByName查 Profile- 按配置的 fieldsMapping 把 Profile 字段写入 metadata
上游需保证 metadata 里已有 deviceType(可用 originator fields 等节点先写入)。
2.2、TbGetOriginatorProfileFieldsConfiguration
java
package org.thingsboard.rule.engine.custom;
import lombok.Data;
import org.thingsboard.rule.engine.api.NodeConfiguration;
import java.util.HashMap;
import java.util.Map;
@Data
public class TbGetOriginatorProfileFieldsConfiguration
implements NodeConfiguration<TbGetOriginatorProfileFieldsConfiguration> {
private Map<String, String> fieldsMapping;
private boolean ignoreNullStrings;
@Override
public TbGetOriginatorProfileFieldsConfiguration defaultConfiguration() {
TbGetOriginatorProfileFieldsConfiguration configuration =
new TbGetOriginatorProfileFieldsConfiguration();
Map<String, String> fieldsMapping = new HashMap<>();
fieldsMapping.put("name", "profileName");
fieldsMapping.put("description", "profileDescription");
configuration.setFieldsMapping(fieldsMapping);
configuration.setIgnoreNullStrings(false);
return configuration;
}
}默认映射:Profile 的 name → metadata profileName,description → profileDescription。
打包放入 extensions/ 或并入主工程的方式,与 自定义 entity query 节点 相同。
3、测试效果
验证效果如下:


4、文件
原稿附件类名:
TbGetOriginatorProfileFieldsNode.javaTbGetOriginatorProfileFieldsConfiguration.java
补充(辅)
- 本实现按 Device Profile 查询;资产配置需改为
AssetProfileService及对应 metadata 键。 configDirective复用了官方 originator fields 的 UI;字段映射界面与官方类似。- API 名(如
findDeviceProfileByName)以你分支为准。
相关文章
- 自定义万能查询节点 entity query
- 源码分析规则节点(originator fields 等)
- 专栏导读
