diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index 21bc090c87..147c214a2f 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -321,7 +321,7 @@ public class ActorSystemContext { .put("msgId", tbMsg.getId().toString()) .put("msgType", tbMsg.getType()) .put("dataType", tbMsg.getDataType().name()) - .put("data", convertToString(tbMsg.getDataType(), tbMsg.getData())) + .put("data", tbMsg.getData()) .put("metadata", metadata); if (error != null) { @@ -335,21 +335,6 @@ public class ActorSystemContext { } } - private String convertToString(TbMsgDataType messageType, byte[] data) { - if (data == null) { - return null; - } - switch (messageType) { - case JSON: - case TEXT: - return new String(data, StandardCharsets.UTF_8); - case BINARY: - return Base64Utils.encodeToString(data); - default: - throw new RuntimeException("Message type: " + messageType + " is not supported!"); - } - } - public static Exception toException(Throwable error) { return Exception.class.isInstance(error) ? (Exception) error : new Exception(error); } diff --git a/application/src/test/java/org/thingsboard/server/rules/flow/AbstractRuleEngineFlowIntegrationTest.java b/application/src/test/java/org/thingsboard/server/rules/flow/AbstractRuleEngineFlowIntegrationTest.java index acbace6ae7..f88eb24336 100644 --- a/application/src/test/java/org/thingsboard/server/rules/flow/AbstractRuleEngineFlowIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/rules/flow/AbstractRuleEngineFlowIntegrationTest.java @@ -149,7 +149,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule "CUSTOM", device.getId(), new TbMsgMetaData(), - new byte[]{}); + "{}"); actorService.onMsg(new ServiceToRuleEngineMsg(savedTenant.getId(), tbMsg)); Thread.sleep(3000); diff --git a/application/src/test/java/org/thingsboard/server/rules/lifecycle/AbstractRuleEngineLifecycleIntegrationTest.java b/application/src/test/java/org/thingsboard/server/rules/lifecycle/AbstractRuleEngineLifecycleIntegrationTest.java index de690a745f..22d79f090f 100644 --- a/application/src/test/java/org/thingsboard/server/rules/lifecycle/AbstractRuleEngineLifecycleIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/rules/lifecycle/AbstractRuleEngineLifecycleIntegrationTest.java @@ -135,7 +135,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac "CUSTOM", device.getId(), new TbMsgMetaData(), - new byte[]{}); + "{}"); actorService.onMsg(new ServiceToRuleEngineMsg(savedTenant.getId(), tbMsg)); Thread.sleep(3000); diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java index 524cc5fe60..1c7de3bf10 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java @@ -39,9 +39,9 @@ public final class TbMsg implements Serializable { private final EntityId originator; private final TbMsgMetaData metaData; private final TbMsgDataType dataType; - private final byte[] data; + private final String data; - public TbMsg(UUID id, String type, EntityId originator, TbMsgMetaData metaData, byte[] data) { + public TbMsg(UUID id, String type, EntityId originator, TbMsgMetaData metaData, String data) { this.id = id; this.type = type; this.originator = originator; @@ -64,7 +64,7 @@ public final class TbMsg implements Serializable { } builder.setDataType(msg.getDataType().ordinal()); - builder.setData(ByteString.copyFrom(msg.getData())); + builder.setData(msg.getData()); byte[] bytes = builder.build().toByteArray(); return ByteBuffer.wrap(bytes); } @@ -75,16 +75,13 @@ public final class TbMsg implements Serializable { TbMsgMetaData metaData = new TbMsgMetaData(proto.getMetaData().getDataMap()); EntityId entityId = EntityIdFactory.getByTypeAndId(proto.getEntityType(), proto.getEntityId()); TbMsgDataType dataType = TbMsgDataType.values()[proto.getDataType()]; - return new TbMsg(UUID.fromString(proto.getId()), proto.getType(), entityId, metaData, dataType, proto.getData().toByteArray()); + return new TbMsg(UUID.fromString(proto.getId()), proto.getType(), entityId, metaData, dataType, proto.getData()); } catch (InvalidProtocolBufferException e) { throw new IllegalStateException("Could not parse protobuf for TbMsg", e); } } public TbMsg copy() { - int dataSize = data.length; - byte[] dataCopy = new byte[dataSize]; - System.arraycopy( data, 0, dataCopy, 0, data.length ); - return new TbMsg(id, type, originator, metaData.copy(), dataType, dataCopy); + return new TbMsg(id, type, originator, metaData.copy(), dataType, data); } } diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsgMetaData.java b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsgMetaData.java index eca153bdfe..ce13e23e17 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsgMetaData.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsgMetaData.java @@ -33,7 +33,7 @@ public final class TbMsgMetaData implements Serializable { private Map data = new ConcurrentHashMap<>(); - TbMsgMetaData(Map data) { + public TbMsgMetaData(Map data) { this.data = data; } diff --git a/common/message/src/main/proto/tbmsg.proto b/common/message/src/main/proto/tbmsg.proto index 62acff20ce..4ce1fb69bc 100644 --- a/common/message/src/main/proto/tbmsg.proto +++ b/common/message/src/main/proto/tbmsg.proto @@ -32,5 +32,5 @@ message TbMsgProto { TbMsgMetaDataProto metaData = 5; int32 dataType = 6; - bytes data = 7; + string data = 7; } \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/queue/QueueBenchmark.java b/dao/src/main/java/org/thingsboard/server/dao/queue/QueueBenchmark.java index bb76b97b18..85f42ae169 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/queue/QueueBenchmark.java +++ b/dao/src/main/java/org/thingsboard/server/dao/queue/QueueBenchmark.java @@ -126,7 +126,7 @@ public class QueueBenchmark implements CommandLineRunner { TbMsgMetaData metaData = new TbMsgMetaData(); metaData.putValue("key", "value"); String dataStr = "someContent"; - return new TbMsg(UUIDs.timeBased(), "type", null, metaData, TbMsgDataType.JSON, dataStr.getBytes()); + return new TbMsg(UUIDs.timeBased(), "type", null, metaData, TbMsgDataType.JSON, dataStr); } @Bean diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/repository/impl/CassandraMsgRepositoryTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/repository/impl/CassandraMsgRepositoryTest.java index 99c6a91f84..a766aa48ce 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/repository/impl/CassandraMsgRepositoryTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/queue/cassandra/repository/impl/CassandraMsgRepositoryTest.java @@ -45,7 +45,7 @@ public class CassandraMsgRepositoryTest extends AbstractServiceTest { @Test public void msgCanBeSavedAndRead() throws ExecutionException, InterruptedException { - TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), null, TbMsgDataType.JSON, new byte[4]); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), null, TbMsgDataType.JSON, "0000"); UUID nodeId = UUIDs.timeBased(); ListenableFuture future = msgRepository.save(msg, nodeId, 1L, 1L, 1L); future.get(); @@ -55,7 +55,7 @@ public class CassandraMsgRepositoryTest extends AbstractServiceTest { @Test public void expiredMsgsAreNotReturned() throws ExecutionException, InterruptedException { - TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), null, TbMsgDataType.JSON, new byte[4]); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), null, TbMsgDataType.JSON, "0000"); UUID nodeId = UUIDs.timeBased(); ListenableFuture future = msgRepository.save(msg, nodeId, 2L, 2L, 2L); future.get(); @@ -68,7 +68,7 @@ public class CassandraMsgRepositoryTest extends AbstractServiceTest { TbMsgMetaData metaData = new TbMsgMetaData(); metaData.putValue("key", "value"); String dataStr = "someContent"; - TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), metaData, TbMsgDataType.JSON, dataStr.getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "type", new DeviceId(UUIDs.timeBased()), metaData, TbMsgDataType.JSON, dataStr); UUID nodeId = UUIDs.timeBased(); ListenableFuture future = msgRepository.save(msg, nodeId, 1L, 1L, 1L); future.get(); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java index d319a887d2..857baf6785 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.debug; import com.datastax.driver.core.utils.UUIDs; +import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; import org.thingsboard.rule.engine.TbNodeUtils; @@ -58,9 +59,11 @@ public class TbMsgGeneratorNode implements TbNode { public static final String TB_MSG_GENERATOR_NODE_MSG = "TbMsgGeneratorNodeMsg"; private TbMsgGeneratorNodeConfiguration config; + private NashornJsEngine jsEngine; private long delay; private EntityId originatorId; private UUID nextTickId; + private TbMsg prevMsg; @Override public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { @@ -71,29 +74,41 @@ public class TbMsgGeneratorNode implements TbNode { } else { originatorId = ctx.getSelfId(); } + this.jsEngine = new NashornJsEngine(config.getJsScript(), "Generate", "prevMsg", "prevMetadata", "prevMsgType"); sentTickMsg(ctx); } @Override public void onMsg(TbContext ctx, TbMsg msg) { if (msg.getType().equals(TB_MSG_GENERATOR_NODE_MSG) && msg.getId().equals(nextTickId)) { - TbMsgMetaData metaData = new TbMsgMetaData(); - if (config.getMsgMetaData() != null) { - config.getMsgMetaData().forEach(metaData::putValue); - } - ctx.tellNext(new TbMsg(UUIDs.timeBased(), config.getMsgType(), originatorId, metaData, config.getMsgBody().getBytes(StandardCharsets.UTF_8))); - sentTickMsg(ctx); + withCallback(generate(ctx), + m -> {ctx.tellNext(m); sentTickMsg(ctx);}, + t -> {ctx.tellError(msg, t); sentTickMsg(ctx);}); } } private void sentTickMsg(TbContext ctx) { - TbMsg tickMsg = new TbMsg(UUIDs.timeBased(), TB_MSG_GENERATOR_NODE_MSG, ctx.getSelfId(), new TbMsgMetaData(), new byte[]{}); + TbMsg tickMsg = new TbMsg(UUIDs.timeBased(), TB_MSG_GENERATOR_NODE_MSG, ctx.getSelfId(), new TbMsgMetaData(), ""); nextTickId = tickMsg.getId(); ctx.tellSelf(tickMsg, delay); } + protected ListenableFuture generate(TbContext ctx) { + return ctx.getJsExecutor().executeAsync(() -> { + if (prevMsg == null) { + prevMsg = new TbMsg(UUIDs.timeBased(), "", originatorId, new TbMsgMetaData(), "{}"); + } + TbMsg generated = jsEngine.executeGenerate(prevMsg); + prevMsg = new TbMsg(UUIDs.timeBased(), generated.getType(), originatorId, generated.getMetaData(), generated.getData()); + return prevMsg; + }); + } @Override public void destroy() { + prevMsg = null; + if (jsEngine != null) { + jsEngine.destroy(); + } } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNodeConfiguration.java index 8eb37a2aef..c568e3dd94 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNodeConfiguration.java @@ -28,17 +28,17 @@ public class TbMsgGeneratorNodeConfiguration implements NodeConfiguration msgMetaData; + private String jsScript; @Override public TbMsgGeneratorNodeConfiguration defaultConfiguration() { TbMsgGeneratorNodeConfiguration configuration = new TbMsgGeneratorNodeConfiguration(); configuration.setMsgCount(0); configuration.setPeriodInSeconds(1); - configuration.setMsgType("DebugMsg"); - configuration.setMsgBody("{}"); + configuration.setJsScript("var msg = { temp: 42, humidity: 77 };\n" + + "var metadata = { data: 40 };\n" + + "var msgType = \"DebugMsg\";\n\n" + + "return { msg: msg, metadata: metadata, msgType: msgType };"); return configuration; } } 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 044a8b866d..72074f9096 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 @@ -35,7 +35,8 @@ import static org.thingsboard.rule.engine.DonAsynchron.withCallback; 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 metadata property. For example metadata.customerName === 'John';", + "Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';" + + "Message type can be accessed via msgType property.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeScriptConfig") @@ -53,15 +54,11 @@ public class TbJsFilterNode implements TbNode { @Override public void onMsg(TbContext ctx, TbMsg msg) { ListeningExecutor jsExecutor = ctx.getJsExecutor(); - withCallback(jsExecutor.executeAsync(() -> jsEngine.executeFilter(toBindings(msg))), + withCallback(jsExecutor.executeAsync(() -> jsEngine.executeFilter(msg)), filterResult -> ctx.tellNext(msg, Boolean.toString(filterResult)), t -> ctx.tellError(msg, t)); } - private Bindings toBindings(TbMsg msg) { - return NashornJsEngine.bindMsg(msg); - } - @Override public void destroy() { if (jsEngine != null) { 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 d04b58a4d5..7996ae7a03 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 @@ -36,7 +36,8 @@ import static org.thingsboard.rule.engine.DonAsynchron.withCallback; 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 metadata property. For example metadata.customerName === 'John';", + "Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';" + + "Message type can be accessed via msgType property.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeSwitchConfig") public class TbJsSwitchNode implements TbNode { @@ -53,7 +54,7 @@ public class TbJsSwitchNode implements TbNode { @Override public void onMsg(TbContext ctx, TbMsg msg) { ListeningExecutor jsExecutor = ctx.getJsExecutor(); - withCallback(jsExecutor.executeAsync(() -> jsEngine.executeSwitch(toBindings(msg))), + withCallback(jsExecutor.executeAsync(() -> jsEngine.executeSwitch(msg)), result -> processSwitch(ctx, msg, result), t -> ctx.tellError(msg, t)); } @@ -62,11 +63,7 @@ public class TbJsSwitchNode implements TbNode { ctx.tellNext(msg, nextRelations); } - private Bindings toBindings(TbMsg msg) { - return NashornJsEngine.bindMsg(msg); - } - - @Override + @Override public void destroy() { if (jsEngine != null) { jsEngine.destroy(); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/js/NashornJsEngine.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/js/NashornJsEngine.java index a4add405e7..ecca1c6a89 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/js/NashornJsEngine.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/js/NashornJsEngine.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.js; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Sets; @@ -23,9 +24,13 @@ import jdk.nashorn.api.scripting.NashornScriptEngineFactory; import jdk.nashorn.api.scripting.ScriptObjectMirror; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; import javax.script.*; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -34,112 +39,158 @@ import java.util.Set; @Slf4j public class NashornJsEngine { + + public static final String MSG = "msg"; public static final String METADATA = "metadata"; - public static final String DATA = "msg"; + public static final String MSG_TYPE = "msgType"; - private static final String JS_WRAPPER_PREFIX_TEMPLATE = "function %s(msg, metadata) { "; - private static final String JS_WRAPPER_SUFFIX_TEMPLATE = "}\n %s(msg, metadata);"; + private static final String JS_WRAPPER_PREFIX_TEMPLATE = "function %s(msgStr, metadataStr, msgType) { " + + " var msg = JSON.parse(msgStr); " + + " var metadata = JSON.parse(metadataStr); " + + " return JSON.stringify(%s(msg, metadata, msgType));" + + " function %s(%s, %s, %s) {"; + private static final String JS_WRAPPER_SUFFIX = "}" + + "\n}"; + private static final ObjectMapper mapper = new ObjectMapper(); private static NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); + private static ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}); - private CompiledScript engine; + private final String invokeFunctionName; - public NashornJsEngine(String script, String functionName) { - String jsWrapperPrefix = String.format(JS_WRAPPER_PREFIX_TEMPLATE, functionName); - String jsWrapperSuffix = String.format(JS_WRAPPER_SUFFIX_TEMPLATE, functionName); - engine = compileScript(jsWrapperPrefix + script + jsWrapperSuffix); + public NashornJsEngine(String script, String functionName, String... argNames) { + this.invokeFunctionName = "invokeInternal" + this.hashCode(); + String msgArg; + String metadataArg; + String msgTypeArg; + if (argNames != null && argNames.length == 3) { + msgArg = argNames[0]; + metadataArg = argNames[1]; + msgTypeArg = argNames[2]; + } else { + msgArg = MSG; + metadataArg = METADATA; + msgTypeArg = MSG_TYPE; + } + String jsWrapperPrefix = String.format(JS_WRAPPER_PREFIX_TEMPLATE, this.invokeFunctionName, + functionName, functionName, msgArg, metadataArg, msgTypeArg); + compileScript(jsWrapperPrefix + script + JS_WRAPPER_SUFFIX); } - private static CompiledScript compileScript(String script) { - ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}); - Compilable compEngine = (Compilable) engine; + private static void compileScript(String script) { try { - return compEngine.compile(script); + engine.eval(script); } catch (ScriptException e) { log.warn("Failed to compile JS script: {}", e.getMessage(), e); throw new IllegalArgumentException("Can't compile script: " + e.getMessage()); } } - public static Bindings bindMsg(TbMsg msg) { + private static String[] prepareArgs(TbMsg msg) { try { - Bindings bindings = new SimpleBindings(); - if (ArrayUtils.isNotEmpty(msg.getData())) { - ObjectMapper mapper = new ObjectMapper(); - JsonNode jsonNode = mapper.readTree(msg.getData()); - Map map = mapper.treeToValue(jsonNode, Map.class); - bindings.put(DATA, map); + String[] args = new String[3]; + if (msg.getData() != null) { + args[0] = msg.getData(); } else { - bindings.put(DATA, Collections.emptyMap()); + args[0] = ""; } - bindings.put(METADATA, msg.getMetaData().getData()); - return bindings; + args[1] = mapper.writeValueAsString(msg.getMetaData().getData()); + args[2] = msg.getType(); + return args; } catch (Throwable th) { throw new IllegalArgumentException("Cannot bind js args", th); } } - private static TbMsg unbindMsg(Bindings bindings, TbMsg msg) throws JsonProcessingException { - for (Map.Entry entry : msg.getMetaData().getData().entrySet()) { - Object obj = entry.getValue(); - entry.setValue(obj.toString()); - } - - Object payload = bindings.get(DATA); - if (payload != null) { - ObjectMapper mapper = new ObjectMapper(); - byte[] bytes = mapper.writeValueAsBytes(payload); - return new TbMsg(msg.getId(), msg.getType(), msg.getOriginator(), msg.getMetaData(), bytes); - } - - return msg; - } - - public TbMsg executeUpdate(Bindings bindings, TbMsg msg) throws ScriptException { + private static TbMsg unbindMsg(JsonNode msgData, TbMsg msg) { try { - engine.eval(bindings); - return unbindMsg(bindings, msg); + String data = null; + Map metadata = null; + String messageType = null; + if (msgData.has(MSG)) { + JsonNode msgPayload = msgData.get(MSG); + data = mapper.writeValueAsString(msgPayload); + } + if (msgData.has(METADATA)) { + JsonNode msgMetadata = msgData.get(METADATA); + metadata = mapper.convertValue(msgMetadata, new TypeReference>() { + }); + } + if (msgData.has(MSG_TYPE)) { + messageType = msgData.get(MSG_TYPE).asText(); + } + String newData = data != null ? data : msg.getData(); + TbMsgMetaData newMetadata = metadata != null ? new TbMsgMetaData(metadata) : msg.getMetaData(); + String newMessageType = !StringUtils.isEmpty(messageType) ? messageType : msg.getType(); + return new TbMsg(msg.getId(), newMessageType, msg.getOriginator(), newMetadata, newData); } catch (Throwable th) { th.printStackTrace(); - throw new IllegalArgumentException("Cannot unbind js args", th); + throw new RuntimeException("Failed to unbind message data from javascript result", th); } } - public boolean executeFilter(Bindings bindings) throws ScriptException { - Object eval = engine.eval(bindings); - if (eval instanceof Boolean) { - return (boolean) eval; - } else { - log.warn("Wrong result type: {}", eval); - throw new ScriptException("Wrong result type: " + eval); + public TbMsg executeUpdate(TbMsg msg) throws ScriptException { + JsonNode result = executeScript(msg); + if (!result.isObject()) { + log.warn("Wrong result type: {}", result.getNodeType()); + throw new ScriptException("Wrong result type: " + result.getNodeType()); } + return unbindMsg(result, msg); } - public Set executeSwitch(Bindings bindings) throws ScriptException, NoSuchMethodException { - Object eval = this.engine.eval(bindings); - if (eval instanceof String) { - return Collections.singleton((String) eval); - } else if (eval instanceof ScriptObjectMirror) { - ScriptObjectMirror mir = (ScriptObjectMirror) eval; - if (mir.isArray()) { - Set nextStates = Sets.newHashSet(); - for (Map.Entry entry : mir.entrySet()) { - if (entry.getValue() instanceof String) { - nextStates.add((String) entry.getValue()); - } else { - log.warn("Wrong result type: {}", eval); - throw new ScriptException("Wrong result type: " + eval); - } + public TbMsg executeGenerate(TbMsg prevMsg) throws ScriptException { + JsonNode result = executeScript(prevMsg); + if (!result.isObject()) { + log.warn("Wrong result type: {}", result.getNodeType()); + throw new ScriptException("Wrong result type: " + result.getNodeType()); + } + return unbindMsg(result, prevMsg); + } + + public boolean executeFilter(TbMsg msg) throws ScriptException { + JsonNode result = executeScript(msg); + if (!result.isBoolean()) { + log.warn("Wrong result type: {}", result.getNodeType()); + throw new ScriptException("Wrong result type: " + result.getNodeType()); + } + return result.asBoolean(); + } + + public Set executeSwitch(TbMsg msg) throws ScriptException, NoSuchMethodException { + JsonNode result = executeScript(msg); + if (result.isTextual()) { + return Collections.singleton(result.asText()); + } else if (result.isArray()) { + Set nextStates = Sets.newHashSet(); + for (JsonNode val : result) { + if (!val.isTextual()) { + log.warn("Wrong result type: {}", val.getNodeType()); + throw new ScriptException("Wrong result type: " + val.getNodeType()); + } else { + nextStates.add(val.asText()); } - return nextStates; } + return nextStates; + } else { + log.warn("Wrong result type: {}", result.getNodeType()); + throw new ScriptException("Wrong result type: " + result.getNodeType()); } + } - log.warn("Wrong result type: {}", eval); - throw new ScriptException("Wrong result type: " + eval); + private JsonNode executeScript(TbMsg msg) throws ScriptException { + try { + String[] inArgs = prepareArgs(msg); + String eval = ((Invocable)engine).invokeFunction(this.invokeFunctionName, inArgs[0], inArgs[1], inArgs[2]).toString(); + return mapper.readTree(eval); + } catch (ScriptException | IllegalArgumentException th) { + throw th; + } catch (Throwable th) { + th.printStackTrace(); + throw new RuntimeException("Failed to execute js script", th); + } } public void destroy() { - engine = null; + //engine = null; } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTelemetryNode.java index 61ca8cfb68..0e6687fabf 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTelemetryNode.java @@ -64,7 +64,7 @@ public class TbMsgTelemetryNode implements TbNode { return; } - String src = new String(msg.getData(), StandardCharsets.UTF_8); + String src = msg.getData(); TelemetryUploadRequest telemetryUploadRequest = JsonConverter.convertToTelemetry(new JsonParser().parse(src)); Map> tsKvMap = telemetryUploadRequest.getData(); if (tsKvMap == null) { 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 626d05784a..f57edba753 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 @@ -28,10 +28,14 @@ import javax.script.Bindings; type = ComponentType.TRANSFORMATION, name = "script", configClazz = TbTransformMsgNodeConfiguration.class, - nodeDescription = "Change Message payload and Metadata using JavaScript", - nodeDetails = "JavaScript function recieve 2 input parameters that can be changed inside.
" + + nodeDescription = "Change Message payload, Metadata or Message type using JavaScript", + nodeDetails = "JavaScript function receive 3 input parameters.
" + "metadata - is a Message metadata.
" + - "msg - is a Message payload.
Any properties can be changed/removed/added in those objects.", + "msg - is a Message payload.
" + + "msgType - is a Message type.
" + + "Should return the following structure:
" + + "{ msg: , metadata: , msgType: }" + + "All fields in resulting object are optional and will be taken from original message if not specified.", uiResources = {"static/rulenode/rulenode-core-config.js", "static/rulenode/rulenode-core-config.css"}, configDirective = "tbTransformationNodeScriptConfig") public class TbTransformMsgNode extends TbAbstractTransformNode { @@ -48,11 +52,7 @@ public class TbTransformMsgNode extends TbAbstractTransformNode { @Override protected ListenableFuture transform(TbContext ctx, TbMsg msg) { - return ctx.getJsExecutor().executeAsync(() -> jsEngine.executeUpdate(toBindings(msg), msg)); - } - - private Bindings toBindings(TbMsg msg) { - return NashornJsEngine.bindMsg(msg); + return ctx.getJsExecutor().executeAsync(() -> jsEngine.executeUpdate(msg)); } @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeConfiguration.java index 09d5ac43ad..a710cf8578 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeConfiguration.java @@ -27,7 +27,7 @@ public class TbTransformMsgNodeConfiguration extends TbTransformNodeConfiguratio public TbTransformMsgNodeConfiguration defaultConfiguration() { TbTransformMsgNodeConfiguration configuration = new TbTransformMsgNodeConfiguration(); configuration.setStartNewChain(false); - configuration.setJsScript("return msg.passed = msg.passed * metadata.temp; msg.bigObj.newProp = 'Ukraine' "); + configuration.setJsScript("return {msg: msg, metadata: metadata, msgType: msgType};"); return configuration; } } diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js index 62a0ff56f2..79006c2c72 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -1,2 +1,2 @@ -!function(e){function t(a){if(n[a])return n[a].exports;var r=n[a]={exports:{},id:a,loaded:!1};return e[a].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),a=e[t[0]];return function(e,t,r){a.apply(this,[e,t,r].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){e.exports=n(34)},function(e,t){},1,1,function(e,t){e.exports="
tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
tb.rulenode.message-type-required
"},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},6,function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports="
"},function(e,t){e.exports="
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
{{ \'tb.rulenode.clone-message\' | translate }}
'},function(e,t){e.exports="
{{ 'tb.rulenode.clone-message' | translate }}
"},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.originator=null,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue,n.configuration.originatorId&&n.configuration.originatorType?n.originator={id:n.configuration.originatorId,entityType:n.configuration.originatorType}:n.originator=null,n.$watch("originator",function(e,t){angular.equals(e,t)||(n.originator?(i.$viewValue.originatorId=n.originator.id,i.$viewValue.originatorType=n.originator.entityType):(i.$viewValue.originatorId=null,i.$viewValue.originatorType=null))},!0)},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r,n(1);var i=n(4),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(19),i=a(r),o=n(17),l=a(o);t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTelemetryConfig",i.default).directive("tbActionNodeGeneratorConfig",l.default).name},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(5),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(6),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(22),i=a(r),o=n(23),l=a(o),s=n(20),u=a(s),d=n(24),c=a(d);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",i.default).directive("tbEnrichmentNodeRelatedAttributesConfig",l.default).directive("tbEnrichmentNodeCustomerAttributesConfig",u.default).directive("tbEnrichmentNodeTenantAttributesConfig",c.default).name},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(7),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(8),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(9),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(27),i=a(r),o=n(26),l=a(o),s=n(28),u=a(s);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",i.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).name},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var a=function(a,r,i,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),r.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),r.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=r,t.removeKeyVal=i,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||r.$setViewValue(t.query)}),r.$render=function(){if(r.$viewValue){var e=r.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(13),o=a(i);n(3)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||i.$setViewValue(n.query)}),i.$render=function(){n.query=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(14),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(15),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(31),i=a(r),o=n(33),l=a(o);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",i.default).directive("tbTransformationNodeScriptConfig",l.default).name},[38,16],function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(37),i=a(r),o=n(25),l=a(o),s=n(21),u=a(s),d=n(32),c=a(d),m=n(18),g=a(m),f=n(30),p=a(f),b=n(29),y=a(b),v=n(36),h=a(v);t.default=angular.module("thingsboard.ruleChain.config",[i.default,l.default,u.default,c.default,g.default]).directive("tbRelationsQueryConfig",p.default).directive("tbKvMapConfig",y.default).config(h.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one!","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","latest-timeseries":"Latest timeseries","relations-query":"Relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata"},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};angular.merge(e.en_US,t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){(0,o.default)(t);for(var n in t){var a=t[n];e.translations(n,a)}}r.$inject=["$translateProvider","locales"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(35),o=a(i)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{messageType:{POST_ATTRIBUTES:{name:"Post attributes",value:"POST_ATTRIBUTES"},POST_TELEMETRY:{name:"Post telemetry",value:"POST_TELEMETRY"},RPC_REQUEST:{name:"RPC Request",value:"RPC_REQUEST"}},originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}}}).name},function(e,t,n,a){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,a,r){var i=l.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var o=n(a),l=r(o)}])); +!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),r=e[t[0]];return function(e,t,a){r.apply(this,[e,t,a].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){e.exports=n(34)},function(e,t){},1,1,function(e,t){e.exports="
tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
"},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},6,function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports="
"},function(e,t){e.exports="
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
{{ \'tb.rulenode.clone-message\' | translate }}
'},function(e,t){e.exports="
{{ 'tb.rulenode.clone-message' | translate }}
"},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.originator=null,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue,n.configuration.originatorId&&n.configuration.originatorType?n.originator={id:n.configuration.originatorId,entityType:n.configuration.originatorType}:n.originator=null,n.$watch("originator",function(e,t){angular.equals(e,t)||(n.originator?(i.$viewValue.originatorId=n.originator.id,i.$viewValue.originatorType=n.originator.entityType):(i.$viewValue.originatorId=null,i.$viewValue.originatorType=null))},!0)},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a,n(1);var i=n(4),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(19),i=r(a),o=n(17),l=r(o);t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTelemetryConfig",i.default).directive("tbActionNodeGeneratorConfig",l.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(5),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(6),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(22),i=r(a),o=n(23),l=r(o),s=n(20),u=r(s),d=n(24),c=r(d);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",i.default).directive("tbEnrichmentNodeRelatedAttributesConfig",l.default).directive("tbEnrichmentNodeCustomerAttributesConfig",u.default).directive("tbEnrichmentNodeTenantAttributesConfig",c.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(7),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(8),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(9),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(27),i=r(a),o=n(26),l=r(o),s=n(28),u=r(s);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",i.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),a.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),a.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=a,t.removeKeyVal=i,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||a.$setViewValue(t.query)}),a.$render=function(){if(a.$viewValue){var e=a.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(13),o=r(i);n(3)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||i.$setViewValue(n.query)}),i.$render=function(){n.query=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(14),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(15),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(31),i=r(a),o=n(33),l=r(o);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",i.default).directive("tbTransformationNodeScriptConfig",l.default).name},[38,16],function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(37),i=r(a),o=n(25),l=r(o),s=n(21),u=r(s),d=n(32),c=r(d),m=n(18),g=r(m),f=n(30),p=r(f),b=n(29),v=r(b),y=n(36),h=r(y);t.default=angular.module("thingsboard.ruleChain.config",[i.default,l.default,u.default,c.default,g.default]).directive("tbRelationsQueryConfig",p.default).directive("tbKvMapConfig",v.default).config(h.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one!","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","latest-timeseries":"Latest timeseries","relations-query":"Relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate"},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};angular.merge(e.en_US,t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){(0,o.default)(t);for(var n in t){var r=t[n];e.translations(n,r)}}a.$inject=["$translateProvider","locales"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(35),o=r(i)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{messageType:{POST_ATTRIBUTES:{name:"Post attributes",value:"POST_ATTRIBUTES"},POST_TELEMETRY:{name:"Post telemetry",value:"POST_TELEMETRY"},RPC_REQUEST:{name:"RPC Request",value:"RPC_REQUEST"}},originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}}}).name},function(e,t,n,r){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,a){var i=l.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var o=n(r),l=a(o)}])); //# sourceMappingURL=rulenode-core-config.js.map \ No newline at end of file diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java index de9d9c4e45..34232b2434 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java @@ -52,7 +52,7 @@ public class TbJsFilterNodeTest { @Test public void falseEvaluationDoNotSendMsg() throws TbNodeException { initWithScript("return 10 > 15;"); - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, new TbMsgMetaData(), "{}".getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, new TbMsgMetaData(), "{}"); mockJsExecutor(); @@ -65,7 +65,7 @@ public class TbJsFilterNodeTest { @Test public void notValidMsgDataThrowsException() throws TbNodeException { initWithScript("return 10 > 15;"); - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, new TbMsgMetaData(), new byte[4]); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, null, "{}"); when(ctx.getJsExecutor()).thenReturn(executor); @@ -79,11 +79,11 @@ public class TbJsFilterNodeTest { public void exceptionInJsThrowsException() throws TbNodeException { initWithScript("return metadata.temp.curr < 15;"); TbMsgMetaData metaData = new TbMsgMetaData(); - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, "{}".getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, "{}"); mockJsExecutor(); node.onMsg(ctx, msg); - String expectedMessage = "TypeError: Cannot get property \"curr\" of null in at line number 1"; + String expectedMessage = "TypeError: Cannot read property \"curr\" from undefined in at line number 1"; verifyError(msg, expectedMessage, ScriptException.class); } @@ -98,7 +98,7 @@ public class TbJsFilterNodeTest { TbMsgMetaData metaData = new TbMsgMetaData(); metaData.putValue("temp", "10"); metaData.putValue("humidity", "99"); - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, "{}".getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, "{}"); mockJsExecutor(); node.onMsg(ctx, msg); @@ -113,7 +113,7 @@ public class TbJsFilterNodeTest { TbMsgMetaData metaData = new TbMsgMetaData(); metaData.putValue("temp", "10"); metaData.putValue("humidity", "99"); - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, "{}".getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, "{}"); mockJsExecutor(); node.onMsg(ctx, msg); @@ -129,7 +129,7 @@ public class TbJsFilterNodeTest { metaData.putValue("humidity", "99"); String rawJson = "{\"name\": \"Vit\", \"passed\": 5, \"bigObj\": {\"prop\":42}}"; - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson.getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); mockJsExecutor(); node.onMsg(ctx, msg); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java index f1f2d73259..a4ea56cab2 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java @@ -68,7 +68,7 @@ public class TbJsSwitchNodeTest { metaData.putValue("humidity", "99"); String rawJson = "{\"name\": \"Vit\", \"passed\": 5}"; - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson.getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); mockJsExecutor(); node.onMsg(ctx, msg); @@ -92,7 +92,7 @@ public class TbJsSwitchNodeTest { metaData.putValue("humidity", "99"); String rawJson = "{\"name\": \"Vit\", \"passed\": 5}"; - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson.getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); mockJsExecutor(); node.onMsg(ctx, msg); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java index 2218749af5..e26312b7ca 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java @@ -98,7 +98,7 @@ public class TbGetCustomerAttributeNodeTest { User user = new User(); user.setCustomerId(customerId); - msg = new TbMsg(UUIDs.timeBased(), "USER", userId, new TbMsgMetaData(), new byte[4]); + msg = new TbMsg(UUIDs.timeBased(), "USER", userId, new TbMsgMetaData(), "{}"); when(ctx.getUserService()).thenReturn(userService); when(userService.findUserByIdAsync(userId)).thenReturn(Futures.immediateFuture(user)); @@ -123,7 +123,7 @@ public class TbGetCustomerAttributeNodeTest { User user = new User(); user.setCustomerId(customerId); - msg = new TbMsg(UUIDs.timeBased(), "USER", userId, new TbMsgMetaData(), new byte[4]); + msg = new TbMsg(UUIDs.timeBased(), "USER", userId, new TbMsgMetaData(), "{}"); when(ctx.getUserService()).thenReturn(userService); when(userService.findUserByIdAsync(userId)).thenReturn(Futures.immediateFuture(user)); @@ -148,7 +148,7 @@ public class TbGetCustomerAttributeNodeTest { User user = new User(); user.setCustomerId(customerId); - msg = new TbMsg(UUIDs.timeBased(), "USER", userId, new TbMsgMetaData(), new byte[4]); + msg = new TbMsg(UUIDs.timeBased(), "USER", userId, new TbMsgMetaData(), "{}"); when(ctx.getUserService()).thenReturn(userService); when(userService.findUserByIdAsync(userId)).thenReturn(Futures.immediateFuture(null)); @@ -166,7 +166,7 @@ public class TbGetCustomerAttributeNodeTest { @Test public void customerAttributeAddedInMetadata() { CustomerId customerId = new CustomerId(UUIDs.timeBased()); - msg = new TbMsg(UUIDs.timeBased(), "CUSTOMER", customerId, new TbMsgMetaData(), new byte[4]); + msg = new TbMsg(UUIDs.timeBased(), "CUSTOMER", customerId, new TbMsgMetaData(), "{}"); entityAttributeFetched(customerId); } @@ -177,7 +177,7 @@ public class TbGetCustomerAttributeNodeTest { User user = new User(); user.setCustomerId(customerId); - msg = new TbMsg(UUIDs.timeBased(), "USER", userId, new TbMsgMetaData(), new byte[4]); + msg = new TbMsg(UUIDs.timeBased(), "USER", userId, new TbMsgMetaData(), "{}"); when(ctx.getUserService()).thenReturn(userService); when(userService.findUserByIdAsync(userId)).thenReturn(Futures.immediateFuture(user)); @@ -192,7 +192,7 @@ public class TbGetCustomerAttributeNodeTest { Asset asset = new Asset(); asset.setCustomerId(customerId); - msg = new TbMsg(UUIDs.timeBased(), "USER", assetId, new TbMsgMetaData(), new byte[4]); + msg = new TbMsg(UUIDs.timeBased(), "USER", assetId, new TbMsgMetaData(), "{}"); when(ctx.getAssetService()).thenReturn(assetService); when(assetService.findAssetByIdAsync(assetId)).thenReturn(Futures.immediateFuture(asset)); @@ -207,7 +207,7 @@ public class TbGetCustomerAttributeNodeTest { Device device = new Device(); device.setCustomerId(customerId); - msg = new TbMsg(UUIDs.timeBased(), "USER", deviceId, new TbMsgMetaData(), new byte[4]); + msg = new TbMsg(UUIDs.timeBased(), "USER", deviceId, new TbMsgMetaData(), "{}"); when(ctx.getDeviceService()).thenReturn(deviceService); when(deviceService.findDeviceByIdAsync(deviceId)).thenReturn(Futures.immediateFuture(device)); @@ -234,7 +234,7 @@ public class TbGetCustomerAttributeNodeTest { Device device = new Device(); device.setCustomerId(customerId); - msg = new TbMsg(UUIDs.timeBased(), "USER", deviceId, new TbMsgMetaData(), new byte[4]); + msg = new TbMsg(UUIDs.timeBased(), "USER", deviceId, new TbMsgMetaData(), "{}"); when(ctx.getDeviceService()).thenReturn(deviceService); when(deviceService.findDeviceByIdAsync(deviceId)).thenReturn(Futures.immediateFuture(device)); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNodeTest.java index 39e0121e53..1b66433085 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNodeTest.java @@ -57,7 +57,7 @@ public class TbChangeOriginatorNodeTest { Asset asset = new Asset(); asset.setCustomerId(customerId); - TbMsg msg = new TbMsg(UUIDs.timeBased(), "ASSET", assetId, new TbMsgMetaData(), new byte[4]); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "ASSET", assetId, new TbMsgMetaData(), "{}"); when(ctx.getAssetService()).thenReturn(assetService); when(assetService.findAssetByIdAsync(assetId)).thenReturn(Futures.immediateFuture(asset)); @@ -78,7 +78,7 @@ public class TbChangeOriginatorNodeTest { Asset asset = new Asset(); asset.setCustomerId(customerId); - TbMsg msg = new TbMsg(UUIDs.timeBased(), "ASSET", assetId, new TbMsgMetaData(), new byte[4]); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "ASSET", assetId, new TbMsgMetaData(), "{}"); when(ctx.getAssetService()).thenReturn(assetService); when(assetService.findAssetByIdAsync(assetId)).thenReturn(Futures.immediateFuture(asset)); @@ -99,7 +99,7 @@ public class TbChangeOriginatorNodeTest { Asset asset = new Asset(); asset.setCustomerId(customerId); - TbMsg msg = new TbMsg(UUIDs.timeBased(), "ASSET", assetId, new TbMsgMetaData(), new byte[4]); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "ASSET", assetId, new TbMsgMetaData(), "{}"); when(ctx.getAssetService()).thenReturn(assetService); when(assetService.findAssetByIdAsync(assetId)).thenReturn(Futures.immediateFailedFuture(new IllegalStateException("wrong"))); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java index 46be7f8cb4..579392cec7 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java @@ -51,13 +51,13 @@ public class TbTransformMsgNodeTest { @Test public void metadataCanBeUpdated() throws TbNodeException { - initWithScript("return metadata.temp = metadata.temp * 10;"); + initWithScript("metadata.temp = metadata.temp * 10; return {metadata: metadata};"); TbMsgMetaData metaData = new TbMsgMetaData(); metaData.putValue("temp", "7"); metaData.putValue("humidity", "99"); String rawJson = "{\"name\": \"Vit\", \"passed\": 5, \"bigObj\": {\"prop\":42}}"; - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson.getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); mockJsExecutor(); node.onMsg(ctx, msg); @@ -65,18 +65,18 @@ public class TbTransformMsgNodeTest { ArgumentCaptor captor = ArgumentCaptor.forClass(TbMsg.class); verify(ctx).tellNext(captor.capture()); TbMsg actualMsg = captor.getValue(); - assertEquals("70.0", actualMsg.getMetaData().getValue("temp")); + assertEquals("70", actualMsg.getMetaData().getValue("temp")); } @Test public void metadataCanBeAdded() throws TbNodeException { - initWithScript("return metadata.newAttr = metadata.humidity - msg.passed;"); + initWithScript("metadata.newAttr = metadata.humidity - msg.passed; return {metadata: metadata};"); TbMsgMetaData metaData = new TbMsgMetaData(); metaData.putValue("temp", "7"); metaData.putValue("humidity", "99"); String rawJson = "{\"name\": \"Vit\", \"passed\": 5, \"bigObj\": {\"prop\":42}}"; - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson.getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); mockJsExecutor(); node.onMsg(ctx, msg); @@ -84,18 +84,18 @@ public class TbTransformMsgNodeTest { ArgumentCaptor captor = ArgumentCaptor.forClass(TbMsg.class); verify(ctx).tellNext(captor.capture()); TbMsg actualMsg = captor.getValue(); - assertEquals("94.0", actualMsg.getMetaData().getValue("newAttr")); + assertEquals("94", actualMsg.getMetaData().getValue("newAttr")); } @Test public void payloadCanBeUpdated() throws TbNodeException { - initWithScript("msg.passed = msg.passed * metadata.temp; return msg.bigObj.newProp = 'Ukraine' "); + initWithScript("msg.passed = msg.passed * metadata.temp; msg.bigObj.newProp = 'Ukraine'; return {msg: msg};"); TbMsgMetaData metaData = new TbMsgMetaData(); metaData.putValue("temp", "7"); metaData.putValue("humidity", "99"); String rawJson = "{\"name\":\"Vit\",\"passed\": 5,\"bigObj\":{\"prop\":42}}"; - TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson.getBytes()); + TbMsg msg = new TbMsg(UUIDs.timeBased(), "USER", null, metaData, rawJson); mockJsExecutor(); node.onMsg(ctx, msg); @@ -103,7 +103,7 @@ public class TbTransformMsgNodeTest { ArgumentCaptor captor = ArgumentCaptor.forClass(TbMsg.class); verify(ctx).tellNext(captor.capture()); TbMsg actualMsg = captor.getValue(); - String expectedJson = "{\"name\":\"Vit\",\"passed\":35.0,\"bigObj\":{\"prop\":42,\"newProp\":\"Ukraine\"}}"; + String expectedJson = "{\"name\":\"Vit\",\"passed\":35,\"bigObj\":{\"prop\":42,\"newProp\":\"Ukraine\"}}"; assertEquals(expectedJson, new String(actualMsg.getData())); }