Refactor MVEL -> TBEL
This commit is contained in:
parent
d8f87c45c8
commit
d10f64c348
@ -57,9 +57,9 @@
|
|||||||
"name": "Log RPC from Device",
|
"name": "Log RPC from Device",
|
||||||
"debugMode": false,
|
"debugMode": false,
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"scriptLang": "MVEL",
|
"scriptLang": "TBEL",
|
||||||
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
||||||
"mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
"tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -71,9 +71,9 @@
|
|||||||
"name": "Log Other",
|
"name": "Log Other",
|
||||||
"debugMode": false,
|
"debugMode": false,
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"scriptLang": "MVEL",
|
"scriptLang": "TBEL",
|
||||||
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
||||||
"mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
"tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -70,9 +70,9 @@
|
|||||||
"name": "Log RPC from Device",
|
"name": "Log RPC from Device",
|
||||||
"debugMode": false,
|
"debugMode": false,
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"scriptLang": "MVEL",
|
"scriptLang": "TBEL",
|
||||||
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
||||||
"mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
"tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -84,9 +84,9 @@
|
|||||||
"name": "Log Other",
|
"name": "Log Other",
|
||||||
"debugMode": false,
|
"debugMode": false,
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"scriptLang": "MVEL",
|
"scriptLang": "TBEL",
|
||||||
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
||||||
"mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
"tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -57,9 +57,9 @@
|
|||||||
"name": "Log RPC from Device",
|
"name": "Log RPC from Device",
|
||||||
"debugMode": false,
|
"debugMode": false,
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"scriptLang": "MVEL",
|
"scriptLang": "TBEL",
|
||||||
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
||||||
"mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
"tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -71,9 +71,9 @@
|
|||||||
"name": "Log Other",
|
"name": "Log Other",
|
||||||
"debugMode": false,
|
"debugMode": false,
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"scriptLang": "MVEL",
|
"scriptLang": "TBEL",
|
||||||
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
|
||||||
"mvelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
"tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import org.thingsboard.rule.engine.api.MailService;
|
|||||||
import org.thingsboard.rule.engine.api.SmsService;
|
import org.thingsboard.rule.engine.api.SmsService;
|
||||||
import org.thingsboard.rule.engine.api.sms.SmsSenderFactory;
|
import org.thingsboard.rule.engine.api.sms.SmsSenderFactory;
|
||||||
import org.thingsboard.script.api.js.JsInvokeService;
|
import org.thingsboard.script.api.js.JsInvokeService;
|
||||||
import org.thingsboard.script.api.mvel.MvelInvokeService;
|
import org.thingsboard.script.api.tbel.TbelInvokeService;
|
||||||
import org.thingsboard.server.actors.service.ActorService;
|
import org.thingsboard.server.actors.service.ActorService;
|
||||||
import org.thingsboard.server.actors.tenant.DebugTbRateLimits;
|
import org.thingsboard.server.actors.tenant.DebugTbRateLimits;
|
||||||
import org.thingsboard.server.cluster.TbClusterService;
|
import org.thingsboard.server.cluster.TbClusterService;
|
||||||
@ -274,7 +274,7 @@ public class ActorSystemContext {
|
|||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
@Getter
|
@Getter
|
||||||
private MvelInvokeService mvelInvokeService;
|
private TbelInvokeService tbelInvokeService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Getter
|
@Getter
|
||||||
|
|||||||
@ -97,7 +97,7 @@ import org.thingsboard.server.gen.transport.TransportProtos;
|
|||||||
import org.thingsboard.server.queue.TbQueueCallback;
|
import org.thingsboard.server.queue.TbQueueCallback;
|
||||||
import org.thingsboard.server.queue.TbQueueMsgMetadata;
|
import org.thingsboard.server.queue.TbQueueMsgMetadata;
|
||||||
import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
|
import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
|
||||||
import org.thingsboard.server.service.script.RuleNodeMvelScriptEngine;
|
import org.thingsboard.server.service.script.RuleNodeTbelScriptEngine;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -474,11 +474,11 @@ class DefaultTbContext implements TbContext {
|
|||||||
return new RuleNodeJsScriptEngine(getTenantId(), mainCtx.getJsInvokeService(), script, argNames);
|
return new RuleNodeJsScriptEngine(getTenantId(), mainCtx.getJsInvokeService(), script, argNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScriptEngine createMvelScriptEngine(String script, String... argNames) {
|
private ScriptEngine createTbelScriptEngine(String script, String... argNames) {
|
||||||
if (mainCtx.getMvelInvokeService() == null) {
|
if (mainCtx.getTbelInvokeService() == null) {
|
||||||
throw new RuntimeException("MVEL execution is disabled!");
|
throw new RuntimeException("TBEL execution is disabled!");
|
||||||
}
|
}
|
||||||
return new RuleNodeMvelScriptEngine(getTenantId(), mainCtx.getMvelInvokeService(), script, argNames);
|
return new RuleNodeTbelScriptEngine(getTenantId(), mainCtx.getTbelInvokeService(), script, argNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -492,11 +492,11 @@ class DefaultTbContext implements TbContext {
|
|||||||
switch (scriptLang) {
|
switch (scriptLang) {
|
||||||
case JS:
|
case JS:
|
||||||
return createJsScriptEngine(script, argNames);
|
return createJsScriptEngine(script, argNames);
|
||||||
case MVEL:
|
case TBEL:
|
||||||
if (Arrays.isNullOrEmpty(argNames)) {
|
if (Arrays.isNullOrEmpty(argNames)) {
|
||||||
return createMvelScriptEngine(script, "msg", "metadata", "msgType");
|
return createTbelScriptEngine(script, "msg", "metadata", "msgType");
|
||||||
} else {
|
} else {
|
||||||
return createMvelScriptEngine(script, argNames);
|
return createTbelScriptEngine(script, argNames);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Unsupported script language: " + scriptLang.name());
|
throw new RuntimeException("Unsupported script language: " + scriptLang.name());
|
||||||
|
|||||||
@ -38,7 +38,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.thingsboard.rule.engine.api.ScriptEngine;
|
import org.thingsboard.rule.engine.api.ScriptEngine;
|
||||||
import org.thingsboard.script.api.js.JsInvokeService;
|
import org.thingsboard.script.api.js.JsInvokeService;
|
||||||
import org.thingsboard.script.api.mvel.MvelInvokeService;
|
import org.thingsboard.script.api.tbel.TbelInvokeService;
|
||||||
import org.thingsboard.server.actors.ActorSystemContext;
|
import org.thingsboard.server.actors.ActorSystemContext;
|
||||||
import org.thingsboard.server.actors.tenant.DebugTbRateLimits;
|
import org.thingsboard.server.actors.tenant.DebugTbRateLimits;
|
||||||
import org.thingsboard.server.common.data.EventInfo;
|
import org.thingsboard.server.common.data.EventInfo;
|
||||||
@ -69,7 +69,7 @@ import org.thingsboard.server.dao.event.EventService;
|
|||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||||
import org.thingsboard.server.service.rule.TbRuleChainService;
|
import org.thingsboard.server.service.rule.TbRuleChainService;
|
||||||
import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
|
import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
|
||||||
import org.thingsboard.server.service.script.RuleNodeMvelScriptEngine;
|
import org.thingsboard.server.service.script.RuleNodeTbelScriptEngine;
|
||||||
import org.thingsboard.server.service.security.permission.Operation;
|
import org.thingsboard.server.service.security.permission.Operation;
|
||||||
import org.thingsboard.server.service.security.permission.Resource;
|
import org.thingsboard.server.service.security.permission.Resource;
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ public class RuleChainController extends BaseController {
|
|||||||
private JsInvokeService jsInvokeService;
|
private JsInvokeService jsInvokeService;
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private MvelInvokeService mvelInvokeService;
|
private TbelInvokeService tbelInvokeService;
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private ActorSystemContext actorContext;
|
private ActorSystemContext actorContext;
|
||||||
@ -154,8 +154,8 @@ public class RuleChainController extends BaseController {
|
|||||||
@Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}")
|
@Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}")
|
||||||
private boolean debugPerTenantEnabled;
|
private boolean debugPerTenantEnabled;
|
||||||
|
|
||||||
@Value("${mvel.enabled:true}")
|
@Value("${tbel.enabled:true}")
|
||||||
private boolean mvelEnabled;
|
private boolean tbelEnabled;
|
||||||
|
|
||||||
@ApiOperation(value = "Get Rule Chain (getRuleChainById)",
|
@ApiOperation(value = "Get Rule Chain (getRuleChainById)",
|
||||||
notes = "Fetch the Rule Chain object based on the provided Rule Chain Id. " + RULE_CHAIN_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
|
notes = "Fetch the Rule Chain object based on the provided Rule Chain Id. " + RULE_CHAIN_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
|
||||||
@ -378,13 +378,13 @@ public class RuleChainController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "Is MVEL script executor enabled",
|
@ApiOperation(value = "Is TBEL script executor enabled",
|
||||||
notes = "Returns 'True' if the MVEL script execution is enabled" + TENANT_AUTHORITY_PARAGRAPH)
|
notes = "Returns 'True' if the TBEL script execution is enabled" + TENANT_AUTHORITY_PARAGRAPH)
|
||||||
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
|
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
|
||||||
@RequestMapping(value = "/ruleChain/mvelEnabled", method = RequestMethod.GET)
|
@RequestMapping(value = "/ruleChain/tbelEnabled", method = RequestMethod.GET)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public Boolean isMvelEnabled() {
|
public Boolean isTbelEnabled() {
|
||||||
return mvelEnabled;
|
return tbelEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "Test Script function",
|
@ApiOperation(value = "Test Script function",
|
||||||
@ -393,7 +393,7 @@ public class RuleChainController extends BaseController {
|
|||||||
@RequestMapping(value = "/ruleChain/testScript", method = RequestMethod.POST)
|
@RequestMapping(value = "/ruleChain/testScript", method = RequestMethod.POST)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public JsonNode testScript(
|
public JsonNode testScript(
|
||||||
@ApiParam(value = "Script language: JS or MVEL")
|
@ApiParam(value = "Script language: JS or TBEL")
|
||||||
@RequestParam(required = false) ScriptLanguage scriptLang,
|
@RequestParam(required = false) ScriptLanguage scriptLang,
|
||||||
@ApiParam(value = "Test JS request. See API call description above.")
|
@ApiParam(value = "Test JS request. See API call description above.")
|
||||||
@RequestBody JsonNode inputParams) throws ThingsboardException {
|
@RequestBody JsonNode inputParams) throws ThingsboardException {
|
||||||
@ -418,10 +418,10 @@ public class RuleChainController extends BaseController {
|
|||||||
if (ScriptLanguage.JS.equals(scriptLang)) {
|
if (ScriptLanguage.JS.equals(scriptLang)) {
|
||||||
engine = new RuleNodeJsScriptEngine(getTenantId(), jsInvokeService, script, argNames);
|
engine = new RuleNodeJsScriptEngine(getTenantId(), jsInvokeService, script, argNames);
|
||||||
} else {
|
} else {
|
||||||
if (mvelInvokeService == null) {
|
if (tbelInvokeService == null) {
|
||||||
throw new IllegalArgumentException("MVEL script engine is disabled!");
|
throw new IllegalArgumentException("TBEL script engine is disabled!");
|
||||||
}
|
}
|
||||||
engine = new RuleNodeMvelScriptEngine(getTenantId(), mvelInvokeService, script, argNames);
|
engine = new RuleNodeTbelScriptEngine(getTenantId(), tbelInvokeService, script, argNames);
|
||||||
}
|
}
|
||||||
TbMsg inMsg = TbMsg.newMsg(msgType, null, new TbMsgMetaData(metadata), TbMsgDataType.JSON, data);
|
TbMsg inMsg = TbMsg.newMsg(msgType, null, new TbMsgMetaData(metadata), TbMsgDataType.JSON, data);
|
||||||
switch (scriptType) {
|
switch (scriptType) {
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import com.google.common.util.concurrent.MoreExecutors;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
import org.thingsboard.script.api.RuleNodeScriptFactory;
|
import org.thingsboard.script.api.RuleNodeScriptFactory;
|
||||||
import org.thingsboard.script.api.mvel.MvelInvokeService;
|
import org.thingsboard.script.api.tbel.TbelInvokeService;
|
||||||
import org.thingsboard.server.common.data.StringUtils;
|
import org.thingsboard.server.common.data.StringUtils;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.msg.TbMsg;
|
import org.thingsboard.server.common.msg.TbMsg;
|
||||||
@ -42,9 +42,9 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class RuleNodeMvelScriptEngine extends RuleNodeScriptEngine<MvelInvokeService, Object> {
|
public class RuleNodeTbelScriptEngine extends RuleNodeScriptEngine<TbelInvokeService, Object> {
|
||||||
|
|
||||||
public RuleNodeMvelScriptEngine(TenantId tenantId, MvelInvokeService scriptInvokeService, String script, String... argNames) {
|
public RuleNodeTbelScriptEngine(TenantId tenantId, TbelInvokeService scriptInvokeService, String script, String... argNames) {
|
||||||
super(tenantId, scriptInvokeService, script, argNames);
|
super(tenantId, scriptInvokeService, script, argNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,25 +611,25 @@ state:
|
|||||||
defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:60}"
|
defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:60}"
|
||||||
persistToTelemetry: "${PERSIST_STATE_TO_TELEMETRY:false}"
|
persistToTelemetry: "${PERSIST_STATE_TO_TELEMETRY:false}"
|
||||||
|
|
||||||
mvel:
|
tbel:
|
||||||
enabled: "${MVEL_ENABLED:true}"
|
enabled: "${TBEL_ENABLED:true}"
|
||||||
max_total_args_size: "${MVEL_MAX_TOTAL_ARGS_SIZE:100000}"
|
max_total_args_size: "${TBEL_MAX_TOTAL_ARGS_SIZE:100000}"
|
||||||
max_result_size: "${MVEL_MAX_RESULT_SIZE:300000}"
|
max_result_size: "${TBEL_MAX_RESULT_SIZE:300000}"
|
||||||
max_script_body_size: "${MVEL_MAX_SCRIPT_BODY_SIZE:50000}"
|
max_script_body_size: "${TBEL_MAX_SCRIPT_BODY_SIZE:50000}"
|
||||||
# Maximum allowed MVEL script execution memory
|
# Maximum allowed TBEL script execution memory
|
||||||
max_memory_limit_mb: "${MVEL_MAX_MEMORY_LIMIT_MB: 8}"
|
max_memory_limit_mb: "${TBEL_MAX_MEMORY_LIMIT_MB: 8}"
|
||||||
# Maximum allowed MVEL script execution errors before it will be blacklisted
|
# Maximum allowed TBEL script execution errors before it will be blacklisted
|
||||||
max_errors: "${MVEL_MAX_ERRORS:3}"
|
max_errors: "${TBEL_MAX_ERRORS:3}"
|
||||||
# MVEL Eval max request timeout in milliseconds. 0 - no timeout
|
# TBEL Eval max request timeout in milliseconds. 0 - no timeout
|
||||||
max_requests_timeout: "${MVEL_MAX_REQUEST_TIMEOUT:500}"
|
max_requests_timeout: "${TBEL_MAX_REQUEST_TIMEOUT:500}"
|
||||||
# Maximum time in seconds for black listed function to stay in the list.
|
# Maximum time in seconds for black listed function to stay in the list.
|
||||||
max_black_list_duration_sec: "${MVEL_MAX_BLACKLIST_DURATION_SEC:60}"
|
max_black_list_duration_sec: "${TBEL_MAX_BLACKLIST_DURATION_SEC:60}"
|
||||||
# Specify thread pool size for javascript executor service
|
# Specify thread pool size for javascript executor service
|
||||||
thread_pool_size: "${MVEL_THREAD_POOL_SIZE:50}"
|
thread_pool_size: "${TBEL_THREAD_POOL_SIZE:50}"
|
||||||
compiled_scripts_cache_size: "${MVEL_COMPILED_SCRIPTS_CACHE_SIZE:1000}"
|
compiled_scripts_cache_size: "${TBEL_COMPILED_SCRIPTS_CACHE_SIZE:1000}"
|
||||||
stats:
|
stats:
|
||||||
enabled: "${TB_MVEL_STATS_ENABLED:false}"
|
enabled: "${TB_TBEL_STATS_ENABLED:false}"
|
||||||
print_interval_ms: "${TB_MVEL_STATS_PRINT_INTERVAL_MS:10000}"
|
print_interval_ms: "${TB_TBEL_STATS_PRINT_INTERVAL_MS:10000}"
|
||||||
|
|
||||||
js:
|
js:
|
||||||
evaluator: "${JS_EVALUATOR:local}" # local/remote
|
evaluator: "${JS_EVALUATOR:local}" # local/remote
|
||||||
|
|||||||
@ -24,8 +24,8 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.test.context.TestPropertySource;
|
import org.springframework.test.context.TestPropertySource;
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
import org.thingsboard.script.api.ScriptType;
|
import org.thingsboard.script.api.ScriptType;
|
||||||
import org.thingsboard.script.api.mvel.MvelInvokeService;
|
import org.thingsboard.script.api.tbel.TbelInvokeService;
|
||||||
import org.thingsboard.script.api.mvel.MvelScript;
|
import org.thingsboard.script.api.tbel.TbelScript;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.controller.AbstractControllerTest;
|
import org.thingsboard.server.controller.AbstractControllerTest;
|
||||||
import org.thingsboard.server.dao.service.DaoSqlTest;
|
import org.thingsboard.server.dao.service.DaoSqlTest;
|
||||||
@ -45,18 +45,18 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|||||||
|
|
||||||
@DaoSqlTest
|
@DaoSqlTest
|
||||||
@TestPropertySource(properties = {
|
@TestPropertySource(properties = {
|
||||||
"mvel.max_script_body_size=100",
|
"tbel.max_script_body_size=100",
|
||||||
"mvel.max_total_args_size=50",
|
"tbel.max_total_args_size=50",
|
||||||
"mvel.max_result_size=50",
|
"tbel.max_result_size=50",
|
||||||
"mvel.max_errors=2",
|
"tbel.max_errors=2",
|
||||||
"mvel.compiled_scripts_cache_size=100"
|
"tbel.compiled_scripts_cache_size=100"
|
||||||
})
|
})
|
||||||
class MvelInvokeServiceTest extends AbstractControllerTest {
|
class TbelInvokeServiceTest extends AbstractControllerTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MvelInvokeService invokeService;
|
private TbelInvokeService invokeService;
|
||||||
|
|
||||||
@Value("${mvel.max_errors}")
|
@Value("${tbel.max_errors}")
|
||||||
private int maxJsErrors;
|
private int maxJsErrors;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -129,7 +129,7 @@ class MvelInvokeServiceTest extends AbstractControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<UUID, String> scriptIdToHash = getFieldValue(invokeService, "scriptIdToHash");
|
Map<UUID, String> scriptIdToHash = getFieldValue(invokeService, "scriptIdToHash");
|
||||||
Map<String, MvelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
|
Map<String, TbelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
|
||||||
Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
|
Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
|
||||||
|
|
||||||
String scriptHash = scriptIdToHash.get(scriptsIds.get(0));
|
String scriptHash = scriptIdToHash.get(scriptsIds.get(0));
|
||||||
@ -149,7 +149,7 @@ class MvelInvokeServiceTest extends AbstractControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map<UUID, String> scriptIdToHash = getFieldValue(invokeService, "scriptIdToHash");
|
Map<UUID, String> scriptIdToHash = getFieldValue(invokeService, "scriptIdToHash");
|
||||||
Map<String, MvelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
|
Map<String, TbelScript> scriptMap = getFieldValue(invokeService, "scriptMap");
|
||||||
Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
|
Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
|
||||||
|
|
||||||
String scriptHash = scriptIdToHash.get(scriptsIds.get(0));
|
String scriptHash = scriptIdToHash.get(scriptsIds.get(0));
|
||||||
@ -173,7 +173,7 @@ class MvelInvokeServiceTest extends AbstractControllerTest {
|
|||||||
Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
|
Cache<String, Serializable> compiledScriptsCache = getFieldValue(invokeService, "compiledScriptsCache");
|
||||||
|
|
||||||
List<UUID> scriptsIds = new ArrayList<>();
|
List<UUID> scriptsIds = new ArrayList<>();
|
||||||
for (int i = 0; i < 110; i++) { // mvel.compiled_scripts_cache_size = 100
|
for (int i = 0; i < 110; i++) { // tbel.compiled_scripts_cache_size = 100
|
||||||
String script = "return msg.temperature > " + i;
|
String script = "return msg.temperature > " + i;
|
||||||
UUID scriptId = evalScript(script);
|
UUID scriptId = evalScript(script);
|
||||||
scriptsIds.add(scriptId);
|
scriptsIds.add(scriptId);
|
||||||
@ -16,5 +16,5 @@
|
|||||||
package org.thingsboard.server.common.data.script;
|
package org.thingsboard.server.common.data.script;
|
||||||
|
|
||||||
public enum ScriptLanguage {
|
public enum ScriptLanguage {
|
||||||
JS, MVEL
|
JS, TBEL
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,7 +90,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.thingsboard</groupId>
|
<groupId>org.thingsboard</groupId>
|
||||||
<artifactId>mvel2</artifactId>
|
<artifactId>tbel</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.script.api.mvel;
|
package org.thingsboard.script.api.tbel;
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Cache;
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
@ -58,12 +58,12 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ConditionalOnProperty(prefix = "mvel", value = "enabled", havingValue = "true", matchIfMissing = true)
|
@ConditionalOnProperty(prefix = "tbel", value = "enabled", havingValue = "true", matchIfMissing = true)
|
||||||
@Service
|
@Service
|
||||||
public class DefaultMvelInvokeService extends AbstractScriptInvokeService implements MvelInvokeService {
|
public class DefaultTbelInvokeService extends AbstractScriptInvokeService implements TbelInvokeService {
|
||||||
|
|
||||||
protected final Map<UUID, String> scriptIdToHash = new ConcurrentHashMap<>();
|
protected final Map<UUID, String> scriptIdToHash = new ConcurrentHashMap<>();
|
||||||
protected final Map<String, MvelScript> scriptMap = new ConcurrentHashMap<>();
|
protected final Map<String, TbelScript> scriptMap = new ConcurrentHashMap<>();
|
||||||
protected Cache<String, Serializable> compiledScriptsCache;
|
protected Cache<String, Serializable> compiledScriptsCache;
|
||||||
|
|
||||||
private SandboxedParserConfiguration parserConfig;
|
private SandboxedParserConfiguration parserConfig;
|
||||||
@ -71,49 +71,49 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
|
|||||||
private static final Pattern NEW_KEYWORD_PATTERN = Pattern.compile("new\\s");
|
private static final Pattern NEW_KEYWORD_PATTERN = Pattern.compile("new\\s");
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Value("${mvel.max_total_args_size:100000}")
|
@Value("${tbel.max_total_args_size:100000}")
|
||||||
private long maxTotalArgsSize;
|
private long maxTotalArgsSize;
|
||||||
@Getter
|
@Getter
|
||||||
@Value("${mvel.max_result_size:300000}")
|
@Value("${tbel.max_result_size:300000}")
|
||||||
private long maxResultSize;
|
private long maxResultSize;
|
||||||
@Getter
|
@Getter
|
||||||
@Value("${mvel.max_script_body_size:50000}")
|
@Value("${tbel.max_script_body_size:50000}")
|
||||||
private long maxScriptBodySize;
|
private long maxScriptBodySize;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Value("${mvel.max_errors:3}")
|
@Value("${tbel.max_errors:3}")
|
||||||
private int maxErrors;
|
private int maxErrors;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Value("${mvel.max_black_list_duration_sec:60}")
|
@Value("${tbel.max_black_list_duration_sec:60}")
|
||||||
private int maxBlackListDurationSec;
|
private int maxBlackListDurationSec;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Value("${mvel.max_requests_timeout:0}")
|
@Value("${tbel.max_requests_timeout:0}")
|
||||||
private long maxInvokeRequestsTimeout;
|
private long maxInvokeRequestsTimeout;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Value("${mvel.stats.enabled:false}")
|
@Value("${tbel.stats.enabled:false}")
|
||||||
private boolean statsEnabled;
|
private boolean statsEnabled;
|
||||||
|
|
||||||
@Value("${mvel.thread_pool_size:50}")
|
@Value("${tbel.thread_pool_size:50}")
|
||||||
private int threadPoolSize;
|
private int threadPoolSize;
|
||||||
|
|
||||||
@Value("${mvel.max_memory_limit_mb:8}")
|
@Value("${tbel.max_memory_limit_mb:8}")
|
||||||
private long maxMemoryLimitMb;
|
private long maxMemoryLimitMb;
|
||||||
|
|
||||||
@Value("${mvel.compiled_scripts_cache_size:1000}")
|
@Value("${tbel.compiled_scripts_cache_size:1000}")
|
||||||
private int compiledScriptsCacheSize;
|
private int compiledScriptsCacheSize;
|
||||||
|
|
||||||
private ListeningExecutorService executor;
|
private ListeningExecutorService executor;
|
||||||
|
|
||||||
private final Lock lock = new ReentrantLock();
|
private final Lock lock = new ReentrantLock();
|
||||||
|
|
||||||
protected DefaultMvelInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) {
|
protected DefaultTbelInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) {
|
||||||
super(apiUsageStateClient, apiUsageReportClient);
|
super(apiUsageStateClient, apiUsageReportClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(fixedDelayString = "${mvel.stats.print_interval_ms:10000}")
|
@Scheduled(fixedDelayString = "${tbel.stats.print_interval_ms:10000}")
|
||||||
public void printStats() {
|
public void printStats() {
|
||||||
super.printStats();
|
super.printStats();
|
||||||
}
|
}
|
||||||
@ -127,9 +127,9 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
|
|||||||
parserConfig.addImport("JSON", TbJson.class);
|
parserConfig.addImport("JSON", TbJson.class);
|
||||||
parserConfig.registerDataType("Date", TbDate.class, date -> 8L);
|
parserConfig.registerDataType("Date", TbDate.class, date -> 8L);
|
||||||
TbUtils.register(parserConfig);
|
TbUtils.register(parserConfig);
|
||||||
executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(threadPoolSize, "mvel-executor"));
|
executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(threadPoolSize, "tbel-executor"));
|
||||||
try {
|
try {
|
||||||
// Special command to warm up MVEL engine
|
// Special command to warm up TBEL engine
|
||||||
Serializable script = compileScript("var warmUp = {}; warmUp");
|
Serializable script = compileScript("var warmUp = {}; warmUp");
|
||||||
MVEL.executeTbExpression(script, new ExecutionContext(parserConfig), Collections.emptyMap());
|
MVEL.executeTbExpression(script, new ExecutionContext(parserConfig), Collections.emptyMap());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -149,7 +149,7 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getStatsName() {
|
protected String getStatsName() {
|
||||||
return "MVEL Scripts Stats";
|
return "TBEL Scripts Stats";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -167,15 +167,11 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
|
|||||||
return executor.submit(() -> {
|
return executor.submit(() -> {
|
||||||
try {
|
try {
|
||||||
String scriptHash = hash(scriptBody, argNames);
|
String scriptHash = hash(scriptBody, argNames);
|
||||||
compiledScriptsCache.get(scriptHash, k -> {
|
compiledScriptsCache.get(scriptHash, k -> compileScript(scriptBody));
|
||||||
return compileScript(scriptBody);
|
|
||||||
});
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
scriptIdToHash.put(scriptId, scriptHash);
|
scriptIdToHash.put(scriptId, scriptHash);
|
||||||
scriptMap.computeIfAbsent(scriptHash, k -> {
|
scriptMap.computeIfAbsent(scriptHash, k -> new TbelScript(scriptBody, argNames));
|
||||||
return new MvelScript(scriptBody, argNames);
|
|
||||||
});
|
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -187,17 +183,15 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MvelScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args) {
|
protected TbelScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args) {
|
||||||
ExecutionContext executionContext = new ExecutionContext(this.parserConfig, maxMemoryLimitMb * 1024 * 1024);
|
ExecutionContext executionContext = new ExecutionContext(this.parserConfig, maxMemoryLimitMb * 1024 * 1024);
|
||||||
return new MvelScriptExecutionTask(executionContext, executor.submit(() -> {
|
return new TbelScriptExecutionTask(executionContext, executor.submit(() -> {
|
||||||
String scriptHash = scriptIdToHash.get(scriptId);
|
String scriptHash = scriptIdToHash.get(scriptId);
|
||||||
if (scriptHash == null) {
|
if (scriptHash == null) {
|
||||||
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.OTHER, null, new RuntimeException("Script not found!"));
|
throw new TbScriptException(scriptId, TbScriptException.ErrorCode.OTHER, null, new RuntimeException("Script not found!"));
|
||||||
}
|
}
|
||||||
MvelScript script = scriptMap.get(scriptHash);
|
TbelScript script = scriptMap.get(scriptHash);
|
||||||
Serializable compiledScript = compiledScriptsCache.get(scriptHash, k -> {
|
Serializable compiledScript = compiledScriptsCache.get(scriptHash, k -> compileScript(script.getScriptBody()));
|
||||||
return compileScript(script.getScriptBody());
|
|
||||||
});
|
|
||||||
try {
|
try {
|
||||||
return MVEL.executeTbExpression(compiledScript, executionContext, script.createVars(args));
|
return MVEL.executeTbExpression(compiledScript, executionContext, script.createVars(args));
|
||||||
} catch (ScriptMemoryOverflowException e) {
|
} catch (ScriptMemoryOverflowException e) {
|
||||||
@ -209,7 +203,7 @@ public class DefaultMvelInvokeService extends AbstractScriptInvokeService implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doRelease(UUID scriptId) throws Exception {
|
protected void doRelease(UUID scriptId) {
|
||||||
String scriptHash = scriptIdToHash.remove(scriptId);
|
String scriptHash = scriptIdToHash.remove(scriptId);
|
||||||
if (scriptHash != null) {
|
if (scriptHash != null) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.script.api.mvel;
|
package org.thingsboard.script.api.tbel;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@ -60,7 +60,7 @@ public class TbDate extends Date {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toISOString() {
|
public String toISOString() {
|
||||||
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sssZ");
|
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||||
return formatter.format(this);
|
return formatter.format(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.script.api.mvel;
|
package org.thingsboard.script.api.tbel;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import org.mvel2.ExecutionContext;
|
import org.mvel2.ExecutionContext;
|
||||||
@ -13,19 +13,25 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.script.api.mvel;
|
package org.thingsboard.script.api.tbel;
|
||||||
|
|
||||||
import org.mvel2.ExecutionContext;
|
import org.mvel2.ExecutionContext;
|
||||||
import org.mvel2.ParserConfiguration;
|
import org.mvel2.ParserConfiguration;
|
||||||
import org.mvel2.execution.ExecutionArrayList;
|
import org.mvel2.execution.ExecutionArrayList;
|
||||||
import org.mvel2.util.MethodStub;
|
import org.mvel2.util.MethodStub;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TbUtils {
|
public class TbUtils {
|
||||||
|
|
||||||
|
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
|
||||||
|
|
||||||
public static void register(ParserConfiguration parserConfig) throws Exception {
|
public static void register(ParserConfiguration parserConfig) throws Exception {
|
||||||
parserConfig.addImport("btoa", new MethodStub(TbUtils.class.getMethod("btoa",
|
parserConfig.addImport("btoa", new MethodStub(TbUtils.class.getMethod("btoa",
|
||||||
String.class)));
|
String.class)));
|
||||||
@ -35,6 +41,10 @@ public class TbUtils {
|
|||||||
List.class)));
|
List.class)));
|
||||||
parserConfig.addImport("bytesToString", new MethodStub(TbUtils.class.getMethod("bytesToString",
|
parserConfig.addImport("bytesToString", new MethodStub(TbUtils.class.getMethod("bytesToString",
|
||||||
List.class, String.class)));
|
List.class, String.class)));
|
||||||
|
parserConfig.addImport("decodeToString", new MethodStub(TbUtils.class.getMethod("bytesToString",
|
||||||
|
List.class)));
|
||||||
|
parserConfig.addImport("decodeToJson", new MethodStub(TbUtils.class.getMethod("decodeToJson",
|
||||||
|
ExecutionContext.class, List.class)));
|
||||||
parserConfig.addImport("stringToBytes", new MethodStub(TbUtils.class.getMethod("stringToBytes",
|
parserConfig.addImport("stringToBytes", new MethodStub(TbUtils.class.getMethod("stringToBytes",
|
||||||
ExecutionContext.class, String.class)));
|
ExecutionContext.class, String.class)));
|
||||||
parserConfig.addImport("stringToBytes", new MethodStub(TbUtils.class.getMethod("stringToBytes",
|
parserConfig.addImport("stringToBytes", new MethodStub(TbUtils.class.getMethod("stringToBytes",
|
||||||
@ -47,10 +57,24 @@ public class TbUtils {
|
|||||||
String.class)));
|
String.class)));
|
||||||
parserConfig.addImport("parseDouble", new MethodStub(TbUtils.class.getMethod("parseDouble",
|
parserConfig.addImport("parseDouble", new MethodStub(TbUtils.class.getMethod("parseDouble",
|
||||||
String.class)));
|
String.class)));
|
||||||
}
|
parserConfig.addImport("parseLittleEndianHexToInt", new MethodStub(TbUtils.class.getMethod("parseLittleEndianHexToInt",
|
||||||
|
String.class)));
|
||||||
public static void main(String[] args) {
|
parserConfig.addImport("parseBigEndianHexToInt", new MethodStub(TbUtils.class.getMethod("parseBigEndianHexToInt",
|
||||||
System.out.println(Integer.class == int.class);
|
String.class)));
|
||||||
|
parserConfig.addImport("parseHexToInt", new MethodStub(TbUtils.class.getMethod("parseHexToInt",
|
||||||
|
String.class)));
|
||||||
|
parserConfig.addImport("parseHexToInt", new MethodStub(TbUtils.class.getMethod("parseHexToInt",
|
||||||
|
String.class, boolean.class)));
|
||||||
|
parserConfig.addImport("toFixed", new MethodStub(TbUtils.class.getMethod("toFixed",
|
||||||
|
double.class, int.class)));
|
||||||
|
parserConfig.addImport("hexToBytes", new MethodStub(TbUtils.class.getMethod("hexToBytes",
|
||||||
|
ExecutionContext.class, String.class)));
|
||||||
|
parserConfig.addImport("base64ToHex", new MethodStub(TbUtils.class.getMethod("base64ToHex",
|
||||||
|
String.class)));
|
||||||
|
parserConfig.addImport("bytesToHex", new MethodStub(TbUtils.class.getMethod("bytesToHex",
|
||||||
|
byte[].class)));
|
||||||
|
parserConfig.addImport("bytesToHex", new MethodStub(TbUtils.class.getMethod("bytesToHex",
|
||||||
|
ExecutionArrayList.class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String btoa(String input) {
|
public static String btoa(String input) {
|
||||||
@ -61,6 +85,10 @@ public class TbUtils {
|
|||||||
return new String(Base64.getDecoder().decode(encoded));
|
return new String(Base64.getDecoder().decode(encoded));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Object decodeToJson(ExecutionContext ctx, List<Byte> bytesList) throws IOException {
|
||||||
|
return TbJson.parse(ctx, bytesToString(bytesList));
|
||||||
|
}
|
||||||
|
|
||||||
public static String bytesToString(List<Byte> bytesList) {
|
public static String bytesToString(List<Byte> bytesList) {
|
||||||
byte[] bytes = bytesFromList(bytesList);
|
byte[] bytes = bytesFromList(bytesList);
|
||||||
return new String(bytes);
|
return new String(bytes);
|
||||||
@ -149,6 +177,72 @@ public class TbUtils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int parseLittleEndianHexToInt(String hex) {
|
||||||
|
return parseHexToInt(hex, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int parseBigEndianHexToInt(String hex) {
|
||||||
|
return parseHexToInt(hex, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int parseHexToInt(String hex) {
|
||||||
|
return parseHexToInt(hex, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int parseHexToInt(String hex, boolean bigEndian) {
|
||||||
|
int length = hex.length();
|
||||||
|
if (length > 8) {
|
||||||
|
throw new IllegalArgumentException("Hex string is too large. Maximum 8 symbols allowed.");
|
||||||
|
}
|
||||||
|
if (bigEndian) {
|
||||||
|
return Integer.parseInt(hex, 16);
|
||||||
|
} else {
|
||||||
|
if (length < 8) {
|
||||||
|
hex = hex + "0".repeat(8 - length);
|
||||||
|
}
|
||||||
|
return Integer.reverseBytes(Integer.parseInt(hex, 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExecutionArrayList<Integer> hexToBytes(ExecutionContext ctx, String hex) {
|
||||||
|
int len = hex.length();
|
||||||
|
if (len % 2 > 0) {
|
||||||
|
throw new IllegalArgumentException("Hex string must be even-length.");
|
||||||
|
}
|
||||||
|
ExecutionArrayList<Integer> data = new ExecutionArrayList<>(ctx);
|
||||||
|
for (int i = 0; i < len; i += 2) {
|
||||||
|
data.add((Character.digit(hex.charAt(i), 16) << 4)
|
||||||
|
+ Character.digit(hex.charAt(i+1), 16));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String base64ToHex(String base64) {
|
||||||
|
return bytesToHex(Base64.getDecoder().decode(base64));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bytesToHex(ExecutionArrayList<?> bytesList) {
|
||||||
|
byte[] bytes = new byte[bytesList.size()];
|
||||||
|
for (int i = 0; i < bytesList.size(); i++) {
|
||||||
|
bytes[i] = Byte.parseByte(bytesList.get(i).toString());
|
||||||
|
}
|
||||||
|
return bytesToHex(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bytesToHex(byte[] bytes) {
|
||||||
|
byte[] hexChars = new byte[bytes.length * 2];
|
||||||
|
for (int j = 0; j < bytes.length; j++) {
|
||||||
|
int v = bytes[j] & 0xFF;
|
||||||
|
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
|
||||||
|
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
|
||||||
|
}
|
||||||
|
return new String(hexChars, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double toFixed(double value, int precision) {
|
||||||
|
return BigDecimal.valueOf(value).setScale(precision, RoundingMode.HALF_UP).doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isHexadecimal(String value) {
|
private static boolean isHexadecimal(String value) {
|
||||||
return value != null && (value.contains("0x") || value.contains("0X"));
|
return value != null && (value.contains("0x") || value.contains("0X"));
|
||||||
}
|
}
|
||||||
@ -13,16 +13,16 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.script.api.mvel;
|
package org.thingsboard.script.api.tbel;
|
||||||
|
|
||||||
import org.thingsboard.script.api.ScriptInvokeService;
|
import org.thingsboard.script.api.ScriptInvokeService;
|
||||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
||||||
|
|
||||||
public interface MvelInvokeService extends ScriptInvokeService {
|
public interface TbelInvokeService extends ScriptInvokeService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default ScriptLanguage getLanguage() {
|
default ScriptLanguage getLanguage() {
|
||||||
return ScriptLanguage.MVEL;
|
return ScriptLanguage.TBEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -13,16 +13,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.script.api.mvel;
|
package org.thingsboard.script.api.tbel;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class MvelScript {
|
public class TbelScript {
|
||||||
|
|
||||||
private final String scriptBody;
|
private final String scriptBody;
|
||||||
private final String[] argNames;
|
private final String[] argNames;
|
||||||
@ -13,20 +13,18 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.thingsboard.script.api.mvel;
|
package org.thingsboard.script.api.tbel;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import lombok.Data;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.mvel2.ExecutionContext;
|
import org.mvel2.ExecutionContext;
|
||||||
import org.thingsboard.script.api.TbScriptExecutionTask;
|
import org.thingsboard.script.api.TbScriptExecutionTask;
|
||||||
|
|
||||||
|
|
||||||
public class MvelScriptExecutionTask extends TbScriptExecutionTask {
|
public class TbelScriptExecutionTask extends TbScriptExecutionTask {
|
||||||
|
|
||||||
private final ExecutionContext context;
|
private final ExecutionContext context;
|
||||||
|
|
||||||
public MvelScriptExecutionTask(ExecutionContext context, ListenableFuture<Object> resultFuture) {
|
public TbelScriptExecutionTask(ExecutionContext context, ListenableFuture<Object> resultFuture) {
|
||||||
super(resultFuture);
|
super(resultFuture);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
6
pom.xml
6
pom.xml
@ -77,7 +77,7 @@
|
|||||||
<zookeeper.version>3.5.5</zookeeper.version>
|
<zookeeper.version>3.5.5</zookeeper.version>
|
||||||
<protobuf.version>3.21.9</protobuf.version>
|
<protobuf.version>3.21.9</protobuf.version>
|
||||||
<grpc.version>1.42.1</grpc.version>
|
<grpc.version>1.42.1</grpc.version>
|
||||||
<mvel.version>2.4.25TB</mvel.version>
|
<tbel.version>1.0.0</tbel.version>
|
||||||
<lombok.version>1.18.18</lombok.version>
|
<lombok.version>1.18.18</lombok.version>
|
||||||
<paho.client.version>1.2.4</paho.client.version>
|
<paho.client.version>1.2.4</paho.client.version>
|
||||||
<netty.version>4.1.75.Final</netty.version>
|
<netty.version>4.1.75.Final</netty.version>
|
||||||
@ -1575,8 +1575,8 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.thingsboard</groupId>
|
<groupId>org.thingsboard</groupId>
|
||||||
<artifactId>mvel2</artifactId>
|
<artifactId>tbel</artifactId>
|
||||||
<version>${mvel.version}</version>
|
<version>${tbel.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
|
|||||||
@ -48,7 +48,7 @@ public abstract class TbAbstractAlarmNode<C extends TbAbstractAlarmNodeConfigura
|
|||||||
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
||||||
this.config = loadAlarmNodeConfig(configuration);
|
this.config = loadAlarmNodeConfig(configuration);
|
||||||
scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
||||||
ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getAlarmDetailsBuildMvel() : config.getAlarmDetailsBuildJs());
|
ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getAlarmDetailsBuildTbel() : config.getAlarmDetailsBuildJs());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract C loadAlarmNodeConfig(TbNodeConfiguration configuration) throws TbNodeException;
|
protected abstract C loadAlarmNodeConfig(TbNodeConfiguration configuration) throws TbNodeException;
|
||||||
|
|||||||
@ -33,7 +33,7 @@ public abstract class TbAbstractAlarmNodeConfiguration {
|
|||||||
"\n" +
|
"\n" +
|
||||||
"return details;";
|
"return details;";
|
||||||
|
|
||||||
static final String ALARM_DETAILS_BUILD_MVEL_TEMPLATE = "" +
|
static final String ALARM_DETAILS_BUILD_TBEL_TEMPLATE = "" +
|
||||||
"var details = {};\n" +
|
"var details = {};\n" +
|
||||||
"if (metadata.prevAlarmDetails != null) {\n" +
|
"if (metadata.prevAlarmDetails != null) {\n" +
|
||||||
" details = JSON.parse(metadata.prevAlarmDetails);\n" +
|
" details = JSON.parse(metadata.prevAlarmDetails);\n" +
|
||||||
@ -49,6 +49,6 @@ public abstract class TbAbstractAlarmNodeConfiguration {
|
|||||||
private String alarmType;
|
private String alarmType;
|
||||||
private ScriptLanguage scriptLang;
|
private ScriptLanguage scriptLang;
|
||||||
private String alarmDetailsBuildJs;
|
private String alarmDetailsBuildJs;
|
||||||
private String alarmDetailsBuildMvel;
|
private String alarmDetailsBuildTbel;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,6 @@ package org.thingsboard.rule.engine.action;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.thingsboard.rule.engine.api.NodeConfiguration;
|
import org.thingsboard.rule.engine.api.NodeConfiguration;
|
||||||
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
|
|
||||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ -26,9 +25,9 @@ public class TbClearAlarmNodeConfiguration extends TbAbstractAlarmNodeConfigurat
|
|||||||
@Override
|
@Override
|
||||||
public TbClearAlarmNodeConfiguration defaultConfiguration() {
|
public TbClearAlarmNodeConfiguration defaultConfiguration() {
|
||||||
TbClearAlarmNodeConfiguration configuration = new TbClearAlarmNodeConfiguration();
|
TbClearAlarmNodeConfiguration configuration = new TbClearAlarmNodeConfiguration();
|
||||||
configuration.setScriptLang(ScriptLanguage.MVEL);
|
configuration.setScriptLang(ScriptLanguage.TBEL);
|
||||||
configuration.setAlarmDetailsBuildJs(ALARM_DETAILS_BUILD_JS_TEMPLATE);
|
configuration.setAlarmDetailsBuildJs(ALARM_DETAILS_BUILD_JS_TEMPLATE);
|
||||||
configuration.setAlarmDetailsBuildMvel(ALARM_DETAILS_BUILD_MVEL_TEMPLATE);
|
configuration.setAlarmDetailsBuildTbel(ALARM_DETAILS_BUILD_TBEL_TEMPLATE);
|
||||||
configuration.setAlarmType("General Alarm");
|
configuration.setAlarmType("General Alarm");
|
||||||
return configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,9 +39,9 @@ public class TbCreateAlarmNodeConfiguration extends TbAbstractAlarmNodeConfigura
|
|||||||
@Override
|
@Override
|
||||||
public TbCreateAlarmNodeConfiguration defaultConfiguration() {
|
public TbCreateAlarmNodeConfiguration defaultConfiguration() {
|
||||||
TbCreateAlarmNodeConfiguration configuration = new TbCreateAlarmNodeConfiguration();
|
TbCreateAlarmNodeConfiguration configuration = new TbCreateAlarmNodeConfiguration();
|
||||||
configuration.setScriptLang(ScriptLanguage.MVEL);
|
configuration.setScriptLang(ScriptLanguage.TBEL);
|
||||||
configuration.setAlarmDetailsBuildJs(ALARM_DETAILS_BUILD_JS_TEMPLATE);
|
configuration.setAlarmDetailsBuildJs(ALARM_DETAILS_BUILD_JS_TEMPLATE);
|
||||||
configuration.setAlarmDetailsBuildMvel(ALARM_DETAILS_BUILD_MVEL_TEMPLATE);
|
configuration.setAlarmDetailsBuildTbel(ALARM_DETAILS_BUILD_TBEL_TEMPLATE);
|
||||||
configuration.setAlarmType("General Alarm");
|
configuration.setAlarmType("General Alarm");
|
||||||
configuration.setSeverity(AlarmSeverity.CRITICAL.name());
|
configuration.setSeverity(AlarmSeverity.CRITICAL.name());
|
||||||
configuration.setPropagate(false);
|
configuration.setPropagate(false);
|
||||||
|
|||||||
@ -56,7 +56,7 @@ public class TbLogNode implements TbNode {
|
|||||||
this.config = TbNodeUtils.convert(configuration, TbLogNodeConfiguration.class);
|
this.config = TbNodeUtils.convert(configuration, TbLogNodeConfiguration.class);
|
||||||
this.standard = new TbLogNodeConfiguration().defaultConfiguration().getJsScript().equals(config.getJsScript());
|
this.standard = new TbLogNodeConfiguration().defaultConfiguration().getJsScript().equals(config.getJsScript());
|
||||||
this.scriptEngine = this.standard ? null : ctx.createScriptEngine(config.getScriptLang(),
|
this.scriptEngine = this.standard ? null : ctx.createScriptEngine(config.getScriptLang(),
|
||||||
ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript());
|
ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -24,14 +24,14 @@ public class TbLogNodeConfiguration implements NodeConfiguration {
|
|||||||
|
|
||||||
private ScriptLanguage scriptLang;
|
private ScriptLanguage scriptLang;
|
||||||
private String jsScript;
|
private String jsScript;
|
||||||
private String mvelScript;
|
private String tbelScript;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TbLogNodeConfiguration defaultConfiguration() {
|
public TbLogNodeConfiguration defaultConfiguration() {
|
||||||
TbLogNodeConfiguration configuration = new TbLogNodeConfiguration();
|
TbLogNodeConfiguration configuration = new TbLogNodeConfiguration();
|
||||||
configuration.setScriptLang(ScriptLanguage.MVEL);
|
configuration.setScriptLang(ScriptLanguage.TBEL);
|
||||||
configuration.setJsScript("return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);");
|
configuration.setJsScript("return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);");
|
||||||
configuration.setMvelScript("return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);");
|
configuration.setTbelScript("return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);");
|
||||||
return configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,7 +96,7 @@ public class TbMsgGeneratorNode implements TbNode {
|
|||||||
if (ctx.isLocalEntity(originatorId)) {
|
if (ctx.isLocalEntity(originatorId)) {
|
||||||
if (initialized.compareAndSet(false, true)) {
|
if (initialized.compareAndSet(false, true)) {
|
||||||
this.scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
this.scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
||||||
ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript(), "prevMsg", "prevMetadata", "prevMsgType");
|
ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript(), "prevMsg", "prevMetadata", "prevMsgType");
|
||||||
scheduleTickMsg(ctx);
|
scheduleTickMsg(ctx);
|
||||||
}
|
}
|
||||||
} else if (initialized.compareAndSet(true, false)) {
|
} else if (initialized.compareAndSet(true, false)) {
|
||||||
|
|||||||
@ -35,16 +35,16 @@ public class TbMsgGeneratorNodeConfiguration implements NodeConfiguration<TbMsgG
|
|||||||
private EntityType originatorType;
|
private EntityType originatorType;
|
||||||
private ScriptLanguage scriptLang;
|
private ScriptLanguage scriptLang;
|
||||||
private String jsScript;
|
private String jsScript;
|
||||||
private String mvelScript;
|
private String tbelScript;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TbMsgGeneratorNodeConfiguration defaultConfiguration() {
|
public TbMsgGeneratorNodeConfiguration defaultConfiguration() {
|
||||||
TbMsgGeneratorNodeConfiguration configuration = new TbMsgGeneratorNodeConfiguration();
|
TbMsgGeneratorNodeConfiguration configuration = new TbMsgGeneratorNodeConfiguration();
|
||||||
configuration.setMsgCount(UNLIMITED_MSG_COUNT);
|
configuration.setMsgCount(UNLIMITED_MSG_COUNT);
|
||||||
configuration.setPeriodInSeconds(1);
|
configuration.setPeriodInSeconds(1);
|
||||||
configuration.setScriptLang(ScriptLanguage.MVEL);
|
configuration.setScriptLang(ScriptLanguage.TBEL);
|
||||||
configuration.setJsScript(DEFAULT_SCRIPT);
|
configuration.setJsScript(DEFAULT_SCRIPT);
|
||||||
configuration.setMvelScript(DEFAULT_SCRIPT);
|
configuration.setTbelScript(DEFAULT_SCRIPT);
|
||||||
return configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,6 @@ import org.thingsboard.rule.engine.api.TbNode;
|
|||||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeException;
|
import org.thingsboard.rule.engine.api.TbNodeException;
|
||||||
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
|
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
|
||||||
import org.thingsboard.server.common.data.StringUtils;
|
|
||||||
import org.thingsboard.server.common.data.plugin.ComponentType;
|
import org.thingsboard.server.common.data.plugin.ComponentType;
|
||||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
||||||
import org.thingsboard.server.common.msg.TbMsg;
|
import org.thingsboard.server.common.msg.TbMsg;
|
||||||
@ -53,7 +52,7 @@ public class TbJsFilterNode implements TbNode {
|
|||||||
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
||||||
this.config = TbNodeUtils.convert(configuration, TbJsFilterNodeConfiguration.class);
|
this.config = TbNodeUtils.convert(configuration, TbJsFilterNodeConfiguration.class);
|
||||||
scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
||||||
ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript());
|
ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -24,14 +24,14 @@ public class TbJsFilterNodeConfiguration implements NodeConfiguration<TbJsFilter
|
|||||||
|
|
||||||
private ScriptLanguage scriptLang;
|
private ScriptLanguage scriptLang;
|
||||||
private String jsScript;
|
private String jsScript;
|
||||||
private String mvelScript;
|
private String tbelScript;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TbJsFilterNodeConfiguration defaultConfiguration() {
|
public TbJsFilterNodeConfiguration defaultConfiguration() {
|
||||||
TbJsFilterNodeConfiguration configuration = new TbJsFilterNodeConfiguration();
|
TbJsFilterNodeConfiguration configuration = new TbJsFilterNodeConfiguration();
|
||||||
configuration.setScriptLang(ScriptLanguage.MVEL);
|
configuration.setScriptLang(ScriptLanguage.TBEL);
|
||||||
configuration.setJsScript("return msg.temperature > 20;");
|
configuration.setJsScript("return msg.temperature > 20;");
|
||||||
configuration.setMvelScript("return msg.temperature > 20;");
|
configuration.setTbelScript("return msg.temperature > 20;");
|
||||||
return configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@ public class TbJsSwitchNode implements TbNode {
|
|||||||
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
||||||
this.config = TbNodeUtils.convert(configuration, TbJsSwitchNodeConfiguration.class);
|
this.config = TbNodeUtils.convert(configuration, TbJsSwitchNodeConfiguration.class);
|
||||||
this.scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
this.scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
||||||
ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript());
|
ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -15,13 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.rule.engine.filter;
|
package org.thingsboard.rule.engine.filter;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.thingsboard.rule.engine.api.NodeConfiguration;
|
import org.thingsboard.rule.engine.api.NodeConfiguration;
|
||||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TbJsSwitchNodeConfiguration implements NodeConfiguration<TbJsSwitchNodeConfiguration> {
|
public class TbJsSwitchNodeConfiguration implements NodeConfiguration<TbJsSwitchNodeConfiguration> {
|
||||||
|
|
||||||
@ -33,7 +30,7 @@ public class TbJsSwitchNodeConfiguration implements NodeConfiguration<TbJsSwitch
|
|||||||
"}\n" +
|
"}\n" +
|
||||||
"return nextRelation(metadata, msg);";
|
"return nextRelation(metadata, msg);";
|
||||||
|
|
||||||
private static final String DEFAULT_MVEL_SCRIPT = "function nextRelation(metadata, msg) {\n" +
|
private static final String DEFAULT_TBEL_SCRIPT = "function nextRelation(metadata, msg) {\n" +
|
||||||
" return ['one','nine'];\n" +
|
" return ['one','nine'];\n" +
|
||||||
"}\n" +
|
"}\n" +
|
||||||
"if(msgType == 'POST_TELEMETRY_REQUEST') {\n" +
|
"if(msgType == 'POST_TELEMETRY_REQUEST') {\n" +
|
||||||
@ -43,14 +40,14 @@ public class TbJsSwitchNodeConfiguration implements NodeConfiguration<TbJsSwitch
|
|||||||
|
|
||||||
private ScriptLanguage scriptLang;
|
private ScriptLanguage scriptLang;
|
||||||
private String jsScript;
|
private String jsScript;
|
||||||
private String mvelScript;
|
private String tbelScript;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TbJsSwitchNodeConfiguration defaultConfiguration() {
|
public TbJsSwitchNodeConfiguration defaultConfiguration() {
|
||||||
TbJsSwitchNodeConfiguration configuration = new TbJsSwitchNodeConfiguration();
|
TbJsSwitchNodeConfiguration configuration = new TbJsSwitchNodeConfiguration();
|
||||||
configuration.setScriptLang(ScriptLanguage.MVEL);
|
configuration.setScriptLang(ScriptLanguage.TBEL);
|
||||||
configuration.setJsScript(DEFAULT_JS_SCRIPT);
|
configuration.setJsScript(DEFAULT_JS_SCRIPT);
|
||||||
configuration.setMvelScript(DEFAULT_MVEL_SCRIPT);
|
configuration.setTbelScript(DEFAULT_TBEL_SCRIPT);
|
||||||
return configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import org.thingsboard.rule.engine.api.TbContext;
|
|||||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
||||||
import org.thingsboard.rule.engine.api.TbNodeException;
|
import org.thingsboard.rule.engine.api.TbNodeException;
|
||||||
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
|
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
|
||||||
import org.thingsboard.server.common.data.StringUtils;
|
|
||||||
import org.thingsboard.server.common.data.plugin.ComponentType;
|
import org.thingsboard.server.common.data.plugin.ComponentType;
|
||||||
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
import org.thingsboard.server.common.data.script.ScriptLanguage;
|
||||||
import org.thingsboard.server.common.msg.TbMsg;
|
import org.thingsboard.server.common.msg.TbMsg;
|
||||||
@ -53,7 +52,7 @@ public class TbTransformMsgNode extends TbAbstractTransformNode {
|
|||||||
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
|
||||||
this.config = TbNodeUtils.convert(configuration, TbTransformMsgNodeConfiguration.class);
|
this.config = TbNodeUtils.convert(configuration, TbTransformMsgNodeConfiguration.class);
|
||||||
scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
scriptEngine = ctx.createScriptEngine(config.getScriptLang(),
|
||||||
ScriptLanguage.MVEL.equals(config.getScriptLang()) ? config.getMvelScript() : config.getJsScript());
|
ScriptLanguage.TBEL.equals(config.getScriptLang()) ? config.getTbelScript() : config.getJsScript());
|
||||||
setConfig(config);
|
setConfig(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,14 +24,14 @@ public class TbTransformMsgNodeConfiguration extends TbTransformNodeConfiguratio
|
|||||||
|
|
||||||
private ScriptLanguage scriptLang;
|
private ScriptLanguage scriptLang;
|
||||||
private String jsScript;
|
private String jsScript;
|
||||||
private String mvelScript;
|
private String tbelScript;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TbTransformMsgNodeConfiguration defaultConfiguration() {
|
public TbTransformMsgNodeConfiguration defaultConfiguration() {
|
||||||
TbTransformMsgNodeConfiguration configuration = new TbTransformMsgNodeConfiguration();
|
TbTransformMsgNodeConfiguration configuration = new TbTransformMsgNodeConfiguration();
|
||||||
configuration.setScriptLang(ScriptLanguage.MVEL);
|
configuration.setScriptLang(ScriptLanguage.TBEL);
|
||||||
configuration.setJsScript("return {msg: msg, metadata: metadata, msgType: msgType};");
|
configuration.setJsScript("return {msg: msg, metadata: metadata, msgType: msgType};");
|
||||||
configuration.setMvelScript("return {msg: msg, metadata: metadata, msgType: msgType};");
|
configuration.setTbelScript("return {msg: msg, metadata: metadata, msgType: msgType};");
|
||||||
return configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -21,7 +21,7 @@ export interface SysParamsState {
|
|||||||
allowedDashboardIds: string[];
|
allowedDashboardIds: string[];
|
||||||
edgesSupportEnabled: boolean;
|
edgesSupportEnabled: boolean;
|
||||||
hasRepository: boolean;
|
hasRepository: boolean;
|
||||||
mvelEnabled: boolean;
|
tbelEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthPayload extends SysParamsState {
|
export interface AuthPayload extends SysParamsState {
|
||||||
|
|||||||
@ -25,7 +25,7 @@ const emptyUserAuthState: AuthPayload = {
|
|||||||
allowedDashboardIds: [],
|
allowedDashboardIds: [],
|
||||||
edgesSupportEnabled: false,
|
edgesSupportEnabled: false,
|
||||||
hasRepository: false,
|
hasRepository: false,
|
||||||
mvelEnabled: false
|
tbelEnabled: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export const initialState: AuthState = {
|
export const initialState: AuthState = {
|
||||||
|
|||||||
@ -60,9 +60,9 @@ export const selectHasRepository = createSelector(
|
|||||||
(state: AuthState) => state.hasRepository
|
(state: AuthState) => state.hasRepository
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectMvelEnabled = createSelector(
|
export const selectTbelEnabled = createSelector(
|
||||||
selectAuthState,
|
selectAuthState,
|
||||||
(state: AuthState) => state.mvelEnabled
|
(state: AuthState) => state.tbelEnabled
|
||||||
);
|
);
|
||||||
|
|
||||||
export function getCurrentAuthState(store: Store<AppState>): AuthState {
|
export function getCurrentAuthState(store: Store<AppState>): AuthState {
|
||||||
|
|||||||
@ -482,9 +482,9 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadMvelEnabled(authUser: AuthUser): Observable<boolean> {
|
private loadTbelEnabled(authUser: AuthUser): Observable<boolean> {
|
||||||
if (authUser.authority === Authority.TENANT_ADMIN) {
|
if (authUser.authority === Authority.TENANT_ADMIN) {
|
||||||
return this.http.get<boolean>('/api/ruleChain/mvelEnabled', defaultHttpOptions());
|
return this.http.get<boolean>('/api/ruleChain/tbelEnabled', defaultHttpOptions());
|
||||||
} else {
|
} else {
|
||||||
return of(false);
|
return of(false);
|
||||||
}
|
}
|
||||||
@ -495,7 +495,7 @@ export class AuthService {
|
|||||||
this.fetchAllowedDashboardIds(authPayload),
|
this.fetchAllowedDashboardIds(authPayload),
|
||||||
this.loadIsEdgesSupportEnabled(),
|
this.loadIsEdgesSupportEnabled(),
|
||||||
this.loadHasRepository(authPayload.authUser),
|
this.loadHasRepository(authPayload.authUser),
|
||||||
this.loadMvelEnabled(authPayload.authUser),
|
this.loadTbelEnabled(authPayload.authUser),
|
||||||
this.timeService.loadMaxDatapointsLimit()];
|
this.timeService.loadMaxDatapointsLimit()];
|
||||||
return forkJoin(sources)
|
return forkJoin(sources)
|
||||||
.pipe(map((data) => {
|
.pipe(map((data) => {
|
||||||
@ -503,8 +503,8 @@ export class AuthService {
|
|||||||
const allowedDashboardIds: string[] = data[1] as string[];
|
const allowedDashboardIds: string[] = data[1] as string[];
|
||||||
const edgesSupportEnabled: boolean = data[2] as boolean;
|
const edgesSupportEnabled: boolean = data[2] as boolean;
|
||||||
const hasRepository: boolean = data[3] as boolean;
|
const hasRepository: boolean = data[3] as boolean;
|
||||||
const mvelEnabled: boolean = data[4] as boolean;
|
const tbelEnabled: boolean = data[4] as boolean;
|
||||||
return {userTokenAccessEnabled, allowedDashboardIds, edgesSupportEnabled, hasRepository, mvelEnabled};
|
return {userTokenAccessEnabled, allowedDashboardIds, edgesSupportEnabled, hasRepository, tbelEnabled};
|
||||||
}, catchError((err) => {
|
}, catchError((err) => {
|
||||||
return of({});
|
return of({});
|
||||||
})));
|
})));
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
<form class="tb-node-script-test-dialog"
|
<form class="tb-node-script-test-dialog"
|
||||||
[formGroup]="nodeScriptTestFormGroup" (ngSubmit)="save()">
|
[formGroup]="nodeScriptTestFormGroup" (ngSubmit)="save()">
|
||||||
<mat-toolbar fxLayout="row" color="primary">
|
<mat-toolbar fxLayout="row" color="primary">
|
||||||
<h2>{{ 'rulenode.test-script-function' | translate }} ({{ (scriptLang === scriptLanguage.JS ? 'rulenode.script-lang-java-script' : 'rulenode.script-lang-mvel') | translate }})</h2>
|
<h2>{{ 'rulenode.test-script-function' | translate }} ({{ (scriptLang === scriptLanguage.JS ? 'rulenode.script-lang-java-script' : 'rulenode.script-lang-tbel') | translate }})</h2>
|
||||||
<span fxFlex></span>
|
<span fxFlex></span>
|
||||||
<button mat-button mat-icon-button
|
<button mat-button mat-icon-button
|
||||||
(click)="cancel()"
|
(click)="cancel()"
|
||||||
@ -77,7 +77,7 @@
|
|||||||
functionName="{{ data.functionName }}"
|
functionName="{{ data.functionName }}"
|
||||||
[functionArgs]="data.argNames"
|
[functionArgs]="data.argNames"
|
||||||
[validationArgs]="[data.msg, data.metadata, data.msgType]"
|
[validationArgs]="[data.msg, data.metadata, data.msgType]"
|
||||||
[disableUndefinedCheck]="scriptLang === scriptLanguage.MVEL"
|
[disableUndefinedCheck]="scriptLang === scriptLanguage.TBEL"
|
||||||
resultType="object"
|
resultType="object"
|
||||||
[helpId]="data.helpId"
|
[helpId]="data.helpId"
|
||||||
[fillHeight]="true">
|
[fillHeight]="true">
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
<mat-button-toggle-group class="tb-script-lang-toggle-group"
|
<mat-button-toggle-group class="tb-script-lang-toggle-group"
|
||||||
style="width: 320px;"
|
style="width: 320px;"
|
||||||
formControlName="scriptLang" aria-label="Script language">
|
formControlName="scriptLang" aria-label="Script language">
|
||||||
<mat-button-toggle fxFlex value="{{ scriptLanguage.MVEL }}">{{ 'rulenode.script-lang-mvel' | translate }}</mat-button-toggle>
|
<mat-button-toggle fxFlex value="{{ scriptLanguage.TBEL }}">{{ 'rulenode.script-lang-tbel' | translate }}</mat-button-toggle>
|
||||||
<mat-button-toggle fxFlex value="{{ scriptLanguage.JS }}">{{ 'rulenode.script-lang-java-script' | translate }}</mat-button-toggle>
|
<mat-button-toggle fxFlex value="{{ scriptLanguage.JS }}">{{ 'rulenode.script-lang-java-script' | translate }}</mat-button-toggle>
|
||||||
</mat-button-toggle-group>
|
</mat-button-toggle-group>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -330,7 +330,7 @@ export interface FcRuleEdge extends FcEdge {
|
|||||||
|
|
||||||
export enum ScriptLanguage {
|
export enum ScriptLanguage {
|
||||||
JS = 'JS',
|
JS = 'JS',
|
||||||
MVEL = 'MVEL'
|
TBEL = 'TBEL'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TestScriptInputParams {
|
export interface TestScriptInputParams {
|
||||||
|
|||||||
@ -3013,7 +3013,7 @@
|
|||||||
"invalid-target-rulechain": "Unable to resolve target rule chain!",
|
"invalid-target-rulechain": "Unable to resolve target rule chain!",
|
||||||
"test-script-function": "Test script function",
|
"test-script-function": "Test script function",
|
||||||
"script-lang-java-script": "Java Script",
|
"script-lang-java-script": "Java Script",
|
||||||
"script-lang-mvel": "MVEL",
|
"script-lang-tbel": "TBEL",
|
||||||
"message": "Message",
|
"message": "Message",
|
||||||
"message-type": "Message type",
|
"message-type": "Message type",
|
||||||
"select-message-type": "Select message type",
|
"select-message-type": "Select message type",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user