fix rule node descriptions & fix validation messages & updated tests

This commit is contained in:
ShvaykaD 2023-05-22 15:57:26 +03:00
parent 2a51125358
commit d67313cf8c
14 changed files with 87 additions and 80 deletions

View File

@ -48,10 +48,10 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
name = "calculate delta", relationTypes = {"Success", "Failure", "Other"}, name = "calculate delta", relationTypes = {"Success", "Failure", "Other"},
configClazz = CalculateDeltaNodeConfiguration.class, configClazz = CalculateDeltaNodeConfiguration.class,
nodeDescription = "Calculates and adds 'delta' value into message based on the incoming and previous value", nodeDescription = "Calculates and adds 'delta' value into message based on the incoming and previous value",
nodeDetails = "Calculates delta and period based on the previous time-series reading and current data. " + nodeDetails = "Calculates delta and period based on the previous timeseries reading and current data. " +
"Delta calculation is done in scope of the message originator, e.g. device, asset or customer. " + "Delta calculation is done in scope of the message originator, e.g. device, asset or customer.<br><br>" +
"If there is input key, the output relation will be 'Success' unless delta is negative and corresponding configuration parameter is set. " + "If there is input key, the output relation will be <code>Success</code> unless delta is negative and corresponding configuration parameter is set. <br>" +
"If there is no input value key in the incoming message, the output relation will be 'Other'.", "If there is no input value key in the incoming message, the output relation will be <code>Other</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeCalculateDeltaConfig") configDirective = "tbEnrichmentNodeCalculateDeltaConfig")
public class CalculateDeltaNode implements TbNode { public class CalculateDeltaNode implements TbNode {

View File

@ -30,10 +30,13 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
@Slf4j @Slf4j
public abstract class TbAbstractGetEntityDataNode<T extends EntityId> extends TbAbstractGetMappedDataNode<T, TbGetEntityDataNodeConfiguration> { public abstract class TbAbstractGetEntityDataNode<T extends EntityId> extends TbAbstractGetMappedDataNode<T, TbGetEntityDataNodeConfiguration> {
protected final static String DATA_TO_FETCH_PROPERTY_NAME = "dataToFetch"; private final static String DATA_TO_FETCH_PROPERTY_NAME = "dataToFetch";
protected static final String OLD_DATA_TO_FETCH_PROPERTY_NAME = "telemetry"; private static final String OLD_DATA_TO_FETCH_PROPERTY_NAME = "telemetry";
protected final static String DATA_MAPPING_PROPERTY_NAME = "dataMapping"; private final static String DATA_MAPPING_PROPERTY_NAME = "dataMapping";
protected static final String OLD_DATA_MAPPING_PROPERTY_NAME = "attrMapping"; private static final String OLD_DATA_MAPPING_PROPERTY_NAME = "attrMapping";
private static final String DATA_TO_FETCH_VALIDATION_MSG = "DataToFetch property has invalid value: %s." +
" Only ATTRIBUTES and LATEST_TELEMETRY values supported!";
@Override @Override
public void onMsg(TbContext ctx, TbMsg msg) { public void onMsg(TbContext ctx, TbMsg msg) {
@ -45,7 +48,11 @@ public abstract class TbAbstractGetEntityDataNode<T extends EntityId> extends Tb
protected abstract ListenableFuture<T> findEntityAsync(TbContext ctx, EntityId originator); protected abstract ListenableFuture<T> findEntityAsync(TbContext ctx, EntityId originator);
protected abstract void checkDataToFetchSupportedOrElseThrow(DataToFetch dataToFetch) throws TbNodeException; protected void checkDataToFetchSupportedOrElseThrow(DataToFetch dataToFetch) throws TbNodeException {
if (dataToFetch == null || dataToFetch.equals(DataToFetch.FIELDS)) {
throw new TbNodeException(String.format(DATA_TO_FETCH_VALIDATION_MSG, dataToFetch));
}
}
protected void processDataAndTell(TbContext ctx, TbMsg msg, T entityId, ObjectNode msgDataAsJsonNode) { protected void processDataAndTell(TbContext ctx, TbMsg msg, T entityId, ObjectNode msgDataAsJsonNode) {
DataToFetch dataToFetch = config.getDataToFetch(); DataToFetch dataToFetch = config.getDataToFetch();

View File

@ -37,11 +37,10 @@ import java.util.concurrent.ExecutionException;
type = ComponentType.ENRICHMENT, type = ComponentType.ENRICHMENT,
name = "fetch device credentials", name = "fetch device credentials",
configClazz = TbFetchDeviceCredentialsNodeConfiguration.class, configClazz = TbFetchDeviceCredentialsNodeConfiguration.class,
nodeDescription = "Enrich the message body or metadata with the device credentials", nodeDescription = "Adds device credentials to the message or message metadata",
nodeDetails = "Adds <b>credentialsType</b> and <b>credentials</b> properties to the message metadata if the " + nodeDetails = "if message originator type is Device and device credentials was successfully fetched, " +
"configuration parameter <b>fetchToMetadata</b> is set to <code>true</code>, otherwise, adds properties " + "rule node enriches message or message metadata with <i>credentialsType</i> and <i>credentials</i> properties " +
"to the message data. If originator type is not <b>DEVICE</b> or rule node failed to get device credentials " + "and send message via <code>Success</code> chain. Otherwise message will be forwarded via <code>Failure</code> chain.",
"- send Message via <code>Failure</code> chain, otherwise <code>Success</code> chain is used.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeFetchDeviceCredentialsConfig") configDirective = "tbEnrichmentNodeFetchDeviceCredentialsConfig")
public class TbFetchDeviceCredentialsNode extends TbAbstractNodeWithFetchTo<TbFetchDeviceCredentialsNodeConfiguration> { public class TbFetchDeviceCredentialsNode extends TbAbstractNodeWithFetchTo<TbFetchDeviceCredentialsNodeConfiguration> {

View File

@ -36,11 +36,13 @@ import org.thingsboard.server.common.msg.TbMsg;
@RuleNode(type = ComponentType.ENRICHMENT, @RuleNode(type = ComponentType.ENRICHMENT,
name = "originator attributes", name = "originator attributes",
configClazz = TbGetAttributesNodeConfiguration.class, configClazz = TbGetAttributesNodeConfiguration.class,
nodeDescription = "Enrich the message body or metadata with the originator attributes and/or timeseries data", nodeDescription = "Adds originator attributes and/or latest timeseries data for the message originator to the message or message metadata",
nodeDetails = "If Attributes enrichment configured, <b>CLIENT/SHARED/SERVER</b> attributes are added into Message data/metadata " + nodeDetails = "If attributes enrichment configured, <i>CLIENT/SHARED/SERVER</i> attributes are added into message or message metadata " +
"with specific prefix: <i>cs/shared/ss</i>. Latest telemetry value added into Message data/metadata without prefix. " + "with specific prefix: <i>cs/shared/ss</i>. Latest telemetry value adds without prefix. <br><br>" +
"To access those attributes in other nodes this template can be used " + "See the following examples of accessing those attributes in other nodes:<br>" +
"<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ", "<code>metadata.cs_serialNumber</code> - to access client side attribute 'serialNumber' that was fetched to message metadata.<br>" +
"<code>metadata.shared_limit</code> - to access shared side attribute 'limit' that was fetched to message metadata.<br>" +
"<code>msg.temperature</code> - to access latest telemetry 'temperature' that was fetched to message.<br>",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeOriginatorAttributesConfig") configDirective = "tbEnrichmentNodeOriginatorAttributesConfig")
public class TbGetAttributesNode extends TbAbstractGetAttributesNode<TbGetAttributesNodeConfiguration, EntityId> { public class TbGetAttributesNode extends TbAbstractGetAttributesNode<TbGetAttributesNodeConfiguration, EntityId> {

View File

@ -35,16 +35,17 @@ import org.thingsboard.server.common.data.util.TbPair;
type = ComponentType.ENRICHMENT, type = ComponentType.ENRICHMENT,
name = "customer attributes", name = "customer attributes",
configClazz = TbGetEntityDataNodeConfiguration.class, configClazz = TbGetEntityDataNodeConfiguration.class,
nodeDescription = "Add Originators Customer Attributes or Latest Telemetry into Message or Metadata", nodeDescription = "Adds message originator customer attributes or latest telemetry into message or message metadata",
nodeDetails = "Enrich the Message or Metadata with the corresponding customer's latest attributes or telemetry value. " + nodeDetails = "Enriches incoming message or message metadata with the customer's attributes or latest telemetry values. <br><br>" +
"The customer is selected based on the originator of the message: device, asset, etc. " + "The customer is selected based on the originator of the message. " +
"</br>" + "Supported originator types: <br><br>" +
"Customer, User, Asset, Device. <br><br>" +
"Useful when you store some parameters on the customer level and would like to use them for message processing.", "Useful when you store some parameters on the customer level and would like to use them for message processing.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeCustomerAttributesConfig") configDirective = "tbEnrichmentNodeCustomerAttributesConfig")
public class TbGetCustomerAttributeNode extends TbAbstractGetEntityDataNode<CustomerId> { public class TbGetCustomerAttributeNode extends TbAbstractGetEntityDataNode<CustomerId> {
private static final String CUSTOMER_NOT_FOUND_MESSAGE = "Failed to find customer for entity with id %s and type %s"; private static final String CUSTOMER_NOT_FOUND_MESSAGE = "Failed to find customer for entity with id: %s and type: %s";
@Override @Override
protected TbGetEntityDataNodeConfiguration loadNodeConfiguration(TbNodeConfiguration configuration) throws TbNodeException { protected TbGetEntityDataNodeConfiguration loadNodeConfiguration(TbNodeConfiguration configuration) throws TbNodeException {
@ -54,14 +55,6 @@ public class TbGetCustomerAttributeNode extends TbAbstractGetEntityDataNode<Cust
return config; return config;
} }
@Override
protected void checkDataToFetchSupportedOrElseThrow(DataToFetch dataToFetch) throws TbNodeException {
if (dataToFetch == null || dataToFetch.equals(DataToFetch.FIELDS)) {
throw new TbNodeException("DataToFetch property has invalid value: " + dataToFetch +
". Only ATTRIBUTES and LATEST_TELEMETRY values supported!");
}
}
@Override @Override
protected ListenableFuture<CustomerId> findEntityAsync(TbContext ctx, EntityId originator) { protected ListenableFuture<CustomerId> findEntityAsync(TbContext ctx, EntityId originator) {
return Futures.transformAsync(EntitiesCustomerIdAsyncLoader.findEntityIdAsync(ctx, originator), return Futures.transformAsync(EntitiesCustomerIdAsyncLoader.findEntityIdAsync(ctx, originator),

View File

@ -44,10 +44,13 @@ import java.util.NoSuchElementException;
@RuleNode(type = ComponentType.ENRICHMENT, @RuleNode(type = ComponentType.ENRICHMENT,
name = "customer details", name = "customer details",
configClazz = TbGetCustomerDetailsNodeConfiguration.class, configClazz = TbGetCustomerDetailsNodeConfiguration.class,
nodeDescription = "Enrich the message body or metadata with the corresponding customer details: title, address, email, phone, etc.", nodeDescription = "Adds originator customer details into message or message metadata",
nodeDetails = "If checkbox: <b>Add selected details to the message metadata</b> is selected, existing fields will be added to the message metadata instead of message data.<br><br>" + nodeDetails = "Enriches incoming message or message metadata with the corresponding customer details. " +
"<b>Note:</b> only Device, Asset, and Entity View type are allowed.<br><br>" + "Selected details adds to the message with predefined prefix: <code>customer_</code>. Examples: <code>customer_title</code>, <code>customer_address</code>, etc. <br><br>" +
"If the originator of the message is not assigned to Customer, or originator type is not supported - Message will be forwarded to <b>Failure</b> chain, otherwise, <b>Success</b> chain will be used.", "The customer is selected based on the originator of the message. Supported originator types: <br><br>" +
"Device, Asset, Entity view, User, Edge. <br><br>" +
"If message originator is not assigned to customer, or originator is not supported - " +
"message will be forwarded via <code>Failure</code> chain, otherwise, <code>Success</code> chain will be used.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeEntityDetailsConfig") configDirective = "tbEnrichmentNodeEntityDetailsConfig")
public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetCustomerDetailsNodeConfiguration, CustomerId> { public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetCustomerDetailsNodeConfiguration, CustomerId> {
@ -96,9 +99,9 @@ public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode<TbG
if (hasCustomerId.getCustomerId() == null || hasCustomerId.getCustomerId().isNullUid()) { if (hasCustomerId.getCustomerId() == null || hasCustomerId.getCustomerId().isNullUid()) {
if (hasCustomerId instanceof HasName) { if (hasCustomerId instanceof HasName) {
var hasName = (HasName) hasCustomerId; var hasName = (HasName) hasCustomerId;
throw new RuntimeException(originator.getEntityType().getNormalName() + " with name '" + hasName.getName() + "' is not assigned to Customer."); throw new RuntimeException(originator.getEntityType().getNormalName() + " with name '" + hasName.getName() + "' is not assigned to Customer!");
} }
throw new RuntimeException(originator.getEntityType().getNormalName() + " with id '" + originator + "' is not assigned to Customer."); throw new RuntimeException(originator.getEntityType().getNormalName() + " with id '" + originator + "' is not assigned to Customer!");
} else { } else {
return ctx.getCustomerService().findCustomerByIdAsync(ctx.getTenantId(), hasCustomerId.getCustomerId()); return ctx.getCustomerService().findCustomerByIdAsync(ctx.getTenantId(), hasCustomerId.getCustomerId());
} }

View File

@ -34,11 +34,15 @@ import org.thingsboard.server.common.msg.TbMsg;
@RuleNode(type = ComponentType.ENRICHMENT, @RuleNode(type = ComponentType.ENRICHMENT,
name = "related device attributes", name = "related device attributes",
configClazz = TbGetDeviceAttrNodeConfiguration.class, configClazz = TbGetDeviceAttrNodeConfiguration.class,
nodeDescription = "Add Originators Related Device Attributes and Latest Telemetry value into Message Data or Metadata", nodeDescription = "Add originators related device attributes and latest telemetry values into message or message metadata",
nodeDetails = "If Attributes enrichment configured, <b>CLIENT/SHARED/SERVER</b> attributes are added into Message data/metadata " + nodeDetails = "Related device lookup based on the configured relation query. " +
"with specific prefix: <i>cs/shared/ss</i>. Latest telemetry value added into Message data/metadata without prefix. " + "If multiple related devices are found, only first device is used for message enrichment, other entities are discarded.<br><br>" +
"To access those attributes in other nodes this template can be used " + "If Attributes enrichment configured, <i>CLIENT/SHARED/SERVER</i> attributes are added into message or message metadata " +
"<code>metadata.cs_temperature</code> or <code>metadata.shared_limit</code> ", "with specific prefix: <i>cs/shared/ss</i>. Latest telemetry value adds into message or message metadata without prefix. <br><br>" +
"See the following examples of accessing those attributes in other nodes:<br>" +
"<code>metadata.cs_serialNumber</code> - to access client side attribute 'serialNumber' that was fetched to message metadata.<br>" +
"<code>metadata.shared_limit</code> - to access shared side attribute 'limit' that was fetched to message metadata.<br>" +
"<code>msg.temperature</code> - to access latest telemetry 'temperature' that was fetched to message.<br>",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeDeviceAttributesConfig") configDirective = "tbEnrichmentNodeDeviceAttributesConfig")
public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode<TbGetDeviceAttrNodeConfiguration, DeviceId> { public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode<TbGetDeviceAttrNodeConfiguration, DeviceId> {

View File

@ -37,9 +37,12 @@ import java.util.concurrent.ExecutionException;
@RuleNode(type = ComponentType.ENRICHMENT, @RuleNode(type = ComponentType.ENRICHMENT,
name = "originator fields", name = "originator fields",
configClazz = TbGetOriginatorFieldsConfiguration.class, configClazz = TbGetOriginatorFieldsConfiguration.class,
nodeDescription = "Add Message Originator fields values into Message Metadata or Message Data", nodeDescription = "Adds message originator fields values into message or message metadata",
nodeDetails = "Will fetch fields values specified in mapping. If specified field is not part of originator fields it will be ignored. " + nodeDetails = "Fetches fields values specified in the mapping. If specified field is not part of originator fields it will be ignored. " +
"This node supports only following originator types: TENANT, CUSTOMER, USER, ASSET, DEVICE, ALARM, RULE_CHAIN, ENTITY_VIEW.", "Supported originator types: <br><br>" +
"Tenant, Customer, User, Asset, Device, Alarm, Rule chain, Entity view.<br><br>" +
"If message originator is not supported - message will be forwarded via <code>Failure</code> chain, " +
"otherwise, <code>Success</code> chain will be used.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeOriginatorFieldsConfig") configDirective = "tbEnrichmentNodeOriginatorFieldsConfig")
public class TbGetOriginatorFieldsNode extends TbAbstractGetMappedDataNode<EntityId, TbGetOriginatorFieldsConfiguration> { public class TbGetOriginatorFieldsNode extends TbAbstractGetMappedDataNode<EntityId, TbGetOriginatorFieldsConfiguration> {

View File

@ -34,15 +34,18 @@ import java.util.Arrays;
@Slf4j @Slf4j
@RuleNode( @RuleNode(
type = ComponentType.ENRICHMENT, type = ComponentType.ENRICHMENT,
name = "related attributes", name = "related entity data",
configClazz = TbGetRelatedDataNodeConfiguration.class, configClazz = TbGetRelatedDataNodeConfiguration.class,
nodeDescription = "Add Originators Related Entity Attributes or Latest Telemetry into Message Metadata/Data", nodeDescription = "Adds originators related entity data into message or message metadata",
nodeDetails = "Related Entity found using configured relation direction and Relation Type. " + nodeDetails = "Related entity lookup based on the configured relation query. " +
"If multiple Related Entities are found, only first Entity is used for attributes enrichment, other entities are discarded. " + "If multiple related entities are found, only first entity is used for message enrichment, other entities are discarded.<br><br>" +
"If Attributes enrichment configured, server scope attributes are added into Message Metadata/Data. " + "Data to fetch configuration: <br><br>" +
"If Latest Telemetry enrichment configured, latest telemetry added into Metadata/Data. " + "<i>Attributes</i> - rule node fetches server scope attributes configured in mapping and adds them into message or message metadata. " +
"To access those attributes in other nodes this template can be used " + "Access example in other nodes: <code>metadata.serialNumber</code>, <code>msg.serialNumber</code>.<br>" +
"<code>metadata.temperature</code>.", "<i>Latest telemetry</i> - rule node fetches latest telemetry configured in mapping and adds them into message or message metadata. " +
"Access example in other nodes: <code>metadata.temperature</code>, <code>msg.temperature</code>.<br>" +
"<i>Fields</i> - rule node fetches fields configured in mapping and adds them into message or message metadata. " +
"Access example in other nodes: <code>metadata.entityName</code>, <code>msg.entityName</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeRelatedAttributesConfig") configDirective = "tbEnrichmentNodeRelatedAttributesConfig")
public class TbGetRelatedAttributeNode extends TbAbstractGetEntityDataNode<EntityId> { public class TbGetRelatedAttributeNode extends TbAbstractGetEntityDataNode<EntityId> {

View File

@ -54,13 +54,17 @@ import static org.thingsboard.rule.engine.metadata.TbGetTelemetryNodeConfigurati
@RuleNode(type = ComponentType.ENRICHMENT, @RuleNode(type = ComponentType.ENRICHMENT,
name = "originator telemetry", name = "originator telemetry",
configClazz = TbGetTelemetryNodeConfiguration.class, configClazz = TbGetTelemetryNodeConfiguration.class,
nodeDescription = "Add Message Originator Telemetry for selected time range into Message Metadata\n", nodeDescription = "Adds message originator telemetry for selected time range into message metadata",
nodeDetails = "The node allows you to select fetch mode: <b>FIRST/LAST/ALL</b> to fetch telemetry of certain time range that are added into Message metadata without any prefix. " + nodeDetails = "The node allows you to configure fetch interval and fetch strategy. Fetch strategy section allows you to select fetch mode: <i>First/Last/All</i> <br><br>" +
"If selected fetch mode <b>ALL</b> Telemetry will be added like array into Message Metadata where <b>key</b> is Timestamp and <b>value</b> is value of Telemetry.</br>" + "If selected fetch mode <i>First</i> rule node will retrieve the closest telemetry to the fetch interval's start.<br>" +
"If selected fetch mode <b>FIRST</b> or <b>LAST</b> Telemetry will be added like string without Timestamp.</br>" + "If selected fetch mode <i>Last</i> rule node will retrieve the closest telemetry to the fetch interval's end.<br>" +
"Also, the rule node allows you to select telemetry sampling order: <b>ASC</b> or <b>DESC</b>. </br>" + "If selected fetch mode <i>All</i> rule node will retrieve telemetry from the fetch interval with configurable query parameters.<br><br>" +
"Aggregation feature allows you to fetch aggregated telemetry as a single value by <b>AVG, COUNT, SUM, MIN, MAX, NONE</b>. </br>" + "Query parameters: <br><br>" +
"<b>Note</b>: The maximum size of the fetched array is 1000 records.\n ", "Data aggregation function: <i>Min/Max/Average/Sum/Count/None</i>. " +
"If selected aggregation function <i>None</i> rule node allows you to configure additional query parameters: <br><br>" +
"Order by timestamp: <i>Ascending/Descending</i><br><br>" +
"Limit: Min value - 2, max value - 1000.<br><br>" +
"Other data aggregation functions useful when you need to get the aggregated telemetry data as a single value for the configured fetch interval.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase") configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase")
public class TbGetTelemetryNode implements TbNode { public class TbGetTelemetryNode implements TbNode {

View File

@ -34,11 +34,9 @@ import org.thingsboard.server.common.data.util.TbPair;
type = ComponentType.ENRICHMENT, type = ComponentType.ENRICHMENT,
name = "tenant attributes", name = "tenant attributes",
configClazz = TbGetEntityDataNodeConfiguration.class, configClazz = TbGetEntityDataNodeConfiguration.class,
nodeDescription = "Add Originators Tenant Attributes or Latest Telemetry into Message Metadata/Data", nodeDescription = "Adds message originator tenant attributes or latest telemetry into message or message metadata",
nodeDetails = "If Attributes enrichment configured, server scope attributes are added into Message Metadata/Data. " + nodeDetails = "Enriches incoming message or message metadata with the tenant's attributes or latest telemetry values. " +
"If Latest Telemetry enrichment configured, latest telemetry added into Metadata/Data. " + "Useful when you store some parameters on the tenant level and would like to use them for message processing.",
"To access those attributes in other nodes this template can be used " +
"<code>metadata.temperature</code>.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeTenantAttributesConfig") configDirective = "tbEnrichmentNodeTenantAttributesConfig")
public class TbGetTenantAttributeNode extends TbAbstractGetEntityDataNode<TenantId> { public class TbGetTenantAttributeNode extends TbAbstractGetEntityDataNode<TenantId> {
@ -56,14 +54,6 @@ public class TbGetTenantAttributeNode extends TbAbstractGetEntityDataNode<Tenant
return Futures.immediateFuture(ctx.getTenantId()); return Futures.immediateFuture(ctx.getTenantId());
} }
@Override
protected void checkDataToFetchSupportedOrElseThrow(DataToFetch dataToFetch) throws TbNodeException {
if (dataToFetch == null || dataToFetch.equals(DataToFetch.FIELDS)) {
throw new TbNodeException("DataToFetch property has invalid value: " + dataToFetch +
". Only ATTRIBUTES and LATEST_TELEMETRY values supported!");
}
}
@Override @Override
public TbPair<Boolean, JsonNode> upgrade(int fromVersion, JsonNode oldConfiguration) throws TbNodeException { public TbPair<Boolean, JsonNode> upgrade(int fromVersion, JsonNode oldConfiguration) throws TbNodeException {
return fromVersion == 0 ? upgradeToUseFetchToAndDataToFetch(oldConfiguration) : new TbPair<>(false, oldConfiguration); return fromVersion == 0 ? upgradeToUseFetchToAndDataToFetch(oldConfiguration) : new TbPair<>(false, oldConfiguration);

View File

@ -33,10 +33,9 @@ import org.thingsboard.server.common.msg.TbMsg;
@RuleNode(type = ComponentType.ENRICHMENT, @RuleNode(type = ComponentType.ENRICHMENT,
name = "tenant details", name = "tenant details",
configClazz = TbGetTenantDetailsNodeConfiguration.class, configClazz = TbGetTenantDetailsNodeConfiguration.class,
nodeDescription = "Adds fields from Tenant details to the message body or metadata", nodeDescription = "Adds originator tenant details into message or message metadata",
nodeDetails = "If checkbox: <b>Add selected details to the message metadata</b> is selected, existing fields will be added to the message metadata instead of message data.<br><br>" + nodeDetails = "Enriches incoming message or message metadata with the corresponding tenant details. " +
"<b>Note:</b> only Device, Asset, and Entity View type are allowed.<br><br>" + "Selected details adds to the message with predefined prefix: <code>tenant_</code>, Examples: <code>tenant_title</code> or <code>tenant_address</code>, etc.",
"If the originator of the message is not assigned to Tenant, or originator type is not supported - Message will be forwarded to <b>Failure</b> chain, otherwise, <b>Success</b> chain will be used.",
uiResources = {"static/rulenode/rulenode-core-config.js"}, uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbEnrichmentNodeEntityDetailsConfig") configDirective = "tbEnrichmentNodeEntityDetailsConfig")
public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetTenantDetailsNodeConfiguration, TenantId> { public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode<TbGetTenantDetailsNodeConfiguration, TenantId> {

View File

@ -262,7 +262,7 @@ public class TbGetCustomerAttributeNodeTest {
var actualException = actualExceptionCaptor.getValue(); var actualException = actualExceptionCaptor.getValue();
var expectedExceptionMessage = String.format( var expectedExceptionMessage = String.format(
"Failed to find customer for entity with id %s and type %s", "Failed to find customer for entity with id: %s and type: %s",
userId.getId(), userId.getEntityType().getNormalName()); userId.getId(), userId.getEntityType().getNormalName());
assertEquals(msg, actualMessage); assertEquals(msg, actualMessage);

View File

@ -385,7 +385,7 @@ public class TbGetCustomerDetailsNodeTest {
assertThat(actualMsg.getMetaData()).isEqualTo(msg.getMetaData()); assertThat(actualMsg.getMetaData()).isEqualTo(msg.getMetaData());
assertThat(actualException).isInstanceOf(RuntimeException.class); assertThat(actualException).isInstanceOf(RuntimeException.class);
assertThat(actualException.getMessage()).isEqualTo("Device with name 'Thermostat' is not assigned to Customer."); assertThat(actualException.getMessage()).isEqualTo("Device with name 'Thermostat' is not assigned to Customer!");
} }
@Test @Test