fix rule node descriptions & fix validation messages & updated tests
This commit is contained in:
parent
2a51125358
commit
d67313cf8c
@ -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 {
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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),
|
||||||
|
|||||||
@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user