组件调整、增加httpbiz组件、删除第三方接入模块
parent
447e481111
commit
b9d6054198
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>iotkit-parent</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -23,6 +23,11 @@
|
|||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
|
|
|
@ -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<String, URLClassLoader> classLoaders = new HashMap<>();
|
||||
|
||||
protected static Class<IComponent> findClass(String name, String clsName) throws ClassNotFoundException {
|
||||
protected static <T> Class<T> findClass(String name, String clsName) throws ClassNotFoundException {
|
||||
ClassLoader classLoader = classLoaders.get(name);
|
||||
return (Class<IComponent>) classLoader.loadClass(clsName);
|
||||
return (Class<T>) 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<IComponent> 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> T getComponent(String name, File jarFile) throws Exception {
|
||||
String className = addUrl(name, jarFile);
|
||||
Class<T> componentClass = findClass(name, className);
|
||||
return componentClass.newInstance();
|
||||
}
|
||||
|
||||
}
|
|
@ -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";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>iotkit-parent</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -11,4 +11,6 @@ public interface ProtocolComponentRepository extends MongoRepository<ProtocolCom
|
|||
|
||||
List<ProtocolComponent> findByState(String state);
|
||||
|
||||
List<ProtocolComponent> findByStateAndType(String state, String type);
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>iotkit-parent</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -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<String, Object> 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<String, Object> args) {
|
||||
dataOwnerService.checkWriteRole();
|
||||
|
@ -93,6 +95,39 @@ public class DeviceController {
|
|||
return deviceDao.find(condition, size, page);
|
||||
}
|
||||
|
||||
@PostMapping("/list/{size}/{page}")
|
||||
public Paging<DeviceInfo> 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<Product> 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()));
|
||||
}
|
||||
|
|
|
@ -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<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()) ?
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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<String> subUid = device.getSubUid();
|
||||
if (subUid != null && subUid.contains(uid)) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
throw new BizException("无权限操作");
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
//保存设备日志
|
||||
|
|
|
@ -34,6 +34,10 @@ public class AuthUtil {
|
|||
return AuthUtil.getUserRoles().contains(Constants.ROLE_ADMIN);
|
||||
}
|
||||
|
||||
public static boolean isClientUser() {
|
||||
return AuthUtil.getUserRoles().contains(Constants.ROLE_CLIENT);
|
||||
}
|
||||
|
||||
public static boolean hasWriteRole() {
|
||||
return AuthUtil.getUserRoles().contains(Constants.ROLE_WRITE);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
<parent>
|
||||
<artifactId>iotkit-parent</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>model</artifactId>
|
||||
|
|
|
@ -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<String> subUid;
|
||||
|
||||
private State state = new State();
|
||||
|
||||
private Map<String, Object> property;
|
||||
|
|
|
@ -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;
|
||||
|
|
22
pom.xml
22
pom.xml
|
@ -9,7 +9,6 @@
|
|||
<module>common</module>
|
||||
<module>manager</module>
|
||||
<module>dao</module>
|
||||
<module>tppa-server</module>
|
||||
<module>protocol-gateway</module>
|
||||
<module>standalone-package</module>
|
||||
</modules>
|
||||
|
@ -22,7 +21,7 @@
|
|||
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<artifactId>iotkit-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>iotkit-parent</name>
|
||||
<description>iotkit parent</description>
|
||||
<properties>
|
||||
|
@ -71,6 +70,12 @@
|
|||
<version>1.14</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.22</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
|
@ -161,19 +166,12 @@
|
|||
<version>2.9.1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||
<version>1.2.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.pulsar</groupId>
|
||||
<artifactId>pulsar-functions-api</artifactId>
|
||||
<version>2.6.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-core</artifactId>
|
||||
|
@ -192,6 +190,12 @@
|
|||
<version>4.2.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-web-client</artifactId>
|
||||
<version>4.2.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<artifactId>model</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>protocol-gateway</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -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<String, IComponent> components = new HashMap<>();
|
||||
private final Map<String, Boolean> states = new HashMap<>();
|
||||
|
||||
@Autowired
|
||||
private ComponentConfig componentConfig;
|
||||
@Autowired
|
||||
private ProtocolComponentRepository componentRepository;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
try {
|
||||
List<ProtocolComponent> 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String, IComponent> components = new HashMap<>();
|
||||
private final Map<String, String> scripts = new HashMap<>();
|
||||
private final Map<String, IDeviceComponent> components = new HashMap<>();
|
||||
private final Map<String, Boolean> 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);
|
|
@ -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,
|
||||
public DeviceMessageHandler(DeviceComponentManager deviceComponentManager,
|
||||
IDeviceComponent component,
|
||||
String script, IConverter converter,
|
||||
DeviceBehaviourService deviceBehaviourService) {
|
||||
this.componentManager = componentManager;
|
||||
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();
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>protocol-gateway</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -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,6 +15,8 @@ public abstract class AbstractComponent implements IComponent {
|
|||
|
||||
protected CompConfig config;
|
||||
|
||||
protected String script;
|
||||
|
||||
@Override
|
||||
public void create(CompConfig config) {
|
||||
this.config = config;
|
26
protocol-gateway/component/src/main/java/cc/iotkit/comp/IComponent.java
Executable file → Normal file
26
protocol-gateway/component/src/main/java/cc/iotkit/comp/IComponent.java
Executable file → Normal file
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>protocol-gateway</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>protocol-gateway</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>emqx-component</artifactId>
|
||||
|
@ -61,19 +61,19 @@
|
|||
<dependency>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<artifactId>model</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<artifactId>component</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>protocol-gateway</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -1 +1 @@
|
|||
cc.iotkit.comp.emqx.EmqxComponent
|
||||
cc.iotkit.comp.emqx.EmqxDeviceComponent
|
|
@ -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">
|
||||
<parent>
|
||||
<artifactId>iotkit-parent</artifactId>
|
||||
<artifactId>protocol-gateway</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>tppa-server</artifactId>
|
||||
<artifactId>http-biz-component</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
|
@ -18,21 +18,27 @@
|
|||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-web-proxy</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-web-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<artifactId>component</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -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<Buffer> 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<Buffer> 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<String, Object> properties) {
|
||||
HttpRequest<Buffer> 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<String, Object> params) {
|
||||
HttpRequest<Buffer> 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<Buffer> request, Map<String, Object> params) {
|
||||
AtomicReference<ApiResponse> 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;
|
||||
}
|
||||
}
|
|
@ -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<String, Object> httpHeader = getData(rc.request().headers());
|
||||
log.info("request header:{}", JsonUtil.toJsonString(httpHeader));
|
||||
Map<String, List<Object>> 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<String, List<Object>> getListData(MultiMap multiMap) {
|
||||
Map<String, List<Object>> listData = new HashMap<>();
|
||||
for (Map.Entry<String, String> 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<String, Object> getData(MultiMap multiMap) {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
for (Map.Entry<String, String> entry : multiMap.entries()) {
|
||||
data.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package cc.iotkit.comp.biz;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class HttpConfig {
|
||||
|
||||
private int port;
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
cc.iotkit.comp.biz.HttpBizComponent
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>protocol-gateway</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<description>mqtt客户端模拟器</description>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>protocol-gateway</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>mqtt-component</artifactId>
|
||||
|
@ -73,13 +73,13 @@
|
|||
<dependency>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<artifactId>component</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>protocol-gateway</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -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<String, Device> deviceChildToParent = new HashMap<>();
|
||||
private final Map<String, Device> 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<String> future = vertx.deployVerticle(mqttVerticle);
|
|
@ -1,5 +1,41 @@
|
|||
!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)))<<o|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<<t%32,n[14+(t+64>>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h<n.length;h+=16)c=l(r=c,e=f,o=i,u=a,n[h],7,-680876936),a=l(a,c,f,i,n[h+1],12,-389564586),i=l(i,a,c,f,n[h+2],17,606105819),f=l(f,i,a,c,n[h+3],22,-1044525330),c=l(c,f,i,a,n[h+4],7,-176418897),a=l(a,c,f,i,n[h+5],12,1200080426),i=l(i,a,c,f,n[h+6],17,-1473231341),f=l(f,i,a,c,n[h+7],22,-45705983),c=l(c,f,i,a,n[h+8],7,1770035416),a=l(a,c,f,i,n[h+9],12,-1958414417),i=l(i,a,c,f,n[h+10],17,-42063),f=l(f,i,a,c,n[h+11],22,-1990404162),c=l(c,f,i,a,n[h+12],7,1804603682),a=l(a,c,f,i,n[h+13],12,-40341101),i=l(i,a,c,f,n[h+14],17,-1502002290),c=g(c,f=l(f,i,a,c,n[h+15],22,1236535329),i,a,n[h+1],5,-165796510),a=g(a,c,f,i,n[h+6],9,-1069501632),i=g(i,a,c,f,n[h+11],14,643717713),f=g(f,i,a,c,n[h],20,-373897302),c=g(c,f,i,a,n[h+5],5,-701558691),a=g(a,c,f,i,n[h+10],9,38016083),i=g(i,a,c,f,n[h+15],14,-660478335),f=g(f,i,a,c,n[h+4],20,-405537848),c=g(c,f,i,a,n[h+9],5,568446438),a=g(a,c,f,i,n[h+14],9,-1019803690),i=g(i,a,c,f,n[h+3],14,-187363961),f=g(f,i,a,c,n[h+8],20,1163531501),c=g(c,f,i,a,n[h+13],5,-1444681467),a=g(a,c,f,i,n[h+2],9,-51403784),i=g(i,a,c,f,n[h+7],14,1735328473),c=v(c,f=g(f,i,a,c,n[h+12],20,-1926607734),i,a,n[h+5],4,-378558),a=v(a,c,f,i,n[h+8],11,-2022574463),i=v(i,a,c,f,n[h+11],16,1839030562),f=v(f,i,a,c,n[h+14],23,-35309556),c=v(c,f,i,a,n[h+1],4,-1530992060),a=v(a,c,f,i,n[h+4],11,1272893353),i=v(i,a,c,f,n[h+7],16,-155497632),f=v(f,i,a,c,n[h+10],23,-1094730640),c=v(c,f,i,a,n[h+13],4,681279174),a=v(a,c,f,i,n[h],11,-358537222),i=v(i,a,c,f,n[h+3],16,-722521979),f=v(f,i,a,c,n[h+6],23,76029189),c=v(c,f,i,a,n[h+9],4,-640364487),a=v(a,c,f,i,n[h+12],11,-421815835),i=v(i,a,c,f,n[h+15],16,530742520),c=m(c,f=v(f,i,a,c,n[h+2],23,-995338651),i,a,n[h],6,-198630844),a=m(a,c,f,i,n[h+7],10,1126891415),i=m(i,a,c,f,n[h+14],15,-1416354905),f=m(f,i,a,c,n[h+5],21,-57434055),c=m(c,f,i,a,n[h+12],6,1700485571),a=m(a,c,f,i,n[h+3],10,-1894986606),i=m(i,a,c,f,n[h+10],15,-1051523),f=m(f,i,a,c,n[h+1],21,-2054922799),c=m(c,f,i,a,n[h+8],6,1873313359),a=m(a,c,f,i,n[h+15],10,-30611744),i=m(i,a,c,f,n[h+6],15,-1560198380),f=m(f,i,a,c,n[h+13],21,1309151649),c=m(c,f,i,a,n[h+4],6,-145523070),a=m(a,c,f,i,n[h+11],10,-1120210379),i=m(i,a,c,f,n[h+2],15,718787259),f=m(f,i,a,c,n[h+9],21,-343485551),c=d(c,r),f=d(f,e),i=d(i,o),a=d(a,u);return[c,f,i,a]}function i(n){for(var t="",r=32*n.length,e=0;e<r;e+=8)t+=String.fromCharCode(n[e>>5]>>>e%32&255);return t}function a(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e<t.length;e+=1)t[e]=0;for(var r=8*n.length,e=0;e<r;e+=8)t[e>>5]|=(255&n.charCodeAt(e/8))<<e%32;return t}function e(n){for(var t,r="0123456789abcdef",e="",o=0;o<n.length;o+=1)t=n.charCodeAt(o),e+=r.charAt(t>>>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,16<e.length&&(e=c(e,8*n.length)),r=0;r<16;r+=1)o[r]=909522486^e[r],u[r]=1549556828^e[r];return t=c(o.concat(a(t)),512+8*t.length),i(c(u.concat(t),640))}(r(n),r(t))}function t(n,t,r){return t?r?u(t,n):e(u(t,n)):r?o(n):e(o(n))}"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:n.md5=t}(this);
|
||||
var md5=this.md5;
|
||||
/**
|
||||
网关上线
|
||||
订阅:/sys/hbtgIA0SuVw9lxjB/AA:BB:CC:DD:10/c/#
|
||||
|
||||
子设备注册:
|
||||
/sys/hbtgIA0SuVw9lxjB/AA:BB:CC:DD:10/s/register
|
||||
{
|
||||
"id": "6",
|
||||
"params":{
|
||||
"productKey":"Rf4QSjbm65X45753",
|
||||
"deviceName":"ABC12400001",
|
||||
"model":"S1"
|
||||
}
|
||||
}
|
||||
子设备上线
|
||||
订阅:/sys/Rf4QSjbm65X45753/ABC12400001/c/#
|
||||
|
||||
数据上报:
|
||||
/sys/Rf4QSjbm65X45753/ABC12400001/s/event/property/post
|
||||
{
|
||||
"id": "6",
|
||||
"params":{
|
||||
"powerstate": 1
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
var registered={};
|
||||
|
||||
function getPkDn(clientId){
|
||||
var arr=clientId.split("_");
|
||||
return {
|
||||
pk:arr[0],
|
||||
dn:arr[1]
|
||||
};
|
||||
}
|
||||
|
||||
function register(payload){
|
||||
var auth= JSON.parse(payload);
|
||||
|
@ -25,7 +61,48 @@ function register(payload){
|
|||
};
|
||||
}
|
||||
|
||||
function online(topic){
|
||||
function subRegister(topic,parent,payload){
|
||||
var params= payload.params;
|
||||
var reply=
|
||||
{
|
||||
productKey:parent.productKey,
|
||||
deviceName:parent.deviceName,
|
||||
mid:"0",
|
||||
content:{
|
||||
topic:topic.replace("/s/","/c/")+"_reply",
|
||||
payload:JSON.stringify({
|
||||
id:"0",
|
||||
code:0,
|
||||
data:{
|
||||
"productKey":params.productKey,
|
||||
"deviceName":params.deviceName
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
type:"register",
|
||||
data:{
|
||||
productKey:parent.productKey,
|
||||
deviceName:parent.deviceName,
|
||||
subDevices:[{
|
||||
productKey:params.productKey,
|
||||
deviceName:params.deviceName,
|
||||
model:params.model
|
||||
}]
|
||||
},
|
||||
action:{
|
||||
type:"ack",
|
||||
content:JSON.stringify(reply)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function deviceStateChange(head,clientId,state){
|
||||
var topic=head.topic;
|
||||
var device=getPkDn(clientId);
|
||||
|
||||
var arr= topic.split('/');
|
||||
if(arr.length<6){
|
||||
throw new Error("incorrect topic")
|
||||
|
@ -38,7 +115,23 @@ function online(topic){
|
|||
data:{
|
||||
productKey:pk,
|
||||
deviceName:dn,
|
||||
state:"online"
|
||||
state:state,
|
||||
parent:{
|
||||
productKey:device.pk,
|
||||
deviceName:device.dn,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function disconnect(clientId){
|
||||
var device=getPkDn(clientId);
|
||||
return {
|
||||
type:"state",
|
||||
data:{
|
||||
productKey:device.pk,
|
||||
deviceName:device.dn,
|
||||
state:"offline"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +143,15 @@ this.onReceive=function(head,type,payload){
|
|||
}
|
||||
|
||||
if(type=='subscribe'){
|
||||
return online(payload);
|
||||
return deviceStateChange(head,payload,'online');
|
||||
}
|
||||
|
||||
if(type=='unsubscribe'){
|
||||
return deviceStateChange(head,payload,'offline');
|
||||
}
|
||||
|
||||
if(type=='disconnect'){
|
||||
return disconnect(payload);
|
||||
}
|
||||
|
||||
var topic=head['topic'];
|
||||
|
@ -62,16 +163,29 @@ this.onReceive=function(head,type,payload){
|
|||
if(arr.length<6){
|
||||
throw new Error("incorrect topic")
|
||||
}
|
||||
|
||||
var pk=arr[2];
|
||||
var dn=arr[3];
|
||||
payload=JSON.parse(payload);
|
||||
|
||||
//子设备注册
|
||||
if(topic.endsWith('/register')){
|
||||
return subRegister(topic,{productKey:pk,deviceName:dn},payload);
|
||||
}
|
||||
|
||||
//数据上报
|
||||
return {
|
||||
type:"report",
|
||||
data:{
|
||||
productKey:pk,
|
||||
deviceName:dn,
|
||||
content:payload
|
||||
mid:payload.id,
|
||||
content:{
|
||||
topic:topic,
|
||||
payload:payload
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.onRegistered=function(regInfo,result){
|
||||
}
|
|
@ -1 +1 @@
|
|||
cc.iotkit.comp.mqtt.MqttComponent
|
||||
cc.iotkit.comp.mqtt.MqttDeviceComponent
|
|
@ -1,14 +1,26 @@
|
|||
|
||||
var mid=1;
|
||||
|
||||
function getMid(){
|
||||
mid++;
|
||||
if(mid>10000){
|
||||
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, //可根据消息内容判断填写不同产品
|
||||
productKey: msg.productKey,
|
||||
deviceName: msg.deviceName,
|
||||
type:"property",
|
||||
identifier: "report", //属性上报
|
||||
|
@ -17,7 +29,6 @@ this.decode = function (msg) {
|
|||
data: payload.params,
|
||||
};
|
||||
} else if (topic.indexOf("/event/") > 0) {
|
||||
var identifier = topic.substring(topic.lastIndexOf("/") + 1);
|
||||
//事件上报
|
||||
return {
|
||||
mid: msg.mid,
|
||||
|
@ -29,15 +40,26 @@ this.decode = function (msg) {
|
|||
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"),
|
||||
identifier: identifier,
|
||||
occur: new Date().getTime(),
|
||||
time: new Date().getTime(),
|
||||
code: payload.code,
|
||||
|
@ -46,3 +68,37 @@ this.decode = function (msg) {
|
|||
}
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>iotkit-parent</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
|||
<module>emqx-component</module>
|
||||
<module>component</module>
|
||||
<module>mqtt-client-simulator</module>
|
||||
<module>http-biz-component</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>iotkit-parent</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>iotkit-parent</artifactId>
|
||||
<groupId>cc.iotkit</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
tppa 即第三方平台接入
|
||||
|
||||
天猫精灵
|
||||
小度
|
||||
发现设备,输入: 小度小度,发现设备
|
||||
|
||||
|
||||
小米
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<String, IRequestHandler> 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));
|
||||
|
||||
}
|
||||
}
|
|
@ -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<DiscoverAppliancesRequest, DiscoverAppliancesResponse> {
|
||||
|
||||
@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<DiscoverAppliancesResponse.DiscoveredAppliance> 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<DiscoverAppliancesResponse.DiscoveredGroup> discoveredGroups = new ArrayList<>();
|
||||
payload.setDiscoveredGroups(discoveredGroups);
|
||||
discoveredGroups.add(new DiscoverAppliancesResponse.DiscoveredGroup("客厅",
|
||||
Arrays.asList("11223344"),
|
||||
"",
|
||||
new ArrayList()
|
||||
));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package cc.iotkit.tppa.xiaodu.handler;
|
||||
|
||||
public interface IRequestHandler<T, R> {
|
||||
|
||||
String getName();
|
||||
|
||||
Class getRequestType();
|
||||
|
||||
R handle(T request);
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package cc.iotkit.tppa.xiaodu.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PayloadToken {
|
||||
|
||||
protected String accessToken;
|
||||
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package cc.iotkit.tppa.xiaodu.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TurnOnRequest {
|
||||
|
||||
private Header header;
|
||||
|
||||
|
||||
}
|
|
@ -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<DiscoveredAppliance> discoveredAppliances;
|
||||
/**
|
||||
* discoveredGroups 对象的数组,该对象包含可发现分组,与用户设备帐户相关联的。
|
||||
* 如果没有与用户帐户关联的分组,此属性应包含一个空数组。
|
||||
* 如果发生错误,该属性可以为空数组[]。阵列中允许的最大项目数量为10。
|
||||
*/
|
||||
private List<DiscoveredGroup> discoveredGroups;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public static class DiscoveredAppliance {
|
||||
private List<String> 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<Attribute> 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<String> applianceIds;
|
||||
/**
|
||||
* 分组备注信息
|
||||
*/
|
||||
private String groupNotes;
|
||||
/**
|
||||
* 提供给技能使用的分组相关的附加信息的键值对
|
||||
*/
|
||||
private List additionalGroupDetails;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue