thingsboard-memoizeit
Changes
application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java 90(+56 -34)
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/FilterNode.java 50(+0 -50)
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/NodeDefinition.java 34(+12 -22)
rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TransformationNode.java 51(+0 -51)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java 11(+7 -4)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java 9(+6 -3)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java 7(+5 -2)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java 12(+7 -5)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java 9(+6 -3)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java 13(+6 -7)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java 9(+6 -3)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java 5(+4 -1)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java 11(+7 -4)
ui/src/app/common/types.constant.js 15(+13 -2)
ui/src/app/rulechain/rulechain.scss 29(+29 -0)
Details
diff --git a/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java b/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java
index d9416d7..52d7d7d 100644
--- a/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java
+++ b/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java
@@ -16,6 +16,8 @@
package org.thingsboard.server.service.component;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import lombok.extern.slf4j.Slf4j;
@@ -26,16 +28,14 @@ import org.springframework.context.annotation.ClassPathScanningCandidateComponen
import org.springframework.core.env.Environment;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Service;
-import org.thingsboard.rule.engine.api.ActionNode;
-import org.thingsboard.rule.engine.api.EnrichmentNode;
-import org.thingsboard.rule.engine.api.FilterNode;
-import org.thingsboard.rule.engine.api.TransformationNode;
+import org.thingsboard.rule.engine.api.*;
import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.dao.component.ComponentDescriptorService;
import org.thingsboard.server.extensions.api.component.*;
import javax.annotation.PostConstruct;
+import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.stream.Collectors;
@@ -70,6 +70,24 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
}
}
+ private void registerRuleNodeComponents() {
+ Set<BeanDefinition> ruleNodeBeanDefinitions = getBeanDefinitions(RuleNode.class);
+ for (BeanDefinition def : ruleNodeBeanDefinitions) {
+ try {
+ String clazzName = def.getBeanClassName();
+ Class<?> clazz = Class.forName(clazzName);
+ RuleNode ruleNodeAnnotation = clazz.getAnnotation(RuleNode.class);
+ ComponentType type = ruleNodeAnnotation.type();
+ ComponentDescriptor component = scanAndPersistComponent(def, type);
+ components.put(component.getClazz(), component);
+ componentsMap.computeIfAbsent(type, k -> new ArrayList<>()).add(component);
+ } catch (Exception e) {
+ log.error("Can't initialize component {}, due to {}", def.getBeanClassName(), e.getMessage(), e);
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
private void registerComponents(ComponentType type, Class<? extends Annotation> annotation) {
List<ComponentDescriptor> components = persist(getBeanDefinitions(annotation), type);
componentsMap.put(type, components);
@@ -97,34 +115,25 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
String descriptorResourceName;
switch (type) {
case ENRICHMENT:
- EnrichmentNode enrichmentAnnotation = clazz.getAnnotation(EnrichmentNode.class);
- scannedComponent.setName(enrichmentAnnotation.name());
- scannedComponent.setScope(enrichmentAnnotation.scope());
- descriptorResourceName = enrichmentAnnotation.descriptor();
- break;
case FILTER:
- FilterNode filterAnnotation = clazz.getAnnotation(FilterNode.class);
- scannedComponent.setName(filterAnnotation.name());
- scannedComponent.setScope(filterAnnotation.scope());
- descriptorResourceName = filterAnnotation.descriptor();
- break;
case TRANSFORMATION:
- TransformationNode trAnnotation = clazz.getAnnotation(TransformationNode.class);
- scannedComponent.setName(trAnnotation.name());
- scannedComponent.setScope(trAnnotation.scope());
- descriptorResourceName = trAnnotation.descriptor();
- break;
case ACTION:
- ActionNode actionAnnotation = clazz.getAnnotation(ActionNode.class);
- scannedComponent.setName(actionAnnotation.name());
- scannedComponent.setScope(actionAnnotation.scope());
- descriptorResourceName = actionAnnotation.descriptor();
+ RuleNode ruleNodeAnnotation = clazz.getAnnotation(RuleNode.class);
+ scannedComponent.setName(ruleNodeAnnotation.name());
+ scannedComponent.setScope(ruleNodeAnnotation.scope());
+ NodeDefinition nodeDefinition = prepareNodeDefinition(ruleNodeAnnotation);
+ ObjectNode configurationDescriptor = mapper.createObjectNode();
+ JsonNode node = mapper.valueToTree(nodeDefinition);
+ configurationDescriptor.set("nodeDefinition", node);
+ scannedComponent.setConfigurationDescriptor(configurationDescriptor);
break;
case OLD_ACTION:
Action oldActionAnnotation = clazz.getAnnotation(Action.class);
scannedComponent.setName(oldActionAnnotation.name());
scannedComponent.setScope(oldActionAnnotation.scope());
descriptorResourceName = oldActionAnnotation.descriptor();
+ scannedComponent.setConfigurationDescriptor(mapper.readTree(
+ Resources.toString(Resources.getResource(descriptorResourceName), Charsets.UTF_8)));
break;
case PLUGIN:
Plugin pluginAnnotation = clazz.getAnnotation(Plugin.class);
@@ -143,12 +152,12 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
}
}
scannedComponent.setActions(Arrays.stream(pluginAnnotation.actions()).map(Class::getName).collect(Collectors.joining(",")));
+ scannedComponent.setConfigurationDescriptor(mapper.readTree(
+ Resources.toString(Resources.getResource(descriptorResourceName), Charsets.UTF_8)));
break;
default:
throw new RuntimeException(type + " is not supported yet!");
}
- scannedComponent.setConfigurationDescriptor(mapper.readTree(
- Resources.toString(Resources.getResource(descriptorResourceName), Charsets.UTF_8)));
scannedComponent.setClazz(clazzName);
log.info("Processing scanned component: {}", scannedComponent);
} catch (Exception e) {
@@ -171,6 +180,20 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
return scannedComponent;
}
+ private NodeDefinition prepareNodeDefinition(RuleNode nodeAnnotation) throws IOException {
+ NodeDefinition nodeDefinition = new NodeDefinition();
+ nodeDefinition.setDetails(nodeAnnotation.nodeDetails());
+ nodeDefinition.setDescription(nodeAnnotation.nodeDescription());
+ nodeDefinition.setInEnabled(nodeAnnotation.inEnabled());
+ nodeDefinition.setOutEnabled(nodeAnnotation.outEnabled());
+ nodeDefinition.setRelationTypes(nodeAnnotation.relationTypes());
+ nodeDefinition.setCustomRelations(nodeAnnotation.customRelations());
+ String defaultConfigResourceName = nodeAnnotation.defaultConfigResource();
+ nodeDefinition.setDefaultConfiguration(mapper.readTree(
+ Resources.toString(Resources.getResource(defaultConfigResourceName), Charsets.UTF_8)));
+ return nodeDefinition;
+ }
+
private Set<BeanDefinition> getBeanDefinitions(Class<? extends Annotation> componentType) {
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(componentType));
@@ -183,13 +206,8 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
@Override
public void discoverComponents() {
- registerComponents(ComponentType.ENRICHMENT, EnrichmentNode.class);
-
- registerComponents(ComponentType.FILTER, FilterNode.class);
-
- registerComponents(ComponentType.TRANSFORMATION, TransformationNode.class);
- registerComponents(ComponentType.ACTION, ActionNode.class);
+ registerRuleNodeComponents();
registerComponents(ComponentType.OLD_ACTION, Action.class);
@@ -200,15 +218,19 @@ public class AnnotationComponentDiscoveryService implements ComponentDiscoverySe
@Override
public List<ComponentDescriptor> getComponents(ComponentType type) {
- return Collections.unmodifiableList(componentsMap.get(type));
+ if (componentsMap.containsKey(type)) {
+ return Collections.unmodifiableList(componentsMap.get(type));
+ } else {
+ return Collections.emptyList();
+ }
}
@Override
public List<ComponentDescriptor> getComponents(Set<ComponentType> types) {
List<ComponentDescriptor> result = new ArrayList<>();
- for (ComponentType type : types) {
+ types.stream().filter(type -> componentsMap.containsKey(type)).forEach(type -> {
result.addAll(componentsMap.get(type));
- }
+ });
return Collections.unmodifiableList(result);
}
diff --git a/rule-engine/rule-engine-api/src/main/resources/EmptyNodeConfig.json b/rule-engine/rule-engine-api/src/main/resources/EmptyNodeConfig.json
new file mode 100644
index 0000000..7a73a41
--- /dev/null
+++ b/rule-engine/rule-engine-api/src/main/resources/EmptyNodeConfig.json
@@ -0,0 +1,2 @@
+{
+}
\ No newline at end of file
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
index 393496a..c85d480 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
@@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.thingsboard.rule.engine.TbNodeUtils;
import org.thingsboard.rule.engine.api.*;
import org.thingsboard.rule.engine.js.NashornJsEngine;
+import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
import javax.script.Bindings;
@@ -26,12 +27,14 @@ import javax.script.Bindings;
import static org.thingsboard.rule.engine.DonAsynchron.withCallback;
@Slf4j
-@FilterNode(name = "script", relationTypes = {"True", "False", "Failure"},
+@RuleNode(
+ type = ComponentType.FILTER,
+ name = "script", relationTypes = {"True", "False", "Failure"},
nodeDescription = "Filter incoming messages using JS script",
nodeDetails = "Evaluate incoming Message with configured JS condition. " +
- "If 'True' - send Message via 'True' chain, otherwise 'False' chain is used." +
- "Message payload can be accessed via 'msg' property. For example 'msg.temperature < 10;'" +
- "Message metadata can be accessed via 'meta' property. For example 'meta.customerName === 'John';'")
+ "If <b>True</b> - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used." +
+ "Message payload can be accessed via <code>msg</code> property. For example <code>msg.temperature < 10;</code>" +
+ "Message metadata can be accessed via <code>meta</code> property. For example <code>meta.customerName === 'John';</code>")
public class TbJsFilterNode implements TbNode {
private TbJsFilterNodeConfiguration config;
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
index dff2145..faf97b4 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
@@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.thingsboard.rule.engine.TbNodeUtils;
import org.thingsboard.rule.engine.api.*;
import org.thingsboard.rule.engine.js.NashornJsEngine;
+import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
import javax.script.Bindings;
@@ -27,12 +28,14 @@ import java.util.Set;
import static org.thingsboard.rule.engine.DonAsynchron.withCallback;
@Slf4j
-@FilterNode(name = "switch", customRelations = true,
+@RuleNode(
+ type = ComponentType.FILTER,
+ name = "switch", customRelations = true,
nodeDescription = "Route incoming Message to one or multiple output chains",
nodeDetails = "Node executes configured JS script. Script should return array of next Chain names where Message should be routed. " +
"If Array is empty - message not routed to next Node. " +
- "Message payload can be accessed via 'msg' property. For example 'msg.temperature < 10;' " +
- "Message metadata can be accessed via 'meta' property. For example 'meta.customerName === 'John';' ")
+ "Message payload can be accessed via <code>msg</code> property. For example <code>msg.temperature < 10;</code> " +
+ "Message metadata can be accessed via <code>meta</code> property. For example <code>meta.customerName === 'John';</code>")
public class TbJsSwitchNode implements TbNode {
private TbJsSwitchNodeConfiguration config;
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java
index c08c3e0..7a6f9fd 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java
@@ -18,16 +18,19 @@ package org.thingsboard.rule.engine.filter;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.rule.engine.TbNodeUtils;
import org.thingsboard.rule.engine.api.*;
+import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
/**
* Created by ashvayka on 19.01.18.
*/
@Slf4j
-@FilterNode(name = "message type",
+@RuleNode(
+ type = ComponentType.FILTER,
+ name = "message type",
nodeDescription = "Filter incoming messages by Message Type",
nodeDetails = "Evaluate incoming Message with configured JS condition. " +
- "If incoming MessageType is expected - send Message via 'Success' chain, otherwise 'Failure' chain is used.")
+ "If incoming MessageType is expected - send Message via <b>Success</b> chain, otherwise <b>Failure</b> chain is used.")
public class TbMsgTypeFilterNode implements TbNode {
TbMsgTypeFilterNodeConfiguration config;
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java
index 216cf28..6228206 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java
@@ -24,6 +24,7 @@ import org.thingsboard.rule.engine.TbNodeUtils;
import org.thingsboard.rule.engine.api.*;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
+import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
import java.util.List;
@@ -35,11 +36,12 @@ import static org.thingsboard.server.common.data.DataConstants.*;
* Created by ashvayka on 19.01.18.
*/
@Slf4j
-@EnrichmentNode(name = "originator attributes",
- nodeDescription = "Add Message Originator Attributes or Latest Telemetry into Message Metadata",
- nodeDetails = "If Attributes enrichment configured, CLIENT/SHARED/SERVER attributes are added into Message metadata " +
- "with specific prefix: cs/shared/ss. To access those attributes in other nodes this template can be used " +
- "'meta.cs.temperature' or 'meta.shared.limit' " +
+@RuleNode(type = ComponentType.ENRICHMENT,
+ name = "originator attributes",
+ nodeDescription = "Add Message Originator Attributes or Latest Telemetry into Message Metadata",
+ nodeDetails = "If Attributes enrichment configured, <b>CLIENT/SHARED/SERVER</b> attributes are added into Message metadata " +
+ "with specific prefix: <i>cs/shared/ss</i>. To access those attributes in other nodes this template can be used " +
+ "<code>meta.cs.temperature</code> or <code>meta.shared.limit</code> " +
"If Latest Telemetry enrichment configured, latest telemetry added into metadata without prefix.")
public class TbGetAttributesNode implements TbNode {
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java
index c9cabaa..d85fb56 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java
@@ -16,17 +16,20 @@
package org.thingsboard.rule.engine.metadata;
import com.google.common.util.concurrent.ListenableFuture;
-import org.thingsboard.rule.engine.api.EnrichmentNode;
+import org.thingsboard.rule.engine.api.RuleNode;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.util.EntitiesCustomerIdAsyncLoader;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.plugin.ComponentType;
-@EnrichmentNode(name="customer attributes",
+@RuleNode(
+ type = ComponentType.ENRICHMENT,
+ name="customer attributes",
nodeDescription = "Add Originators Customer Attributes or Latest Telemetry into Message Metadata",
nodeDetails = "If Attributes enrichment configured, server scope attributes are added into Message metadata. " +
"To access those attributes in other nodes this template can be used " +
- "'meta.temperature'. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
+ "<code>meta.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
public class TbGetCustomerAttributeNode extends TbEntityGetAttrNode<CustomerId> {
@Override
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java
index f85d019..26b7561 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java
@@ -17,22 +17,21 @@ package org.thingsboard.rule.engine.metadata;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.rule.engine.TbNodeUtils;
-import org.thingsboard.rule.engine.api.TbContext;
-import org.thingsboard.rule.engine.api.TbNodeConfiguration;
-import org.thingsboard.rule.engine.api.TbNodeException;
-import org.thingsboard.rule.engine.api.TbNodeState;
-import org.thingsboard.rule.engine.api.EnrichmentNode;
+import org.thingsboard.rule.engine.api.*;
import org.thingsboard.rule.engine.util.EntitiesRelatedEntityIdAsyncLoader;
import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.plugin.ComponentType;
-@EnrichmentNode(name="related attributes",
+@RuleNode(
+ type = ComponentType.ENRICHMENT,
+ name="related attributes",
nodeDescription = "Add Originators Related Entity Attributes or Latest Telemetry into Message Metadata",
nodeDetails = "Related Entity found using configured relation direction and Relation Type. " +
"If multiple Related Entities are found, only first Entity is used for attributes enrichment, other entities are discarded. " +
"If Attributes enrichment configured, server scope attributes are added into Message metadata. " +
"To access those attributes in other nodes this template can be used " +
- "'meta.temperature'. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
+ "<code>meta.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
public class TbGetRelatedAttributeNode extends TbEntityGetAttrNode<EntityId> {
private TbGetRelatedAttrNodeConfiguration config;
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java
index 2603bc5..7d9c50b 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java
@@ -17,18 +17,21 @@ package org.thingsboard.rule.engine.metadata;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
-import org.thingsboard.rule.engine.api.EnrichmentNode;
+import org.thingsboard.rule.engine.api.RuleNode;
import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.rule.engine.util.EntitiesTenantIdAsyncLoader;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.plugin.ComponentType;
@Slf4j
-@EnrichmentNode(name="tenant attributes",
+@RuleNode(
+ type = ComponentType.ENRICHMENT,
+ name="tenant attributes",
nodeDescription = "Add Originators Tenant Attributes or Latest Telemetry into Message Metadata",
nodeDetails = "If Attributes enrichment configured, server scope attributes are added into Message metadata. " +
"To access those attributes in other nodes this template can be used " +
- "'meta.temperature'. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
+ "<code>meta.temperature</code>. If Latest Telemetry enrichment configured, latest telemetry added into metadata")
public class TbGetTenantAttributeNode extends TbEntityGetAttrNode<TenantId> {
@Override
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java
index 8ab8e18..d237df8 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java
@@ -27,12 +27,15 @@ import org.thingsboard.rule.engine.util.EntitiesCustomerIdAsyncLoader;
import org.thingsboard.rule.engine.util.EntitiesRelatedEntityIdAsyncLoader;
import org.thingsboard.rule.engine.util.EntitiesTenantIdAsyncLoader;
import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
import java.util.HashSet;
@Slf4j
-@TransformationNode(name="change originator",
+@RuleNode(
+ type = ComponentType.TRANSFORMATION,
+ name="change originator",
nodeDescription = "Change Message Originator To Tenant/Customer/Related Entity",
nodeDetails = "Related Entity found using configured relation direction and Relation Type. " +
"If multiple Related Entities are found, only first Entity is used as new Originator, other entities are discarded. ")
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java
index 3cd7cd1..babdbc3 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java
@@ -19,15 +19,18 @@ import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.rule.engine.TbNodeUtils;
import org.thingsboard.rule.engine.api.*;
import org.thingsboard.rule.engine.js.NashornJsEngine;
+import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;
import javax.script.Bindings;
-@TransformationNode(name = "script",
+@RuleNode(
+ type = ComponentType.TRANSFORMATION,
+ name = "script",
nodeDescription = "Change Message payload and Metadata using JavaScript",
- nodeDetails = "JavaScript function recieve 2 input parameters that can be changed inside. " +
- "'meta' - is a Message metadata. " +
- "'msg' - is a Message payload. Any properties can be changed/removed/added in those objects.")
+ nodeDetails = "JavaScript function recieve 2 input parameters that can be changed inside.<br/> " +
+ "<code>meta</code> - is a Message metadata.<br/>" +
+ "<code>msg</code> - is a Message payload.<br/>Any properties can be changed/removed/added in those objects.")
public class TbTransformMsgNode extends TbAbstractTransformNode {
private TbTransformMsgNodeConfiguration config;
ui/src/app/common/types.constant.js 15(+13 -2)
diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js
index 2f8d152..4dd961a 100644
--- a/ui/src/app/common/types.constant.js
+++ b/ui/src/app/common/types.constant.js
@@ -460,8 +460,19 @@ export default angular.module('thingsboard.types', [])
ruleNodeTypeComponentTypes: ["FILTER", "ENRICHMENT", "TRANSFORMATION", "ACTION"],
ruleChainNodeComponent: {
type: 'RULE_CHAIN',
- name: 'Rule chain',
- clazz: 'tb.internal.RuleChain'
+ name: 'rule chain',
+ clazz: 'tb.internal.RuleChain',
+ configurationDescriptor: {
+ nodeDefinition: {
+ description: "Forwards incoming messages to specified Rule Chain",
+ details: "Forwards incoming messages to specified Rule Chain",
+ inEnabled: true,
+ outEnabled: false,
+ relationTypes: [],
+ customRelations: false,
+ defaultConfiguration: {}
+ }
+ }
},
inputNodeComponent: {
type: 'INPUT',
diff --git a/ui/src/app/rulechain/rulechain.controller.js b/ui/src/app/rulechain/rulechain.controller.js
index 76d0fec..973618d 100644
--- a/ui/src/app/rulechain/rulechain.controller.js
+++ b/ui/src/app/rulechain/rulechain.controller.js
@@ -183,7 +183,8 @@ export function RuleChainController($stateParams, $scope, $compile, $q, $mdUtil,
'<div class="tb-rule-node-tooltip">' +
'<div id="tooltip-content" layout="column">' +
'<div class="tb-node-title">' + node.component.name + '</div>' +
- '<div class="tb-node-description">' + 'Some description of node' + '</div>' +
+ '<div class="tb-node-description">' + node.component.configurationDescriptor.nodeDefinition.description + '</div>' +
+ '<div class="tb-node-details">' + node.component.configurationDescriptor.nodeDefinition.details + '</div>' +
'</div>' +
'</div>'
);
ui/src/app/rulechain/rulechain.scss 29(+29 -0)
diff --git a/ui/src/app/rulechain/rulechain.scss b/ui/src/app/rulechain/rulechain.scss
index 258e232..26a5225 100644
--- a/ui/src/app/rulechain/rulechain.scss
+++ b/ui/src/app/rulechain/rulechain.scss
@@ -260,3 +260,32 @@
stroke-dashoffset: 500;
}
}
+
+.tb-rule-node-tooltip {
+ font-size: 14px;
+ width: 300px;
+ color: #333;
+ #tooltip-content {
+ .tb-node-title {
+ font-weight: 600;
+ }
+ .tb-node-description {
+ font-style: italic;
+ color: #555;
+ }
+ .tb-node-details {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ }
+ code {
+ padding: 0px 3px 2px 3px;
+ margin: 1px;
+ color: #AD1625;
+ white-space: nowrap;
+ background-color: #f7f7f9;
+ border: 1px solid #e1e1e8;
+ border-radius: 2px;
+ font-size: 12px;
+ }
+ }
+}
\ No newline at end of file