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.javaV0.5.x
commit
b236d517e5
Binary file not shown.
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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": "",
|
||||
|
|
|
@ -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
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
package cc.iotkit.converter;
|
||||
|
||||
public interface IScriptConvertFactory {
|
||||
|
||||
IConverter getCovert(String name);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
package cc.iotkit.engine;
|
||||
|
||||
public interface IScriptEngineFactory {
|
||||
|
||||
IScriptEngine getScriptEngine(String name);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package cc.iotkit.engine;
|
||||
|
||||
public class IScriptException extends Exception{
|
||||
public IScriptException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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..."));
|
||||
|
|
|
@ -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 clientId,默认通过mqtt 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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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";
|
||||
|
|
|
@ -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 = "";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package cc.iotkit.script;
|
||||
|
||||
public class ScriptException extends Exception{
|
||||
public ScriptException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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
39
pom.xml
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue