Merge remote-tracking branch 'remotes/openOrigin/dev' into dev

# Conflicts:
#	iot-components/iot-component-server/src/main/java/cc/iotkit/comps/DeviceComponentManager.java
#	iot-components/iot-websocket-component/src/main/java/cc/iotkit/comp/websocket/server/WebSocketServerVerticle.java
V0.5.x
tangfudong 2023-04-20 13:53:38 +08:00
commit b236d517e5
98 changed files with 1686 additions and 1594 deletions

View File

@ -60,9 +60,12 @@ function acl(head,type,payload){
};
}
// 客户端订阅处理
if (/^\/sys\/.+\/.+\/c\/#/i.test(_topic)) {
return subscribe(head,type,payload);
}
// 服务端订阅处理
if (/^\/sys\/.+\/.+\/s\/.*/i.test(_topic)) {
return subscribe(head,type,payload);
}
@ -224,9 +227,6 @@ function subscribe(head,type,payload){
}
}
var messageHandler = {
"/sys/client/connected":connect,
"/sys/client/disconnected":disconnect,
@ -240,30 +240,17 @@ var messageHandler = {
this.onReceive=function(head,type,payload){
payload=JSON.parse(payload);
print("======================================================================= ");
print("【message from】: " + (isServerId(payload.clientid)?"Server":"Device") );
print("onReceive head: "+JSON.stringify(head));
print("onReceive type: "+JSON.stringify(type));
print("onReceive payload: "+ JSON.stringify(payload));
//print("onReceive compMqttClientIdList: "+ component.getCompMqttClientIdList());
var result = {};
var topic = head.topic;
if(!topic) {
print("【result】: " + JSON.stringify(result));
print("======================================================================= ");
return result;
}
var fun = messageHandler[topic];
if(fun){
result = fun(head,type,payload)
}
else{
}else{
var arr= topic.split('/');
if(arr.length<6){
throw new Error("incorrect topic: "+topic)
@ -292,8 +279,6 @@ this.onReceive=function(head,type,payload){
}
}
print("【result】: " + JSON.stringify(result));
print("======================================================================= ");
return result;
}

View File

@ -5,7 +5,7 @@
"name": "MQTT标准协议组件",
"type": "device",
"protocol": "mqtt",
"jarFile": "iot-mqtt-component-0.4.2-SNAPSHOT.jar",
"jarFile": "iot-mqtt-component-0.4.3-SNAPSHOT.jar",
"config": "{\"port\":1883,\"ssl\":false,\"type\":\"server\"}",
"converter": "6260396d67aced2696184053",
"converType": "custom",
@ -18,7 +18,7 @@
"name": "EMQX标准协议组件",
"type": "device",
"protocol": "mqtt",
"jarFile": "iot-emqx-component-0.4.2-SNAPSHOT.jar",
"jarFile": "iot-emqx-component-0.4.3-SNAPSHOT.jar",
"config": "{\"port\":\"1884\",\"ssl\":false,\"type\":\"client\",\"subscribeTopics\":[\"/sys/+/+/s/#\",\"/sys/client/connected\",\"/sys/client/disconnected\",\"/sys/session/subscribed\",\"/sys/session/unsubscribed\"],\"authPort\":\"8088\",\"broker\":\"127.0.0.1\",\"clientId\":\"test\",\"username\":\"test\",\"password\":\"123\"}",
"converter": "6260396d67aced2696184053",
"converType": "custom",
@ -31,7 +31,7 @@
"name": "小度音箱接入组件",
"type": "biz",
"protocol": "http",
"jarFile": "iot-http-biz-component-0.4.2-SNAPSHOT.jar",
"jarFile": "iot-http-biz-component-0.4.3-SNAPSHOT.jar",
"config": "{\"port\":\"8084\"}",
"converter": "",
"converType": "",

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -14,14 +14,8 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import lombok.SneakyThrows;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class JsonUtil {
private final static ObjectMapper MAPPER = new ObjectMapper()
@ -47,33 +41,4 @@ public final class JsonUtil {
public static JsonNode parse(String json) {
return MAPPER.readTree(json);
}
public static Object toObject(ScriptObjectMirror mirror) {
if (mirror.isEmpty()) {
return new Object();
}
if (mirror.isArray()) {
List<Object> list = new ArrayList<>();
for (Map.Entry<String, Object> entry : mirror.entrySet()) {
Object result = entry.getValue();
if (result instanceof ScriptObjectMirror) {
list.add(toObject((ScriptObjectMirror) result));
} else {
list.add(result);
}
}
return list;
}
Map<String, Object> map = new HashMap<>();
for (Map.Entry<String, Object> entry : mirror.entrySet()) {
Object result = entry.getValue();
if (result instanceof ScriptObjectMirror) {
map.put(entry.getKey(), toObject((ScriptObjectMirror) result));
} else {
map.put(entry.getKey(), result);
}
}
return map;
}
}

View File

@ -38,4 +38,17 @@ public class ReflectUtil {
BeanUtils.populate(to, map);
return to;
}
public static Map<String, ?> toMap(Object bean) {
Map<String, Object> map = new HashMap<>();
new BeanMap(bean).forEach((key, value) -> {
if (key.equals("class")) {
return;
}
String field = key.toString();
map.put(field, value);
});
return map;
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -9,9 +9,17 @@
*/
package cc.iotkit.comp.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldNameConstants;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@FieldNameConstants
public class AuthInfo {
private String productKey;

View File

@ -9,14 +9,19 @@
*/
package cc.iotkit.comp.model;
import cc.iotkit.common.utils.JsonUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldNameConstants;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@Data
@Slf4j
@NoArgsConstructor
@AllArgsConstructor
@Builder
@FieldNameConstants
public class DeviceState {
public static final String STATE_ONLINE = "online";
@ -30,11 +35,11 @@ public class DeviceState {
private Parent parent;
public static DeviceState from(Map map) {
return JsonUtil.parse(JsonUtil.toJsonString(map), DeviceState.class);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@FieldNameConstants
public static class Parent {
private String productKey;
private String deviceName;

View File

@ -13,8 +13,8 @@ import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldNameConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import java.util.ArrayList;
import java.util.List;
@ -28,6 +28,7 @@ import java.util.Map;
@NoArgsConstructor
@AllArgsConstructor
@Builder
@FieldNameConstants
public class RegisterInfo {
private String productKey;
@ -56,31 +57,11 @@ public class RegisterInfo {
}
}
public static RegisterInfo from(Map map) {
RegisterInfo bean = new RegisterInfo();
try {
BeanUtils.populate(bean, map);
List<SubDevice> subDevices = new ArrayList<>();
List<Object> sourceSubDevices = (List<Object>) map.get("subDevices");
if (sourceSubDevices == null) {
return bean;
}
for (Object sourceSubDevice : sourceSubDevices) {
SubDevice subDevice = new SubDevice();
BeanUtils.populate(subDevice, (Map<String, ? extends Object>) sourceSubDevice);
subDevices.add(subDevice);
}
bean.setSubDevices(subDevices);
} catch (Throwable e) {
log.error("parse bean from map error", e);
return null;
}
return bean;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@FieldNameConstants
public static class SubDevice {
private String productKey;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -28,11 +28,6 @@
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-model</artifactId>
</dependency>
<!--javascript运行环境-->
<dependency>
<groupId>org.graalvm.sdk</groupId>
@ -46,7 +41,16 @@
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-model</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
</dependency>
</dependencies>

View File

@ -1,47 +0,0 @@
package cc.iotkit.converter;
import org.graalvm.polyglot.Value;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class CovertUtils {
private static final Map<Class<?>, Map<String, Field>> FIELD_CACHE = new ConcurrentHashMap<>();
private static final Map<Class<?>, Map<String, Method>> SETTER_CACHE = new ConcurrentHashMap<>();
public static void copyProperties(Object javaObj, Value jsObj) {
Map<String, Field> fieldMap = FIELD_CACHE.computeIfAbsent(javaObj.getClass(), clazz -> {
Map<String, Field> fields = new ConcurrentHashMap<>();
for (Field field : clazz.getDeclaredFields()) {
fields.put(field.getName(), field);
}
return fields;
});
Map<String, Method> setterMap = SETTER_CACHE.computeIfAbsent(javaObj.getClass(), clazz -> {
Map<String, Method> setters = new ConcurrentHashMap<>();
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().startsWith("set") && method.getParameterCount() == 1) {
String propName = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
setters.put(propName, method);
}
}
return setters;
});
for (String propName : jsObj.getMemberKeys()) {
try {
Field field = fieldMap.get(propName);
Method setter = setterMap.get(propName);
if (field != null && setter != null) {
Class<?> propType = field.getType();
Object propValue = jsObj.getMember(propName).as(propType);
setter.invoke(javaObj, propValue);
}
} catch (Exception e) {
// ignore errors
}
}
}
}

View File

@ -1,20 +0,0 @@
package cc.iotkit.converter;
import org.apache.commons.lang3.StringUtils;
public class DefaultScriptConvertFactory implements IScriptConvertFactory{
@Override
public IConverter getCovert(String name) {
if(StringUtils.isNotBlank(name)){
if (name.endsWith("graaljs")){
return new GraalJsScriptConverter();
}
}
// 默认是NashornScript js实现方式
return new ScriptConverter();
}
}

View File

@ -9,9 +9,16 @@
*/
package cc.iotkit.converter;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DeviceMessage {
private String productKey;
@ -21,4 +28,5 @@ public class DeviceMessage {
private String mid;
private Object content;
}

View File

@ -1,70 +0,0 @@
/*
* +----------------------------------------------------------------------
* | Copyright (c) 2021-2022 All rights reserved.
* +----------------------------------------------------------------------
* | Licensed
* +----------------------------------------------------------------------
* | Author: xw2sy@163.com
* +----------------------------------------------------------------------
*/
package cc.iotkit.converter;
import cc.iotkit.common.thing.ThingService;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.model.device.message.ThingModelMessage;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.graalvm.polyglot.*;
@Slf4j
@Data
public class GraalJsScriptConverter implements IConverter {
private final Context context = Context.newBuilder("js").allowHostAccess(true).build();
private Value decoder;
private Value encoder;
public void setScript(String script) {
Value myFunctions = context.eval("js",String.format("new (function () {\n%s})()", script));
// 调用JavaScript函数
decoder = myFunctions.getMember("decode");
encoder = myFunctions.getMember("encode");
}
public ThingModelMessage decode(DeviceMessage msg) {
try {
// String msgJson = JsonUtil.toJsonString(msg);
Value rst = decoder.execute(msg);
ThingModelMessage modelMessage = new ThingModelMessage();
CovertUtils.copyProperties(modelMessage, rst);
return modelMessage;
} catch (Throwable e) {
log.error("execute decode script error", e);
}
return null;
}
@Override
public DeviceMessage encode(ThingService<?> service, Device device) {
try {
Value rst = encoder.execute(service,device);
DeviceMessage modelMessage = rst.as(DeviceMessage.class);
return modelMessage;
} catch (Throwable e) {
log.error("execute encode script error", e);
}
return null;
}
@Override
public void putScriptEnv(String key, Object value) {
context.getBindings("js").putMember(key, value);
}
}

View File

@ -1,6 +0,0 @@
package cc.iotkit.converter;
public interface IScriptConvertFactory {
IConverter getCovert(String name);
}

View File

@ -0,0 +1,49 @@
/*
* +----------------------------------------------------------------------
* | Copyright (c) 2021-2022 All rights reserved.
* +----------------------------------------------------------------------
* | Licensed
* +----------------------------------------------------------------------
* | Author: xw2sy@163.com
* +----------------------------------------------------------------------
*/
package cc.iotkit.converter;
import cc.iotkit.common.thing.ThingService;
import cc.iotkit.model.device.message.ThingModelMessage;
import cc.iotkit.script.IScriptEngine;
import cc.iotkit.script.ScriptEngineFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Data
public class JavaScriptConverter implements IConverter {
private IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
@SneakyThrows
public void setScript(String script) {
scriptEngine.setScript(script);
}
@SneakyThrows
public ThingModelMessage decode(DeviceMessage msg) {
return scriptEngine.invokeMethod(new TypeReference<>() {
}, "decode", msg);
}
@SneakyThrows
@Override
public DeviceMessage encode(ThingService<?> service, Device device) {
return scriptEngine.invokeMethod(new TypeReference<>() {
}, "encode", service, device);
}
@Override
public void putScriptEnv(String key, Object value) {
scriptEngine.putScriptEnv(key, value);
}
}

View File

@ -0,0 +1,41 @@
package cc.iotkit.converter;
import cc.iotkit.common.thing.ThingService;
import cc.iotkit.model.device.message.ThingModelMessage;
public class ScriptConvertFactory {
public static IConverter getCovert(String type) {
if (type == null) {
type = "js";
}
switch (type) {
case "python":
case "lua":
return new IConverter() {
@Override
public void setScript(String script) {
}
@Override
public ThingModelMessage decode(DeviceMessage msg) {
return null;
}
@Override
public DeviceMessage encode(ThingService<?> service, Device device) {
return null;
}
@Override
public void putScriptEnv(String key, Object value) {
}
};
case "js":
default:
return new JavaScriptConverter();
}
}
}

View File

@ -1,75 +0,0 @@
/*
* +----------------------------------------------------------------------
* | Copyright (c) 2021-2022 All rights reserved.
* +----------------------------------------------------------------------
* | Licensed
* +----------------------------------------------------------------------
* | Author: xw2sy@163.com
* +----------------------------------------------------------------------
*/
package cc.iotkit.converter;
import cc.iotkit.common.thing.ThingService;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.model.device.message.ThingModelMessage;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.Map;
@Slf4j
@Data
public class ScriptConverter implements IConverter {
private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn");
private Object scriptObj;
public void setScript(String script) {
try {
scriptObj = engine.eval(String.format("new (function () {\n%s})()", script));
} catch (ScriptException e) {
log.error("eval converter script error", e);
}
}
public ThingModelMessage decode(DeviceMessage msg) {
try {
Object rst = engine.invokeMethod(scriptObj, "decode", msg);
if (rst instanceof ThingModelMessage) {
return (ThingModelMessage) rst;
}
ScriptObjectMirror result = (ScriptObjectMirror) rst;
ThingModelMessage modelMessage = new ThingModelMessage();
BeanUtils.populate(modelMessage, result);
return modelMessage;
} catch (Throwable e) {
log.error("execute decode script error", e);
}
return null;
}
@Override
public DeviceMessage encode(ThingService<?> service, Device device) {
try {
ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeMethod(scriptObj, "encode", service, device);
Map map = (Map) JsonUtil.toObject(result);
DeviceMessage message = new DeviceMessage();
BeanUtils.populate(message, map);
return message;
} catch (Throwable e) {
log.error("execute encode script error", e);
}
return null;
}
@Override
public void putScriptEnv(String key, Object value) {
engine.put(key, value);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -96,11 +96,10 @@
<groupId>cc.iotkit</groupId>
<artifactId>iot-data-cache</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-components-engine</artifactId>
<version>0.4.2-SNAPSHOT</version>
<scope>compile</scope>
<artifactId>iot-script-engine</artifactId>
</dependency>
</dependencies>

View File

@ -67,6 +67,10 @@ public class BizComponentManager {
Path path = componentConfig.getComponentFilePath(id);
File file = path.resolve(component.getJarFile()).toAbsolutePath().toFile();
if (!file.exists()) {
throw new BizException("jar file:" + file.getAbsolutePath() + " not found");
}
IComponent componentInstance;
try {
componentInstance = ComponentClassLoader.getComponent(component.getId(), file);

View File

@ -28,13 +28,13 @@ import cc.iotkit.data.IDeviceInfoData;
import cc.iotkit.data.IProductData;
import cc.iotkit.data.IProtocolComponentData;
import cc.iotkit.data.IProtocolConverterData;
import cc.iotkit.engine.IScriptEngine;
import cc.iotkit.engine.IScriptEngineFactory;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.device.message.ThingModelMessage;
import cc.iotkit.model.product.Product;
import cc.iotkit.model.protocol.ProtocolComponent;
import cc.iotkit.model.protocol.ProtocolConverter;
import cc.iotkit.script.IScriptEngine;
import cc.iotkit.script.ScriptEngineFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -78,17 +78,7 @@ public class DeviceComponentManager {
@Autowired
private IProtocolConverterData protocolConverterData;
private final IScriptConvertFactory scriptConverterFactory;
private final IScriptEngineFactory scriptEngineFactory;
private IScriptEngine scriptEngine;
public DeviceComponentManager(IScriptConvertFactory scriptConverterFactory,
IScriptEngineFactory scriptEngineFactory ) {
this.scriptConverterFactory = scriptConverterFactory;
this.scriptEngineFactory = scriptEngineFactory;
}
private IScriptEngine scriptEngine;
@PostConstruct
public void init() {
@ -132,8 +122,7 @@ public class DeviceComponentManager {
}else{
setScriptConvert(component, componentInstance);
}
scriptEngine = scriptEngineFactory.getScriptEngine(component.getScriptTyp());
scriptEngine = ScriptEngineFactory.getScriptEngine(component.getScriptTyp());
String componentScript = FileUtils.readFileToString(path.
resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile(), "UTF-8");
@ -147,7 +136,7 @@ public class DeviceComponentManager {
private void setScriptConvert(ProtocolComponent component, IDeviceComponent componentInstance) throws IOException {
ProtocolConverter protocolConvert = protocolConverterData.findById(component.getConverter());
IConverter scriptConverter = scriptConverterFactory.getCovert(protocolConvert.getTyp());
IConverter scriptConverter = ScriptConvertFactory.getCovert(protocolConvert.getTyp());
// 从文件方式内容
Path converterPath = componentConfig.getConverterFilePath(component.getConverter());
String converterScript = FileUtils.readFileToString(converterPath.
@ -181,10 +170,9 @@ public class DeviceComponentManager {
}
DeviceMessageHandler messageHandler = new DeviceMessageHandler(
this, component,
scriptEngine,
scriptEngine,
component.getScript(), component.getConverter(),
deviceBehaviourService, deviceRouter);
messageHandler.putScriptEnv("apiTool", new ApiTool());

View File

@ -9,7 +9,6 @@
*/
package cc.iotkit.comps;
import cc.iotkit.common.exception.BizException;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.common.utils.UniqueIdUtil;
import cc.iotkit.comp.IDeviceComponent;
@ -21,17 +20,13 @@ import cc.iotkit.converter.DeviceMessage;
import cc.iotkit.comp.model.DeviceState;
import cc.iotkit.comps.service.DeviceBehaviourService;
import cc.iotkit.converter.IConverter;
import cc.iotkit.engine.IScriptEngine;
import cc.iotkit.engine.IScriptException;
import cc.iotkit.engine.JsNashornScriptEngine;
import cc.iotkit.model.device.message.ThingModelMessage;
import cc.iotkit.script.IScriptEngine;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import javax.script.ScriptException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.*;
import java.util.function.Consumer;
@ -75,76 +70,67 @@ public class DeviceMessageHandler implements IMessageHandler {
scriptEngine.setScript(script);
}
@Override
public void onReceive(Map<String, Object> head, String type, String msg) {
onReceive(head, type, msg, (r) -> {
});
}
@Override
public void onReceive(Map<String, Object> head, String type, String msg, Consumer<ReceiveResult> onResult) {
executorService.submit(() -> {
try {
DeviceMsgScriptResult result = invokeMethodWithResult("onReceive", head, type, msg);
log.info("onReceive script result:{}", JsonUtil.toJsonString(result));
Object rstType = result.getType();
if (rstType == null) {
Map<String, Object> rst = scriptEngine.invokeMethod(new TypeReference<>() {
}, "onReceive", head, type, msg);
Object objType = rst.get("type");
if (objType == null) {
onResult.accept(null);
return;
}
//取脚本执行后返回的数据
Object data = result.getData();
if (!(data instanceof Map)) {
throw new BizException("script result data is incorrect");
Object objData = rst.get("data");
if (!(objData instanceof Map)) {
onResult.accept(null);
return;
}
Map data = (Map) objData;
Map<String, Object> dataMap = (Map) data;
//获取动作数据
Action action = getAction(result.getAction());
Action action = MessageParser.parse(new Action(), rst.get("action"));
if ("register".equals(rstType)) {
//注册数据
RegisterInfo regInfo = RegisterInfo.from(dataMap);
if (regInfo == null) {
onResult.accept(null);
switch (objType.toString()) {
case "register":
//注册数据
RegisterInfo regInfo = MessageParser.parseRegisterInfo(data);
if (regInfo == null) {
onResult.accept(null);
return;
}
doRegister(regInfo);
doAction(action);
onResult.accept(new ReceiveResult(regInfo.getProductKey(), regInfo.getDeviceName(), regInfo));
return;
}
doRegister(regInfo);
doAction(action);
onResult.accept(new ReceiveResult(regInfo.getProductKey(), regInfo.getDeviceName(), regInfo));
return;
} else if ("auth".equals(rstType)) {
//设备认证
AuthInfo authInfo = new AuthInfo();
BeanUtils.populate(authInfo, dataMap);
doAuth(authInfo);
doAction(action);
onResult.accept(new ReceiveResult(authInfo.getProductKey(), authInfo.getDeviceName(), authInfo));
return;
} else if ("state".equals(rstType)) {
//设备状态变更
DeviceState state = DeviceState.from(dataMap);
if (state == null) {
onResult.accept(null);
case "auth":
//设备认证
AuthInfo authInfo = MessageParser.parse(new AuthInfo(), data);
doAuth(authInfo);
doAction(action);
onResult.accept(new ReceiveResult(authInfo.getProductKey(), authInfo.getDeviceName(), authInfo));
return;
case "state":
//设备状态变更
DeviceState state = MessageParser.parseDeviceState(data);
doStateChange(state);
doAction(action);
onResult.accept(new ReceiveResult(state.getProductKey(), state.getDeviceName(), state));
return;
case "report":
//上报数据
DeviceMessage message = MessageParser.parse(new DeviceMessage(), data);
doReport(message);
doAction(action);
onResult.accept(new ReceiveResult(message.getProductKey(), message.getDeviceName(), message));
return;
}
doStateChange(state);
doAction(action);
onResult.accept(new ReceiveResult(state.getProductKey(), state.getDeviceName(), state));
return;
} else if ("report".equals(rstType)) {
//上报数据
DeviceMessage message = new DeviceMessage();
BeanUtils.populate(message, dataMap);
doReport(message);
doAction(action);
onResult.accept(new ReceiveResult(message.getProductKey(), message.getDeviceName(), message));
return;
} else if ("action".equals(rstType)) {
//纯做回复操作
DeviceMessage message = new DeviceMessage();
BeanUtils.populate(message, dataMap);
doAction(action);
onResult.accept(new ReceiveResult(message.getProductKey(), message.getDeviceName(), message));
return;
}
} catch (Throwable e) {
@ -154,17 +140,17 @@ public class DeviceMessageHandler implements IMessageHandler {
});
}
private void doRegister(RegisterInfo reg) throws IScriptException {
private void doRegister(RegisterInfo reg) {
try {
deviceBehaviourService.register(reg);
} catch (Throwable e) {
log.error("register error", e);
} finally {
invokeMethod("onRegistered", reg, "false");
scriptEngine.invokeMethod("onRegistered", reg, "false");
}
}
private void doAuth(AuthInfo auth) throws IScriptException {
private void doAuth(AuthInfo auth) {
try {
deviceBehaviourService.deviceAuth(auth.getProductKey(),
auth.getDeviceName(),
@ -173,22 +159,10 @@ public class DeviceMessageHandler implements IMessageHandler {
} catch (Throwable e) {
log.error("device auth error", e);
} finally {
invokeMethod("onAuthed", auth, "false");
scriptEngine.invokeMethod("onAuthed", auth, "false");
}
}
private void invokeMethod(String name, Object... args) throws IScriptException {
scriptEngine.invokeMethod(name, args);
}
private DeviceMsgScriptResult invokeMethodWithResult(String name, Object... args) throws InvocationTargetException, IllegalAccessException, IScriptException {
Object o = scriptEngine.invokeMethod(name, args);
DeviceMsgScriptResult result = new DeviceMsgScriptResult();
BeanUtils.copyProperties(result, o);
return result;
}
private void doStateChange(DeviceState state) {
try {
String pk = state.getProductKey();
@ -199,8 +173,6 @@ public class DeviceMessageHandler implements IMessageHandler {
} else {
deviceRouter.removeRouter(pk, dn);
}
// 避免已在线多此发送上线消息
if (isOnline == deviceBehaviourService.isOnline(pk, dn)) return;
component.onDeviceStateChange(state);
deviceBehaviourService.deviceStateChange(pk, dn, isOnline);
} catch (Throwable e) {
@ -226,19 +198,6 @@ public class DeviceMessageHandler implements IMessageHandler {
deviceBehaviourService.reportMessage(thingModelMessage);
}
private Action getAction(Object objAction) {
if (!(objAction instanceof Map)) {
return null;
}
Action action = new Action();
try {
BeanUtils.populate(action, (Map<String, ? extends Object>) objAction);
} catch (Throwable e) {
log.error("parse action error", e);
}
return action;
}
private void doAction(Action action) {
if (action == null) {
return;

View File

@ -1,17 +0,0 @@
package cc.iotkit.comps;
import lombok.Data;
import java.util.Map;
@Data
public class DeviceMsgScriptResult {
private String type;
private Object data;
private Map action;
}

View File

@ -0,0 +1,62 @@
package cc.iotkit.comps;
import cc.iotkit.comp.model.DeviceState;
import cc.iotkit.comp.model.RegisterInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Slf4j
public class MessageParser {
public static RegisterInfo parseRegisterInfo(Map value) {
RegisterInfo registerInfo = new RegisterInfo();
try {
List<RegisterInfo.SubDevice> subDevices = new ArrayList<>();
Object objSubDevices = value.get(RegisterInfo.Fields.subDevices);
if (objSubDevices instanceof List) {
for (Object item : (List) objSubDevices) {
subDevices.add(parse(new RegisterInfo.SubDevice(), item));
}
}
registerInfo.setSubDevices(subDevices);
return RegisterInfo.builder()
.deviceName(Objects.toString(value.get(RegisterInfo.Fields.deviceName), ""))
.productKey(Objects.toString(value.get(RegisterInfo.Fields.productKey), ""))
.model(Objects.toString(value.get(RegisterInfo.Fields.model), ""))
.subDevices(subDevices)
.build();
} catch (Throwable e) {
log.error("parse bean from Value error", e);
return null;
}
}
@SneakyThrows
public static DeviceState parseDeviceState(Map value) {
return DeviceState.builder()
.deviceName(Objects.toString(value.get(DeviceState.Fields.deviceName), ""))
.productKey(Objects.toString(value.get(DeviceState.Fields.productKey), ""))
.state(Objects.toString(value.get(DeviceState.Fields.state), ""))
.parent(
parse(new DeviceState.Parent(), value.get(DeviceState.Fields.parent))
)
.build();
}
@SneakyThrows
public static <T> T parse(T obj, Object map) {
if (!(map instanceof Map)) {
return null;
}
BeanUtils.populate(obj, (Map<String, ? extends Object>) map);
return obj;
}
}

View File

@ -1,14 +1,7 @@
package cc.iotkit.comps.config;
import cc.iotkit.converter.IScriptConvertFactory;
import cc.iotkit.converter.DefaultScriptConvertFactory;
import cc.iotkit.engine.DefaultScriptEngineFactory;
import cc.iotkit.engine.IScriptEngineFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.nio.file.Path;
@ -33,20 +26,4 @@ public class ComponentConfig {
return Paths.get(converterDir, conId)
.toAbsolutePath().normalize();
}
@Bean("objectMapper")
public ObjectMapper myMapper() {
return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
}
@Bean
public IScriptConvertFactory scriptConverterFactory(){
return new DefaultScriptConvertFactory();
}
@Bean
public IScriptEngineFactory scriptEngineFactory(){
return new DefaultScriptEngineFactory();
}
}

View File

@ -54,14 +54,15 @@ public class DeviceBehaviourService {
DeviceInfo deviceInfo = register(null, info);
//子设备注册
List<RegisterInfo.SubDevice> subDevices = info.getSubDevices();
if (subDevices != null && subDevices.size() != 0) {
for (RegisterInfo.SubDevice subDevice : subDevices) {
register(deviceInfo.getDeviceId(),
new RegisterInfo(subDevice.getProductKey(),
subDevice.getDeviceName(),
subDevice.getModel(),
subDevice.getTag(), null));
}
if (subDevices == null) {
return;
}
for (RegisterInfo.SubDevice subDevice : subDevices) {
register(deviceInfo.getDeviceId(),
new RegisterInfo(subDevice.getProductKey(),
subDevice.getDeviceName(),
subDevice.getModel(),
subDevice.getTag(), null));
}
} catch (BizException e) {
log.error("register device error", e);
@ -176,7 +177,7 @@ public class DeviceBehaviourService {
}
public boolean isOnline(String productKey,
String deviceName){
String deviceName) {
DeviceInfo device = deviceInfoData.findByProductKeyAndDeviceName(productKey, deviceName);
DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(device.getDeviceId());
return deviceInfo.getState().isOnline();
@ -187,7 +188,7 @@ public class DeviceBehaviourService {
boolean online) {
DeviceInfo device = deviceInfoData.findByProductKeyAndDeviceName(productKey, deviceName);
if (device == null) {
log.warn(String.format("productKey: %s,device: %s,online: %s", productKey, device, online));
log.warn("productKey: {},deviceName:{},online: {}", productKey, deviceName, online);
throw new BizException("device does not exist");
}
deviceStateChange(device, online);
@ -242,6 +243,7 @@ public class DeviceBehaviourService {
if (device == null) {
return;
}
message.setId(UUID.randomUUID().toString());
if (message.getOccurred() == null) {
message.setOccurred(System.currentTimeMillis());
}

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>iot-component-tcp</artifactId>
@ -24,7 +24,6 @@
<artifactSet>
<includes>
<include>io.vertx:vertx-core</include>
<include>org.luaj:luaj-jse</include>
</includes>
</artifactSet>
</configuration>
@ -77,28 +76,28 @@
<version>1.7.32</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.luaj</groupId>
<artifactId>luaj-jse</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-common</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-component-base</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-data-service</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -40,11 +40,6 @@
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.luaj</groupId>
<artifactId>luaj-jse</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-common</artifactId>
@ -60,6 +55,11 @@
<artifactId>iot-data-service</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
</dependency>
</dependencies>
<build>
@ -80,7 +80,6 @@
<artifactSet>
<includes>
<include>io.vertx:vertx-core</include>
<include>org.luaj:luaj-jse</include>
</includes>
</artifactSet>
</configuration>

View File

@ -20,6 +20,7 @@ public class TcpClientDeviceComponent extends AbstractDeviceComponent {
private TcpClientVerticle tcpClientVerticle;
private String deployedId;
@Override
public void create(CompConfig config) {
super.create(config);
vertx = Vertx.vertx();

View File

@ -1,56 +1,33 @@
package cc.iotkit.comp.tcp.parser;
import cc.iotkit.script.IScriptEngine;
import cc.iotkit.script.ScriptEngineFactory;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.parsetools.RecordParser;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.EmitterProcessor;
import reactor.core.publisher.Flux;
import reactor.core.publisher.FluxSink;
import javax.script.ScriptEngineManager;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
/**
*
*
* @copy jetLink
* @author huangwenl
* @date 2022-10-13
*/
/**
* <pre>
* PipePayloadParser parser = new PipePayloadParser();
* parser.fixed(4)
* .handler(buffer -> {
* int len = BytesUtils.highBytes2Int(buffer.getBytes());
* parser.fixed(len);
* })
* .handler(buffer -> parser.result(buffer.toString("UTF-8")).complete());
* </pre>
*/
@Slf4j
public class ScriptPayloadParser implements PayloadParser {
private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager())
.getEngineByName("nashorn");
private final IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
@SneakyThrows
@Override
public PayloadParser init(Object param) {
String script = (String) param;
;
ScriptObjectMirror scriptObject = (ScriptObjectMirror) engine.eval("new (function(){" + script + "})()");
scriptEngine.setScript(script);
//执行转换脚本
engine.invokeMethod(scriptObject, "payloadParser", this);
scriptEngine.invokeMethod("payloadParser", this);
return this;
}

View File

@ -1,17 +0,0 @@
package cc.iotkit.engine;
import org.apache.commons.lang3.StringUtils;
public class DefaultScriptEngineFactory implements IScriptEngineFactory{
@Override
public IScriptEngine getScriptEngine(String name) {
if(StringUtils.isNotBlank(name)){
if (name.endsWith("graaljs")){
return new JsGraalJsScriptEngine();
}
}
// 默认是NashornScript js实现方式
return new JsNashornScriptEngine();
}
}

View File

@ -1,12 +0,0 @@
package cc.iotkit.engine;
public interface IScriptEngine {
void setScript(String key) throws IScriptException;
void putScriptEnv(String key, Object val);
Object invokeMethod(String methodName, Object ...args) throws IScriptException;
}

View File

@ -1,6 +0,0 @@
package cc.iotkit.engine;
public interface IScriptEngineFactory {
IScriptEngine getScriptEngine(String name);
}

View File

@ -1,7 +0,0 @@
package cc.iotkit.engine;
public class IScriptException extends Exception{
public IScriptException(String message) {
super(message);
}
}

View File

@ -1,35 +0,0 @@
package cc.iotkit.engine;
import org.graalvm.polyglot.*;
import java.util.Objects;
public class JsGraalJsScriptEngine implements IScriptEngine{
private final Context context = Context.newBuilder("js").allowHostAccess(true).build();
private Value jsScript;
@Override
public void setScript(String script) {
jsScript = context.eval("js", String.format("new (function () {\n%s})()", script));
}
@Override
public void putScriptEnv(String key, Object value) {
context.getBindings("js").putMember(key, value);
}
@Override
public Object invokeMethod(String methodName, Object... args) throws IScriptException {
Value member = jsScript.getMember(methodName);
if(Objects.nonNull(member)){
Value execute = member.execute(args);
return execute.as(Object.class);
}
return null;
}
}

View File

@ -1,41 +0,0 @@
package cc.iotkit.engine;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class JsNashornScriptEngine implements IScriptEngine{
private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn");
private Object scriptObj;
@Override
public void setScript(String script) throws IScriptException {
try {
scriptObj = engine.eval(String.format("new (function () {\n%s})()", script));
} catch (ScriptException e) {
throw new IScriptException(e.getMessage());
}
}
@Override
public void putScriptEnv(String key, Object val) {
engine.put(key, val);
}
@Override
public Object invokeMethod(String methodName, Object... args) throws IScriptException{
if (((ScriptObjectMirror) scriptObj).get(methodName) != null) {
try {
return engine.invokeMethod(scriptObj, methodName, args);
} catch (Throwable e) {
throw new IScriptException(e.getMessage());
}
}
return null;
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>iot-emqx-component</artifactId>
@ -84,25 +84,31 @@
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-model</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-common</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-component-base</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-data-service</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -53,6 +53,11 @@
<artifactId>iot-data-service</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -13,6 +13,7 @@ import cc.iotkit.comp.IMessageHandler;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import lombok.extern.slf4j.Slf4j;
@ -27,7 +28,7 @@ public class AuthVerticle extends AbstractVerticle {
private IMessageHandler executor;
private EmqxConfig config;
private final EmqxConfig config;
public void setExecutor(IMessageHandler executor) {
this.executor = executor;
@ -38,7 +39,7 @@ public class AuthVerticle extends AbstractVerticle {
}
@Override
public void start() throws Exception {
public void start() {
backendServer = vertx.createHttpServer();
//第一步 声明Router&初始化Router
@ -54,11 +55,9 @@ public class AuthVerticle extends AbstractVerticle {
Map<String, Object> head = new HashMap<>();
head.put("topic", "/mqtt/auth");
executor.onReceive(head, "auth", json);
rc.response().setStatusCode(200)
.end();
httpResult(rc.response(), 200);
} catch (Throwable e) {
rc.response().setStatusCode(500)
.end();
httpResult(rc.response(), 500);
log.error("mqtt auth failed", e);
}
});
@ -69,12 +68,9 @@ public class AuthVerticle extends AbstractVerticle {
Map<String, Object> head = new HashMap<>();
head.put("topic", "/mqtt/acl");
executor.onReceive(head, "acl", json);
rc.response().setStatusCode(200)
.end();
httpResult(rc.response(), 200);
} catch (Throwable e) {
rc.response().setStatusCode(500)
.end();
httpResult(rc.response(), 500);
log.error("mqtt acl failed", e);
}
});
@ -82,6 +78,14 @@ public class AuthVerticle extends AbstractVerticle {
backendServer.requestHandler(backendRouter).listen(config.getAuthPort());
}
private void httpResult(HttpServerResponse response, int code) {
response.putHeader("Content-Type", "application/json");
response
.setStatusCode(code);
response
.end("{\"result\": \"" + (code == 200 ? "allow" : "deny") + "\"}");
}
@Override
public void stop() throws Exception {
backendServer.close(voidAsyncResult -> log.info("close emqx auth server..."));

View File

@ -11,6 +11,7 @@ package cc.iotkit.comp.emqx;
import cc.iotkit.common.exception.BizException;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.common.utils.ThreadUtil;
import cc.iotkit.comp.AbstractDeviceComponent;
import cc.iotkit.comp.CompConfig;
import cc.iotkit.comp.IMessageHandler;
@ -36,9 +37,11 @@ import java.lang.reflect.InvocationTargetException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class EmqxDeviceComponent extends AbstractDeviceComponent {
public class EmqxDeviceComponent extends AbstractDeviceComponent implements Runnable {
private static final Logger log = LoggerFactory.getLogger(EmqxDeviceComponent.class);
private Vertx vertx;
@ -47,12 +50,17 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
private String deployedId;
private EmqxConfig mqttConfig;
private MqttClient client;
private boolean mqttConnected = false;
private final ScheduledThreadPoolExecutor emqxConnectTask = ThreadUtil.newScheduled(1, "emqx_connect");
//组件mqtt clientId默认通过mqtt auth / acl验证。
/**
* mqtt clientIdmqtt auth / acl
*/
private final Set<String> compMqttClientIdList = new HashSet<>();
private final TransparentConverter transparentConverter = new TransparentConverter();
@Override
public void create(CompConfig config) {
super.create(config);
vertx = Vertx.vertx();
@ -64,22 +72,33 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
public void start() {
try {
compMqttClientIdList.add(mqttConfig.getClientId());
authVerticle.setExecutor(getHandler());
countDownLatch = new CountDownLatch(1);
Future<String> future = vertx.deployVerticle(authVerticle);
future.onSuccess((s -> {
deployedId = s;
countDownLatch.countDown();
log.error("start emqx auth component success");
log.info("start emqx auth component success");
}));
future.onFailure((e) -> {
countDownLatch.countDown();
log.error("start emqx auth component failed", e);
});
countDownLatch.await();
emqxConnectTask.scheduleWithFixedDelay(this, 0, 3, TimeUnit.SECONDS);
} catch (Throwable e) {
throw new BizException("start emqx auth component error", e);
}
}
@Override
public void run() {
try {
if (mqttConnected) {
return;
}
MqttClientOptions options = new MqttClientOptions()
.setClientId(mqttConfig.getClientId())
.setUsername(mqttConfig.getUsername())
@ -101,14 +120,6 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
subscribes.put(topic, 1);
}
/*subscribes.put("/sys/+/+/s/#", 1);
subscribes.put("/sys/client/connected", 1);
subscribes.put("/sys/client/disconnected", 1);
subscribes.put("/sys/session/subscribed", 1);
subscribes.put("/sys/session/unsubscribed", 1);*/
// handler will be called when we have a message in topic we subscribe for
client.publishHandler(p -> {
log.info("Client received message on [{}] payload [{}] with QoS [{}]", p.topicName(), p.payload().toString(Charset.defaultCharset()), p.qosLevel());
@ -131,6 +142,15 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
client.connect(mqttConfig.getPort(), mqttConfig.getBroker(), s -> {
if (s.succeeded()) {
log.info("client connect success.");
mqttConnected = true;
/*
*
* /sys/+/+/s/#
* /sys/client/connected
* /sys/client/disconnected
* /sys/session/subscribed
* /sys/session/unsubscribed
*/
client.subscribe(subscribes, e -> {
if (e.succeeded()) {
log.info("===>subscribe success: {}", e.result());
@ -140,14 +160,13 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
});
} else {
mqttConnected = false;
log.error("client connect fail: ", s.cause());
}
}).exceptionHandler(event -> {
log.error("client fail: ", event.getCause());
});
}).exceptionHandler(event -> log.error("client fail", event));
} catch (Throwable e) {
throw new BizException("start emqx auth component error", e);
throw new BizException("start emqx component error", e);
}
}
@ -157,9 +176,15 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
authVerticle.stop();
Future<Void> future = vertx.undeploy(deployedId);
future.onSuccess(unused -> log.info("stop emqx auth component success"));
client.disconnect()
.onSuccess(unused -> log.info("stop emqx component success"))
.onSuccess(unused -> {
mqttConnected = false;
log.info("stop emqx component success");
})
.onFailure(unused -> log.info("stop emqx component failure"));
emqxConnectTask.shutdown();
}
@Override

View File

@ -10,17 +10,14 @@
package cc.iotkit.comp.emqx;
import cc.iotkit.common.thing.ThingService;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.model.device.message.ThingModelMessage;
import cc.iotkit.model.product.ProductModel;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import cc.iotkit.script.IScriptEngine;
import cc.iotkit.script.ScriptEngineFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import javax.script.ScriptEngineManager;
import java.util.Map;
@Slf4j
@Data
@ -28,48 +25,29 @@ public class JsScripter implements IScripter {
private ProductModel model;
private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn");
private Object scriptObj;
private IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
public JsScripter(ProductModel model) {
this.model = model;
}
@SneakyThrows
@Override
public void setScript(String script) {
try {
scriptObj = engine.eval(String.format("new (function () {\n%s})()", script));
} catch (Throwable e) {
throw new RuntimeException("init script error", e);
}
scriptEngine.setScript(script);
}
@SneakyThrows
public ThingModelMessage decode(TransparentMsg msg) {
try {
ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeMethod(scriptObj, "decode", msg);
ThingModelMessage message = new ThingModelMessage();
BeanUtils.populate(message, result);
return message;
} catch (Throwable e) {
log.error("invoke decode script error", e);
return null;
}
return scriptEngine.invokeMethod(new TypeReference<>() {
}, "decode", msg);
}
@SneakyThrows
public TransparentMsg encode(ThingService<?> service) {
try {
ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeMethod(scriptObj, "encode", service);
Map map = (Map) JsonUtil.toObject(result);
TransparentMsg message = new TransparentMsg();
BeanUtils.populate(message, map);
message.setProductKey(model.getProductKey());
message.setModel(model.getModel());
message.setDeviceName(service.getDeviceName());
return message;
} catch (Throwable e) {
log.error("invoke encode script error", e);
return null;
}
return scriptEngine.invokeMethod(new TypeReference<>() {
}, "encode", service);
}
}

View File

@ -9,9 +9,17 @@
*/
package cc.iotkit.comp.emqx;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldNameConstants;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@FieldNameConstants
public class TransparentMsg {
private String productKey;

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>iot-http-biz-component</artifactId>
@ -58,7 +58,13 @@
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-component-base</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -28,6 +28,11 @@
<artifactId>iot-component-base</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -12,21 +12,19 @@ package cc.iotkit.comp.biz;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.comp.CompConfig;
import cc.iotkit.comp.IComponent;
import cc.iotkit.script.IScriptEngine;
import cc.iotkit.script.ScriptEngineFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import io.vertx.core.MultiMap;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.*;
@Data
@ -35,7 +33,7 @@ public class HttpBizComponent implements IComponent {
private final Vertx vertx = Vertx.vertx();
private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn");
private final IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
private Object scriptObj;
@ -53,11 +51,7 @@ public class HttpBizComponent implements IComponent {
public void create(CompConfig config) {
this.id = UUID.randomUUID().toString();
this.httpConfig = JsonUtil.parse(config.getOther(), HttpConfig.class);
try {
scriptObj = engine.eval(String.format("new (function () {\n%s})()", script));
} catch (ScriptException e) {
log.error("init script error", e);
}
scriptEngine.setScript(script);
}
@Override
@ -74,41 +68,35 @@ public class HttpBizComponent implements IComponent {
HttpServerRequest httpRequest = rc.request();
String contentType = httpRequest.headers().get("Content-Type");
JsonObject responseHeader = new JsonObject();
Map<String, Object> responseHeader = new HashMap<>();
if ("application/json".equals(contentType)) {
String bodyStr = rc.getBody().toString();
Map body = JsonUtil.parse(bodyStr, Map.class);
log.info("request body:{}", bodyStr);
String response = "unknown error";
String name = "onReceive";
if (((ScriptObjectMirror) scriptObj).get(name) != null) {
try {
Object result = engine.invokeMethod(scriptObj,
name,
httpRequest.method().name(),
httpRequest.path(),
httpHeader,
httpParams,
body);
Object resultObj = JsonUtil.toObject((ScriptObjectMirror) result);
if (resultObj instanceof Map) {
JsonObject data = JsonObject.mapFrom(resultObj);
responseHeader = data.getJsonObject("header");
response = data.getString("content");
response = response == null ? "" : response;
}
} catch (Throwable e) {
log.error("invokeMethod onReceive error", e);
response = e.getMessage();
}
} else {
log.error("required [onReceive] method");
String response;
try {
HttpContent content =
scriptEngine.invokeMethod(
new TypeReference<>() {
},
"onReceive",
httpRequest.method().name(),
httpRequest.path(),
httpHeader,
httpParams,
body);
responseHeader = content.getHeader();
response = content.getContent();
response = response == null ? "" : response;
} catch (Throwable e) {
log.error("invokeMethod onReceive error", e);
response = e.getMessage();
}
HttpServerResponse httpServerResponse = rc.response();
//设置响应头
responseHeader.getMap().forEach((key, value) -> {
responseHeader.forEach((key, value) -> {
//大写转换
key = key.replaceAll("([A-Z])", "-$1").toLowerCase();
httpServerResponse.putHeader(key, value.toString());
@ -139,7 +127,7 @@ public class HttpBizComponent implements IComponent {
@Override
public void putScriptEnv(String key, Object value) {
engine.put(key, value);
scriptEngine.putScriptEnv(key, value);
}
@Override

View File

@ -0,0 +1,19 @@
package cc.iotkit.comp.biz;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class HttpContent {
private Map<String, Object> header;
private String content;
}

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>iot-mqtt-component</artifactId>
@ -82,19 +82,25 @@
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-common</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-component-base</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-data-service</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -58,6 +58,11 @@
<artifactId>iot-data-service</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -10,17 +10,14 @@
package cc.iotkit.comp.mqtt;
import cc.iotkit.common.thing.ThingService;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.model.device.message.ThingModelMessage;
import cc.iotkit.model.product.ProductModel;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import cc.iotkit.script.IScriptEngine;
import cc.iotkit.script.ScriptEngineFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import javax.script.ScriptEngineManager;
import java.util.Map;
@Slf4j
@Data
@ -28,48 +25,30 @@ public class JsScripter implements IScripter {
private ProductModel model;
private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn");
private Object scriptObj;
private IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
public JsScripter(ProductModel model) {
this.model = model;
}
@SneakyThrows
@Override
public void setScript(String script) {
try {
scriptObj = engine.eval(String.format("new (function () {\n%s})()", script));
} catch (Throwable e) {
throw new RuntimeException("init script error", e);
}
scriptEngine.setScript(script);
}
@SneakyThrows
public ThingModelMessage decode(TransparentMsg msg) {
try {
ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeMethod(scriptObj, "decode", msg);
ThingModelMessage message = new ThingModelMessage();
BeanUtils.populate(message, result);
return message;
} catch (Throwable e) {
log.error("invoke decode script error", e);
return null;
}
return scriptEngine.invokeMethod(new TypeReference<>() {
}, "decode", msg);
}
@SneakyThrows
public TransparentMsg encode(ThingService<?> service) {
try {
ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeMethod(scriptObj, "encode", service);
Map map = (Map) JsonUtil.toObject(result);
TransparentMsg message = new TransparentMsg();
BeanUtils.populate(message, map);
message.setProductKey(model.getProductKey());
message.setModel(model.getModel());
message.setDeviceName(service.getDeviceName());
return message;
} catch (Throwable e) {
log.error("invoke encode script error", e);
return null;
}
return scriptEngine.invokeMethod(new TypeReference<>() {
}, "encode", service);
}
}

View File

@ -38,6 +38,7 @@ public class MqttDeviceComponent extends AbstractDeviceComponent {
private final Map<String, Device> deviceChildToParent = new HashMap<>();
private final TransparentConverter transparentConverter = new TransparentConverter();
@Override
public void create(CompConfig config) {
super.create(config);
vertx = Vertx.vertx();

View File

@ -183,6 +183,9 @@ public class MqttVerticle extends AbstractVerticle {
}
private String getEndpointKey(ReceiveResult result) {
if (result == null) {
return null;
}
return getEndpointKey(result.getProductKey(), result.getDeviceName());
}

View File

@ -9,9 +9,17 @@
*/
package cc.iotkit.comp.mqtt;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldNameConstants;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@FieldNameConstants
public class TransparentMsg {
private String productKey;

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>iot-websocket-component</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactSet>
<includes>
<include>io.vertx:vertx-core</include>
<include>org.luaj:luaj-jse</include>
</includes>
</artifactSet>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>4.2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.luaj</groupId>
<artifactId>luaj-jse</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-common</artifactId>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-component-base</artifactId>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-data-service</artifactId>
<version>0.4.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-components</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -23,13 +23,13 @@ public class WebSocketDeviceComponent extends AbstractDeviceComponent {
private CountDownLatch countDownLatch;
private String deployedId;
private AbstractDeviceVerticle webSocketVerticle;
private String type;
private final Map<String, Device> deviceChildToParent = new HashMap<>();
@Override
public void create(CompConfig config) {
super.create(config);
vertx = Vertx.vertx();
type= JsonUtil.parse(config.getOther(), Map.class).get("type").toString();
String type = JsonUtil.parse(config.getOther(), Map.class).get("type").toString();
if(AbstractDeviceVerticle.TYPE_CLIENT.equals(type)){
webSocketVerticle = new WebSocketClientVerticle(config.getOther());
}else{
@ -37,6 +37,7 @@ public class WebSocketDeviceComponent extends AbstractDeviceComponent {
}
}
@Override
public void start() {
try {
webSocketVerticle.setExecutor(getHandler());
@ -57,6 +58,7 @@ public class WebSocketDeviceComponent extends AbstractDeviceComponent {
}
}
@Override
@SneakyThrows
public void stop() {
webSocketVerticle.stop();
@ -64,6 +66,7 @@ public class WebSocketDeviceComponent extends AbstractDeviceComponent {
future.onSuccess(unused -> log.info("stop websocket component success"));
}
@Override
public void destroy() {
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -19,7 +19,7 @@
<module>iot-component-base</module>
<module>iot-http-biz-component</module>
<module>iot-component-tcp</module>
<module>iot-components-engine</module>
<module>iot-websocket-component</module>
<!-- <module>iot-ctwing-component</module>-->
</modules>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-data</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-data</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-data</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,9 +5,9 @@
<parent>
<artifactId>iot-data</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<artifactId>iot-model</artifactId>

View File

@ -5,9 +5,9 @@
<parent>
<artifactId>iot-data</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<artifactId>iot-rdb-data-service</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-data</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-data</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>cc.iotkit</groupId>
<artifactId>iot-data</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<artifactId>iot-ts-temporal-service</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-message-bus</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-message-bus</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-message-bus</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -51,6 +51,18 @@
<artifactId>lombok</artifactId>
</dependency>
<!--mqtt-->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mqtt</artifactId>
</dependency>
<!--kafka-->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-kafka-client</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-model</artifactId>
@ -71,17 +83,11 @@
<artifactId>iot-message-core</artifactId>
</dependency>
<!-- mqtt-->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mqtt</artifactId>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
</dependency>
<!-- kafka-->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-kafka-client</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -11,6 +11,7 @@ package cc.iotkit.ruleengine.action;
import cc.iotkit.model.device.message.ThingModelMessage;
import cc.iotkit.ruleengine.alert.Alerter;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
@ -29,7 +30,8 @@ public class AlertService<T extends Alerter> extends ScriptService {
@SneakyThrows
public String execute(ThingModelMessage msg) {
//执行转换脚本
Map result = execScript(msg);
Map<String, Object> result = execScript(new TypeReference<>() {
}, msg);
if (result == null) {
log.warn("execScript result is null");
return "execScript result is null";

View File

@ -11,6 +11,7 @@ package cc.iotkit.ruleengine.action;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.model.device.message.ThingModelMessage;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
@ -32,15 +33,13 @@ public class HttpService extends ScriptService {
@SneakyThrows
public String execute(ThingModelMessage msg) {
//执行转换脚本
Map result = execScript(msg);
if (result == null) {
HttpData httpData = execScript(new TypeReference<>() {
}, msg);
if (httpData == null) {
log.warn("execScript result is null");
return "execScript result is null";
}
HttpData httpData = new HttpData();
BeanUtils.populate(httpData, result);
//组装http请求
String url = this.url + httpData.getPath();
Request.Builder builder = new Request.Builder();
@ -57,7 +56,7 @@ public class HttpService extends ScriptService {
httpData.getBody().toString());
Request request = builder.method(httpData.getMethod().toUpperCase(), requestBody).build();
String requestDataStr = JsonUtil.toJsonString(result);
String requestDataStr = JsonUtil.toJsonString(httpData);
log.info("send http request:{} ,{}", url, requestDataStr);
String responseBody = "";

View File

@ -9,52 +9,37 @@
*/
package cc.iotkit.ruleengine.action;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.data.IDeviceInfoData;
import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.device.message.ThingModelMessage;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import cc.iotkit.script.IScriptEngine;
import cc.iotkit.script.ScriptEngineFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import javax.script.ScriptEngineManager;
import java.util.Map;
@Slf4j
@Data
public class ScriptService {
private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager())
.getEngineByName("nashorn");
private IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
private String script;
private ScriptObjectMirror scriptObject;
private IDeviceInfoData deviceInfoData;
public Map execScript(ThingModelMessage msg) {
public void setScript(String script) {
scriptEngine.setScript(script);
}
public <T> T execScript(TypeReference<T> type, ThingModelMessage msg) {
try {
if (scriptObject == null) {
scriptObject = (ScriptObjectMirror) engine.eval("new (function(){" + script + "})()");
}
//取设备信息
DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(msg.getDeviceId());
//执行转换脚本
ScriptObjectMirror result = (ScriptObjectMirror) engine
.invokeMethod(scriptObject, "translate", msg, deviceInfo);
if (result == null) {
return null;
}
Object objResult = JsonUtil.toObject(result);
if (!(objResult instanceof Map)) {
return null;
}
return (Map) objResult;
return scriptEngine.invokeMethod(type, "translate", msg, deviceInfo);
} catch (Throwable e) {
log.error("run script error", e);
return null;

View File

@ -6,6 +6,7 @@ import cc.iotkit.ruleengine.action.ScriptService;
import cc.iotkit.ruleengine.link.LinkFactory;
import cc.iotkit.ruleengine.link.LinkService;
import cc.iotkit.ruleengine.link.impl.KafkaLink;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
@ -28,7 +29,8 @@ public class KafkaService extends ScriptService implements LinkService {
public String execute(ThingModelMessage msg) {
//执行转换脚本
Map result = execScript(msg);
Map<String, Object> result = execScript(new TypeReference<>() {
}, msg);
if (result == null) {
log.warn("execScript result is null");
return "execScript result is null";

View File

@ -6,6 +6,7 @@ import cc.iotkit.ruleengine.action.ScriptService;
import cc.iotkit.ruleengine.link.LinkFactory;
import cc.iotkit.ruleengine.link.LinkService;
import cc.iotkit.ruleengine.link.impl.MqttClientLink;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
@ -31,7 +32,8 @@ public class MqttService extends ScriptService implements LinkService {
public String execute(ThingModelMessage msg) {
//执行转换脚本
Map result = execScript(msg);
Map<String, Object> result = execScript(new TypeReference<>() {
}, msg);
if (result == null) {
log.warn("execScript result is null");
return "execScript result is null";

View File

@ -6,6 +6,7 @@ import cc.iotkit.ruleengine.action.ScriptService;
import cc.iotkit.ruleengine.link.LinkFactory;
import cc.iotkit.ruleengine.link.LinkService;
import cc.iotkit.ruleengine.link.impl.TcpClientLink;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
@ -27,7 +28,8 @@ public class TcpService extends ScriptService implements LinkService {
public String execute(ThingModelMessage msg) {
//执行转换脚本
Map result = execScript(msg);
Map<String, Object> result = execScript(new TypeReference<>() {
},msg);
if (result == null) {
log.warn("execScript result is null");
return "execScript result is null";

View File

@ -2,14 +2,14 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<artifactId>iot-components</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>iot-components-engine</artifactId>
<artifactId>iot-script-engine</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
@ -22,21 +22,43 @@
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,15 @@
package cc.iotkit.script;
import com.fasterxml.jackson.core.type.TypeReference;
public interface IScriptEngine {
void setScript(String key);
void putScriptEnv(String key, Object val);
void invokeMethod(String methodName, Object... args);
<T> T invokeMethod(TypeReference<T> type, String methodName, Object... args);
}

View File

@ -0,0 +1,76 @@
/*
* +----------------------------------------------------------------------
* | Copyright (c) 2021-2022 All rights reserved.
* +----------------------------------------------------------------------
* | Licensed
* +----------------------------------------------------------------------
* | Author: xw2sy@163.com
* +----------------------------------------------------------------------
*/
package cc.iotkit.script;
import cc.iotkit.common.utils.JsonUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.HostAccess;
import org.graalvm.polyglot.Value;
@Slf4j
public class JavaScriptEngine implements IScriptEngine {
private final Context context = Context.newBuilder("js").allowHostAccess(HostAccess.ALL).build();
private Value jsScript;
@Override
public void setScript(String script) {
jsScript = context.eval("js", String.format(
"new (function () {\n%s; " +
" this.invoke=function(f,args){" +
" for(i in args){" +
" args[i]=JSON.parse(args[i]);" +
" }" +
" return JSON.stringify(this[f].apply(this,args));" +
" }; " +
"})()", script));
}
@Override
public void putScriptEnv(String key, Object value) {
context.getBindings("js").putMember(key, value);
}
@Override
public void invokeMethod(String methodName, Object... args) {
invokeMethod(new TypeReference<Void>() {
}, methodName, args);
}
@Override
public <T> T invokeMethod(TypeReference<T> type, String methodName, Object... args) {
Value member = jsScript.getMember("invoke");
StringBuilder sbArgs = new StringBuilder("[");
//将入参转成json
for (int i = 0; i < args.length; i++) {
args[i] = JsonUtil.toJsonString(args[i]);
sbArgs.append(i == args.length - 1 ? "," : "").append(args[i]);
}
sbArgs.append("]");
//通过调用invoke方法将目标方法返回结果转成json
Value rst = member.execute(methodName, args);
String json = rst.asString();
log.info("invoke script {},args:{}, result:{}", methodName, sbArgs, json);
//没有返回值
if (json == null || "null".equals(json)) {
return null;
}
return JsonUtil.parse(json, type);
}
}

View File

@ -0,0 +1,30 @@
package cc.iotkit.script;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ProcessStringToJsonExample {
public static void main(String[] args) {
String input = "{type: \"register\", data: {productKey: \"hbtgIA0SuVw9lxjB\", deviceName: \"TEST:GW:000003\", model: \"GW01\"}}";
// String input = "{type: \"ack\", content: \"{\\\"productKey\\\":\\\"hbtgIA0SuVw9lxjB\\\",\\\"deviceName\\\":\\\"TEST:GW:000001\\\",\\\"mid\\\":\\\"0\\\",\\\"content\\\":{\\\"topic\\\":\\\"/sys/hbtgIA0SuVw9lxjB/TEST:GW:000001/c/register_reply\\\",\\\"payload\\\":\\\"{\\\\\\\"id\\\\\\\":\\\\\\\"0\\\\\\\",\\\\\\\"code\\\\\\\":0,\\\\\\\"data\\\\\\\":{\\\\\\\"productKey\\\\\\\":\\\\\\\"cGCrkK7Ex4FESAwe\\\\\\\",\\\\\\\"deviceName\\\\\\\":\\\\\\\"TEST_SC_000001\\\\\\\"}}\\\"}}\"}";
// 使用正则表达式匹配所有键名,并在两端加上双引号
Pattern pattern = Pattern.compile("[^\":/](\\b\\w+\\b)\\s*:");
Matcher matcher = pattern.matcher(input);
StringBuilder jsonBuilder = new StringBuilder(input);
int offset = 0;
while (matcher.find()) {
int start = matcher.start(1) + offset;
int end = matcher.end(1) + offset;
if (jsonBuilder.charAt(start - 1) != '\"' || jsonBuilder.charAt(end) != '\"') {
jsonBuilder.insert(start, '\"');
jsonBuilder.insert(end + 1, '\"');
offset += 2;
}
}
String output = jsonBuilder.toString();
System.out.println(output);
}
}

View File

@ -0,0 +1,43 @@
package cc.iotkit.script;
import com.fasterxml.jackson.core.type.TypeReference;
public class ScriptEngineFactory {
public static IScriptEngine getScriptEngine(String type) {
if (type == null) {
type = "js";
}
switch (type) {
case "python":
case "lua":
return new IScriptEngine() {
@Override
public void setScript(String key) {
}
@Override
public void putScriptEnv(String key, Object val) {
}
@Override
public void invokeMethod(String methodName, Object... args) {
}
@Override
public <T> T invokeMethod(TypeReference<T> type, String methodName, Object... args) {
return null;
}
};
case "js":
default:
return new JavaScriptEngine();
}
}
}

View File

@ -0,0 +1,7 @@
package cc.iotkit.script;
public class ScriptException extends Exception{
public ScriptException(String message) {
super(message);
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iot-test-tool</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -19,8 +19,8 @@ public class Simulator {
public static void main(String[] args) throws IOException {
if (args.length == 0) {
// Mqtt.brokerHost = "127.0.0.1";
Mqtt.brokerHost = "120.76.96.206";
Mqtt.brokerHost = "127.0.0.1";
// Mqtt.brokerHost = "120.76.96.206";
} else {
Mqtt.brokerHost = args[0];
}

View File

@ -34,6 +34,7 @@ public class ReportTest {
if (args.length == 0) {
Mqtt.brokerHost = "127.0.0.1";
// Mqtt.brokerPort = 2883;
// Mqtt.brokerHost = "120.76.96.206";
// Mqtt.brokerHost = "172.16.1.109";
} else {

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>iotkit-parent</artifactId>
<groupId>cc.iotkit</groupId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -21,7 +21,6 @@
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
@ -34,6 +33,11 @@
<artifactId>iot-component-server</artifactId>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -18,26 +18,23 @@ import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.device.VirtualDevice;
import cc.iotkit.model.device.VirtualDeviceLog;
import cc.iotkit.model.device.message.ThingModelMessage;
import cc.iotkit.script.IScriptEngine;
import cc.iotkit.script.ScriptEngineFactory;
import cc.iotkit.temporal.IVirtualDeviceLogData;
import cc.iotkit.virtualdevice.trigger.RandomScheduleBuilder;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import javax.annotation.PostConstruct;
import javax.script.ScriptEngineManager;
import java.util.*;
@Slf4j
public class VirtualManager {
private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn");
private final Map<String, Object> virtualScripts = new HashMap<>();
private final Map<String, IScriptEngine> virtualScripts = new HashMap<>();
private final Map<String, Set<String>> deviceIdToVirtualId = new HashMap<>();
@Autowired
@ -76,6 +73,7 @@ public class VirtualManager {
/**
*
*/
@SneakyThrows
public void send(ThingService<?> service) {
DeviceInfo deviceInfo = deviceInfoData.findByProductKeyAndDeviceName(service.getProductKey(), service.getDeviceName());
String deviceId = deviceInfo.getDeviceId();
@ -83,10 +81,14 @@ public class VirtualManager {
//根据设备Id取虚拟设备列表
Set<String> virtualIds = deviceIdToVirtualId.get(deviceId);
for (String virtualId : virtualIds) {
Object scriptObj = virtualScripts.get(virtualId);
Object result = invokeMethod(scriptObj, "receive", service);
for (Object value : ((ScriptObjectMirror) result).values()) {
processReport(value);
IScriptEngine scriptEngine = virtualScripts.get(virtualId);
//多条虚拟设备消息
List<ThingModelMessage> result = scriptEngine.invokeMethod(
new TypeReference<>() {
},
"receive", service);
for (ThingModelMessage msg : result) {
processReport(msg);
}
log.info("virtual device send result:{}", JsonUtil.toJsonString(result));
}
@ -121,10 +123,11 @@ public class VirtualManager {
.logAt(System.currentTimeMillis())
.build();
try {
Object scriptObj = engine.eval(String.format("new (function () {\n%s})()", virtualDevice.getScript()));
IScriptEngine scriptEngine = virtualScripts.get(virtualDevice.getId());
for (String deviceId : devices) {
DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
processReport(invokeMethod(scriptObj, "report", device));
processReport(scriptEngine.invokeMethod(new TypeReference<>() {
}, "report", device));
}
} catch (Throwable e) {
virtualDeviceLog.setResult(e.getMessage());
@ -161,7 +164,9 @@ public class VirtualManager {
log.info("adding virtual device job,id:{},name:{}", id, name);
//添加新的脚本对象
virtualScripts.put(id, engine.eval(String.format("new (function () {\n%s})()", script)));
IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
scriptEngine.setScript(script);
virtualScripts.put(id, scriptEngine);
List<DeviceInfo> devices = new ArrayList<>();
for (String deviceId : virtualDevice.getDevices()) {
devices.add(deviceInfoData.findByDeviceId(deviceId));
@ -240,44 +245,28 @@ public class VirtualManager {
/**
* js
*/
public void processReport(Object sourceMsg) {
private void processReport(ThingModelMessage modelMessage) {
try {
ScriptObjectMirror result = (ScriptObjectMirror) sourceMsg;
ThingModelMessage modelMessage = new ThingModelMessage();
BeanUtils.populate(modelMessage, result);
deviceBehaviourService.reportMessage(modelMessage);
} catch (Throwable e) {
log.error("process js data error", e);
}
}
/**
* js
*/
private Object invokeMethod(Object scriptObj, String name, Object... args) {
try {
if (((ScriptObjectMirror) scriptObj).get(name) != null) {
return engine.invokeMethod(scriptObj, name, args);
}
return null;
} catch (Throwable e) {
log.error("invoke js method error", e);
}
return null;
}
/**
*
*/
@SneakyThrows
public void invokeReport(DeviceInfo device, String virtualId) {
//设备上线
deviceOnline(device);
Object scriptObj = virtualScripts.get(virtualId);
if (scriptObj == null) {
IScriptEngine scriptEngine = virtualScripts.get(virtualId);
if (scriptEngine == null) {
return;
}
processReport(invokeMethod(scriptObj, "report", device));
processReport(scriptEngine.invokeMethod(new TypeReference<>() {
}, "report", device));
}
/**

39
pom.xml
View File

@ -14,6 +14,7 @@
<module>iot-message-bus</module>
<module>iot-test-tool</module>
<module>iot-data</module>
<module>iot-script-engine</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
@ -24,7 +25,7 @@
<groupId>cc.iotkit</groupId>
<artifactId>iotkit-parent</artifactId>
<version>0.4.2-SNAPSHOT</version>
<version>0.4.3-SNAPSHOT</version>
<name>iotkit-parent</name>
<description>iotkit parent</description>
<properties>
@ -215,6 +216,24 @@
<version>${vertx.version}</version>
</dependency>
<!--javascript运行环境-->
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<version>${graalvm.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>${graalvm.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>${graalvm.version}</version>
</dependency>
<dependency>
<groupId>cc.iotkit</groupId>
<artifactId>iot-model</artifactId>
@ -334,22 +353,10 @@
<version>${project.version}</version>
</dependency>
<!--javascript运行环境-->
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<version>${graalvm.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>${graalvm.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>${graalvm.version}</version>
<groupId>cc.iotkit</groupId>
<artifactId>iot-script-engine</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>