Forráskód Böngészése

组件脚本-添加脚本类型js,graaljs

jay 2 éve
szülő
commit
b84d4789c8

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

@@ -0,0 +1,20 @@
+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();
+    }
+
+
+}

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

@@ -1,16 +0,0 @@
-package cc.iotkit.converter;
-
-public class ScriptConvertFactory implements IScriptConvertFactory{
-
-    @Override
-    public IConverter getCovert(String name) {
-        if (name.endsWith("graaljs")){
-            return new GraalJsScriptConverter();
-        }
-
-        // 默认是NashornScript js实现方式
-        return new ScriptConverter();
-    }
-
-
-}

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

@@ -25,6 +25,9 @@ import cc.iotkit.data.IDeviceInfoData;
 import cc.iotkit.data.IProductData;
 import cc.iotkit.data.IProtocolComponentData;
 import cc.iotkit.data.IProtocolConverterData;
+import cc.iotkit.engine.IScriptEngine;
+import cc.iotkit.engine.IScriptEngineFactory;
+import cc.iotkit.engine.JsNashornScriptEngine;
 import cc.iotkit.model.device.DeviceInfo;
 import cc.iotkit.model.device.message.ThingModelMessage;
 import cc.iotkit.model.product.Product;
@@ -75,8 +78,14 @@ public class DeviceComponentManager {
 
     private final IScriptConvertFactory scriptConverterFactory;
 
-    public DeviceComponentManager(IScriptConvertFactory scriptConverterFactory) {
+    private final IScriptEngineFactory scriptEngineFactory;
+
+    private  IScriptEngine scriptEngine;
+
+    public DeviceComponentManager(IScriptConvertFactory scriptConverterFactory,
+                                  IScriptEngineFactory scriptEngineFactory ) {
         this.scriptConverterFactory = scriptConverterFactory;
+        this.scriptEngineFactory = scriptEngineFactory;
     }
 
     @PostConstruct
@@ -112,10 +121,11 @@ public class DeviceComponentManager {
         try {
             setScriptConvert(component, componentInstance);
 
+            scriptEngine = scriptEngineFactory.getScriptEngine(component.getScriptTyp());
+
             String componentScript = FileUtils.readFileToString(path.
                     resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile(), "UTF-8");
             componentInstance.setScript(componentScript);
-
             register(id, componentInstance);
         } catch (IOException e) {
             throw new BizException("get device component script error", e);
@@ -126,12 +136,12 @@ public class DeviceComponentManager {
         ProtocolConverter protocolConvert = protocolConverterData.findById(component.getConverter());
 
         IConverter scriptConverter = scriptConverterFactory.getCovert(protocolConvert.getTyp());
-
+        // 从文件方式内容
         Path converterPath = componentConfig.getConverterFilePath(component.getConverter());
         String converterScript = FileUtils.readFileToString(converterPath.
                 resolve(ProtocolConverter.SCRIPT_FILE_NAME).toFile(), "UTF-8");
 
-//        scriptConverter.setScript(protocolConvert.getScript());
+//        scriptConverter.setScript(protocolConvert.getScript());  // 从数据库加载,以后可以加版本号
         scriptConverter.setScript(converterScript);
         scriptConverter.putScriptEnv("component", componentInstance);
         componentInstance.setConverter(scriptConverter);
@@ -157,8 +167,12 @@ public class DeviceComponentManager {
         if (component == null) {
             return;
         }
+
+
+
         DeviceMessageHandler messageHandler = new DeviceMessageHandler(
                 this, component,
+                 scriptEngine,
                 component.getScript(), component.getConverter(),
                 deviceBehaviourService, deviceRouter);
         messageHandler.putScriptEnv("apiTool", new ApiTool());

+ 2 - 1
iot-components/iot-component-server/src/main/java/cc/iotkit/comps/DeviceMessageHandler.java

@@ -60,6 +60,7 @@ public class DeviceMessageHandler implements IMessageHandler {
     @SneakyThrows
     public DeviceMessageHandler(DeviceComponentManager deviceComponentManager,
                                 IDeviceComponent component,
+                                IScriptEngine scriptEngine,
                                 String script, IConverter converter,
                                 DeviceBehaviourService deviceBehaviourService,
                                 DeviceRouter deviceRouter
@@ -69,7 +70,7 @@ public class DeviceMessageHandler implements IMessageHandler {
         this.converter = converter;
         this.deviceBehaviourService = deviceBehaviourService;
         this.deviceRouter = deviceRouter;
-        this.scriptEngine = new JsNashornScriptEngine();
+        this.scriptEngine = scriptEngine;
         scriptEngine.putScriptEnv("component", component);
         scriptEngine.setScript(script);
     }

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

@@ -1,9 +1,9 @@
 package cc.iotkit.comps.config;
 
-import cc.iotkit.converter.GraalJsScriptConverter;
-import cc.iotkit.converter.IConverter;
 import cc.iotkit.converter.IScriptConvertFactory;
-import cc.iotkit.converter.ScriptConvertFactory;
+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;
@@ -42,7 +42,11 @@ public class ComponentConfig {
 
     @Bean
     public IScriptConvertFactory scriptConverterFactory(){
-        return new ScriptConvertFactory();
+        return new DefaultScriptConvertFactory();
     }
 
+    @Bean
+    public IScriptEngineFactory scriptEngineFactory(){
+        return new DefaultScriptEngineFactory();
+    }
 }

+ 4 - 0
iot-components/iot-components-engine/pom.xml

@@ -33,6 +33,10 @@
             <artifactId>js-scriptengine</artifactId>
 
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
     </dependencies>
 
 </project>

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

@@ -0,0 +1,17 @@
+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();
+    }
+}

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

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

+ 178 - 0
iot-components/iot-mqtt-component/src/main/resources/graaljs-converter.js

@@ -0,0 +1,178 @@
+
+var mid=1;
+
+function getMid(){
+	mid++;
+	if(mid>10000){
+		mid=1;
+	}
+	return mid+"";
+}
+
+this.decode = function (msg) {
+
+	//对msg进行解析,并返回物模型数据
+	console.log("msg", msg);
+	var content= msg.getContent();
+	console.log("content",content);
+	var topic = content.topic;
+	console.log("topic",topic);
+	var payload = content.get("payload");
+	console.log("payload",payload);
+	var identifier = topic.substring(topic.lastIndexOf("/") + 1);
+
+	//透传上报
+	if(topic.endsWith("/event/rawReport")){
+		var rst= component.transparentDecode(payload.params);
+		if(!rst){
+			return null;
+		}
+		rst.occured=new Date().getTime();
+		rst.time=new Date().getTime();
+		return rst;
+	}
+
+	if (topic.endsWith("/property/post")) {
+		//属性上报
+		return {
+			"mid": msg.getMid(),
+			"productKey": msg.getProductKey(),
+			"deviceName": msg.getDeviceName(),
+			"type":"property",
+			"identifier": "report", //属性上报
+			"occured": new Date().getTime(), //时间戳,设备上的事件或数据产生的本地时间
+			"time": new Date().getTime(), //时间戳,消息上报时间
+			data: payload,
+		};
+	} else if (topic.indexOf("/event/") > 0) {
+		//事件上报
+		return {
+			mid: msg.getMid(),
+			productKey: msg.getProductKey(),
+			deviceName: msg.getDeviceName(),
+			type:"event",
+			identifier: identifier,
+			occured: new Date().getTime(),
+			time: new Date().getTime(),
+			data: payload.params,
+		};
+	}else if(topic.endsWith("/service/property/set_reply")){
+		//属性设置回复
+		return {
+			mid: msg.getMid(),
+			productKey: msg.getProductKey(),
+			deviceName: msg.getDeviceName(),
+			type:"property",
+			identifier: identifier,
+			occured: new Date().getTime(),
+			time: new Date().getTime(),
+			code: payload.code
+		};
+	}else if(topic.endsWith("/config/set_reply")){
+		//设备配置设置回复
+		return {
+			mid: msg.getMid(),
+			productKey: msg.getProductKey(),
+			deviceName: msg.getDeviceName(),
+			type:"config",
+			identifier: "set_reply",
+			occured: new Date().getTime(),
+			time: new Date().getTime(),
+			code: payload.code
+		};
+	}else if(topic.endsWith("/config/get")){
+		//设备配置获取
+		return {
+			mid: msg.getMid(),
+			productKey: msg.getProductKey(),
+			deviceName: msg.getDeviceName(),
+			type:"config",
+			identifier: "get",
+			occured: new Date().getTime(),
+			time: new Date().getTime(),
+			data: {},
+		};
+	} else if (topic.endsWith("_reply")) {
+		//服务回复
+		return {
+			mid: msg.getMid(),
+			productKey: msg.getProductKey(),
+			deviceName: msg.getDeviceName(),
+			type:"service",
+			identifier: identifier,
+			occured: new Date().getTime(),
+			time: new Date().getTime(),
+			code: payload.code,
+			data: payload.data,
+		};
+	}
+	return null;
+};
+
+this.encode = function (service,device) {
+	var deviceMid=getMid();
+	var method="thing.service.";
+	var topic="/sys/"+service.getProductKey()+"/"+service.getDeviceName()+"/c/service/";
+	var params={};
+
+	//透传下发
+	if(device.isTransparent()){
+		var rst=component.transparentEncode(service,device);
+		topic="/sys/"+rst.productKey+"/"+rst.deviceName+"/c/service/rawSend";
+		params.model=rst.content.model;
+		params.deviceName=rst.content.deviceName;
+		params.data=rst.content.data;
+
+		return {
+			productKey:rst.productKey,
+			deviceName:rst.deviceName,
+			mid:rst.mid,
+			content:{
+				topic:topic,
+				payload:JSON.stringify({
+					id:rst.mid,
+					method:method+"rawSend",
+					params:params
+				})
+			}
+		}
+
+	}
+
+	var type=service.getType();
+	var identifier=service.getIdentifier();
+
+	if(type=="property"){
+		method+="property."+identifier;
+		topic+="property/"+identifier;
+	}else if(type=="service"){
+		method+=identifier;
+		topic+=identifier;
+	}else if(type=="config"){
+		//设备配置下发
+		method+=identifier;
+		topic="/sys/"+service.getProductKey()+"/"+service.getDeviceName()+"/c/config/"+identifier;
+	}else if(type="lifetime"){
+		//子设备注销下发
+		method+=identifier;
+		topic="/sys/"+service.getProductKey()+"/"+service.getDeviceName()+"/c/deregister";
+	}
+
+	for(var p in service.getParams()){
+		params[p]=service.getParams()[p];
+	}
+
+	return {
+		productKey:service.getProductKey(),
+		deviceName:service.getDeviceName(),
+		mid:deviceMid,
+		content:{
+			topic:topic,
+			payload:JSON.stringify({
+				id:deviceMid,
+				method:method,
+				params:params
+			})
+		}
+	}
+};

+ 4 - 0
iot-data/iot-model/src/main/java/cc/iotkit/model/protocol/ProtocolComponent.java

@@ -45,4 +45,8 @@ public class ProtocolComponent implements Owned<String> {
 
     private Long createAt;
 
+    private String scriptTyp;
+
+    private String script;
+
 }

+ 6 - 0
iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/TbProtocolComponent.java

@@ -36,4 +36,10 @@ public class TbProtocolComponent {
     private String state;
 
     private Long createAt;
+
+    private String scriptTyp;
+
+    @Column(columnDefinition = "text")//设置映射为text类型
+    private String script;
+
 }

+ 1 - 0
iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/model/TbProtocolConverter.java

@@ -40,6 +40,7 @@ public class TbProtocolConverter {
     private String typ;
 
     // 脚本内容
+    @Column(columnDefinition = "text")//设置映射为text类型
     private String script;
 
 }

+ 27 - 12
iot-standalone/src/main/java/cc/iotkit/manager/controller/ProtocolController.java

@@ -131,26 +131,41 @@ public class ProtocolController {
     }
 
     @GetMapping("/getComponentScript/{id}")
-    public String getComponentScript(@PathVariable("id") String id) {
-        getAndCheckComponent(id);
-        try {
-            File file = getComponentScriptFile(id);
-            return FileUtils.readFileToString(file, "UTF-8");
-        } catch (Throwable e) {
-            log.error("read component script file error", e);
-            return "";
+    public ProtocolComponent getComponentScript(@PathVariable("id") String id) {
+        ProtocolComponent component = getAndCheckComponent(id);
+
+        String script = component.getScript();
+        // 如果数据库里不存在,则从文件中读取脚本
+        if(!StringUtils.hasText(script)){
+            try {
+                File file = getComponentScriptFile(id);
+                script = FileUtils.readFileToString(file, "UTF-8");
+            } catch (Throwable e) {
+                log.error("read converter script file error", e);
+                script = "";
+            }
+            component.setScript(script);
         }
+        return component;
+
     }
 
     @PostMapping("/saveComponentScript/{id}")
     public void saveComponentScript(
             @PathVariable("id") String id,
-            @RequestBody String script) {
-        getAndCheckComponent(id);
+            @RequestBody ProtocolComponent upReq) {
+        ProtocolComponent old = getAndCheckComponent(id);
         try {
+            // 保存到文件
             File file = getComponentScriptFile(id);
-            script = JsonUtil.parse(script, String.class);
+            String script = upReq.getScript();
             FileUtils.writeStringToFile(file, script, "UTF-8", false);
+
+            // 保存到数据库,后续加版本号
+            old.setScript(upReq.getScript());
+            old.setScriptTyp(upReq.getScriptTyp());
+            protocolComponentData.save(old);
+
             componentManager.deRegister(id);
         } catch (Throwable e) {
             throw new BizException("save protocol component script error", e);
@@ -252,7 +267,7 @@ public class ProtocolController {
         ProtocolConverter converter = getAndCheckConverter(id);
         String script = converter.getScript();
         // 如果数据库里不存在,则从文件中读取脚本
-        if(StringUtils.hasText(script)){
+        if(!StringUtils.hasText(script)){
             try {
                 Path path = componentConfig.getConverterFilePath(id);
                 File file = path.resolve(ProtocolConverter.SCRIPT_FILE_NAME).toFile();