Browse Source

通讯组件修改

xiwa 3 years ago
parent
commit
983e857275

+ 5 - 0
dao/src/main/java/cc/iotkit/dao/ProtocolComponentRepository.java

@@ -4,6 +4,11 @@ import cc.iotkit.model.protocol.ProtocolComponent;
 import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 @Repository
 public interface ProtocolComponentRepository extends MongoRepository<ProtocolComponent, String> {
+
+    List<ProtocolComponent> findByState(String state);
+
 }

+ 62 - 89
dao/src/main/java/cc/iotkit/dao/ProtocolConverterRepository.java

@@ -6,6 +6,7 @@ import cc.iotkit.common.utils.ReflectUtil;
 import cc.iotkit.comp.CompConfig;
 import cc.iotkit.comp.mqtt.MqttComponent;
 import cc.iotkit.comps.ComponentManager;
+import cc.iotkit.comps.config.ComponentConfig;
 import cc.iotkit.converter.ScriptConverter;
 import cc.iotkit.dao.ProtocolComponentRepository;
 import cc.iotkit.dao.ProtocolConverterRepository;
@@ -37,11 +38,8 @@ import java.util.UUID;
 @RequestMapping("/protocol")
 public class ProtocolController {
 
-    @Value("${component.dir:./data/components}")
-    private String componentDir;
-
-    @Value("${converter.dir:./data/converters}")
-    private String converterDir;
+    @Autowired
+    private ComponentConfig componentConfig;
 
     @Autowired
     private ProtocolComponentRepository protocolComponentRepository;
@@ -58,16 +56,6 @@ public class ProtocolController {
     @Autowired
     private ComponentManager componentManager;
 
-    private Path getComponentFilePath(String comId) {
-        return Paths.get(String.format("%s/%s", componentDir, comId))
-                .toAbsolutePath().normalize();
-    }
-
-    private Path getConverterFilePath(String conId) {
-        return Paths.get(String.format("%s/%s", converterDir, conId))
-                .toAbsolutePath().normalize();
-    }
-
     @PostMapping("/uploadJar")
     public String uploadJar(@RequestParam("file") MultipartFile file, String id) {
         if (file == null) {
@@ -77,15 +65,11 @@ public class ProtocolController {
         String fileName = StringUtils.cleanPath(file.getOriginalFilename());
         try {
             if (StringUtils.hasLength(id)) {
-                Optional<ProtocolComponent> optComponent = protocolComponentRepository.findById(id);
-                if (!optComponent.isPresent()) {
-                    throw new BizException("the protocol component does not exists");
-                }
-                dataOwnerService.checkOwner(optComponent.get());
+                getAndCheckComponent(id);
             } else {
                 id = UUID.randomUUID().toString();
             }
-            Path jarFilePath = getComponentFilePath(id);
+            Path jarFilePath = componentConfig.getComponentFilePath(id);
             Files.createDirectories(jarFilePath);
             Path targetLocation = jarFilePath.resolve(fileName);
             Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
@@ -101,7 +85,7 @@ public class ProtocolController {
         if (!StringUtils.hasLength(id)) {
             throw new BizException("component id is blank");
         }
-        Path jarPath = getComponentFilePath(id);
+        Path jarPath = componentConfig.getComponentFilePath(id);
         if (!jarPath.resolve(component.getJarFile()).toFile().exists()) {
             throw new BizException("component jar file does not exist");
         }
@@ -125,20 +109,15 @@ public class ProtocolController {
         if (!StringUtils.hasLength(id)) {
             throw new BizException("component id is blank");
         }
-        Path jarPath = getComponentFilePath(id);
+        Path jarPath = componentConfig.getComponentFilePath(id);
         if (!jarPath.resolve(component.getJarFile()).toFile().exists()) {
             throw new BizException("component jar file does not exist");
         }
 
-        Optional<ProtocolComponent> optComponent = protocolComponentRepository.findById(component.getId());
-        if (!optComponent.isPresent()) {
-            throw new BizException("the protocol component does not exists");
-        }
-
-        ProtocolComponent oldComponent = optComponent.get();
+        ProtocolComponent oldComponent = getAndCheckComponent(id);
         component = ReflectUtil.copyNoNulls(component, oldComponent);
-        dataOwnerService.checkOwner(component);
         try {
+            componentManager.deRegister(id);
             protocolComponentRepository.save(component);
         } catch (Throwable e) {
             throw new BizException("add protocol component error", e);
@@ -147,14 +126,9 @@ public class ProtocolController {
 
     @GetMapping("/getComponentScript/{id}")
     public String getComponentScript(@PathVariable("id") String id) {
-        Optional<ProtocolComponent> optComponent = protocolComponentRepository.findById(id);
-        if (!optComponent.isPresent()) {
-            throw new BizException("the component does not exists");
-        }
-        ProtocolComponent component = optComponent.get();
-        dataOwnerService.checkOwner(component);
+        getAndCheckComponent(id);
         try {
-            Path path = getComponentFilePath(id);
+            Path path = componentConfig.getComponentFilePath(id);
             File file = path.resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile();
             return FileUtils.readFileToString(file, "UTF-8");
         } catch (Throwable e) {
@@ -167,28 +141,37 @@ public class ProtocolController {
     public void saveComponentScript(
             @PathVariable("id") String id,
             @RequestBody String script) {
-        Optional<ProtocolComponent> optComponent = protocolComponentRepository.findById(id);
-        if (!optComponent.isPresent()) {
-            throw new BizException("the component does not exists");
-        }
-        ProtocolComponent oldComponent = optComponent.get();
-        dataOwnerService.checkOwner(oldComponent);
+        ProtocolComponent oldComponent = getAndCheckComponent(id);
         try {
-            Path path = getComponentFilePath(id);
+            Path path = componentConfig.getComponentFilePath(id);
             File file = path.resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile();
             script = JsonUtil.parse(script, String.class);
             FileUtils.writeStringToFile(file, script, "UTF-8", false);
+
+            componentManager.deRegister(id);
             protocolComponentRepository.save(oldComponent);
         } catch (Throwable e) {
             throw new BizException("save protocol component script error", e);
         }
     }
 
+    private ProtocolComponent getAndCheckComponent(@PathVariable("id") String id) {
+        Optional<ProtocolComponent> optComponent = protocolComponentRepository.findById(id);
+        if (!optComponent.isPresent()) {
+            throw new BizException("the component does not exists");
+        }
+        ProtocolComponent oldComponent = optComponent.get();
+        dataOwnerService.checkOwner(oldComponent);
+        return oldComponent;
+    }
+
     @PostMapping("/deleteComponent/{id}")
     public void deleteComponent(@PathVariable("id") String id) {
-        dataOwnerService.checkOwner(protocolComponentRepository, id);
+        ProtocolComponent component = getAndCheckComponent(id);
         try {
-            Path path = Paths.get(String.format("%s/%s", componentDir, id))
+            componentManager.deRegister(id);
+
+            Path path = Paths.get(String.format("%s/%s", componentConfig.getComponentDir(), id))
                     .toAbsolutePath().normalize();
             File file = path.toFile();
             try {
@@ -200,7 +183,7 @@ public class ProtocolController {
             } catch (NoSuchFileException e) {
                 log.warn("delete component script error", e);
             }
-            protocolComponentRepository.deleteById(id);
+            protocolComponentRepository.deleteById(component.getId());
         } catch (Throwable e) {
             throw new BizException("delete protocol component error", e);
         }
@@ -212,6 +195,8 @@ public class ProtocolController {
             @PathVariable("page") int page) {
         Page<ProtocolComponent> components = protocolComponentRepository.findAll(
                 PageRequest.of(page - 1, size, Sort.by(Sort.Order.desc("createAt"))));
+        components.getContent().forEach(c -> c.setState(componentManager.isRunning(c.getId()) ?
+                ProtocolComponent.STATE_RUNNING : ProtocolComponent.STATE_STOPPED));
         return new Paging<>(components.getTotalElements(), components.getContent());
     }
 
@@ -240,14 +225,8 @@ public class ProtocolController {
 
     @PostMapping("/saveConverter")
     public void saveConverter(ProtocolConverter converter) {
-        Optional<ProtocolConverter> optConverter = protocolConverterRepository.findById(converter.getId());
-        if (!optConverter.isPresent()) {
-            throw new BizException("the protocol converter does not exists");
-        }
-
-        ProtocolConverter oldConverter = optConverter.get();
+        ProtocolConverter oldConverter = getAndCheckConverter(converter.getId());
         converter = ReflectUtil.copyNoNulls(converter, oldConverter);
-        dataOwnerService.checkOwner(converter);
         try {
             protocolConverterRepository.save(converter);
         } catch (Throwable e) {
@@ -255,16 +234,22 @@ public class ProtocolController {
         }
     }
 
-    @GetMapping("/getConverterScript/{id}")
-    public String getConverterScript(@PathVariable("id") String id) {
+    private ProtocolConverter getAndCheckConverter(String id) {
         Optional<ProtocolConverter> optConverter = protocolConverterRepository.findById(id);
         if (!optConverter.isPresent()) {
-            throw new BizException("the converter does not exists");
+            throw new BizException("the protocol converter does not exists");
         }
+
         ProtocolConverter converter = optConverter.get();
         dataOwnerService.checkOwner(converter);
+        return converter;
+    }
+
+    @GetMapping("/getConverterScript/{id}")
+    public String getConverterScript(@PathVariable("id") String id) {
+        getAndCheckConverter(id);
         try {
-            Path path = getConverterFilePath(id);
+            Path path = componentConfig.getConverterFilePath(id);
             File file = path.resolve(ProtocolConverter.SCRIPT_FILE_NAME).toFile();
             return FileUtils.readFileToString(file, "UTF-8");
         } catch (Throwable e) {
@@ -277,14 +262,9 @@ public class ProtocolController {
     public void saveConverterScript(
             @PathVariable("id") String id,
             @RequestBody String script) {
-        Optional<ProtocolConverter> optConverter = protocolConverterRepository.findById(id);
-        if (!optConverter.isPresent()) {
-            throw new BizException("the converter does not exists");
-        }
-        ProtocolConverter oldConverter = optConverter.get();
-        dataOwnerService.checkOwner(oldConverter);
+        getAndCheckConverter(id);
         try {
-            Path path = getConverterFilePath(id);
+            Path path = componentConfig.getConverterFilePath(id);
             File file = path.resolve(ProtocolConverter.SCRIPT_FILE_NAME).toFile();
             script = JsonUtil.parse(script, String.class);
             FileUtils.writeStringToFile(file, script, "UTF-8", false);
@@ -295,9 +275,9 @@ public class ProtocolController {
 
     @PostMapping("/deleteConverter/{id}")
     public void deleteConverter(@PathVariable("id") String id) {
-        dataOwnerService.checkOwner(protocolConverterRepository, id);
+        getAndCheckConverter(id);
         try {
-            Path path = Paths.get(String.format("%s/%s", componentDir, id))
+            Path path = Paths.get(String.format("%s/%s", componentConfig.getConverterDir(), id))
                     .toAbsolutePath().normalize();
             File file = path.toFile();
             try {
@@ -315,28 +295,21 @@ public class ProtocolController {
         }
     }
 
-    @PostMapping("/component/{id}/{state}")
-    public void startComponent(@PathVariable("id") String id,
-                               @PathVariable("state") String state) {
-        
-    }
-
-
-    @GetMapping("/registerMqtt")
-    public void registerMqtt() throws IOException {
-        MqttComponent component = new MqttComponent();
-        component.create(new CompConfig(300, "{\"port\":2883,\"ssl\":false}"));
-        ScriptConverter converter = new ScriptConverter();
-        converter.setScript(FileUtils.readFileToString(new File("/Users/sjg/home/gitee/open-source/converter.js"), "UTF-8"));
-        component.setConverter(converter);
-        componentManager.register("123", component);
-        componentManager.start("123", FileUtils.readFileToString(new File("/Users/sjg/home/gitee/open-source/component.js"), "UTF-8"));
-    }
-
-    @GetMapping("/deregisterMqtt")
-    public void deregisterMqtt() {
-        componentManager.stop("123");
-        componentManager.deRegister("123");
+    @PostMapping("/component/{id}/state/{state}")
+    public void changeComponentState(@PathVariable("id") String id,
+                                     @PathVariable("state") String state) {
+        ProtocolComponent component = getAndCheckComponent(id);
+        String converterId = component.getConverter();
+        getAndCheckConverter(converterId);
+        if (ProtocolComponent.STATE_RUNNING.equals(state)) {
+            componentManager.register(component);
+            componentManager.start(component.getId());
+            component.setState(ProtocolComponent.STATE_RUNNING);
+        } else {
+            componentManager.deRegister(id);
+            component.setState(ProtocolComponent.STATE_STOPPED);
+        }
+        protocolComponentRepository.save(component);
     }
 
 }

+ 4 - 4
model/src/main/java/cc/iotkit/model/protocol/ProtocolConverter.java

@@ -16,12 +16,12 @@ import java.nio.charset.Charset;
 @Slf4j
 public class ComponentClassLoader {
 
-    protected Class<IComponent> findClass(String name) throws ClassNotFoundException {
+    protected static Class<IComponent> findClass(String name) throws ClassNotFoundException {
         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
         return (Class<IComponent>) classLoader.loadClass(name);
     }
 
-    private String addUrl(File jarPath) throws NoSuchMethodException, InvocationTargetException,
+    private static String addUrl(File jarPath) throws NoSuchMethodException, InvocationTargetException,
             IllegalAccessException, IOException {
         URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
         Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
@@ -35,9 +35,9 @@ public class ComponentClassLoader {
         return StreamUtils.copyToString(is, Charset.forName("UTF-8"));
     }
 
-    public IComponent getComponent(File jarPath) {
+    public static IComponent getComponent(File jarFile) {
         try {
-            String className = addUrl(jarPath);
+            String className = addUrl(jarFile);
             Class<IComponent> componentClass = findClass(className);
             return componentClass.newInstance();
         } catch (Throwable e) {

+ 72 - 2
protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentManager.java

@@ -3,18 +3,30 @@ package cc.iotkit.comps;
 
 import cc.iotkit.common.exception.BizException;
 import cc.iotkit.common.utils.JsonUtil;
+import cc.iotkit.comp.CompConfig;
 import cc.iotkit.comp.IComponent;
 import cc.iotkit.comps.config.CacheKey;
+import cc.iotkit.comps.config.ComponentConfig;
 import cc.iotkit.comps.service.DeviceBehaviourService;
 import cc.iotkit.converter.DeviceMessage;
+import cc.iotkit.converter.ScriptConverter;
 import cc.iotkit.converter.ThingService;
+import cc.iotkit.dao.ProtocolComponentRepository;
 import cc.iotkit.model.device.message.ThingModelMessage;
+import cc.iotkit.model.protocol.ProtocolComponent;
+import cc.iotkit.model.protocol.ProtocolConverter;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.PostConstruct;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
@@ -23,31 +35,84 @@ import java.util.concurrent.TimeUnit;
 public class ComponentManager {
 
     private final Map<String, IComponent> components = new HashMap<>();
+    private final Map<String, String> scripts = new HashMap<>();
+    private final Map<String, Boolean> states = new HashMap<>();
 
     @Autowired
     private DeviceBehaviourService deviceBehaviourService;
     @Autowired
     private StringRedisTemplate redisTemplate;
+    @Autowired
+    private ComponentConfig componentConfig;
+    @Autowired
+    private ProtocolComponentRepository componentRepository;
+
+    @PostConstruct
+    public void init() {
+        List<ProtocolComponent> componentList = componentRepository.findByState(ProtocolComponent.STATE_RUNNING);
+        for (ProtocolComponent component : componentList) {
+            register(component);
+            start(component.getId());
+        }
+    }
+
+    public void register(ProtocolComponent component) {
+        String id = component.getId();
+        if (components.containsKey(id)) {
+            return;
+        }
 
-    public void register(String id, IComponent component) {
+        Path path = componentConfig.getComponentFilePath(id);
+        File file = path.resolve(component.getJarFile()).toAbsolutePath().toFile();
+        IComponent componentInstance = ComponentClassLoader.getComponent(file);
+        if (componentInstance == null) {
+            throw new BizException("instance component failed");
+        }
+        componentInstance.create(new CompConfig(300, component.getConfig()));
+
+        try {
+            ScriptConverter scriptConverter = new ScriptConverter();
+            Path converterPath = componentConfig.getConverterFilePath(component.getConverter());
+            String converterScript = FileUtils.readFileToString(converterPath.
+                    resolve(ProtocolConverter.SCRIPT_FILE_NAME).toFile(), "UTF-8");
+
+            scriptConverter.setScript(converterScript);
+            componentInstance.setConverter(scriptConverter);
+
+            String componentScript = FileUtils.readFileToString(path.
+                    resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile(), "UTF-8");
+            register(id, componentInstance, componentScript);
+        } catch (IOException e) {
+            throw new BizException("get component script error", e);
+        }
+    }
+
+    public void register(String id, IComponent component, String script) {
         components.put(id, component);
+        scripts.put(id, script);
+        states.put(id, false);
     }
 
     public void deRegister(String id) {
         IComponent component = components.remove(id);
+        scripts.remove(id);
+        states.remove(id);
+        component.stop();
         component.destroy();
     }
 
-    public void start(String id, String script) {
+    public void start(String id) {
         IComponent component = components.get(id);
         if (component == null) {
             return;
         }
+        String script = scripts.get(id);
         component.setHandler(
                 new MessageHandler(this, component,
                         script, component.getConverter(),
                         deviceBehaviourService));
         component.start();
+        states.put(id, true);
     }
 
     public void stop(String id) {
@@ -56,6 +121,11 @@ public class ComponentManager {
             return;
         }
         component.stop();
+        states.put(id, false);
+    }
+
+    public boolean isRunning(String id) {
+        return states.containsKey(id) && states.get(id);
     }
 
     public void send(ThingService<?> service) {

+ 13 - 6
protocol-gateway/component-server/src/main/java/cc/iotkit/comps/MessageHandler.java

@@ -48,12 +48,12 @@ public class MessageHandler implements IMessageHandler {
         this.component = component;
         this.converter = converter;
         this.deviceBehaviourService = deviceBehaviourService;
-        scriptObj = engine.eval(script);
+        scriptObj = engine.eval(String.format("new (function () {\n%s})()", script));
     }
 
     public ReceiveResult onReceive(Map<String, Object> head, String type, String msg) {
         try {
-            ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeMethod(scriptObj, "onReceive", head, type, msg);
+            ScriptObjectMirror result = (ScriptObjectMirror) invokeMethod("onReceive", head, type, msg);
             log.info("onReceive script result:{}", JsonUtil.toJsonString(result));
             Object rstType = result.get("type");
             if (rstType == null) {
@@ -107,10 +107,10 @@ public class MessageHandler implements IMessageHandler {
     private void doRegister(RegisterInfo reg) throws ScriptException, NoSuchMethodException {
         try {
             deviceBehaviourService.register(reg);
-            engine.invokeMethod(scriptObj, "onRegistered", reg, "true");
         } catch (Throwable e) {
             log.error("register error", e);
-            engine.invokeMethod(scriptObj, "onRegistered", reg, "false");
+        } finally {
+            invokeMethod("onRegistered", reg, "false");
         }
     }
 
@@ -120,13 +120,20 @@ public class MessageHandler implements IMessageHandler {
                     auth.getDeviceName(),
                     auth.getProductSecret(),
                     auth.getDeviceSecret());
-            engine.invokeMethod(scriptObj, "onAuthed", auth, true);
         } catch (Throwable e) {
             log.error("device auth error", e);
-            engine.invokeMethod(scriptObj, "onAuthed", auth, false);
+        } finally {
+            invokeMethod("onAuthed", auth, "false");
         }
     }
 
+    private Object invokeMethod(String name, Object... args) throws ScriptException, NoSuchMethodException {
+        if (((ScriptObjectMirror) scriptObj).get(name) != null) {
+            return engine.invokeMethod(scriptObj, name, args);
+        }
+        return null;
+    }
+
     private void doStateChange(DeviceState state) {
         try {
             component.onDeviceStateChange(state);

+ 29 - 0
protocol-gateway/component-server/src/main/java/cc/iotkit/comps/config/ComponentConfig.java

@@ -0,0 +1,29 @@
+package cc.iotkit.comps.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+@Configuration
+@Data
+public class ComponentConfig {
+
+    @Value("${component.dir:./data/components}")
+    private String componentDir;
+
+    @Value("${converter.dir:./data/converters}")
+    private String converterDir;
+
+    public Path getComponentFilePath(String comId) {
+        return Paths.get(componentDir, comId)
+                .toAbsolutePath().normalize();
+    }
+
+    public Path getConverterFilePath(String conId) {
+        return Paths.get(converterDir, conId)
+                .toAbsolutePath().normalize();
+    }
+}

+ 1 - 1
protocol-gateway/converter/src/main/java/cc/iotkit/converter/ScriptConverter.java

@@ -21,7 +21,7 @@ public class ScriptConverter implements IConverter {
 
     public void setScript(String script) {
         try {
-            scriptObj = engine.eval(script);
+            scriptObj = engine.eval(String.format("new (function () {\n%s})()", script));
         } catch (ScriptException e) {
             log.error("eval converter script error", e);
         }

+ 0 - 0
protocol-gateway/emqx-component/dependency-reduced-pom.xml