Browse Source

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

# Conflicts:
#	iot-components/iot-component-server/src/main/java/cc/iotkit/comps/DeviceComponentManager.java
#	iot-components/iot-websocket-component/src/main/java/cc/iotkit/comp/websocket/server/WebSocketServerVerticle.java
tangfudong 2 years ago
parent
commit
b236d517e5
98 changed files with 1727 additions and 1635 deletions
  1. BIN
      data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/iot-http-biz-component-0.4.3-SNAPSHOT.jar
  2. 4 19
      data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/component.js
  3. BIN
      data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/iot-emqx-component-0.4.3-SNAPSHOT.jar
  4. BIN
      data/components/eabb131d-8fd1-43a8-88d9-a198abfd3d42/iot-mqtt-component-0.4.3-SNAPSHOT.jar
  5. BIN
      data/components/fee0e826-963f-4e53-a2cf-11e3e5f784ea/iot-http-biz-component-0.4.3-SNAPSHOT.jar
  6. 3 3
      data/init/protocolComponent.json
  7. 1 1
      iot-auth-server/pom.xml
  8. 801 710
      iot-auth-server/src/main/java/cc/iotkit/utils/SoMap.java
  9. 1 1
      iot-common/pom.xml
  10. 0 35
      iot-common/src/main/java/cc/iotkit/common/utils/JsonUtil.java
  11. 13 0
      iot-common/src/main/java/cc/iotkit/common/utils/ReflectUtil.java
  12. 1 1
      iot-components/iot-component-base/pom.xml
  13. 8 0
      iot-components/iot-component-base/src/main/java/cc/iotkit/comp/model/AuthInfo.java
  14. 12 7
      iot-components/iot-component-base/src/main/java/cc/iotkit/comp/model/DeviceState.java
  15. 4 23
      iot-components/iot-component-base/src/main/java/cc/iotkit/comp/model/RegisterInfo.java
  16. 10 6
      iot-components/iot-component-converter/pom.xml
  17. 0 47
      iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/CovertUtils.java
  18. 0 20
      iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/DefaultScriptConvertFactory.java
  19. 8 0
      iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/DeviceMessage.java
  20. 0 70
      iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/GraalJsScriptConverter.java
  21. 0 6
      iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/IScriptConvertFactory.java
  22. 49 0
      iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/JavaScriptConverter.java
  23. 41 0
      iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/ScriptConvertFactory.java
  24. 0 75
      iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/ScriptConverter.java
  25. 3 4
      iot-components/iot-component-server/pom.xml
  26. 4 0
      iot-components/iot-component-server/src/main/java/cc/iotkit/comps/BizComponentManager.java
  27. 6 18
      iot-components/iot-component-server/src/main/java/cc/iotkit/comps/DeviceComponentManager.java
  28. 50 91
      iot-components/iot-component-server/src/main/java/cc/iotkit/comps/DeviceMessageHandler.java
  29. 0 17
      iot-components/iot-component-server/src/main/java/cc/iotkit/comps/DeviceMsgScriptResult.java
  30. 62 0
      iot-components/iot-component-server/src/main/java/cc/iotkit/comps/MessageParser.java
  31. 0 23
      iot-components/iot-component-server/src/main/java/cc/iotkit/comps/config/ComponentConfig.java
  32. 12 10
      iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java
  33. 10 11
      iot-components/iot-component-tcp/dependency-reduced-pom.xml
  34. 6 7
      iot-components/iot-component-tcp/pom.xml
  35. 1 0
      iot-components/iot-component-tcp/src/main/java/cc/iotkit/comp/tcp/cilent/TcpClientDeviceComponent.java
  36. 5 28
      iot-components/iot-component-tcp/src/main/java/cc/iotkit/comp/tcp/parser/ScriptPayloadParser.java
  37. 0 17
      iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/DefaultScriptEngineFactory.java
  38. 0 12
      iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/IScriptEngine.java
  39. 0 6
      iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/IScriptEngineFactory.java
  40. 0 7
      iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/IScriptException.java
  41. 0 35
      iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/JsGraalJsScriptEngine.java
  42. 0 41
      iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/JsNashornScriptEngine.java
  43. 1 1
      iot-components/iot-ctwing-component/pom.xml
  44. 11 5
      iot-components/iot-emqx-component/dependency-reduced-pom.xml
  45. 6 1
      iot-components/iot-emqx-component/pom.xml
  46. 15 11
      iot-components/iot-emqx-component/src/main/java/cc/iotkit/comp/emqx/AuthVerticle.java
  47. 43 18
      iot-components/iot-emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxDeviceComponent.java
  48. 14 36
      iot-components/iot-emqx-component/src/main/java/cc/iotkit/comp/emqx/JsScripter.java
  49. 8 0
      iot-components/iot-emqx-component/src/main/java/cc/iotkit/comp/emqx/TransparentMsg.java
  50. 8 2
      iot-components/iot-http-biz-component/dependency-reduced-pom.xml
  51. 6 1
      iot-components/iot-http-biz-component/pom.xml
  52. 26 38
      iot-components/iot-http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpBizComponent.java
  53. 19 0
      iot-components/iot-http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpContent.java
  54. 10 4
      iot-components/iot-mqtt-component/dependency-reduced-pom.xml
  55. 6 1
      iot-components/iot-mqtt-component/pom.xml
  56. 15 36
      iot-components/iot-mqtt-component/src/main/java/cc/iotkit/comp/mqtt/JsScripter.java
  57. 1 0
      iot-components/iot-mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttDeviceComponent.java
  58. 3 0
      iot-components/iot-mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttVerticle.java
  59. 8 0
      iot-components/iot-mqtt-component/src/main/java/cc/iotkit/comp/mqtt/TransparentMsg.java
  60. 87 0
      iot-components/iot-websocket-component/dependency-reduced-pom.xml
  61. 1 1
      iot-components/iot-websocket-component/pom.xml
  62. 5 2
      iot-components/iot-websocket-component/src/main/java/cc/iotkit/comp/websocket/WebSocketDeviceComponent.java
  63. 2 2
      iot-components/pom.xml
  64. 1 1
      iot-data/iot-data-cache/pom.xml
  65. 1 1
      iot-data/iot-data-service/pom.xml
  66. 1 1
      iot-data/iot-es-temporal-service/pom.xml
  67. 2 2
      iot-data/iot-model/pom.xml
  68. 2 2
      iot-data/iot-rdb-data-service/pom.xml
  69. 1 1
      iot-data/iot-td-temporal-service/pom.xml
  70. 1 1
      iot-data/iot-temporal-service/pom.xml
  71. 1 1
      iot-data/iot-ts-temporal-service/pom.xml
  72. 1 1
      iot-data/pom.xml
  73. 1 1
      iot-message-bus/iot-message-core/pom.xml
  74. 1 1
      iot-message-bus/iot-message-rocketmq/pom.xml
  75. 1 1
      iot-message-bus/iot-vertx-event-bus/pom.xml
  76. 1 1
      iot-message-bus/pom.xml
  77. 1 1
      iot-package/pom.xml
  78. 15 9
      iot-rule-engine/pom.xml
  79. 3 1
      iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/AlertService.java
  80. 5 6
      iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/HttpService.java
  81. 10 25
      iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/ScriptService.java
  82. 3 1
      iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaService.java
  83. 3 1
      iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttService.java
  84. 3 1
      iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpService.java
  85. 28 6
      iot-script-engine/pom.xml
  86. 15 0
      iot-script-engine/src/main/java/cc/iotkit/script/IScriptEngine.java
  87. 76 0
      iot-script-engine/src/main/java/cc/iotkit/script/JavaScriptEngine.java
  88. 30 0
      iot-script-engine/src/main/java/cc/iotkit/script/ProcessStringToJsonExample.java
  89. 43 0
      iot-script-engine/src/main/java/cc/iotkit/script/ScriptEngineFactory.java
  90. 7 0
      iot-script-engine/src/main/java/cc/iotkit/script/ScriptException.java
  91. 1 1
      iot-standalone/pom.xml
  92. 1 1
      iot-test-tool/iot-test-mqtt/pom.xml
  93. 2 2
      iot-test-tool/iot-test-mqtt/src/main/java/cc/iotkit/test/mqtt/Simulator.java
  94. 1 0
      iot-test-tool/iot-test-mqtt/src/main/java/cc/iotkit/test/mqtt/performance/ReportTest.java
  95. 1 1
      iot-test-tool/pom.xml
  96. 6 2
      iot-virtual-device/pom.xml
  97. 25 36
      iot-virtual-device/src/main/java/cc/iotkit/virtualdevice/VirtualManager.java
  98. 23 16
      pom.xml

BIN
data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/iot-http-biz-component-0.4.2-SNAPSHOT.jar → data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/iot-http-biz-component-0.4.3-SNAPSHOT.jar


+ 4 - 19
data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/component.js

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

BIN
data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/iot-emqx-component-0.4.2-SNAPSHOT.jar → data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/iot-emqx-component-0.4.3-SNAPSHOT.jar


BIN
data/components/eabb131d-8fd1-43a8-88d9-a198abfd3d42/iot-mqtt-component-0.4.2-SNAPSHOT.jar → data/components/eabb131d-8fd1-43a8-88d9-a198abfd3d42/iot-mqtt-component-0.4.3-SNAPSHOT.jar


BIN
data/components/fee0e826-963f-4e53-a2cf-11e3e5f784ea/iot-http-biz-component-0.4.2-SNAPSHOT.jar → data/components/fee0e826-963f-4e53-a2cf-11e3e5f784ea/iot-http-biz-component-0.4.3-SNAPSHOT.jar


+ 3 - 3
data/init/protocolComponent.json

@@ -5,7 +5,7 @@
     "name": "MQTT标准协议组件",
     "name": "MQTT标准协议组件",
     "type": "device",
     "type": "device",
     "protocol": "mqtt",
     "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\"}",
     "config": "{\"port\":1883,\"ssl\":false,\"type\":\"server\"}",
     "converter": "6260396d67aced2696184053",
     "converter": "6260396d67aced2696184053",
     "converType": "custom",
     "converType": "custom",
@@ -18,7 +18,7 @@
     "name": "EMQX标准协议组件",
     "name": "EMQX标准协议组件",
     "type": "device",
     "type": "device",
     "protocol": "mqtt",
     "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\"}",
     "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",
     "converter": "6260396d67aced2696184053",
     "converType": "custom",
     "converType": "custom",
@@ -31,7 +31,7 @@
     "name": "小度音箱接入组件",
     "name": "小度音箱接入组件",
     "type": "biz",
     "type": "biz",
     "protocol": "http",
     "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\"}",
     "config": "{\"port\":\"8084\"}",
     "converter": "",
     "converter": "",
     "converType": "",
     "converType": "",

+ 1 - 1
iot-auth-server/pom.xml

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

+ 801 - 710
iot-auth-server/src/main/java/cc/iotkit/utils/SoMap.java

@@ -23,724 +23,815 @@ import java.util.regex.Pattern;
 
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
 
 
+import cc.iotkit.common.utils.JsonUtil;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
 /**
 /**
- * Map< String, Object> 是最常用的一种Map类型,但是它写着麻烦 
- * <p>所以特封装此类,继承Map,进行一些扩展,可以让Map更灵活使用 
+ * Map< String, Object> 是最常用的一种Map类型,但是它写着麻烦
+ * <p>所以特封装此类,继承Map,进行一些扩展,可以让Map更灵活使用
  * <p>最新:2020-12-10 新增部分构造方法
  * <p>最新:2020-12-10 新增部分构造方法
+ *
  * @author kong
  * @author kong
  */
  */
 public class SoMap extends LinkedHashMap<String, Object> {
 public class SoMap extends LinkedHashMap<String, Object> {
 
 
-	private static final long serialVersionUID = 1L;
-
-	public SoMap() {
-	}
-	
-	/** 以下元素会在isNull函数中被判定为Null, */
-	public static final Object[] NULL_ELEMENT_ARRAY = {null, ""};
-	public static final List<Object> NULL_ELEMENT_LIST;
-
-	static {
-		NULL_ELEMENT_LIST = Arrays.asList(NULL_ELEMENT_ARRAY);
-	}
-
-	// ============================= 读值 =============================
-
-	/** 获取一个值 */
-	@Override
-	public Object get(Object key) {
-		if("this".equals(key)) {
-			return this;
-		}
-		return super.get(key);
-	}
-
-	/** 如果为空,则返回默认值 */
-	public Object get(Object key, Object defaultValue) {
-		Object value = get(key);
-		if(valueIsNull(value)) {
-			return defaultValue;
-		}
-		return value;
-	}
-	
-	/** 转为String并返回 */
-	public String getString(String key) {
-		Object value = get(key);
-		if(value == null) {
-			return null;
-		}
-		return String.valueOf(value);
-	}
-
-	/** 如果为空,则返回默认值 */
-	public String getString(String key, String defaultValue) {
-		Object value = get(key);
-		if(valueIsNull(value)) {
-			return defaultValue;
-		}
-		return String.valueOf(value);
-	}
-
-	/** 转为int并返回 */
-	public int getInt(String key) {
-		Object value = get(key);
-		if(valueIsNull(value)) {
-			return 0;
-		}
-		return Integer.valueOf(String.valueOf(value));
-	}
-	/** 转为int并返回,同时指定默认值 */
-	public int getInt(String key, int defaultValue) {
-		Object value = get(key);
-		if(valueIsNull(value)) {
-			return defaultValue;
-		}
-		return Integer.valueOf(String.valueOf(value));
-	}
-
-	/** 转为long并返回 */
-	public long getLong(String key) {
-		Object value = get(key);
-		if(valueIsNull(value)) {
-			return 0;
-		}
-		return Long.valueOf(String.valueOf(value));
-	}
-
-	/** 转为double并返回 */
-	public double getDouble(String key) {
-		Object value = get(key);
-		if(valueIsNull(value)) {
-			return 0.0;
-		}
-		return Double.valueOf(String.valueOf(value));
-	}
-
-	/** 转为boolean并返回 */
-	public boolean getBoolean(String key) {
-		Object value = get(key);
-		if(valueIsNull(value)) {
-			return false;
-		}
-		return Boolean.valueOf(String.valueOf(value));
-	}
-
-	/** 转为Date并返回,根据自定义格式 */
-	public Date getDateByFormat(String key, String format) {
-		try {
-			return new SimpleDateFormat(format).parse(getString(key));
-		} catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	/** 转为Date并返回,根据格式: yyyy-MM-dd */
-	public Date getDate(String key) {
-		return getDateByFormat(key, "yyyy-MM-dd");
-	}
-
-	/** 转为Date并返回,根据格式: yyyy-MM-dd HH:mm:ss */
-	public Date getDateTime(String key) {
-		return getDateByFormat(key, "yyyy-MM-dd HH:mm:ss");
-	}
-
-	/** 转为Map并返回 */
-	@SuppressWarnings({ "unchecked", "rawtypes" })
-	public SoMap getMap(String key) {
-		Object value = get(key);
-		if(value == null) {
-			return SoMap.getSoMap();
-		}
-		if(value instanceof Map) {
-			return SoMap.getSoMap((Map)value);
-		}
-		if(value instanceof String) {
-			return SoMap.getSoMap().setJsonString((String)value);
-		}
-		throw new RuntimeException("值无法转化为SoMap: " + value);
-	}
-
-	/** 获取集合(必须原先就是个集合,否则会创建个新集合并返回) */
-	@SuppressWarnings("unchecked")
-	public List<Object> getList(String key) {
-		Object value = get(key);
-		List<Object> list = null;
-		if(value == null || value.equals("")) {
-			list = new ArrayList<Object>();
-		}
-		else if(value instanceof List) {
-			list = (List<Object>)value;
-		} else {
-			list = new ArrayList<Object>();
-			list.add(value);
-		}
-		return list;
-	}
-
-	/** 获取集合 (指定泛型类型) */
-	public <T> List<T> getList(String key, Class<T> cs) {
-		List<Object> list = getList(key);
-		List<T> list2 = new ArrayList<T>();
-		for (Object obj : list) {
-			T objC = getValueByClass(obj, cs);
-			list2.add(objC);
-		}
-		return list2;
-	}
-
-	/** 获取集合(逗号分隔式),(指定类型) */
-	public <T> List<T> getListByComma(String key, Class<T> cs) {
-		String listStr = getString(key);
-		if(listStr == null || listStr.equals("")) {
-			return new ArrayList<>();
-		}
-		// 开始转化
-		String [] arr = listStr.split(",");
-		List<T> list = new ArrayList<T>();
-		for (String str : arr) {
-			if(cs == int.class || cs == Integer.class || cs == long.class || cs == Long.class) {
-				str = str.trim();
-			}
-			T objC = getValueByClass(str, cs);
-			list.add(objC);
-		}
-		return list;
-	}
-
-
-	/** 根据指定类型从map中取值,返回实体对象 */
-	public <T> T getModel(Class<T> cs) {
-		try {
-			return getModelByObject(cs.newInstance());
-		} catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-	}
-	
-	/** 从map中取值,塞到一个对象中 */
-	public <T> T getModelByObject(T obj) {
-		// 获取类型 
-		Class<?> cs = obj.getClass();
-		// 循环复制  
-		for (Field field : cs.getDeclaredFields()) {
-			try {
-				// 获取对象 
-				Object value = this.get(field.getName());	
-				if(value == null) {
-					continue;
-				}
-				field.setAccessible(true);	
-				Object valueConvert = getValueByClass(value, field.getType());
-				field.set(obj, valueConvert);
-			} catch (IllegalArgumentException | IllegalAccessException e) {
-				throw new RuntimeException("属性取值出错:" + field.getName(), e);
-			}
-		}
-		return obj;
-	}
-
-	
-
-	/**
-	 * 将指定值转化为指定类型并返回
-	 * @param obj
-	 * @param cs
-	 * @param <T>
-	 * @return
-	 */
-	@SuppressWarnings("unchecked")
-	public static <T> T getValueByClass(Object obj, Class<T> cs) {
-		String obj2 = String.valueOf(obj);
-		Object obj3 = null;
-		if (cs.equals(String.class)) {
-			obj3 = obj2;
-		} else if (cs.equals(int.class) || cs.equals(Integer.class)) {
-			obj3 = Integer.valueOf(obj2);
-		} else if (cs.equals(long.class) || cs.equals(Long.class)) {
-			obj3 = Long.valueOf(obj2);
-		} else if (cs.equals(short.class) || cs.equals(Short.class)) {
-			obj3 = Short.valueOf(obj2);
-		} else if (cs.equals(byte.class) || cs.equals(Byte.class)) {
-			obj3 = Byte.valueOf(obj2);
-		} else if (cs.equals(float.class) || cs.equals(Float.class)) {
-			obj3 = Float.valueOf(obj2);
-		} else if (cs.equals(double.class) || cs.equals(Double.class)) {
-			obj3 = Double.valueOf(obj2);
-		} else if (cs.equals(boolean.class) || cs.equals(Boolean.class)) {
-			obj3 = Boolean.valueOf(obj2);
-		} else {
-			obj3 = (T)obj;
-		}
-		return (T)obj3;
-	}
-
-	
-	// ============================= 写值 =============================
-
-	/**
-	 * 给指定key添加一个默认值(只有在这个key原来无值的情况先才会set进去)
-	 */
-	public void setDefaultValue(String key, Object defaultValue) {
-		if(isNull(key)) {
-			set(key, defaultValue);
-		}
-	}
-
-	/** set一个值,连缀风格 */
-	public SoMap set(String key, Object value) {
-		// 防止敏感key 
-		if(key.toLowerCase().equals("this")) {		
-			return this;
-		}
-		put(key, value);
-		return this;
-	}
-
-	/** 将一个Map塞进SoMap */
-	public SoMap setMap(Map<String, ?> map) {
-		if(map != null) {
-			for (String key : map.keySet()) {
-				this.set(key, map.get(key));
-			}
-		}
-		return this;
-	}
-
-	/** 将一个对象解析塞进SoMap */
-	public SoMap setModel(Object model) {
-		if(model == null) {
-			return this;
-		}
-		Field[] fields = model.getClass().getDeclaredFields();
-	    for (Field field : fields) {
-	        try{
-	            field.setAccessible(true);
-	            boolean isStatic = Modifier.isStatic(field.getModifiers());
-	            if(!isStatic) {
-		            this.set(field.getName(), field.get(model));
-	            }
-	        }catch (Exception e){
-	        	throw new RuntimeException(e);
-	        }
-	    }
-		return this;
-	}
-
-	/** 将json字符串解析后塞进SoMap */
-	public SoMap setJsonString(String jsonString) {
-		try {
-			@SuppressWarnings("unchecked")
-			Map<String, Object> map = new ObjectMapper().readValue(jsonString, Map.class);
-			return this.setMap(map);
-		} catch (JsonProcessingException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	
-	// ============================= 删值 =============================
-
-	/** delete一个值,连缀风格 */
-	public SoMap delete(String key) {
-		remove(key);
-		return this;
-	}
-
-	/** 清理所有value为null的字段 */
-	public SoMap clearNull() {
-		Iterator<String> iterator = this.keySet().iterator();
-		while(iterator.hasNext()) {
-			String key = iterator.next();
-			if(this.isNull(key)) {
-				iterator.remove();
-				this.remove(key);
-			}
-
-		}
-		return this;
-	}
-	/** 清理指定key */
-	public SoMap clearIn(String ...keys) {
-		List<String> keys2 = Arrays.asList(keys);
-		Iterator<String> iterator = this.keySet().iterator();
-		while(iterator.hasNext()) {
-			String key = iterator.next();
-			if(keys2.contains(key) == true) {
-				iterator.remove();
-				this.remove(key);
-			}
-		}
-		return this;
-	}
-	/** 清理掉不在列表中的key */
-	public SoMap clearNotIn(String ...keys) {
-		List<String> keys2 = Arrays.asList(keys);
-		Iterator<String> iterator = this.keySet().iterator();
-		while(iterator.hasNext()) {
-			String key = iterator.next();
-			if(keys2.contains(key) == false) {
-				iterator.remove();
-				this.remove(key);
-			}
-
-		}
-		return this;
-	}
-	/** 清理掉所有key */
-	public SoMap clearAll() {
-		clear();
-		return this;
-	}
-	
-
-	// ============================= 快速构建 ============================= 
-
-	/** 构建一个SoMap并返回 */
-	public static SoMap getSoMap() {
-		return new SoMap();
-	}
-	/** 构建一个SoMap并返回 */
-	public static SoMap getSoMap(String key, Object value) {
-		return new SoMap().set(key, value);
-	}
-	/** 构建一个SoMap并返回 */
-	public static SoMap getSoMap(Map<String, ?> map) {
-		return new SoMap().setMap(map);
-	}
-
-	/** 将一个对象集合解析成为SoMap */
-	public static SoMap getSoMapByModel(Object model) {
-		return SoMap.getSoMap().setModel(model);
-	}
-	
-	/** 将一个对象集合解析成为SoMap集合 */
-	public static List<SoMap> getSoMapByList(List<?> list) {
-		List<SoMap> listMap = new ArrayList<SoMap>();
-		for (Object model : list) {
-			listMap.add(getSoMapByModel(model));
-		}
-		return listMap;
-	}
-	
-	/** 克隆指定key,返回一个新的SoMap */
-	public SoMap cloneKeys(String... keys) {
-		SoMap so = new SoMap();
-		for (String key : keys) {
-			so.set(key, this.get(key));
-		}
-		return so;
-	}
-	/** 克隆所有key,返回一个新的SoMap */
-	public SoMap cloneSoMap() {
-		SoMap so = new SoMap();
-		for (String key : this.keySet()) {
-			so.set(key, this.get(key));
-		}
-		return so;
-	}
-
-	/** 将所有key转为大写 */
-	public SoMap toUpperCase() {
-		SoMap so = new SoMap();
-		for (String key : this.keySet()) {
-			so.set(key.toUpperCase(), this.get(key));
-		}
-		this.clearAll().setMap(so);
-		return this;
-	}
-	/** 将所有key转为小写 */
-	public SoMap toLowerCase() {
-		SoMap so = new SoMap();
-		for (String key : this.keySet()) {
-			so.set(key.toLowerCase(), this.get(key));
-		}
-		this.clearAll().setMap(so);
-		return this;
-	}
-	/** 将所有key中下划线转为中划线模式 (kebab-case风格) */
-	public SoMap toKebabCase() {
-		SoMap so = new SoMap();
-		for (String key : this.keySet()) {
-			so.set(wordEachKebabCase(key), this.get(key));
-		}
-		this.clearAll().setMap(so);
-		return this;
-	}
-	/** 将所有key中下划线转为小驼峰模式 */
-	public SoMap toHumpCase() {
-		SoMap so = new SoMap();
-		for (String key : this.keySet()) {
-			so.set(wordEachBigFs(key), this.get(key));
-		}
-		this.clearAll().setMap(so);
-		return this;
-	}
-	/** 将所有key中小驼峰转为下划线模式 */
-	public SoMap humpToLineCase() {
-		SoMap so = new SoMap();
-		for (String key : this.keySet()) {
-			so.set(wordHumpToLine(key), this.get(key));
-		}
-		this.clearAll().setMap(so);
-		return this;
-	}
-	
-	
-	
-	
-	// ============================= 辅助方法 =============================
-
-
-	/** 指定key是否为null,判定标准为 NULL_ELEMENT_ARRAY 中的元素  */
-	public boolean isNull(String key) {
-		return valueIsNull(get(key));
-	}
-
-	/** 指定key列表中是否包含value为null的元素,只要有一个为null,就会返回true */
-	public boolean isContainNull(String ...keys) {
-		for (String key : keys) {
-			if(this.isNull(key)) {
-				return true;
-			}
-		}
-		return false;
-	}
-	
-	/** 与isNull()相反 */
-	public boolean isNotNull(String key) {
-		return !isNull(key);
-	}
-	/** 指定key的value是否为null,作用同isNotNull() */
-	public boolean has(String key) {
-		return !isNull(key);
-	}
-	
-	/** 指定value在此SoMap的判断标准中是否为null */
-	public boolean valueIsNull(Object value) {
-		return NULL_ELEMENT_LIST.contains(value);
-	}
-	
-	/** 验证指定key不为空,为空则抛出异常 */
-	public SoMap checkNull(String ...keys) {
-		for (String key : keys) {
-			if(this.isNull(key)) {
-				throw new RuntimeException("参数" + key + "不能为空");
-			}
-		}
-		return this;
-	}
-
-	static Pattern patternNumber = Pattern.compile("[0-9]*");
-	/** 指定key是否为数字 */
-	public boolean isNumber(String key) {
-		String value = getString(key);
-		if(value == null) {
-			return false;
-		}
-	    return patternNumber.matcher(value).matches();   
-	}
-
-	
-	
-	
-	/**
-	 * 转为JSON字符串
-	 */
-	public String toJsonString() {
-		try {
-//			SoMap so = SoMap.getSoMap(this);
-			return new ObjectMapper().writeValueAsString(this);
-		} catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-//	/**
-//	 * 转为JSON字符串, 带格式的 
-//	 */
-//	public String toJsonFormatString() {
-//		try {
-//			return JSON.toJSONString(this, true); 
-//		} catch (Exception e) {
-//			throw new RuntimeException(e);
-//		}
-//	}
-
-	// ============================= web辅助 =============================
-
-
-	/**
-	 * 返回当前request请求的的所有参数 
-	 * @return
-	 */
-	public static SoMap getRequestSoMap() {
-		// 大善人SpringMVC提供的封装 
-		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
-		if(servletRequestAttributes == null) {
-			throw new RuntimeException("当前线程非JavaWeb环境");
-		}
-		// 当前request
-		HttpServletRequest request = servletRequestAttributes.getRequest(); 
-		if (request.getAttribute("currentSoMap") == null || request.getAttribute("currentSoMap") instanceof SoMap == false ) {
-			initRequestSoMap(request);
-		}
-		return (SoMap)request.getAttribute("currentSoMap");
-	}
-
-	/** 初始化当前request的 SoMap */
-	private static void initRequestSoMap(HttpServletRequest request) {
-		SoMap soMap = new SoMap();
-		Map<String, String[]> parameterMap = request.getParameterMap();	// 获取所有参数 
-		for (String key : parameterMap.keySet()) {
-			try {
-				String[] values = parameterMap.get(key); // 获得values 
-				if(values.length == 1) {
-					soMap.set(key, values[0]);
-				} else {
-					List<String> list = new ArrayList<String>();
-					for (String v : values) {
-						list.add(v);
-					}
-					soMap.set(key, list);
-				}
-			} catch (Exception e) {
-				throw new RuntimeException(e);
-			}
-		}
-		request.setAttribute("currentSoMap", soMap);
-	}
-	
-	/**
-	 * 验证返回当前线程是否为JavaWeb环境 
-	 * @return
-	 */
-	public static boolean isJavaWeb() {
-		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();// 大善人SpringMVC提供的封装 
-		if(servletRequestAttributes == null) {
-			return false;
-		}
-		return true;
-	}
-	
-
-
-	// ============================= 常见key (以下key经常用,所以封装以下,方便写代码) =============================
-
-	/** get 当前页  */
-	public int getKeyPageNo() {
-		int pageNo = getInt("pageNo", 1);
-		if(pageNo <= 0) {
-			pageNo = 1;
-		}
-		return pageNo;
-	}
-	/** get 页大小  */
-	public int getKeyPageSize() {
-		int pageSize = getInt("pageSize", 10);
-		if(pageSize <= 0 || pageSize > 1000) {
-			pageSize = 10;
-		}
-		return pageSize;
-	}
-
-	/** get 排序方式 */
-	public int getKeySortType() {
-		return getInt("sortType");
-	}
-
-
-
-
-	
-
-	// ============================= 工具方法 =============================
-	
-
-	/**
-	 * 将一个一维集合转换为树形集合 
-	 * @param list         集合
-	 * @param idKey        id标识key
-	 * @param parentIdKey  父id标识key
-	 * @param childListKey 子节点标识key
-	 * @return 转换后的tree集合 
-	 */
-	public static List<SoMap> listToTree(List<SoMap> list, String idKey, String parentIdKey, String childListKey) {
-		// 声明新的集合,存储tree形数据 
-		List<SoMap> newTreeList = new ArrayList<SoMap>();
-		// 声明hash-Map,方便查找数据 
-		SoMap hash = new SoMap();
-		// 将数组转为Object的形式,key为数组中的id 
-		for (int i = 0; i < list.size(); i++) {
-			SoMap json = (SoMap) list.get(i);
-			hash.put(json.getString(idKey), json);
-		}
-		// 遍历结果集
-		for (int j = 0; j < list.size(); j++) {
-			// 单条记录
-			SoMap aVal = (SoMap) list.get(j);
-			// 在hash中取出key为单条记录中pid的值
-			SoMap hashVp = (SoMap) hash.get(aVal.get(parentIdKey, "").toString());
-			// 如果记录的pid存在,则说明它有父节点,将她添加到孩子节点的集合中
-			if (hashVp != null) {
-				// 检查是否有child属性,有则添加,没有则新建 
-				if (hashVp.get(childListKey) != null) {
-					@SuppressWarnings("unchecked")
-					List<SoMap> ch = (List<SoMap>) hashVp.get(childListKey);
-					ch.add(aVal);
-					hashVp.put(childListKey, ch);
-				} else {
-					List<SoMap> ch = new ArrayList<SoMap>();
-					ch.add(aVal);
-					hashVp.put(childListKey, ch);
-				}
-			} else {
-				newTreeList.add(aVal);
-			}
-		}
-		return newTreeList;
-	}
-	
-	
-
-	/** 指定字符串的字符串下划线转大写模式 */
-	private static String wordEachBig(String str){
-		String newStr = "";
-		for (String s : str.split("_")) {
-			newStr += wordFirstBig(s);
-		}
-		return newStr;
-	}
-	/** 返回下划线转小驼峰形式 */
-	private static String wordEachBigFs(String str){
-		return wordFirstSmall(wordEachBig(str));
-	}
-
-	/** 将指定单词首字母大写 */
-	private static String wordFirstBig(String str) {
-		return str.substring(0, 1).toUpperCase() + str.substring(1, str.length());
-	}
-
-	/** 将指定单词首字母小写 */
-	private static String wordFirstSmall(String str) {
-		return str.substring(0, 1).toLowerCase() + str.substring(1, str.length());
-	}
-
-	/** 下划线转中划线 */
-	private static String wordEachKebabCase(String str) {
-		return str.replaceAll("_", "-");
-	}
-
-	/** 驼峰转下划线  */
-	private static String wordHumpToLine(String str) {
-		return str.replaceAll("[A-Z]", "_$0").toLowerCase();
-	}
-	
+    private static final long serialVersionUID = 1L;
+
+    public SoMap() {
+    }
+
+    /**
+     * 以下元素会在isNull函数中被判定为Null,
+     */
+    public static final Object[] NULL_ELEMENT_ARRAY = {null, ""};
+    public static final List<Object> NULL_ELEMENT_LIST;
+
+    static {
+        NULL_ELEMENT_LIST = Arrays.asList(NULL_ELEMENT_ARRAY);
+    }
+
+    // ============================= 读值 =============================
+
+    /**
+     * 获取一个值
+     */
+    @Override
+    public Object get(Object key) {
+        if ("this".equals(key)) {
+            return this;
+        }
+        return super.get(key);
+    }
+
+    /**
+     * 如果为空,则返回默认值
+     */
+    public Object get(Object key, Object defaultValue) {
+        Object value = get(key);
+        if (valueIsNull(value)) {
+            return defaultValue;
+        }
+        return value;
+    }
+
+    /**
+     * 转为String并返回
+     */
+    public String getString(String key) {
+        Object value = get(key);
+        if (value == null) {
+            return null;
+        }
+        return String.valueOf(value);
+    }
+
+    /**
+     * 如果为空,则返回默认值
+     */
+    public String getString(String key, String defaultValue) {
+        Object value = get(key);
+        if (valueIsNull(value)) {
+            return defaultValue;
+        }
+        return String.valueOf(value);
+    }
+
+    /**
+     * 转为int并返回
+     */
+    public int getInt(String key) {
+        Object value = get(key);
+        if (valueIsNull(value)) {
+            return 0;
+        }
+        return Integer.parseInt(String.valueOf(value));
+    }
+
+    /**
+     * 转为int并返回,同时指定默认值
+     */
+    public int getInt(String key, int defaultValue) {
+        Object value = get(key);
+        if (valueIsNull(value)) {
+            return defaultValue;
+        }
+        return Integer.parseInt(String.valueOf(value));
+    }
+
+    /**
+     * 转为long并返回
+     */
+    public long getLong(String key) {
+        Object value = get(key);
+        if (valueIsNull(value)) {
+            return 0;
+        }
+        return Long.parseLong(String.valueOf(value));
+    }
+
+    /**
+     * 转为double并返回
+     */
+    public double getDouble(String key) {
+        Object value = get(key);
+        if (valueIsNull(value)) {
+            return 0.0;
+        }
+        return Double.parseDouble(String.valueOf(value));
+    }
+
+    /**
+     * 转为boolean并返回
+     */
+    public boolean getBoolean(String key) {
+        Object value = get(key);
+        if (valueIsNull(value)) {
+            return false;
+        }
+        return Boolean.parseBoolean(String.valueOf(value));
+    }
+
+    /**
+     * 转为Date并返回,根据自定义格式
+     */
+    public Date getDateByFormat(String key, String format) {
+        try {
+            return new SimpleDateFormat(format).parse(getString(key));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 转为Date并返回,根据格式: yyyy-MM-dd
+     */
+    public Date getDate(String key) {
+        return getDateByFormat(key, "yyyy-MM-dd");
+    }
+
+    /**
+     * 转为Date并返回,根据格式: yyyy-MM-dd HH:mm:ss
+     */
+    public Date getDateTime(String key) {
+        return getDateByFormat(key, "yyyy-MM-dd HH:mm:ss");
+    }
+
+    /**
+     * 转为Map并返回
+     */
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public SoMap getMap(String key) {
+        Object value = get(key);
+        if (value == null) {
+            return SoMap.getSoMap();
+        }
+        if (value instanceof Map) {
+            return SoMap.getSoMap((Map) value);
+        }
+        if (value instanceof String) {
+            return SoMap.getSoMap().setJsonString((String) value);
+        }
+        throw new RuntimeException("值无法转化为SoMap: " + value);
+    }
+
+    /**
+     * 获取集合(必须原先就是个集合,否则会创建个新集合并返回)
+     */
+    @SuppressWarnings("unchecked")
+    public List<Object> getList(String key) {
+        Object value = get(key);
+        List<Object> list;
+        if (value == null || value.equals("")) {
+            list = new ArrayList<>();
+        } else if (value instanceof List) {
+            list = (List<Object>) value;
+        } else {
+            list = new ArrayList<>();
+            list.add(value);
+        }
+        return list;
+    }
+
+    /**
+     * 获取集合 (指定泛型类型)
+     */
+    public <T> List<T> getList(String key, Class<T> cs) {
+        List<Object> list = getList(key);
+        List<T> list2 = new ArrayList<T>();
+        for (Object obj : list) {
+            T objC = getValueByClass(obj, cs);
+            list2.add(objC);
+        }
+        return list2;
+    }
+
+    /**
+     * 获取集合(逗号分隔式),(指定类型)
+     */
+    public <T> List<T> getListByComma(String key, Class<T> cs) {
+        String listStr = getString(key);
+        if (listStr == null || listStr.equals("")) {
+            return new ArrayList<>();
+        }
+        // 开始转化
+        String[] arr = listStr.split(",");
+        List<T> list = new ArrayList<T>();
+        for (String str : arr) {
+            if (cs == int.class || cs == Integer.class || cs == long.class || cs == Long.class) {
+                str = str.trim();
+            }
+            T objC = getValueByClass(str, cs);
+            list.add(objC);
+        }
+        return list;
+    }
+
+
+    /**
+     * 根据指定类型从map中取值,返回实体对象
+     */
+    public <T> T getModel(Class<T> cs) {
+        try {
+            return getModelByObject(cs.newInstance());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 从map中取值,塞到一个对象中
+     */
+    public <T> T getModelByObject(T obj) {
+        // 获取类型
+        Class<?> cs = obj.getClass();
+        // 循环复制
+        for (Field field : cs.getDeclaredFields()) {
+            try {
+                // 获取对象
+                Object value = this.get(field.getName());
+                if (value == null) {
+                    continue;
+                }
+                field.setAccessible(true);
+                Object valueConvert = getValueByClass(value, field.getType());
+                field.set(obj, valueConvert);
+            } catch (IllegalArgumentException | IllegalAccessException e) {
+                throw new RuntimeException("属性取值出错:" + field.getName(), e);
+            }
+        }
+        return obj;
+    }
+
+
+    /**
+     * 将指定值转化为指定类型并返回
+     *
+     * @param obj
+     * @param cs
+     * @param <T>
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getValueByClass(Object obj, Class<T> cs) {
+        String obj2 = String.valueOf(obj);
+        Object obj3;
+        if (cs.equals(String.class)) {
+            obj3 = obj2;
+        } else if (cs.equals(int.class) || cs.equals(Integer.class)) {
+            obj3 = Integer.valueOf(obj2);
+        } else if (cs.equals(long.class) || cs.equals(Long.class)) {
+            obj3 = Long.valueOf(obj2);
+        } else if (cs.equals(short.class) || cs.equals(Short.class)) {
+            obj3 = Short.valueOf(obj2);
+        } else if (cs.equals(byte.class) || cs.equals(Byte.class)) {
+            obj3 = Byte.valueOf(obj2);
+        } else if (cs.equals(float.class) || cs.equals(Float.class)) {
+            obj3 = Float.valueOf(obj2);
+        } else if (cs.equals(double.class) || cs.equals(Double.class)) {
+            obj3 = Double.valueOf(obj2);
+        } else if (cs.equals(boolean.class) || cs.equals(Boolean.class)) {
+            obj3 = Boolean.valueOf(obj2);
+        } else {
+            obj3 = (T) obj;
+        }
+        return (T) obj3;
+    }
+
+
+    // ============================= 写值 =============================
+
+    /**
+     * 给指定key添加一个默认值(只有在这个key原来无值的情况先才会set进去)
+     */
+    public void setDefaultValue(String key, Object defaultValue) {
+        if (isNull(key)) {
+            set(key, defaultValue);
+        }
+    }
+
+    /**
+     * set一个值,连缀风格
+     */
+    public SoMap set(String key, Object value) {
+        // 防止敏感key
+        if (key.toLowerCase().equals("this")) {
+            return this;
+        }
+        put(key, value);
+        return this;
+    }
+
+    /**
+     * 将一个Map塞进SoMap
+     */
+    public SoMap setMap(Map<String, ?> map) {
+        if (map != null) {
+            for (String key : map.keySet()) {
+                this.set(key, map.get(key));
+            }
+        }
+        return this;
+    }
+
+    /**
+     * 将一个对象解析塞进SoMap
+     */
+    public SoMap setModel(Object model) {
+        if (model == null) {
+            return this;
+        }
+        Field[] fields = model.getClass().getDeclaredFields();
+        for (Field field : fields) {
+            try {
+                field.setAccessible(true);
+                boolean isStatic = Modifier.isStatic(field.getModifiers());
+                if (!isStatic) {
+                    this.set(field.getName(), field.get(model));
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * 将json字符串解析后塞进SoMap
+     */
+    public SoMap setJsonString(String jsonString) {
+        return this.setMap(JsonUtil.parse(jsonString, Map.class));
+    }
+
+
+    // ============================= 删值 =============================
+
+    /**
+     * delete一个值,连缀风格
+     */
+    public SoMap delete(String key) {
+        remove(key);
+        return this;
+    }
+
+    /**
+     * 清理所有value为null的字段
+     */
+    public SoMap clearNull() {
+        Iterator<String> iterator = this.keySet().iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next();
+            if (this.isNull(key)) {
+                iterator.remove();
+                this.remove(key);
+            }
+
+        }
+        return this;
+    }
+
+    /**
+     * 清理指定key
+     */
+    public SoMap clearIn(String... keys) {
+        List<String> keys2 = Arrays.asList(keys);
+        Iterator<String> iterator = this.keySet().iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next();
+            if (keys2.contains(key)) {
+                iterator.remove();
+                this.remove(key);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * 清理掉不在列表中的key
+     */
+    public SoMap clearNotIn(String... keys) {
+        List<String> keys2 = Arrays.asList(keys);
+        Iterator<String> iterator = this.keySet().iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next();
+            if (!keys2.contains(key)) {
+                iterator.remove();
+                this.remove(key);
+            }
+
+        }
+        return this;
+    }
+
+    /**
+     * 清理掉所有key
+     */
+    public SoMap clearAll() {
+        clear();
+        return this;
+    }
+
+
+    // ============================= 快速构建 =============================
+
+    /**
+     * 构建一个SoMap并返回
+     */
+    public static SoMap getSoMap() {
+        return new SoMap();
+    }
+
+    /**
+     * 构建一个SoMap并返回
+     */
+    public static SoMap getSoMap(String key, Object value) {
+        return new SoMap().set(key, value);
+    }
+
+    /**
+     * 构建一个SoMap并返回
+     */
+    public static SoMap getSoMap(Map<String, ?> map) {
+        return new SoMap().setMap(map);
+    }
+
+    /**
+     * 将一个对象集合解析成为SoMap
+     */
+    public static SoMap getSoMapByModel(Object model) {
+        return SoMap.getSoMap().setModel(model);
+    }
+
+    /**
+     * 将一个对象集合解析成为SoMap集合
+     */
+    public static List<SoMap> getSoMapByList(List<?> list) {
+        List<SoMap> listMap = new ArrayList<>();
+        for (Object model : list) {
+            listMap.add(getSoMapByModel(model));
+        }
+        return listMap;
+    }
+
+    /**
+     * 克隆指定key,返回一个新的SoMap
+     */
+    public SoMap cloneKeys(String... keys) {
+        SoMap so = new SoMap();
+        for (String key : keys) {
+            so.set(key, this.get(key));
+        }
+        return so;
+    }
+
+    /**
+     * 克隆所有key,返回一个新的SoMap
+     */
+    public SoMap cloneSoMap() {
+        SoMap so = new SoMap();
+        for (String key : this.keySet()) {
+            so.set(key, this.get(key));
+        }
+        return so;
+    }
+
+    /**
+     * 将所有key转为大写
+     */
+    public SoMap toUpperCase() {
+        SoMap so = new SoMap();
+        for (String key : this.keySet()) {
+            so.set(key.toUpperCase(), this.get(key));
+        }
+        this.clearAll().setMap(so);
+        return this;
+    }
+
+    /**
+     * 将所有key转为小写
+     */
+    public SoMap toLowerCase() {
+        SoMap so = new SoMap();
+        for (String key : this.keySet()) {
+            so.set(key.toLowerCase(), this.get(key));
+        }
+        this.clearAll().setMap(so);
+        return this;
+    }
+
+    /**
+     * 将所有key中下划线转为中划线模式 (kebab-case风格)
+     */
+    public SoMap toKebabCase() {
+        SoMap so = new SoMap();
+        for (String key : this.keySet()) {
+            so.set(wordEachKebabCase(key), this.get(key));
+        }
+        this.clearAll().setMap(so);
+        return this;
+    }
+
+    /**
+     * 将所有key中下划线转为小驼峰模式
+     */
+    public SoMap toHumpCase() {
+        SoMap so = new SoMap();
+        for (String key : this.keySet()) {
+            so.set(wordEachBigFs(key), this.get(key));
+        }
+        this.clearAll().setMap(so);
+        return this;
+    }
+
+    /**
+     * 将所有key中小驼峰转为下划线模式
+     */
+    public SoMap humpToLineCase() {
+        SoMap so = new SoMap();
+        for (String key : this.keySet()) {
+            so.set(wordHumpToLine(key), this.get(key));
+        }
+        this.clearAll().setMap(so);
+        return this;
+    }
+
+
+    // ============================= 辅助方法 =============================
+
+
+    /**
+     * 指定key是否为null,判定标准为 NULL_ELEMENT_ARRAY 中的元素
+     */
+    public boolean isNull(String key) {
+        return valueIsNull(get(key));
+    }
+
+    /**
+     * 指定key列表中是否包含value为null的元素,只要有一个为null,就会返回true
+     */
+    public boolean isContainNull(String... keys) {
+        for (String key : keys) {
+            if (this.isNull(key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 与isNull()相反
+     */
+    public boolean isNotNull(String key) {
+        return !isNull(key);
+    }
+
+    /**
+     * 指定key的value是否为null,作用同isNotNull()
+     */
+    public boolean has(String key) {
+        return !isNull(key);
+    }
+
+    /**
+     * 指定value在此SoMap的判断标准中是否为null
+     */
+    public boolean valueIsNull(Object value) {
+        return NULL_ELEMENT_LIST.contains(value);
+    }
+
+    /**
+     * 验证指定key不为空,为空则抛出异常
+     */
+    public SoMap checkNull(String... keys) {
+        for (String key : keys) {
+            if (this.isNull(key)) {
+                throw new RuntimeException("参数" + key + "不能为空");
+            }
+        }
+        return this;
+    }
+
+    static Pattern patternNumber = Pattern.compile("[0-9]*");
+
+    /**
+     * 指定key是否为数字
+     */
+    public boolean isNumber(String key) {
+        String value = getString(key);
+        if (value == null) {
+            return false;
+        }
+        return patternNumber.matcher(value).matches();
+    }
+
+
+    /**
+     * 转为JSON字符串
+     */
+    public String toJsonString() {
+        return JsonUtil.toJsonString(this);
+    }
+
+    // ============================= web辅助 =============================
+
+    /**
+     * 返回当前request请求的的所有参数
+     *
+     * @return
+     */
+    public static SoMap getRequestSoMap() {
+        // 大善人SpringMVC提供的封装
+        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        if (servletRequestAttributes == null) {
+            throw new RuntimeException("当前线程非JavaWeb环境");
+        }
+        // 当前request
+        HttpServletRequest request = servletRequestAttributes.getRequest();
+        if (request.getAttribute("currentSoMap") == null || !(request.getAttribute("currentSoMap") instanceof SoMap)) {
+            initRequestSoMap(request);
+        }
+        return (SoMap) request.getAttribute("currentSoMap");
+    }
+
+    /**
+     * 初始化当前request的 SoMap
+     */
+    private static void initRequestSoMap(HttpServletRequest request) {
+        SoMap soMap = new SoMap();
+        Map<String, String[]> parameterMap = request.getParameterMap();    // 获取所有参数
+        for (String key : parameterMap.keySet()) {
+            try {
+                String[] values = parameterMap.get(key); // 获得values
+                if (values.length == 1) {
+                    soMap.set(key, values[0]);
+                } else {
+                    soMap.set(key, Arrays.asList(values));
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+        request.setAttribute("currentSoMap", soMap);
+    }
+
+    /**
+     * 验证返回当前线程是否为JavaWeb环境
+     *
+     * @return
+     */
+    public static boolean isJavaWeb() {
+        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();// 大善人SpringMVC提供的封装
+        if (servletRequestAttributes == null) {
+            return false;
+        }
+        return true;
+    }
+
+
+    // ============================= 常见key (以下key经常用,所以封装以下,方便写代码) =============================
+
+    /**
+     * get 当前页
+     */
+    public int getKeyPageNo() {
+        int pageNo = getInt("pageNo", 1);
+        if (pageNo <= 0) {
+            pageNo = 1;
+        }
+        return pageNo;
+    }
+
+    /**
+     * get 页大小
+     */
+    public int getKeyPageSize() {
+        int pageSize = getInt("pageSize", 10);
+        if (pageSize <= 0 || pageSize > 1000) {
+            pageSize = 10;
+        }
+        return pageSize;
+    }
+
+    /**
+     * get 排序方式
+     */
+    public int getKeySortType() {
+        return getInt("sortType");
+    }
+
+
+    // ============================= 工具方法 =============================
+
+
+    /**
+     * 将一个一维集合转换为树形集合
+     *
+     * @param list         集合
+     * @param idKey        id标识key
+     * @param parentIdKey  父id标识key
+     * @param childListKey 子节点标识key
+     * @return 转换后的tree集合
+     */
+    public static List<SoMap> listToTree(List<SoMap> list, String idKey, String parentIdKey, String childListKey) {
+        // 声明新的集合,存储tree形数据
+        List<SoMap> newTreeList = new ArrayList<>();
+        // 声明hash-Map,方便查找数据
+        SoMap hash = new SoMap();
+        // 将数组转为Object的形式,key为数组中的id
+        for (SoMap json : list) {
+            hash.put(json.getString(idKey), json);
+        }
+        // 遍历结果集
+        for (SoMap soMap : list) {
+            // 单条记录
+            // 在hash中取出key为单条记录中pid的值
+            SoMap hashVp = (SoMap) hash.get(soMap.get(parentIdKey, "").toString());
+            // 如果记录的pid存在,则说明它有父节点,将她添加到孩子节点的集合中
+            if (hashVp != null) {
+                // 检查是否有child属性,有则添加,没有则新建
+                if (hashVp.get(childListKey) != null) {
+                    @SuppressWarnings("unchecked")
+                    List<SoMap> ch = (List<SoMap>) hashVp.get(childListKey);
+                    ch.add(soMap);
+                    hashVp.put(childListKey, ch);
+                } else {
+                    List<SoMap> ch = new ArrayList<SoMap>();
+                    ch.add(soMap);
+                    hashVp.put(childListKey, ch);
+                }
+            } else {
+                newTreeList.add(soMap);
+            }
+        }
+        return newTreeList;
+    }
+
+
+    /**
+     * 指定字符串的字符串下划线转大写模式
+     */
+    private static String wordEachBig(String str) {
+        StringBuilder newStr = new StringBuilder();
+        for (String s : str.split("_")) {
+            newStr.append(wordFirstBig(s));
+        }
+        return newStr.toString();
+    }
+
+    /**
+     * 返回下划线转小驼峰形式
+     */
+    private static String wordEachBigFs(String str) {
+        return wordFirstSmall(wordEachBig(str));
+    }
+
+    /**
+     * 将指定单词首字母大写
+     */
+    private static String wordFirstBig(String str) {
+        return str.substring(0, 1).toUpperCase() + str.substring(1);
+    }
+
+    /**
+     * 将指定单词首字母小写
+     */
+    private static String wordFirstSmall(String str) {
+        return str.substring(0, 1).toLowerCase() + str.substring(1);
+    }
+
+    /**
+     * 下划线转中划线
+     */
+    private static String wordEachKebabCase(String str) {
+        return str.replaceAll("_", "-");
+    }
+
+    /**
+     * 驼峰转下划线
+     */
+    private static String wordHumpToLine(String str) {
+        return str.replaceAll("[A-Z]", "_$0").toLowerCase();
+    }
+
 
 
 }
 }

+ 1 - 1
iot-common/pom.xml

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

+ 0 - 35
iot-common/src/main/java/cc/iotkit/common/utils/JsonUtil.java

@@ -14,14 +14,8 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.databind.SerializationFeature;
-import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import lombok.SneakyThrows;
 import lombok.SneakyThrows;
 
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 public final class JsonUtil {
 public final class JsonUtil {
 
 
     private final static ObjectMapper MAPPER = new ObjectMapper()
     private final static ObjectMapper MAPPER = new ObjectMapper()
@@ -47,33 +41,4 @@ public final class JsonUtil {
     public static JsonNode parse(String json) {
     public static JsonNode parse(String json) {
         return MAPPER.readTree(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;
-    }
 }
 }

+ 13 - 0
iot-common/src/main/java/cc/iotkit/common/utils/ReflectUtil.java

@@ -38,4 +38,17 @@ public class ReflectUtil {
         BeanUtils.populate(to, map);
         BeanUtils.populate(to, map);
         return to;
         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;
+    }
+
 }
 }

+ 1 - 1
iot-components/iot-component-base/pom.xml

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

+ 8 - 0
iot-components/iot-component-base/src/main/java/cc/iotkit/comp/model/AuthInfo.java

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

+ 12 - 7
iot-components/iot-component-base/src/main/java/cc/iotkit/comp/model/DeviceState.java

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

+ 4 - 23
iot-components/iot-component-base/src/main/java/cc/iotkit/comp/model/RegisterInfo.java

@@ -13,8 +13,8 @@ import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Builder;
 import lombok.Data;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
+import lombok.experimental.FieldNameConstants;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.beanutils.BeanUtils;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
@@ -28,6 +28,7 @@ import java.util.Map;
 @NoArgsConstructor
 @NoArgsConstructor
 @AllArgsConstructor
 @AllArgsConstructor
 @Builder
 @Builder
+@FieldNameConstants
 public class RegisterInfo {
 public class RegisterInfo {
 
 
     private String productKey;
     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
     @Data
     @NoArgsConstructor
     @NoArgsConstructor
     @AllArgsConstructor
     @AllArgsConstructor
+    @Builder
+    @FieldNameConstants
     public static class SubDevice {
     public static class SubDevice {
 
 
         private String productKey;
         private String productKey;

+ 10 - 6
iot-components/iot-component-converter/pom.xml

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

+ 0 - 47
iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/CovertUtils.java

@@ -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
-            }
-        }
-    }
-}

+ 0 - 20
iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/DefaultScriptConvertFactory.java

@@ -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();
-    }
-
-
-}

+ 8 - 0
iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/DeviceMessage.java

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

+ 0 - 70
iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/GraalJsScriptConverter.java

@@ -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);
-    }
-}

+ 0 - 6
iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/IScriptConvertFactory.java

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

+ 49 - 0
iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/JavaScriptConverter.java

@@ -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);
+    }
+}

+ 41 - 0
iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/ScriptConvertFactory.java

@@ -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();
+        }
+    }
+}

+ 0 - 75
iot-components/iot-component-converter/src/main/java/cc/iotkit/converter/ScriptConverter.java

@@ -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);
-    }
-}

+ 3 - 4
iot-components/iot-component-server/pom.xml

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

+ 4 - 0
iot-components/iot-component-server/src/main/java/cc/iotkit/comps/BizComponentManager.java

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

+ 6 - 18
iot-components/iot-component-server/src/main/java/cc/iotkit/comps/DeviceComponentManager.java

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

+ 50 - 91
iot-components/iot-component-server/src/main/java/cc/iotkit/comps/DeviceMessageHandler.java

@@ -9,7 +9,6 @@
  */
  */
 package cc.iotkit.comps;
 package cc.iotkit.comps;
 
 
-import cc.iotkit.common.exception.BizException;
 import cc.iotkit.common.utils.JsonUtil;
 import cc.iotkit.common.utils.JsonUtil;
 import cc.iotkit.common.utils.UniqueIdUtil;
 import cc.iotkit.common.utils.UniqueIdUtil;
 import cc.iotkit.comp.IDeviceComponent;
 import cc.iotkit.comp.IDeviceComponent;
@@ -21,17 +20,13 @@ import cc.iotkit.converter.DeviceMessage;
 import cc.iotkit.comp.model.DeviceState;
 import cc.iotkit.comp.model.DeviceState;
 import cc.iotkit.comps.service.DeviceBehaviourService;
 import cc.iotkit.comps.service.DeviceBehaviourService;
 import cc.iotkit.converter.IConverter;
 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.model.device.message.ThingModelMessage;
+import cc.iotkit.script.IScriptEngine;
+import com.fasterxml.jackson.core.type.TypeReference;
 import lombok.Data;
 import lombok.Data;
 import lombok.SneakyThrows;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 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.Map;
 import java.util.concurrent.*;
 import java.util.concurrent.*;
 import java.util.function.Consumer;
 import java.util.function.Consumer;
@@ -75,76 +70,67 @@ public class DeviceMessageHandler implements IMessageHandler {
         scriptEngine.setScript(script);
         scriptEngine.setScript(script);
     }
     }
 
 
+    @Override
     public void onReceive(Map<String, Object> head, String type, String msg) {
     public void onReceive(Map<String, Object> head, String type, String msg) {
         onReceive(head, type, msg, (r) -> {
         onReceive(head, type, msg, (r) -> {
         });
         });
     }
     }
 
 
+    @Override
     public void onReceive(Map<String, Object> head, String type, String msg, Consumer<ReceiveResult> onResult) {
     public void onReceive(Map<String, Object> head, String type, String msg, Consumer<ReceiveResult> onResult) {
         executorService.submit(() -> {
         executorService.submit(() -> {
             try {
             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);
                     onResult.accept(null);
                     return;
                     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());
-
-                if ("register".equals(rstType)) {
-                    //注册数据
-                    RegisterInfo regInfo = RegisterInfo.from(dataMap);
-                    if (regInfo == null) {
-                        onResult.accept(null);
+                Action action = MessageParser.parse(new Action(), rst.get("action"));
+
+                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;
                         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;
                         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) {
             } 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 {
         try {
             deviceBehaviourService.register(reg);
             deviceBehaviourService.register(reg);
         } catch (Throwable e) {
         } catch (Throwable e) {
             log.error("register error", e);
             log.error("register error", e);
         } finally {
         } finally {
-            invokeMethod("onRegistered", reg, "false");
+            scriptEngine.invokeMethod("onRegistered", reg, "false");
         }
         }
     }
     }
 
 
-    private void doAuth(AuthInfo auth) throws IScriptException {
+    private void doAuth(AuthInfo auth) {
         try {
         try {
             deviceBehaviourService.deviceAuth(auth.getProductKey(),
             deviceBehaviourService.deviceAuth(auth.getProductKey(),
                     auth.getDeviceName(),
                     auth.getDeviceName(),
@@ -173,22 +159,10 @@ public class DeviceMessageHandler implements IMessageHandler {
         } catch (Throwable e) {
         } catch (Throwable e) {
             log.error("device auth error", e);
             log.error("device auth error", e);
         } finally {
         } 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) {
     private void doStateChange(DeviceState state) {
         try {
         try {
             String pk = state.getProductKey();
             String pk = state.getProductKey();
@@ -199,8 +173,6 @@ public class DeviceMessageHandler implements IMessageHandler {
             } else {
             } else {
                 deviceRouter.removeRouter(pk, dn);
                 deviceRouter.removeRouter(pk, dn);
             }
             }
-            // 避免已在线多此发送上线消息
-            if (isOnline == deviceBehaviourService.isOnline(pk, dn)) return;
             component.onDeviceStateChange(state);
             component.onDeviceStateChange(state);
             deviceBehaviourService.deviceStateChange(pk, dn, isOnline);
             deviceBehaviourService.deviceStateChange(pk, dn, isOnline);
         } catch (Throwable e) {
         } catch (Throwable e) {
@@ -226,19 +198,6 @@ public class DeviceMessageHandler implements IMessageHandler {
         deviceBehaviourService.reportMessage(thingModelMessage);
         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) {
     private void doAction(Action action) {
         if (action == null) {
         if (action == null) {
             return;
             return;

+ 0 - 17
iot-components/iot-component-server/src/main/java/cc/iotkit/comps/DeviceMsgScriptResult.java

@@ -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;
-
-}

+ 62 - 0
iot-components/iot-component-server/src/main/java/cc/iotkit/comps/MessageParser.java

@@ -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;
+    }
+
+}

+ 0 - 23
iot-components/iot-component-server/src/main/java/cc/iotkit/comps/config/ComponentConfig.java

@@ -1,14 +1,7 @@
 package cc.iotkit.comps.config;
 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 lombok.Data;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Configuration;
 
 
 import java.nio.file.Path;
 import java.nio.file.Path;
@@ -33,20 +26,4 @@ public class ComponentConfig {
         return Paths.get(converterDir, conId)
         return Paths.get(converterDir, conId)
                 .toAbsolutePath().normalize();
                 .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();
-    }
 }
 }

+ 12 - 10
iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java

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

+ 10 - 11
iot-components/iot-component-tcp/dependency-reduced-pom.xml

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

+ 6 - 7
iot-components/iot-component-tcp/pom.xml

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

+ 1 - 0
iot-components/iot-component-tcp/src/main/java/cc/iotkit/comp/tcp/cilent/TcpClientDeviceComponent.java

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

+ 5 - 28
iot-components/iot-component-tcp/src/main/java/cc/iotkit/comp/tcp/parser/ScriptPayloadParser.java

@@ -1,56 +1,33 @@
 package cc.iotkit.comp.tcp.parser;
 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.buffer.Buffer;
 import io.vertx.core.parsetools.RecordParser;
 import io.vertx.core.parsetools.RecordParser;
-import jdk.nashorn.api.scripting.NashornScriptEngine;
-import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import lombok.SneakyThrows;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import reactor.core.publisher.EmitterProcessor;
 import reactor.core.publisher.EmitterProcessor;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.FluxSink;
 import reactor.core.publisher.FluxSink;
 
 
-import javax.script.ScriptEngineManager;
 import java.util.List;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 import java.util.function.Consumer;
 import java.util.function.Function;
 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
 @Slf4j
 public class ScriptPayloadParser implements PayloadParser {
 public class ScriptPayloadParser implements PayloadParser {
 
 
-
-    private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager())
-            .getEngineByName("nashorn");
+    private final IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
 
 
     @SneakyThrows
     @SneakyThrows
     @Override
     @Override
     public PayloadParser init(Object param) {
     public PayloadParser init(Object param) {
         String script = (String) 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;
         return this;
     }
     }
 
 

+ 0 - 17
iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/DefaultScriptEngineFactory.java

@@ -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();
-    }
-}

+ 0 - 12
iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/IScriptEngine.java

@@ -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;
-
-
-}

+ 0 - 6
iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/IScriptEngineFactory.java

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

+ 0 - 7
iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/IScriptException.java

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

+ 0 - 35
iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/JsGraalJsScriptEngine.java

@@ -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;
-    }
-}

+ 0 - 41
iot-components/iot-components-engine/src/main/java/cc/iotkit/engine/JsNashornScriptEngine.java

@@ -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;
-    }
-}

+ 1 - 1
iot-components/iot-ctwing-component/pom.xml

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

+ 11 - 5
iot-components/iot-emqx-component/dependency-reduced-pom.xml

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

+ 6 - 1
iot-components/iot-emqx-component/pom.xml

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

+ 15 - 11
iot-components/iot-emqx-component/src/main/java/cc/iotkit/comp/emqx/AuthVerticle.java

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

+ 43 - 18
iot-components/iot-emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxDeviceComponent.java

@@ -11,6 +11,7 @@ package cc.iotkit.comp.emqx;
 
 
 import cc.iotkit.common.exception.BizException;
 import cc.iotkit.common.exception.BizException;
 import cc.iotkit.common.utils.JsonUtil;
 import cc.iotkit.common.utils.JsonUtil;
+import cc.iotkit.common.utils.ThreadUtil;
 import cc.iotkit.comp.AbstractDeviceComponent;
 import cc.iotkit.comp.AbstractDeviceComponent;
 import cc.iotkit.comp.CompConfig;
 import cc.iotkit.comp.CompConfig;
 import cc.iotkit.comp.IMessageHandler;
 import cc.iotkit.comp.IMessageHandler;
@@ -36,9 +37,11 @@ import java.lang.reflect.InvocationTargetException;
 import java.nio.charset.Charset;
 import java.nio.charset.Charset;
 import java.util.*;
 import java.util.*;
 import java.util.concurrent.CountDownLatch;
 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 static final Logger log = LoggerFactory.getLogger(EmqxDeviceComponent.class);
     private Vertx vertx;
     private Vertx vertx;
@@ -47,12 +50,17 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
     private String deployedId;
     private String deployedId;
     private EmqxConfig mqttConfig;
     private EmqxConfig mqttConfig;
     private MqttClient client;
     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 Set<String> compMqttClientIdList = new HashSet<>();
 
 
     private final TransparentConverter transparentConverter = new TransparentConverter();
     private final TransparentConverter transparentConverter = new TransparentConverter();
 
 
+    @Override
     public void create(CompConfig config) {
     public void create(CompConfig config) {
         super.create(config);
         super.create(config);
         vertx = Vertx.vertx();
         vertx = Vertx.vertx();
@@ -64,22 +72,33 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
     public void start() {
     public void start() {
         try {
         try {
             compMqttClientIdList.add(mqttConfig.getClientId());
             compMqttClientIdList.add(mqttConfig.getClientId());
-
             authVerticle.setExecutor(getHandler());
             authVerticle.setExecutor(getHandler());
             countDownLatch = new CountDownLatch(1);
             countDownLatch = new CountDownLatch(1);
             Future<String> future = vertx.deployVerticle(authVerticle);
             Future<String> future = vertx.deployVerticle(authVerticle);
             future.onSuccess((s -> {
             future.onSuccess((s -> {
                 deployedId = s;
                 deployedId = s;
                 countDownLatch.countDown();
                 countDownLatch.countDown();
-                log.error("start emqx auth component success");
+                log.info("start emqx auth component success");
             }));
             }));
             future.onFailure((e) -> {
             future.onFailure((e) -> {
                 countDownLatch.countDown();
                 countDownLatch.countDown();
                 log.error("start emqx auth component failed", e);
                 log.error("start emqx auth component failed", e);
             });
             });
-
             countDownLatch.await();
             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()
             MqttClientOptions options = new MqttClientOptions()
                     .setClientId(mqttConfig.getClientId())
                     .setClientId(mqttConfig.getClientId())
                     .setUsername(mqttConfig.getUsername())
                     .setUsername(mqttConfig.getUsername())
@@ -101,14 +120,6 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
                 subscribes.put(topic, 1);
                 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 -> {
             client.publishHandler(p -> {
                 log.info("Client received message on [{}] payload [{}] with QoS [{}]", p.topicName(), p.payload().toString(Charset.defaultCharset()), p.qosLevel());
                 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 -> {
             client.connect(mqttConfig.getPort(), mqttConfig.getBroker(), s -> {
                 if (s.succeeded()) {
                 if (s.succeeded()) {
                     log.info("client connect success.");
                     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 -> {
                     client.subscribe(subscribes, e -> {
                         if (e.succeeded()) {
                         if (e.succeeded()) {
                             log.info("===>subscribe success: {}", e.result());
                             log.info("===>subscribe success: {}", e.result());
@@ -140,14 +160,13 @@ public class EmqxDeviceComponent extends AbstractDeviceComponent {
                     });
                     });
 
 
                 } else {
                 } else {
+                    mqttConnected = false;
                     log.error("client connect fail: ", s.cause());
                     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) {
         } 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();
         authVerticle.stop();
         Future<Void> future = vertx.undeploy(deployedId);
         Future<Void> future = vertx.undeploy(deployedId);
         future.onSuccess(unused -> log.info("stop emqx auth component success"));
         future.onSuccess(unused -> log.info("stop emqx auth component success"));
+
         client.disconnect()
         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"));
                 .onFailure(unused -> log.info("stop emqx component failure"));
+
+        emqxConnectTask.shutdown();
     }
     }
 
 
     @Override
     @Override

+ 14 - 36
iot-components/iot-emqx-component/src/main/java/cc/iotkit/comp/emqx/JsScripter.java

@@ -10,17 +10,14 @@
 package cc.iotkit.comp.emqx;
 package cc.iotkit.comp.emqx;
 
 
 import cc.iotkit.common.thing.ThingService;
 import cc.iotkit.common.thing.ThingService;
-import cc.iotkit.common.utils.JsonUtil;
 import cc.iotkit.model.device.message.ThingModelMessage;
 import cc.iotkit.model.device.message.ThingModelMessage;
 import cc.iotkit.model.product.ProductModel;
 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.Data;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.beanutils.BeanUtils;
-
-import javax.script.ScriptEngineManager;
-import java.util.Map;
 
 
 @Slf4j
 @Slf4j
 @Data
 @Data
@@ -28,48 +25,29 @@ public class JsScripter implements IScripter {
 
 
     private ProductModel model;
     private ProductModel model;
 
 
-    private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn");
-
     private Object scriptObj;
     private Object scriptObj;
 
 
+    private IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
+
     public JsScripter(ProductModel model) {
     public JsScripter(ProductModel model) {
         this.model = model;
         this.model = model;
     }
     }
 
 
+    @SneakyThrows
     @Override
     @Override
     public void setScript(String script) {
     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) {
     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) {
     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);
     }
     }
 }
 }

+ 8 - 0
iot-components/iot-emqx-component/src/main/java/cc/iotkit/comp/emqx/TransparentMsg.java

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

+ 8 - 2
iot-components/iot-http-biz-component/dependency-reduced-pom.xml

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

+ 6 - 1
iot-components/iot-http-biz-component/pom.xml

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

+ 26 - 38
iot-components/iot-http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpBizComponent.java

@@ -12,21 +12,19 @@ package cc.iotkit.comp.biz;
 import cc.iotkit.common.utils.JsonUtil;
 import cc.iotkit.common.utils.JsonUtil;
 import cc.iotkit.comp.CompConfig;
 import cc.iotkit.comp.CompConfig;
 import cc.iotkit.comp.IComponent;
 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.MultiMap;
 import io.vertx.core.Vertx;
 import io.vertx.core.Vertx;
 import io.vertx.core.http.HttpServer;
 import io.vertx.core.http.HttpServer;
 import io.vertx.core.http.HttpServerRequest;
 import io.vertx.core.http.HttpServerRequest;
 import io.vertx.core.http.HttpServerResponse;
 import io.vertx.core.http.HttpServerResponse;
-import io.vertx.core.json.JsonObject;
 import io.vertx.ext.web.Router;
 import io.vertx.ext.web.Router;
 import io.vertx.ext.web.handler.BodyHandler;
 import io.vertx.ext.web.handler.BodyHandler;
-import jdk.nashorn.api.scripting.NashornScriptEngine;
-import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import lombok.Data;
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 
 
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
 import java.util.*;
 import java.util.*;
 
 
 @Data
 @Data
@@ -35,7 +33,7 @@ public class HttpBizComponent implements IComponent {
 
 
     private final Vertx vertx = Vertx.vertx();
     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;
     private Object scriptObj;
 
 
@@ -53,11 +51,7 @@ public class HttpBizComponent implements IComponent {
     public void create(CompConfig config) {
     public void create(CompConfig config) {
         this.id = UUID.randomUUID().toString();
         this.id = UUID.randomUUID().toString();
         this.httpConfig = JsonUtil.parse(config.getOther(), HttpConfig.class);
         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
     @Override
@@ -74,41 +68,35 @@ public class HttpBizComponent implements IComponent {
 
 
                         HttpServerRequest httpRequest = rc.request();
                         HttpServerRequest httpRequest = rc.request();
                         String contentType = httpRequest.headers().get("Content-Type");
                         String contentType = httpRequest.headers().get("Content-Type");
-                        JsonObject responseHeader = new JsonObject();
+                        Map<String, Object> responseHeader = new HashMap<>();
                         if ("application/json".equals(contentType)) {
                         if ("application/json".equals(contentType)) {
                             String bodyStr = rc.getBody().toString();
                             String bodyStr = rc.getBody().toString();
                             Map body = JsonUtil.parse(bodyStr, Map.class);
                             Map body = JsonUtil.parse(bodyStr, Map.class);
                             log.info("request body:{}", bodyStr);
                             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();
                             HttpServerResponse httpServerResponse = rc.response();
                             //设置响应头
                             //设置响应头
-                            responseHeader.getMap().forEach((key, value) -> {
+                            responseHeader.forEach((key, value) -> {
                                 //大写转换
                                 //大写转换
                                 key = key.replaceAll("([A-Z])", "-$1").toLowerCase();
                                 key = key.replaceAll("([A-Z])", "-$1").toLowerCase();
                                 httpServerResponse.putHeader(key, value.toString());
                                 httpServerResponse.putHeader(key, value.toString());
@@ -139,7 +127,7 @@ public class HttpBizComponent implements IComponent {
 
 
     @Override
     @Override
     public void putScriptEnv(String key, Object value) {
     public void putScriptEnv(String key, Object value) {
-        engine.put(key, value);
+        scriptEngine.putScriptEnv(key, value);
     }
     }
 
 
     @Override
     @Override

+ 19 - 0
iot-components/iot-http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpContent.java

@@ -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;
+}

+ 10 - 4
iot-components/iot-mqtt-component/dependency-reduced-pom.xml

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

+ 6 - 1
iot-components/iot-mqtt-component/pom.xml

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

+ 15 - 36
iot-components/iot-mqtt-component/src/main/java/cc/iotkit/comp/mqtt/JsScripter.java

@@ -10,17 +10,14 @@
 package cc.iotkit.comp.mqtt;
 package cc.iotkit.comp.mqtt;
 
 
 import cc.iotkit.common.thing.ThingService;
 import cc.iotkit.common.thing.ThingService;
-import cc.iotkit.common.utils.JsonUtil;
 import cc.iotkit.model.device.message.ThingModelMessage;
 import cc.iotkit.model.device.message.ThingModelMessage;
 import cc.iotkit.model.product.ProductModel;
 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.Data;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.beanutils.BeanUtils;
-
-import javax.script.ScriptEngineManager;
-import java.util.Map;
 
 
 @Slf4j
 @Slf4j
 @Data
 @Data
@@ -28,48 +25,30 @@ public class JsScripter implements IScripter {
 
 
     private ProductModel model;
     private ProductModel model;
 
 
-    private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn");
-
     private Object scriptObj;
     private Object scriptObj;
 
 
+    private IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
+
     public JsScripter(ProductModel model) {
     public JsScripter(ProductModel model) {
         this.model = model;
         this.model = model;
     }
     }
 
 
+    @SneakyThrows
     @Override
     @Override
     public void setScript(String script) {
     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) {
     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) {
     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);
     }
     }
 }
 }

+ 1 - 0
iot-components/iot-mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttDeviceComponent.java

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

+ 3 - 0
iot-components/iot-mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttVerticle.java

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

+ 8 - 0
iot-components/iot-mqtt-component/src/main/java/cc/iotkit/comp/mqtt/TransparentMsg.java

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

+ 87 - 0
iot-components/iot-websocket-component/dependency-reduced-pom.xml

@@ -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>

+ 1 - 1
iot-components/iot-websocket-component/pom.xml

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

+ 5 - 2
iot-components/iot-websocket-component/src/main/java/cc/iotkit/comp/websocket/WebSocketDeviceComponent.java

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

+ 2 - 2
iot-components/pom.xml

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

+ 1 - 1
iot-data/iot-data-cache/pom.xml

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

+ 1 - 1
iot-data/iot-data-service/pom.xml

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

+ 1 - 1
iot-data/iot-es-temporal-service/pom.xml

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

+ 2 - 2
iot-data/iot-model/pom.xml

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

+ 2 - 2
iot-data/iot-rdb-data-service/pom.xml

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

+ 1 - 1
iot-data/iot-td-temporal-service/pom.xml

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

+ 1 - 1
iot-data/iot-temporal-service/pom.xml

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

+ 1 - 1
iot-data/iot-ts-temporal-service/pom.xml

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

+ 1 - 1
iot-data/pom.xml

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

+ 1 - 1
iot-message-bus/iot-message-core/pom.xml

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

+ 1 - 1
iot-message-bus/iot-message-rocketmq/pom.xml

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

+ 1 - 1
iot-message-bus/iot-vertx-event-bus/pom.xml

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

+ 1 - 1
iot-message-bus/pom.xml

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

+ 1 - 1
iot-package/pom.xml

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

+ 15 - 9
iot-rule-engine/pom.xml

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

+ 3 - 1
iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/AlertService.java

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

+ 5 - 6
iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/HttpService.java

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

+ 10 - 25
iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/ScriptService.java

@@ -9,52 +9,37 @@
  */
  */
 package cc.iotkit.ruleengine.action;
 package cc.iotkit.ruleengine.action;
 
 
-import cc.iotkit.common.utils.JsonUtil;
 import cc.iotkit.data.IDeviceInfoData;
 import cc.iotkit.data.IDeviceInfoData;
 import cc.iotkit.model.device.DeviceInfo;
 import cc.iotkit.model.device.DeviceInfo;
 import cc.iotkit.model.device.message.ThingModelMessage;
 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.Data;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 
 
-import javax.script.ScriptEngineManager;
-import java.util.Map;
 
 
 @Slf4j
 @Slf4j
 @Data
 @Data
 public class ScriptService {
 public class ScriptService {
 
 
-    private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager())
-            .getEngineByName("nashorn");
+    private IScriptEngine scriptEngine = ScriptEngineFactory.getScriptEngine("js");
 
 
     private String script;
     private String script;
 
 
-    private ScriptObjectMirror scriptObject;
-
     private IDeviceInfoData deviceInfoData;
     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 {
         try {
-            if (scriptObject == null) {
-                scriptObject = (ScriptObjectMirror) engine.eval("new (function(){" + script + "})()");
-            }
             //取设备信息
             //取设备信息
             DeviceInfo deviceInfo = deviceInfoData.findByDeviceId(msg.getDeviceId());
             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) {
         } catch (Throwable e) {
             log.error("run script error", e);
             log.error("run script error", e);
             return null;
             return null;

+ 3 - 1
iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/kafka/KafkaService.java

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

+ 3 - 1
iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/mqtt/MqttService.java

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

+ 3 - 1
iot-rule-engine/src/main/java/cc/iotkit/ruleengine/action/tcp/TcpService.java

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

+ 28 - 6
iot-components/iot-components-engine/pom.xml → iot-script-engine/pom.xml

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

+ 15 - 0
iot-script-engine/src/main/java/cc/iotkit/script/IScriptEngine.java

@@ -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);
+
+}

+ 76 - 0
iot-script-engine/src/main/java/cc/iotkit/script/JavaScriptEngine.java

@@ -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);
+    }
+
+}

+ 30 - 0
iot-script-engine/src/main/java/cc/iotkit/script/ProcessStringToJsonExample.java

@@ -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);
+    }
+}

+ 43 - 0
iot-script-engine/src/main/java/cc/iotkit/script/ScriptEngineFactory.java

@@ -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();
+        }
+    }
+
+}

+ 7 - 0
iot-script-engine/src/main/java/cc/iotkit/script/ScriptException.java

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

+ 1 - 1
iot-standalone/pom.xml

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

+ 1 - 1
iot-test-tool/iot-test-mqtt/pom.xml

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

+ 2 - 2
iot-test-tool/iot-test-mqtt/src/main/java/cc/iotkit/test/mqtt/Simulator.java

@@ -19,8 +19,8 @@ public class Simulator {
     public static void main(String[] args) throws IOException {
     public static void main(String[] args) throws IOException {
 
 
         if (args.length == 0) {
         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 {
         } else {
             Mqtt.brokerHost = args[0];
             Mqtt.brokerHost = args[0];
         }
         }

+ 1 - 0
iot-test-tool/iot-test-mqtt/src/main/java/cc/iotkit/test/mqtt/performance/ReportTest.java

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

+ 1 - 1
iot-test-tool/pom.xml

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

+ 6 - 2
iot-virtual-device/pom.xml

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

+ 25 - 36
iot-virtual-device/src/main/java/cc/iotkit/virtualdevice/VirtualManager.java

@@ -18,26 +18,23 @@ import cc.iotkit.model.device.DeviceInfo;
 import cc.iotkit.model.device.VirtualDevice;
 import cc.iotkit.model.device.VirtualDevice;
 import cc.iotkit.model.device.VirtualDeviceLog;
 import cc.iotkit.model.device.VirtualDeviceLog;
 import cc.iotkit.model.device.message.ThingModelMessage;
 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.temporal.IVirtualDeviceLogData;
 import cc.iotkit.virtualdevice.trigger.RandomScheduleBuilder;
 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.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.beanutils.BeanUtils;
 import org.quartz.*;
 import org.quartz.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Qualifier;
 
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PostConstruct;
-import javax.script.ScriptEngineManager;
 import java.util.*;
 import java.util.*;
 
 
 @Slf4j
 @Slf4j
 public class VirtualManager {
 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<>();
     private final Map<String, Set<String>> deviceIdToVirtualId = new HashMap<>();
 
 
     @Autowired
     @Autowired
@@ -76,6 +73,7 @@ public class VirtualManager {
     /**
     /**
      * 调用虚拟设备下发
      * 调用虚拟设备下发
      */
      */
+    @SneakyThrows
     public void send(ThingService<?> service) {
     public void send(ThingService<?> service) {
         DeviceInfo deviceInfo = deviceInfoData.findByProductKeyAndDeviceName(service.getProductKey(), service.getDeviceName());
         DeviceInfo deviceInfo = deviceInfoData.findByProductKeyAndDeviceName(service.getProductKey(), service.getDeviceName());
         String deviceId = deviceInfo.getDeviceId();
         String deviceId = deviceInfo.getDeviceId();
@@ -83,10 +81,14 @@ public class VirtualManager {
         //根据设备Id取虚拟设备列表
         //根据设备Id取虚拟设备列表
         Set<String> virtualIds = deviceIdToVirtualId.get(deviceId);
         Set<String> virtualIds = deviceIdToVirtualId.get(deviceId);
         for (String virtualId : virtualIds) {
         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));
             log.info("virtual device send result:{}", JsonUtil.toJsonString(result));
         }
         }
@@ -121,10 +123,11 @@ public class VirtualManager {
                 .logAt(System.currentTimeMillis())
                 .logAt(System.currentTimeMillis())
                 .build();
                 .build();
         try {
         try {
-            Object scriptObj = engine.eval(String.format("new (function () {\n%s})()", virtualDevice.getScript()));
+            IScriptEngine scriptEngine = virtualScripts.get(virtualDevice.getId());
             for (String deviceId : devices) {
             for (String deviceId : devices) {
                 DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
                 DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
-                processReport(invokeMethod(scriptObj, "report", device));
+                processReport(scriptEngine.invokeMethod(new TypeReference<>() {
+                }, "report", device));
             }
             }
         } catch (Throwable e) {
         } catch (Throwable e) {
             virtualDeviceLog.setResult(e.getMessage());
             virtualDeviceLog.setResult(e.getMessage());
@@ -161,7 +164,9 @@ public class VirtualManager {
             log.info("adding virtual device job,id:{},name:{}", id, name);
             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<>();
             List<DeviceInfo> devices = new ArrayList<>();
             for (String deviceId : virtualDevice.getDevices()) {
             for (String deviceId : virtualDevice.getDevices()) {
                 devices.add(deviceInfoData.findByDeviceId(deviceId));
                 devices.add(deviceInfoData.findByDeviceId(deviceId));
@@ -240,44 +245,28 @@ public class VirtualManager {
     /**
     /**
      * 处理js上报方法返回结果
      * 处理js上报方法返回结果
      */
      */
-    public void processReport(Object sourceMsg) {
+    private void processReport(ThingModelMessage modelMessage) {
         try {
         try {
-            ScriptObjectMirror result = (ScriptObjectMirror) sourceMsg;
-            ThingModelMessage modelMessage = new ThingModelMessage();
-            BeanUtils.populate(modelMessage, result);
             deviceBehaviourService.reportMessage(modelMessage);
             deviceBehaviourService.reportMessage(modelMessage);
         } catch (Throwable e) {
         } catch (Throwable e) {
             log.error("process js data error", 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) {
     public void invokeReport(DeviceInfo device, String virtualId) {
         //设备上线
         //设备上线
         deviceOnline(device);
         deviceOnline(device);
 
 
-        Object scriptObj = virtualScripts.get(virtualId);
-        if (scriptObj == null) {
+        IScriptEngine scriptEngine = virtualScripts.get(virtualId);
+        if (scriptEngine == null) {
             return;
             return;
         }
         }
-        processReport(invokeMethod(scriptObj, "report", device));
+        processReport(scriptEngine.invokeMethod(new TypeReference<>() {
+        }, "report", device));
     }
     }
 
 
     /**
     /**

+ 23 - 16
pom.xml

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