diff --git a/common/pom.xml b/common/pom.xml index 8c5784e9..39306785 100755 --- a/common/pom.xml +++ b/common/pom.xml @@ -5,7 +5,7 @@ iotkit-parent cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 @@ -23,6 +23,11 @@ commons-codec + + commons-io + commons-io + + com.fasterxml.jackson.core jackson-core diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentClassLoader.java b/common/src/main/java/cc/iotkit/common/ComponentClassLoader.java old mode 100755 new mode 100644 similarity index 64% rename from protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentClassLoader.java rename to common/src/main/java/cc/iotkit/common/ComponentClassLoader.java index cb875e7b..caf6d999 --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentClassLoader.java +++ b/common/src/main/java/cc/iotkit/common/ComponentClassLoader.java @@ -1,8 +1,4 @@ -package cc.iotkit.comps; - -import cc.iotkit.comp.IComponent; -import lombok.extern.slf4j.Slf4j; -import org.springframework.util.StreamUtils; +package cc.iotkit.common; import java.io.File; import java.io.IOException; @@ -15,13 +11,14 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; -@Slf4j +import org.apache.commons.io.IOUtils; + public class ComponentClassLoader { private static final Map classLoaders = new HashMap<>(); - protected static Class findClass(String name, String clsName) throws ClassNotFoundException { + protected static Class findClass(String name, String clsName) throws ClassNotFoundException { ClassLoader classLoader = classLoaders.get(name); - return (Class) classLoader.loadClass(clsName); + return (Class) classLoader.loadClass(clsName); } private static String addUrl(String name, File jarPath) throws NoSuchMethodException, InvocationTargetException, @@ -42,18 +39,17 @@ public class ComponentClassLoader { URL url = jarPath.toURI().toURL(); method.invoke(classLoader, url); InputStream is = classLoader.getResourceAsStream("component.spi"); - return StreamUtils.copyToString(is, StandardCharsets.UTF_8); - } - - public static IComponent getComponent(String name, File jarFile) { - try { - String className = addUrl(name, jarFile); - Class componentClass = findClass(name, className); - return componentClass.newInstance(); - } catch (Throwable e) { - log.error("instance component from jar error", e); + if (is == null) { return null; } + + return IOUtils.toString(is, StandardCharsets.UTF_8); + } + + public static T getComponent(String name, File jarFile) throws Exception { + String className = addUrl(name, jarFile); + Class componentClass = findClass(name, className); + return componentClass.newInstance(); } } diff --git a/common/src/main/java/cc/iotkit/common/Constants.java b/common/src/main/java/cc/iotkit/common/Constants.java index e5563376..4d951a6a 100755 --- a/common/src/main/java/cc/iotkit/common/Constants.java +++ b/common/src/main/java/cc/iotkit/common/Constants.java @@ -73,4 +73,34 @@ public interface Constants { */ String THING_MODEL_MESSAGE_TOPIC = "device_thing"; + + interface API { + + /** + * 设备-基路径 + */ + String DEVICE_BASE = "/device"; + + /** + * 设备-设备列表 + */ + String DEVICE_LIST = "/list/{size}/{page}"; + + /** + * 设备-设备详情 + */ + String DEVICE_DETAIL = "/{deviceId}/detail"; + + /** + * 设备-属性设置 + */ + String DEVICE_SET_PROPERTIES = "/{deviceId}/service/property/set"; + + /** + * 设备-服务调用 + */ + String DEVICE_INVOKE_SERVICE = "/{deviceId}/service/{service}/invoke"; + + } + } diff --git a/dao/pom.xml b/dao/pom.xml index c01f798b..24fe4e4f 100755 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -5,7 +5,7 @@ iotkit-parent cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 diff --git a/dao/src/main/java/cc/iotkit/dao/ProtocolComponentRepository.java b/dao/src/main/java/cc/iotkit/dao/ProtocolComponentRepository.java index 2da53005..b8d881e3 100755 --- a/dao/src/main/java/cc/iotkit/dao/ProtocolComponentRepository.java +++ b/dao/src/main/java/cc/iotkit/dao/ProtocolComponentRepository.java @@ -11,4 +11,6 @@ public interface ProtocolComponentRepository extends MongoRepository findByState(String state); + List findByStateAndType(String state, String type); + } diff --git a/manager/pom.xml b/manager/pom.xml index 8ce80576..20c62609 100755 --- a/manager/pom.xml +++ b/manager/pom.xml @@ -5,7 +5,7 @@ iotkit-parent cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 diff --git a/manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java b/manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java index 1c67fe5a..1dba73a0 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java @@ -1,10 +1,12 @@ package cc.iotkit.manager.controller; +import cc.iotkit.common.Constants; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.utils.DeviceUtil; import cc.iotkit.common.utils.UniqueIdUtil; import cc.iotkit.comps.service.DeviceBehaviourService; import cc.iotkit.dao.*; +import cc.iotkit.manager.model.query.DeviceQuery; import cc.iotkit.manager.service.DataOwnerService; import cc.iotkit.manager.service.DeviceService; import cc.iotkit.manager.utils.AuthUtil; @@ -52,7 +54,7 @@ public class DeviceController { @Autowired private DeviceBehaviourService behaviourService; - @PostMapping("/{deviceId}/service/{service}") + @PostMapping(Constants.API.DEVICE_INVOKE_SERVICE) public String invokeService(@PathVariable("deviceId") String deviceId, @PathVariable("service") String service, @RequestBody Map args) { @@ -63,7 +65,7 @@ public class DeviceController { return deviceService.invokeService(deviceId, service, args); } - @PostMapping("/{deviceId}/service/property/set") + @PostMapping(Constants.API.DEVICE_SET_PROPERTIES) public String setProperty(@PathVariable("deviceId") String deviceId, @RequestBody Map args) { dataOwnerService.checkWriteRole(); @@ -93,6 +95,39 @@ public class DeviceController { return deviceDao.find(condition, size, page); } + @PostMapping("/list/{size}/{page}") + public Paging getDevices( + @PathVariable("size") int size, + @PathVariable("page") int page, + @RequestBody DeviceQuery query) { + Criteria condition = new Criteria(); + + String uid = AuthUtil.getUserId(); + if (!AuthUtil.isAdmin()) { + //客户端用户使用绑定子用户查询 + if (AuthUtil.isClientUser()) { + condition.and("subUid").elemMatch(new Criteria().is(uid)); + } else { + condition.and("uid").is(uid); + } + } + + String pk = query.getProductKey(); + if (StringUtils.isNotBlank(pk)) { + condition.and("productKey").is(pk); + } + String dn = query.getDeviceName(); + if (StringUtils.isNotBlank(dn)) { + condition.and("deviceName").regex(".*" + dn + ".*"); + } + String state = query.getState(); + if (state != null) { + condition.and("state.online").is(state); + } + + return deviceDao.find(condition, size, page); + } + @PostMapping("/create") public void createDevice(String productKey, String deviceName) { Optional productOpt = productRepository.findById(productKey); @@ -121,7 +156,7 @@ public class DeviceController { .build()))); } - @GetMapping("/{deviceId}") + @GetMapping(Constants.API.DEVICE_DETAIL) public DeviceInfo getDetail(@PathVariable("deviceId") String deviceId) { return dataOwnerService.checkOwner(deviceRepository.findById(deviceId).orElse(new DeviceInfo())); } diff --git a/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java b/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java index 22d7b986..3850cbe0 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java @@ -3,7 +3,7 @@ package cc.iotkit.manager.controller; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.utils.JsonUtil; import cc.iotkit.common.utils.ReflectUtil; -import cc.iotkit.comps.ComponentManager; +import cc.iotkit.comps.DeviceComponentManager; import cc.iotkit.comps.config.ComponentConfig; import cc.iotkit.dao.ProtocolComponentRepository; import cc.iotkit.dao.ProtocolConverterRepository; @@ -50,7 +50,7 @@ public class ProtocolController { private UserInfoRepository userInfoRepository; @Autowired - private ComponentManager componentManager; + private DeviceComponentManager deviceComponentManager; @PostMapping("/uploadJar") public String uploadJar(@RequestParam("file") MultipartFile file, String id) { @@ -113,7 +113,7 @@ public class ProtocolController { ProtocolComponent oldComponent = getAndCheckComponent(id); component = ReflectUtil.copyNoNulls(component, oldComponent); try { - componentManager.deRegister(id); + deviceComponentManager.deRegister(id); protocolComponentRepository.save(component); } catch (Throwable e) { throw new BizException("add protocol component error", e); @@ -144,7 +144,7 @@ public class ProtocolController { script = JsonUtil.parse(script, String.class); FileUtils.writeStringToFile(file, script, "UTF-8", false); - componentManager.deRegister(id); + deviceComponentManager.deRegister(id); } catch (Throwable e) { throw new BizException("save protocol component script error", e); } @@ -164,7 +164,7 @@ public class ProtocolController { public void deleteComponent(@PathVariable("id") String id) { ProtocolComponent component = getAndCheckComponent(id); try { - componentManager.deRegister(id); + deviceComponentManager.deRegister(id); Path path = Paths.get(String.format("%s/%s", componentConfig.getComponentDir(), id)) .toAbsolutePath().normalize(); @@ -190,7 +190,7 @@ public class ProtocolController { @PathVariable("page") int page) { Page components = protocolComponentRepository.findAll( PageRequest.of(page - 1, size, Sort.by(Sort.Order.desc("createAt")))); - components.getContent().forEach(c -> c.setState(componentManager.isRunning(c.getId()) ? + components.getContent().forEach(c -> c.setState(deviceComponentManager.isRunning(c.getId()) ? ProtocolComponent.STATE_RUNNING : ProtocolComponent.STATE_STOPPED)); return new Paging<>(components.getTotalElements(), components.getContent()); } @@ -297,11 +297,11 @@ public class ProtocolController { String converterId = component.getConverter(); getAndCheckConverter(converterId); if (ProtocolComponent.STATE_RUNNING.equals(state)) { - componentManager.register(component); - componentManager.start(component.getId()); + deviceComponentManager.register(component); + deviceComponentManager.start(component.getId()); component.setState(ProtocolComponent.STATE_RUNNING); } else { - componentManager.deRegister(id); + deviceComponentManager.deRegister(id); component.setState(ProtocolComponent.STATE_STOPPED); } protocolComponentRepository.save(component); diff --git a/manager/src/main/java/cc/iotkit/manager/model/query/DeviceQuery.java b/manager/src/main/java/cc/iotkit/manager/model/query/DeviceQuery.java new file mode 100644 index 00000000..118e7434 --- /dev/null +++ b/manager/src/main/java/cc/iotkit/manager/model/query/DeviceQuery.java @@ -0,0 +1,14 @@ +package cc.iotkit.manager.model.query; + +import lombok.Data; + +@Data +public class DeviceQuery { + + private String productKey; + + private String deviceName; + + private String state; + +} diff --git a/manager/src/main/java/cc/iotkit/manager/service/DataOwnerService.java b/manager/src/main/java/cc/iotkit/manager/service/DataOwnerService.java index 8a83e01c..062ffcd2 100755 --- a/manager/src/main/java/cc/iotkit/manager/service/DataOwnerService.java +++ b/manager/src/main/java/cc/iotkit/manager/service/DataOwnerService.java @@ -3,10 +3,13 @@ package cc.iotkit.manager.service; import cc.iotkit.common.exception.BizException; import cc.iotkit.manager.utils.AuthUtil; import cc.iotkit.model.Owned; +import cc.iotkit.model.device.DeviceInfo; import org.apache.commons.lang3.StringUtils; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Service; +import java.util.List; + @Service public class DataOwnerService { @@ -33,10 +36,21 @@ public class DataOwnerService { if (StringUtils.isBlank(data.getUid())) { return data; } - if (AuthUtil.getUserId().equals(data.getUid())) { + + String uid = AuthUtil.getUserId(); + if (uid.equals(data.getUid())) { return data; } + if (data instanceof DeviceInfo) { + DeviceInfo device = (DeviceInfo) data; + //设备子用户验证 + List subUid = device.getSubUid(); + if (subUid != null && subUid.contains(uid)) { + return data; + } + } + throw new BizException("无权限操作"); } diff --git a/manager/src/main/java/cc/iotkit/manager/service/DeviceService.java b/manager/src/main/java/cc/iotkit/manager/service/DeviceService.java index 356950fb..79579f10 100755 --- a/manager/src/main/java/cc/iotkit/manager/service/DeviceService.java +++ b/manager/src/main/java/cc/iotkit/manager/service/DeviceService.java @@ -3,7 +3,7 @@ package cc.iotkit.manager.service; import cc.iotkit.common.exception.NotFoundException; import cc.iotkit.common.exception.OfflineException; import cc.iotkit.common.utils.UniqueIdUtil; -import cc.iotkit.comps.ComponentManager; +import cc.iotkit.comps.DeviceComponentManager; import cc.iotkit.converter.ThingService; import cc.iotkit.dao.DeviceRepository; import cc.iotkit.dao.ThingModelMessageRepository; @@ -24,7 +24,7 @@ public class DeviceService { @Autowired private DataOwnerService dataOwnerService; @Autowired - private ComponentManager componentManager; + private DeviceComponentManager deviceComponentManager; @Autowired private ThingModelService thingModelService; @Autowired @@ -57,7 +57,7 @@ public class DeviceService { .build(); thingModelService.parseParams(thingService); - componentManager.send(thingService); + deviceComponentManager.send(thingService); String mid = thingService.getMid(); //保存设备日志 @@ -103,7 +103,7 @@ public class DeviceService { .build(); thingModelService.parseParams(thingService); - componentManager.send(thingService); + deviceComponentManager.send(thingService); String mid = thingService.getMid(); //保存设备日志 diff --git a/manager/src/main/java/cc/iotkit/manager/utils/AuthUtil.java b/manager/src/main/java/cc/iotkit/manager/utils/AuthUtil.java index 0f604108..9023263c 100755 --- a/manager/src/main/java/cc/iotkit/manager/utils/AuthUtil.java +++ b/manager/src/main/java/cc/iotkit/manager/utils/AuthUtil.java @@ -34,7 +34,11 @@ public class AuthUtil { return AuthUtil.getUserRoles().contains(Constants.ROLE_ADMIN); } - public static boolean hasWriteRole(){ + public static boolean isClientUser() { + return AuthUtil.getUserRoles().contains(Constants.ROLE_CLIENT); + } + + public static boolean hasWriteRole() { return AuthUtil.getUserRoles().contains(Constants.ROLE_WRITE); } diff --git a/model/pom.xml b/model/pom.xml index 1e7c5d40..d5abe3ad 100755 --- a/model/pom.xml +++ b/model/pom.xml @@ -5,9 +5,9 @@ iotkit-parent cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 model diff --git a/model/src/main/java/cc/iotkit/model/device/DeviceInfo.java b/model/src/main/java/cc/iotkit/model/device/DeviceInfo.java index b42f799d..cba31749 100755 --- a/model/src/main/java/cc/iotkit/model/device/DeviceInfo.java +++ b/model/src/main/java/cc/iotkit/model/device/DeviceInfo.java @@ -8,6 +8,7 @@ import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; +import java.util.List; import java.util.Map; @Data @@ -35,6 +36,11 @@ public class DeviceInfo implements Owned { */ private String uid; + /** + * 关联子用户ID列表 + */ + private List subUid; + private State state = new State(); private Map property; diff --git a/model/src/main/java/cc/iotkit/model/protocol/ProtocolComponent.java b/model/src/main/java/cc/iotkit/model/protocol/ProtocolComponent.java index 3d9ab585..eb0f84e6 100755 --- a/model/src/main/java/cc/iotkit/model/protocol/ProtocolComponent.java +++ b/model/src/main/java/cc/iotkit/model/protocol/ProtocolComponent.java @@ -11,6 +11,8 @@ public class ProtocolComponent implements Owned { public static final String STATE_STOPPED = "stopped"; public static final String STATE_RUNNING = "running"; + public static final String TYPE_DEVICE = "device"; + public static final String TYPE_BIZ = "biz"; public static final String SCRIPT_FILE_NAME = "component.js"; @@ -24,6 +26,8 @@ public class ProtocolComponent implements Owned { private String name; + private String type = TYPE_DEVICE; + private String protocol; private String jarFile; diff --git a/pom.xml b/pom.xml index da37389d..ed2ba9dd 100755 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,6 @@ common manager dao - tppa-server protocol-gateway standalone-package @@ -22,7 +21,7 @@ cc.iotkit iotkit-parent - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT iotkit-parent iotkit parent @@ -71,6 +70,12 @@ 1.14 + + org.projectlombok + lombok + 1.18.22 + + com.github.ben-manes.caffeine caffeine @@ -161,19 +166,12 @@ 2.9.1 - org.eclipse.paho org.eclipse.paho.client.mqttv3 1.2.5 - - org.apache.pulsar - pulsar-functions-api - 2.6.0 - - io.vertx vertx-core @@ -192,6 +190,12 @@ 4.2.6 + + io.vertx + vertx-web-client + 4.2.6 + + cc.iotkit model diff --git a/protocol-gateway/component-server/pom.xml b/protocol-gateway/component-server/pom.xml index 2af23c5b..a1a0f1cb 100755 --- a/protocol-gateway/component-server/pom.xml +++ b/protocol-gateway/component-server/pom.xml @@ -5,7 +5,7 @@ protocol-gateway cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/BizComponentManager.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/BizComponentManager.java new file mode 100644 index 00000000..9022c14d --- /dev/null +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/BizComponentManager.java @@ -0,0 +1,113 @@ +package cc.iotkit.comps; + + +import cc.iotkit.common.ComponentClassLoader; +import cc.iotkit.common.exception.BizException; +import cc.iotkit.comp.CompConfig; +import cc.iotkit.comp.IComponent; +import cc.iotkit.comps.config.ComponentConfig; +import cc.iotkit.dao.ProtocolComponentRepository; +import cc.iotkit.model.protocol.ProtocolComponent; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.springframework.beans.factory.annotation.Autowired; +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; + +@Slf4j +@Component +public class BizComponentManager { + + private final Map components = new HashMap<>(); + private final Map states = new HashMap<>(); + + @Autowired + private ComponentConfig componentConfig; + @Autowired + private ProtocolComponentRepository componentRepository; + + @PostConstruct + public void init() { + try { + List componentList = componentRepository + .findByStateAndType(ProtocolComponent.STATE_RUNNING, ProtocolComponent.TYPE_BIZ); + for (ProtocolComponent component : componentList) { + register(component); + start(component.getId()); + } + } catch (Throwable e) { + log.error("init protocol components error", e); + } + } + + public void register(ProtocolComponent component) { + String id = component.getId(); + if (components.containsKey(id)) { + return; + } + + Path path = componentConfig.getComponentFilePath(id); + File file = path.resolve(component.getJarFile()).toAbsolutePath().toFile(); + IComponent componentInstance; + try { + componentInstance = ComponentClassLoader.getComponent(component.getId(), file); + } catch (Throwable e) { + throw new BizException("get component instance error"); + } + componentInstance.create(new CompConfig(300, component.getConfig())); + + try { + 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 component script error", e); + } + } + + public void register(String id, IComponent component) { + components.put(id, component); + states.put(id, false); + } + + public void deRegister(String id) { + IComponent component = components.remove(id); + states.remove(id); + if (component == null) { + return; + } + component.stop(); + component.destroy(); + } + + public void start(String id) { + IComponent component = components.get(id); + if (component == null) { + return; + } + component.start(); + states.put(id, true); + } + + public void stop(String id) { + IComponent component = components.get(id); + if (component == null) { + return; + } + component.stop(); + states.put(id, false); + } + + public boolean isRunning(String id) { + return states.containsKey(id) && states.get(id); + } + +} diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentManager.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/DeviceComponentManager.java old mode 100755 new mode 100644 similarity index 83% rename from protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentManager.java rename to protocol-gateway/component-server/src/main/java/cc/iotkit/comps/DeviceComponentManager.java index ae193199..af9b82cc --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentManager.java +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/DeviceComponentManager.java @@ -1,10 +1,11 @@ package cc.iotkit.comps; +import cc.iotkit.common.ComponentClassLoader; 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.comp.IDeviceComponent; import cc.iotkit.comps.config.CacheKey; import cc.iotkit.comps.config.ComponentConfig; import cc.iotkit.comps.service.DeviceBehaviourService; @@ -32,10 +33,9 @@ import java.util.concurrent.TimeUnit; @Slf4j @Component -public class ComponentManager { +public class DeviceComponentManager { - private final Map components = new HashMap<>(); - private final Map scripts = new HashMap<>(); + private final Map components = new HashMap<>(); private final Map states = new HashMap<>(); @Autowired @@ -68,9 +68,11 @@ public class ComponentManager { Path path = componentConfig.getComponentFilePath(id); File file = path.resolve(component.getJarFile()).toAbsolutePath().toFile(); - IComponent componentInstance = ComponentClassLoader.getComponent(component.getId(), file); - if (componentInstance == null) { - throw new BizException("instance component failed"); + IDeviceComponent componentInstance; + try { + componentInstance = ComponentClassLoader.getComponent(component.getId(), file); + } catch (Throwable e) { + throw new BizException("get device component instance error"); } componentInstance.create(new CompConfig(300, component.getConfig())); @@ -85,21 +87,21 @@ public class ComponentManager { String componentScript = FileUtils.readFileToString(path. resolve(ProtocolComponent.SCRIPT_FILE_NAME).toFile(), "UTF-8"); - register(id, componentInstance, componentScript); + componentInstance.setScript(componentScript); + + register(id, componentInstance); } catch (IOException e) { - throw new BizException("get component script error", e); + throw new BizException("get device component script error", e); } } - public void register(String id, IComponent component, String script) { + public void register(String id, IDeviceComponent component) { 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); + IDeviceComponent component = components.remove(id); states.remove(id); if (component == null) { return; @@ -109,21 +111,20 @@ public class ComponentManager { } public void start(String id) { - IComponent component = components.get(id); + IDeviceComponent component = components.get(id); if (component == null) { return; } - String script = scripts.get(id); component.setHandler( - new MessageHandler(this, component, - script, component.getConverter(), + new DeviceMessageHandler(this, component, + component.getScript(), component.getConverter(), deviceBehaviourService)); component.start(); states.put(id, true); } public void stop(String id) { - IComponent component = components.get(id); + IDeviceComponent component = components.get(id); if (component == null) { return; } @@ -141,7 +142,7 @@ public class ComponentManager { throw new BizException("there is no components"); } - for (IComponent com : components.values()) { + for (IDeviceComponent com : components.values()) { if (com.exist(service.getProductKey(), service.getDeviceName())) { //对下发消息进行编码转换 DeviceMessage message = com.getConverter().encode(service, null); diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/MessageHandler.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/DeviceMessageHandler.java old mode 100755 new mode 100644 similarity index 91% rename from protocol-gateway/component-server/src/main/java/cc/iotkit/comps/MessageHandler.java rename to protocol-gateway/component-server/src/main/java/cc/iotkit/comps/DeviceMessageHandler.java index 07cfd54e..844912af --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/MessageHandler.java +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/DeviceMessageHandler.java @@ -3,7 +3,7 @@ package cc.iotkit.comps; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.utils.JsonUtil; import cc.iotkit.common.utils.UniqueIdUtil; -import cc.iotkit.comp.IComponent; +import cc.iotkit.comp.IDeviceComponent; import cc.iotkit.comp.IMessageHandler; import cc.iotkit.comp.model.AuthInfo; import cc.iotkit.comp.model.ReceiveResult; @@ -22,12 +22,11 @@ import org.apache.commons.beanutils.BeanUtils; import javax.script.ScriptEngineManager; import javax.script.ScriptException; -import java.lang.reflect.InvocationTargetException; import java.util.Map; @Slf4j @Data -public class MessageHandler implements IMessageHandler { +public class DeviceMessageHandler implements IMessageHandler { private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn"); private final Object scriptObj; @@ -36,16 +35,16 @@ public class MessageHandler implements IMessageHandler { private final DeviceBehaviourService deviceBehaviourService; - private final ComponentManager componentManager; + private final DeviceComponentManager deviceComponentManager; - private final IComponent component; + private final IDeviceComponent component; @SneakyThrows - public MessageHandler(ComponentManager componentManager, - IComponent component, - String script, IConverter converter, - DeviceBehaviourService deviceBehaviourService) { - this.componentManager = componentManager; + public DeviceMessageHandler(DeviceComponentManager deviceComponentManager, + IDeviceComponent component, + String script, IConverter converter, + DeviceBehaviourService deviceBehaviourService) { + this.deviceComponentManager = deviceComponentManager; this.component = component; this.converter = converter; this.deviceBehaviourService = deviceBehaviourService; @@ -157,7 +156,7 @@ public class MessageHandler implements IMessageHandler { //服务回复需要重新对应mid if (thingModelMessage.getIdentifier().endsWith("_reply")) { - String platformMid = componentManager.getPlatformMid(message.getDeviceName(), message.getMid()); + String platformMid = deviceComponentManager.getPlatformMid(message.getDeviceName(), message.getMid()); if (platformMid == null) { platformMid = UniqueIdUtil.newRequestId(); } diff --git a/protocol-gateway/component/pom.xml b/protocol-gateway/component/pom.xml index 4086ecf6..85ede8d1 100755 --- a/protocol-gateway/component/pom.xml +++ b/protocol-gateway/component/pom.xml @@ -5,7 +5,7 @@ protocol-gateway cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 diff --git a/protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractComponent.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractDeviceComponent.java old mode 100755 new mode 100644 similarity index 83% rename from protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractComponent.java rename to protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractDeviceComponent.java index 7fd6ebbb..8f2c8caf --- a/protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractComponent.java +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractDeviceComponent.java @@ -7,7 +7,7 @@ import cc.iotkit.converter.IConverter; import lombok.Data; @Data -public abstract class AbstractComponent implements IComponent { +public abstract class AbstractDeviceComponent implements IDeviceComponent { protected IMessageHandler handler; @@ -15,9 +15,11 @@ public abstract class AbstractComponent implements IComponent { protected CompConfig config; + protected String script; + @Override public void create(CompConfig config) { - this.config=config; + this.config = config; } @Override diff --git a/protocol-gateway/component/src/main/java/cc/iotkit/comp/IComponent.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/IComponent.java old mode 100755 new mode 100644 index 7f42d4fe..fba1500d --- a/protocol-gateway/component/src/main/java/cc/iotkit/comp/IComponent.java +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/IComponent.java @@ -1,11 +1,5 @@ package cc.iotkit.comp; -import cc.iotkit.comp.model.AuthInfo; -import cc.iotkit.comp.model.DeviceState; -import cc.iotkit.comp.model.RegisterInfo; -import cc.iotkit.converter.DeviceMessage; -import cc.iotkit.converter.IConverter; - public interface IComponent { void create(CompConfig config); @@ -16,21 +10,9 @@ public interface IComponent { void destroy(); - void onDeviceAuth(AuthInfo authInfo); - - void onDeviceRegister(RegisterInfo info); - - void onDeviceStateChange(DeviceState state); - - void send(DeviceMessage message); - - boolean exist(String productKey, String deviceName); - - void setHandler(IMessageHandler handler); - - void setConverter(IConverter converter); - - IConverter getConverter(); - CompConfig getConfig(); + + void setScript(String script); + + String getScript(); } diff --git a/protocol-gateway/component/src/main/java/cc/iotkit/comp/IDeviceComponent.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/IDeviceComponent.java new file mode 100644 index 00000000..13ece729 --- /dev/null +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/IDeviceComponent.java @@ -0,0 +1,27 @@ +package cc.iotkit.comp; + +import cc.iotkit.comp.model.AuthInfo; +import cc.iotkit.comp.model.DeviceState; +import cc.iotkit.comp.model.RegisterInfo; +import cc.iotkit.converter.DeviceMessage; +import cc.iotkit.converter.IConverter; + +public interface IDeviceComponent extends IComponent { + + void onDeviceAuth(AuthInfo authInfo); + + void onDeviceRegister(RegisterInfo info); + + void onDeviceStateChange(DeviceState state); + + void send(DeviceMessage message); + + boolean exist(String productKey, String deviceName); + + void setHandler(IMessageHandler handler); + + void setConverter(IConverter converter); + + IConverter getConverter(); + +} diff --git a/protocol-gateway/converter/pom.xml b/protocol-gateway/converter/pom.xml index 0dc29b76..e47e47f8 100755 --- a/protocol-gateway/converter/pom.xml +++ b/protocol-gateway/converter/pom.xml @@ -5,7 +5,7 @@ protocol-gateway cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 diff --git a/protocol-gateway/emqx-component/dependency-reduced-pom.xml b/protocol-gateway/emqx-component/dependency-reduced-pom.xml index 7a20b0f0..04482694 100755 --- a/protocol-gateway/emqx-component/dependency-reduced-pom.xml +++ b/protocol-gateway/emqx-component/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ protocol-gateway cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 emqx-component @@ -61,19 +61,19 @@ cc.iotkit model - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT compile cc.iotkit common - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT compile cc.iotkit component - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT compile diff --git a/protocol-gateway/emqx-component/pom.xml b/protocol-gateway/emqx-component/pom.xml index 3e9788b0..679e464d 100755 --- a/protocol-gateway/emqx-component/pom.xml +++ b/protocol-gateway/emqx-component/pom.xml @@ -5,7 +5,7 @@ protocol-gateway cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 diff --git a/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxComponent.java b/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxDeviceComponent.java old mode 100755 new mode 100644 similarity index 97% rename from protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxComponent.java rename to protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxDeviceComponent.java index e1ee27f4..0c66947f --- a/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxComponent.java +++ b/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxDeviceComponent.java @@ -2,7 +2,7 @@ package cc.iotkit.comp.emqx; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.comp.AbstractComponent; +import cc.iotkit.comp.AbstractDeviceComponent; import cc.iotkit.comp.CompConfig; import cc.iotkit.comp.model.DeviceState; import cc.iotkit.converter.DeviceMessage; @@ -20,7 +20,7 @@ import java.util.Map; import java.util.concurrent.CountDownLatch; @Slf4j -public class EmqxComponent extends AbstractComponent { +public class EmqxDeviceComponent extends AbstractDeviceComponent { private Vertx vertx; private AuthVerticle authVerticle; diff --git a/protocol-gateway/emqx-component/src/main/resources/component.spi b/protocol-gateway/emqx-component/src/main/resources/component.spi index 672ee448..6a9c37a6 100755 --- a/protocol-gateway/emqx-component/src/main/resources/component.spi +++ b/protocol-gateway/emqx-component/src/main/resources/component.spi @@ -1 +1 @@ -cc.iotkit.comp.emqx.EmqxComponent \ No newline at end of file +cc.iotkit.comp.emqx.EmqxDeviceComponent \ No newline at end of file diff --git a/tppa-server/pom.xml b/protocol-gateway/http-biz-component/pom.xml old mode 100755 new mode 100644 similarity index 65% rename from tppa-server/pom.xml rename to protocol-gateway/http-biz-component/pom.xml index d93b79d0..42f8acda --- a/tppa-server/pom.xml +++ b/protocol-gateway/http-biz-component/pom.xml @@ -3,13 +3,13 @@ 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"> - iotkit-parent + protocol-gateway cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 - tppa-server + http-biz-component 8 @@ -18,21 +18,27 @@ - - org.springframework.boot - spring-boot-starter-web - - - - cc.iotkit - common - - org.projectlombok lombok + + io.vertx + vertx-web-proxy + + + + io.vertx + vertx-web-client + + + + cc.iotkit + component + + + \ No newline at end of file diff --git a/protocol-gateway/http-biz-component/src/main/java/cc/iotkit/comp/biz/ApiTool.java b/protocol-gateway/http-biz-component/src/main/java/cc/iotkit/comp/biz/ApiTool.java new file mode 100644 index 00000000..3a3f738a --- /dev/null +++ b/protocol-gateway/http-biz-component/src/main/java/cc/iotkit/comp/biz/ApiTool.java @@ -0,0 +1,137 @@ +package cc.iotkit.comp.biz; + +import cc.iotkit.common.Constants; +import io.vertx.core.Vertx; +import io.vertx.core.buffer.Buffer; +import io.vertx.ext.web.client.HttpRequest; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.WebClientOptions; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +/** + * 平台API调用工具类 + */ +public class ApiTool { + + private static final Vertx vertx; + private static final WebClient client; + + static { + if (Vertx.currentContext() == null) { + vertx = Vertx.vertx(); + } else { + vertx = Vertx.currentContext().owner(); + } + + WebClientOptions options = new WebClientOptions() + .setUserAgent("component-api-tool"); + options.setKeepAlive(false); + client = WebClient.create(vertx, options); + } + + private static String host; + private static int port; + private static int timeout; + + public static void config(String host, int port, int timeout) { + ApiTool.host = host; + ApiTool.port = port; + ApiTool.timeout = timeout; + } + + /** + * 获取用户的设备列表 + */ + public static ApiResponse getDevices(String token) { + HttpRequest request = client + .post(port, host, Paths.get(Constants.API.DEVICE_BASE, Constants.API.DEVICE_LIST + .replace("size", "1000") + .replace("page", "1")).toString()) + .timeout(timeout) + .putHeader("authorization", "Bearer " + token); + return sendJson(request, new HashMap<>()); + } + + /** + * 获取设备详情 + */ + public static ApiResponse getDeviceDetail(String token, String deviceId) { + HttpRequest request = client + .post(port, host, Paths.get(Constants.API.DEVICE_BASE, Constants.API.DEVICE_DETAIL + .replace("deviceId", deviceId)).toString()) + .timeout(timeout) + .putHeader("authorization", "Bearer " + token); + return sendJson(request, new HashMap<>()); + } + + /** + * 设置属性 + */ + public static ApiResponse setProperties(String token, String deviceId, Map properties) { + HttpRequest request = client + .post(port, host, Paths.get(Constants.API.DEVICE_BASE, Constants.API.DEVICE_SET_PROPERTIES + .replace("deviceId", deviceId)).toString()) + .timeout(timeout) + .putHeader("authorization", "Bearer " + token); + return sendJson(request, properties); + } + + /** + * 调用服务 + */ + public static ApiResponse invokeService(String token, String deviceId, String service, Map params) { + HttpRequest request = client + .post(port, host, Paths.get(Constants.API.DEVICE_BASE, Constants.API.DEVICE_INVOKE_SERVICE + .replace("deviceId", deviceId) + .replace("service", service)).toString()) + .timeout(timeout) + .putHeader("authorization", "Bearer " + token); + return sendJson(request, params); + } + + private static ApiResponse sendJson(HttpRequest request, Map params) { + AtomicReference apiResponse = new AtomicReference<>(new ApiResponse(500, "", null)); + try { + //转为同步模式便于提供给js调用 + CountDownLatch wait = new CountDownLatch(1); + request.sendJson(params) + .onSuccess((response) -> { + System.out.println(response.bodyAsString()); + apiResponse.set(response.bodyAsJson(ApiResponse.class)); + wait.countDown(); + }) + .onFailure((err) -> { + err.printStackTrace(); + wait.countDown(); + }); + if (wait.await(timeout, TimeUnit.MILLISECONDS)) { + return apiResponse.get(); + } else { + apiResponse.get().setCode(500); + apiResponse.get().setMessage("request timeout"); + } + } catch (Throwable e) { + apiResponse.get().setCode(500); + apiResponse.get().setMessage(e.getMessage()); + } + return apiResponse.get(); + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class ApiResponse { + private int code; + private String message; + private Object data; + } +} diff --git a/protocol-gateway/http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpBizComponent.java b/protocol-gateway/http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpBizComponent.java new file mode 100644 index 00000000..0d694b00 --- /dev/null +++ b/protocol-gateway/http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpBizComponent.java @@ -0,0 +1,134 @@ +package cc.iotkit.comp.biz; + +import cc.iotkit.common.utils.JsonUtil; +import cc.iotkit.comp.CompConfig; +import cc.iotkit.comp.IComponent; +import io.vertx.core.MultiMap; +import io.vertx.core.Vertx; +import io.vertx.core.http.HttpServer; +import io.vertx.core.http.HttpServerResponse; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.handler.BodyHandler; +import jdk.nashorn.api.scripting.NashornScriptEngine; +import jdk.nashorn.api.scripting.ScriptObjectMirror; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +@Data +public class HttpBizComponent implements IComponent { + + private final Vertx vertx = Vertx.vertx(); + + private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn"); + + private Object scriptObj; + + private HttpConfig config; + + private String script; + + private HttpServer backendServer; + + @Override + public void create(CompConfig config) { + this.config = 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); + } + } + + @Override + public void start() { + backendServer = vertx.createHttpServer(); + Router backendRouter = Router.router(vertx); + backendRouter.route().handler(BodyHandler.create()) + .handler(rc -> { + Map httpHeader = getData(rc.request().headers()); + log.info("request header:{}", JsonUtil.toJsonString(httpHeader)); + Map> httpParams = getListData(rc.request().params()); + log.info("request params:{}", JsonUtil.toJsonString(httpParams)); + + String contentType = rc.request().headers().get("Content-Type"); + JsonObject responseHeader = new JsonObject(); + if ("application/json".equals(contentType)) { + String bodyStr = rc.toString(); + Map body = JsonUtil.parse(bodyStr, Map.class); + log.info("request body:{}", bodyStr); + + String response = "unknown error"; + String name = "onReceive"; + if (((ScriptObjectMirror) scriptObj).get(name) != null) { + try { + Object result = engine.invokeMethod(scriptObj, name, body); + Object resultObj = JsonUtil.toObject((ScriptObjectMirror) result); + if (resultObj instanceof Map) { + JsonObject data = JsonObject.mapFrom(resultObj); + responseHeader = data.getJsonObject("header"); + response = data.getString("content"); + } + } catch (Throwable e) { + log.error("invokeMethod onReceive error", e); + response = e.getMessage(); + } + } else { + log.error("required [onReceive] method"); + } + + HttpServerResponse httpServerResponse = rc.response(); + //设置响应头 + responseHeader.getMap().forEach((key, value) -> { + //大写转换 + key = key.replaceAll("([A-Z])", "-$1").toLowerCase(); + httpServerResponse.putHeader(key, value.toString()); + }); + + log.info("response,header:{},content:{}", responseHeader, response); + //设置响应内容 + httpServerResponse + .end(response); + } + }); + + backendServer.requestHandler(backendRouter).listen(config.getPort()); + } + + @Override + public void stop() { + backendServer.close(); + } + + @Override + public void destroy() { + } + + private static Map> getListData(MultiMap multiMap) { + Map> listData = new HashMap<>(); + for (Map.Entry entry : multiMap.entries()) { + String key = entry.getKey(); + Object value = entry.getValue(); + listData.putIfAbsent(key, new ArrayList<>()); + listData.get(key).add(value); + } + return listData; + } + + private static Map getData(MultiMap multiMap) { + Map data = new HashMap<>(); + for (Map.Entry entry : multiMap.entries()) { + data.put(entry.getKey(), entry.getValue()); + } + return data; + } + +} diff --git a/protocol-gateway/http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpConfig.java b/protocol-gateway/http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpConfig.java new file mode 100644 index 00000000..97808c0d --- /dev/null +++ b/protocol-gateway/http-biz-component/src/main/java/cc/iotkit/comp/biz/HttpConfig.java @@ -0,0 +1,10 @@ +package cc.iotkit.comp.biz; + +import lombok.Data; + +@Data +public class HttpConfig { + + private int port; + +} diff --git a/protocol-gateway/http-biz-component/src/main/resources/component.spi b/protocol-gateway/http-biz-component/src/main/resources/component.spi new file mode 100644 index 00000000..90ecd945 --- /dev/null +++ b/protocol-gateway/http-biz-component/src/main/resources/component.spi @@ -0,0 +1 @@ +cc.iotkit.comp.biz.HttpBizComponent \ No newline at end of file diff --git a/protocol-gateway/mqtt-client-simulator/pom.xml b/protocol-gateway/mqtt-client-simulator/pom.xml index 72a6fe2b..980d7a3b 100755 --- a/protocol-gateway/mqtt-client-simulator/pom.xml +++ b/protocol-gateway/mqtt-client-simulator/pom.xml @@ -5,7 +5,7 @@ protocol-gateway cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 mqtt客户端模拟器 diff --git a/protocol-gateway/mqtt-component/dependency-reduced-pom.xml b/protocol-gateway/mqtt-component/dependency-reduced-pom.xml index 71213bd4..cd6986cf 100755 --- a/protocol-gateway/mqtt-component/dependency-reduced-pom.xml +++ b/protocol-gateway/mqtt-component/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ protocol-gateway cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 mqtt-component @@ -73,13 +73,13 @@ cc.iotkit common - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT compile cc.iotkit component - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT compile diff --git a/protocol-gateway/mqtt-component/pom.xml b/protocol-gateway/mqtt-component/pom.xml index 52a9c79d..33c4c0c5 100755 --- a/protocol-gateway/mqtt-component/pom.xml +++ b/protocol-gateway/mqtt-component/pom.xml @@ -5,7 +5,7 @@ protocol-gateway cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 diff --git a/protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttComponent.java b/protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttDeviceComponent.java old mode 100755 new mode 100644 similarity index 94% rename from protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttComponent.java rename to protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttDeviceComponent.java index 0b8a3074..ef5a4adc --- a/protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttComponent.java +++ b/protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttDeviceComponent.java @@ -2,7 +2,7 @@ package cc.iotkit.comp.mqtt; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.comp.AbstractComponent; +import cc.iotkit.comp.AbstractDeviceComponent; import cc.iotkit.comp.CompConfig; import cc.iotkit.comp.model.DeviceState; import cc.iotkit.converter.DeviceMessage; @@ -17,13 +17,13 @@ import java.util.Map; import java.util.concurrent.CountDownLatch; @Slf4j -public class MqttComponent extends AbstractComponent { +public class MqttDeviceComponent extends AbstractDeviceComponent { private Vertx vertx; private CountDownLatch countDownLatch; private String deployedId; private MqttVerticle mqttVerticle; - private Map deviceChildToParent = new HashMap<>(); + private final Map deviceChildToParent = new HashMap<>(); public void create(CompConfig config) { super.create(config); @@ -34,7 +34,6 @@ public class MqttComponent extends AbstractComponent { public void start() { try { - System.out.println("start:======2222222222"); mqttVerticle.setExecutor(getHandler()); countDownLatch = new CountDownLatch(1); Future future = vertx.deployVerticle(mqttVerticle); diff --git a/protocol-gateway/mqtt-component/src/main/resources/component.js b/protocol-gateway/mqtt-component/src/main/resources/component.js index cd505874..9ccd4cf9 100755 --- a/protocol-gateway/mqtt-component/src/main/resources/component.js +++ b/protocol-gateway/mqtt-component/src/main/resources/component.js @@ -1,77 +1,191 @@ !function(n){"use strict";function d(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d((u=d(d(t,n),d(e,u)))<>>32-o,r)}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function c(n,t){var r,e,o,u;n[t>>5]|=128<>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h>5]>>>e%32&255);return t}function a(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e>5]|=(255&n.charCodeAt(e/8))<>>4&15)+r.charAt(15&t);return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return i(c(a(n=r(n)),8*n.length))}function u(n,t){return function(n,t){var r,e=a(n),o=[],u=[];for(o[15]=u[15]=void 0,1610000){ + mid=1; + } + return mid+""; +} + this.decode = function (msg) { //对msg进行解析,并返回物模型数据 - var mqttMsg = JSON.parse(msg.content); - var topic = mqttMsg.topic; - var payload = mqttMsg.payload; + var content=msg.content; + var topic = content.topic; + var payload = content.payload; + var identifier = topic.substring(topic.lastIndexOf("/") + 1); if (topic.endsWith("/property/post")) { - //属性上报 - return { - mid: msg.mid, - productKey: msg.productKey, //可根据消息内容判断填写不同产品 - deviceName: msg.deviceName, - type:"property", - identifier: "report", //属性上报 - occur: new Date().getTime(), //时间戳,设备上的事件或数据产生的本地时间 - time: new Date().getTime(), //时间戳,消息上报时间 - data: payload.params, - }; + //属性上报 + return { + mid: msg.mid, + productKey: msg.productKey, + deviceName: msg.deviceName, + type:"property", + identifier: "report", //属性上报 + occur: new Date().getTime(), //时间戳,设备上的事件或数据产生的本地时间 + time: new Date().getTime(), //时间戳,消息上报时间 + data: payload.params, + }; } else if (topic.indexOf("/event/") > 0) { - var identifier = topic.substring(topic.lastIndexOf("/") + 1); - //事件上报 - return { - mid: msg.mid, - productKey: msg.productKey, - deviceName: msg.deviceName, - type:"event", - identifier: identifier, - occur: new Date().getTime(), - time: new Date().getTime(), - data: payload.params, - }; + //事件上报 + return { + mid: msg.mid, + productKey: msg.productKey, + deviceName: msg.deviceName, + type:"event", + identifier: identifier, + occur: new Date().getTime(), + time: new Date().getTime(), + data: payload.params, + }; + }else if(topic.endsWith("/service/property/set_reply")){ + //属性设置回复 + return { + mid: msg.mid, + productKey: msg.productKey, + deviceName: msg.deviceName, + type:"property", + identifier: identifier, + occur: new Date().getTime(), + time: new Date().getTime(), + code: payload.code + }; } else if (topic.endsWith("_reply")) { - var identifier = topic.substring(topic.lastIndexOf("/") + 1); - //服务回复 - return { - mid: msg.mid, - productKey: msg.productKey, - deviceName: msg.deviceName, - type:"service", - identifier: identifier.replace("_reply", "Reply"), - occur: new Date().getTime(), - time: new Date().getTime(), - code: payload.code, - data: payload.data, - }; + //服务回复 + return { + mid: msg.mid, + productKey: msg.productKey, + deviceName: msg.deviceName, + type:"service", + identifier: identifier, + occur: new Date().getTime(), + time: new Date().getTime(), + code: payload.code, + data: payload.data, + }; } return null; }; + +this.encode = function (service,device) { + var type=service.type; + var identifier=service.identifier; + var topic="/sys/"+service.productKey+"/"+service.deviceName+"/c/service/"; + var method="thing.service."; + + if(type=="property"){ + method+="property."+identifier; + topic+="property/"+identifier; + }else if(type=="service"){ + method+=identifier; + topic+=identifier; + } + var deviceMid=getMid(); + var params={}; + for(var p in service.params){ + params[p]=service.params[p]; + } + + return { + productKey:service.productKey, + deviceName:service.deviceName, + mid:deviceMid, + content:{ + topic:topic, + payload:JSON.stringify({ + id:deviceMid, + method:method, + params:params + }) + } + } +}; \ No newline at end of file diff --git a/protocol-gateway/pom.xml b/protocol-gateway/pom.xml index 81409a9e..8ec9a3c9 100755 --- a/protocol-gateway/pom.xml +++ b/protocol-gateway/pom.xml @@ -5,7 +5,7 @@ iotkit-parent cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 @@ -18,6 +18,7 @@ emqx-component component mqtt-client-simulator + http-biz-component \ No newline at end of file diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index 435630b7..7bec6da0 100755 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -5,7 +5,7 @@ iotkit-parent cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 diff --git a/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceActionService.java b/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceActionService.java index c06f9283..252acda6 100755 --- a/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceActionService.java +++ b/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceActionService.java @@ -1,7 +1,7 @@ package cc.iotkit.ruleengine.action; import cc.iotkit.common.utils.UniqueIdUtil; -import cc.iotkit.comps.ComponentManager; +import cc.iotkit.comps.DeviceComponentManager; import cc.iotkit.converter.ThingService; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; @@ -15,7 +15,7 @@ import java.util.Map; public class DeviceActionService { @Autowired - private ComponentManager componentManager; + private DeviceComponentManager deviceComponentManager; public String invoke(Service service) { String[] pkDn = service.getDevice().split("/"); @@ -25,7 +25,7 @@ public class DeviceActionService { thingService.setDeviceName(pkDn[1]); thingService.setIdentifier(service.getIdentifier()); thingService.setParams(service.parseInputData()); - componentManager.send(thingService); + deviceComponentManager.send(thingService); return thingService.getMid(); } diff --git a/standalone-package/pom.xml b/standalone-package/pom.xml index ca4e4c82..3f884fbb 100755 --- a/standalone-package/pom.xml +++ b/standalone-package/pom.xml @@ -5,7 +5,7 @@ iotkit-parent cc.iotkit - 0.0.1-SNAPSHOT + 0.1.0-SNAPSHOT 4.0.0 diff --git a/tppa-server/README.txt b/tppa-server/README.txt deleted file mode 100755 index 43cd2918..00000000 --- a/tppa-server/README.txt +++ /dev/null @@ -1,8 +0,0 @@ -tppa 即第三方平台接入 - -天猫精灵 -小度 - 发现设备,输入: 小度小度,发现设备 - - -小米 \ No newline at end of file diff --git a/tppa-server/src/main/java/cc/iotkit/tppa/Application.java b/tppa-server/src/main/java/cc/iotkit/tppa/Application.java deleted file mode 100755 index 78c1796f..00000000 --- a/tppa-server/src/main/java/cc/iotkit/tppa/Application.java +++ /dev/null @@ -1,12 +0,0 @@ -package cc.iotkit.tppa; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} diff --git a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/MainController.java b/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/MainController.java deleted file mode 100755 index bc0bd2d9..00000000 --- a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/MainController.java +++ /dev/null @@ -1,53 +0,0 @@ -package cc.iotkit.tppa.xiaodu; - -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.tppa.xiaodu.handler.IRequestHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@Slf4j -@RestController -@RequestMapping("/xiaodu") -public class MainController implements ApplicationContextAware { - - private Pattern requestNamePattern = Pattern.compile(".*\"name\":\"(\\w+)\".*"); - private Map handlerMap = new HashMap<>(); - - - @PostMapping("/receive") - public Object receive(@RequestBody String msg) { - log.info("receive msg:{}", msg); - Matcher matcher = requestNamePattern.matcher(msg); - if (!matcher.matches()) { - return null; - } - - String name = matcher.group(1); - IRequestHandler handler = handlerMap.get(name); - if (handler == null) { - return null; - } - Object response = handler.handle(JsonUtil.parse(msg, handler.getRequestType())); - log.info("response data:{}", JsonUtil.toJsonString(response)); - return response; - } - - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - applicationContext.getBeansOfType(IRequestHandler.class).forEach((name, handler) -> - handlerMap.put(handler.getName(), handler)); - - } -} diff --git a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/handler/DiscoverAppliancesRequestHandler.java b/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/handler/DiscoverAppliancesRequestHandler.java deleted file mode 100755 index 3486bef0..00000000 --- a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/handler/DiscoverAppliancesRequestHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -package cc.iotkit.tppa.xiaodu.handler; - -import cc.iotkit.tppa.xiaodu.request.DiscoverAppliancesRequest; -import cc.iotkit.tppa.xiaodu.request.Header; -import cc.iotkit.tppa.xiaodu.response.DiscoverAppliancesResponse; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - -@Component -public class DiscoverAppliancesRequestHandler implements IRequestHandler { - - @Override - public String getName() { - return "DiscoverAppliancesRequest"; - } - - @Override - public Class getRequestType() { - return DiscoverAppliancesRequest.class; - } - - @Override - public DiscoverAppliancesResponse handle(DiscoverAppliancesRequest request) { - DiscoverAppliancesResponse response = new DiscoverAppliancesResponse(); - response.setHeader(new Header("DuerOS.ConnectedHome.Discovery", - "DiscoverAppliancesResponse", - request.getHeader().getMessageId(), - "1")); - DiscoverAppliancesResponse.Payload payload = new DiscoverAppliancesResponse.Payload(); - response.setPayload(payload); - - List discoveredAppliances = new ArrayList<>(); - discoveredAppliances.add(DiscoverAppliancesResponse.DiscoveredAppliance.builder() - .applianceId("11223344") - .applianceTypes("SWITCH") - .friendlyName("开关") - .isReachable(true) - .friendlyDescription("") - .manufacturerName("奇特") - .modelName("M01") - .version("1.0") - .actions(Arrays.asList("turnOn", "turnOff")) - .attributes(Arrays.asList(new DiscoverAppliancesResponse.Attribute( - "powerstate", - "1", - "", - System.currentTimeMillis() / 1000, - 1000L - ))) - .build()); - payload.setDiscoveredAppliances(discoveredAppliances); - - List discoveredGroups = new ArrayList<>(); - payload.setDiscoveredGroups(discoveredGroups); - discoveredGroups.add(new DiscoverAppliancesResponse.DiscoveredGroup("客厅", - Arrays.asList("11223344"), - "", - new ArrayList() - )); - - return response; - } - -} diff --git a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/handler/IRequestHandler.java b/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/handler/IRequestHandler.java deleted file mode 100755 index 597d470c..00000000 --- a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/handler/IRequestHandler.java +++ /dev/null @@ -1,11 +0,0 @@ -package cc.iotkit.tppa.xiaodu.handler; - -public interface IRequestHandler { - - String getName(); - - Class getRequestType(); - - R handle(T request); - -} diff --git a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/DiscoverAppliancesRequest.java b/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/DiscoverAppliancesRequest.java deleted file mode 100755 index 057f56b6..00000000 --- a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/DiscoverAppliancesRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package cc.iotkit.tppa.xiaodu.request; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Data -public class DiscoverAppliancesRequest { - - private Header header; - - private Payload payload; - - @EqualsAndHashCode(callSuper = true) - @Data - public static class Payload extends PayloadToken { - private String openUid; - } - -} diff --git a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/Header.java b/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/Header.java deleted file mode 100755 index e0e02505..00000000 --- a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/Header.java +++ /dev/null @@ -1,17 +0,0 @@ -package cc.iotkit.tppa.xiaodu.request; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class Header { - - private String namespace; - private String name; - private String messageId; - private String payloadVersion; - -} diff --git a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/PayloadToken.java b/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/PayloadToken.java deleted file mode 100755 index d74bcd4a..00000000 --- a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/PayloadToken.java +++ /dev/null @@ -1,10 +0,0 @@ -package cc.iotkit.tppa.xiaodu.request; - -import lombok.Data; - -@Data -public class PayloadToken { - - protected String accessToken; - -} diff --git a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/TurnOnRequest.java b/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/TurnOnRequest.java deleted file mode 100755 index 8dc3e5ae..00000000 --- a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/request/TurnOnRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package cc.iotkit.tppa.xiaodu.request; - -import lombok.Data; - -@Data -public class TurnOnRequest { - - private Header header; - - -} diff --git a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/response/DiscoverAppliancesResponse.java b/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/response/DiscoverAppliancesResponse.java deleted file mode 100755 index 2cf410b0..00000000 --- a/tppa-server/src/main/java/cc/iotkit/tppa/xiaodu/response/DiscoverAppliancesResponse.java +++ /dev/null @@ -1,128 +0,0 @@ -package cc.iotkit.tppa.xiaodu.response; - -import cc.iotkit.tppa.xiaodu.request.Header; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.ArrayList; -import java.util.List; - -@Data -public class DiscoverAppliancesResponse { - - private Header header; - - private Payload payload; - - @Data - public static class Payload { - private List discoveredAppliances; - /** - * discoveredGroups 对象的数组,该对象包含可发现分组,与用户设备帐户相关联的。 - * 如果没有与用户帐户关联的分组,此属性应包含一个空数组。 - * 如果发生错误,该属性可以为空数组[]。阵列中允许的最大项目数量为10。 - */ - private List discoveredGroups; - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - @Builder - public static class DiscoveredAppliance { - private List actions; - /** - * discoveredAppliance.applianceTypes 支持的设备、场景类型 - */ - private String applianceTypes; - /** - * 设备标识符。标识符在用户拥有的所有设备上必须是唯一的。此外,标识符需要在同一设备的多个发现请求之间保持一致。 - */ - private String applianceId; - /** - * 设备相关的描述,描述内容提需要提及设备厂商,使用场景及连接方式 - */ - private String friendlyDescription; - /** - * 用户用来识别设备的名称 - */ - private String friendlyName; - /** - * 设备当前是否能够到达。true表示设备当前可以到达,false表示当前设备不能到达。 - */ - private boolean isReachable; - /** - * 设备厂商的名字。 - */ - private String manufacturerName; - /** - * 设备型号名称,是字符串类型,长度不能超过128个字符。 - */ - private String modelName; - /** - * 供应商提供的设备版本。是字符串类型,长度不能超过128个字符。 - */ - private String version; - /** - * 设备的属性信息。当设备没有属性信息时,协议中不需要传入该字段。每个设备允许同步的最大的属性数量是10。详细信息请参考设备属性及设备属性上报。 - */ - private List attributes; - /** - * 提供给设备云使用,存放设备或场景相关的附加信息,是键值对。DuerOS不解析或使用这些数据 - */ - private List additionalApplianceDetails=new ArrayList(); - - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class Attribute { - /** - * 属性名称,支持数字、字母和下划线,长度不能超过128个字符。 - */ - private String name; - /** - * 属性值,支持多种json类型。 - */ - private String value; - /** - * 属性值的单位名称,支持数字、字母和下划线,长度不能超过128个字符。 - */ - private String scale; - /** - * 属性值取样的时间戳,单位是秒。 - */ - private Long timestampOfSample; - /** - * 属性值取样的时间误差,单位是ms。如果设备使用的是轮询时间间隔的取样方式,那么uncertaintyInMilliseconds就等于时间间隔。 - * 如温度传感器每1秒取样1次,那么uncertaintyInMilliseconds的值就是1000。 - */ - private Long uncertaintyInMilliseconds; - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class DiscoveredGroup{ - /** - * 用户用来识别分组的名称 - */ - private String groupName; - /** - * 分组所包含设备ID的数组,要求设备ID必须是已经发现的设备中的ID,否则会同步失败 - */ - private List applianceIds; - /** - * 分组备注信息 - */ - private String groupNotes; - /** - * 提供给技能使用的分组相关的附加信息的键值对 - */ - private List additionalGroupDetails; - } - -}