diff --git a/common/src/main/java/cc/iotkit/common/utils/JsonUtil.java b/common/src/main/java/cc/iotkit/common/utils/JsonUtil.java index c3b3365d..8bd2b5e2 100755 --- a/common/src/main/java/cc/iotkit/common/utils/JsonUtil.java +++ b/common/src/main/java/cc/iotkit/common/utils/JsonUtil.java @@ -5,8 +5,14 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import jdk.nashorn.api.scripting.ScriptObjectMirror; import lombok.SneakyThrows; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public final class JsonUtil { private final static ObjectMapper MAPPER = new ObjectMapper() @@ -32,4 +38,33 @@ public final class JsonUtil { public static JsonNode parse(String json) { return MAPPER.readTree(json); } + + public static Object toObject(ScriptObjectMirror mirror) { + if (mirror.isEmpty()) { + return null; + } + if (mirror.isArray()) { + List list = new ArrayList<>(); + for (Map.Entry entry : mirror.entrySet()) { + Object result = entry.getValue(); + if (result instanceof ScriptObjectMirror) { + list.add(toObject((ScriptObjectMirror) result)); + } else { + list.add(result); + } + } + return list; + } + + Map map = new HashMap<>(); + for (Map.Entry entry : mirror.entrySet()) { + Object result = entry.getValue(); + if (result instanceof ScriptObjectMirror) { + map.put(entry.getKey(), toObject((ScriptObjectMirror) result)); + } else { + map.put(entry.getKey(), result); + } + } + return map; + } } diff --git a/common/src/main/java/cc/iotkit/common/utils/ThreadUtil.java b/common/src/main/java/cc/iotkit/common/utils/ThreadUtil.java new file mode 100755 index 00000000..bbe481d5 --- /dev/null +++ b/common/src/main/java/cc/iotkit/common/utils/ThreadUtil.java @@ -0,0 +1,25 @@ +package cc.iotkit.common.utils; + +import java.util.concurrent.ScheduledThreadPoolExecutor; + +public class ThreadUtil { + + public static ScheduledThreadPoolExecutor newScheduled(int poolSize, String threadName) { + return new ScheduledThreadPoolExecutor(poolSize, (Runnable r) -> { + SecurityManager s = System.getSecurityManager(); + ThreadGroup group = (s != null) ? s.getThreadGroup() : + Thread.currentThread().getThreadGroup(); + Thread t = new Thread(group, r, + threadName, + 0); + if (t.isDaemon()) { + t.setDaemon(false); + } + if (t.getPriority() != Thread.NORM_PRIORITY) { + t.setPriority(Thread.NORM_PRIORITY); + } + return t; + }); + } + +} diff --git a/dao/src/main/java/cc/iotkit/dao/AligenieProductDao.java b/dao/src/main/java/cc/iotkit/dao/AligenieProductDao.java deleted file mode 100755 index 2a1d648e..00000000 --- a/dao/src/main/java/cc/iotkit/dao/AligenieProductDao.java +++ /dev/null @@ -1,28 +0,0 @@ -package cc.iotkit.dao; - -import cc.iotkit.model.aligenie.AligenieProduct; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.domain.Example; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.stereotype.Repository; - -@Repository -public class AligenieProductDao extends BaseDao { - - private final AligenieProductRepository aligenieProductRepository; - - @Autowired - public AligenieProductDao(MongoTemplate mongoTemplate, - AligenieProductRepository aligenieProductRepository) { - super(mongoTemplate, AligenieProduct.class); - this.aligenieProductRepository = aligenieProductRepository; - } - - @Cacheable(value = "cache_getAligenieProduct", key = "'getAligenieProduct'+#pk", unless = "#result == null") - public AligenieProduct getAligenieProduct(String pk) { - return aligenieProductRepository.findOne(Example.of( - AligenieProduct.builder().productKey(pk).build() - )).orElse(null); - } -} diff --git a/dao/src/main/java/cc/iotkit/dao/BaseDao.java b/dao/src/main/java/cc/iotkit/dao/BaseDao.java deleted file mode 100755 index 96773013..00000000 --- a/dao/src/main/java/cc/iotkit/dao/BaseDao.java +++ /dev/null @@ -1,59 +0,0 @@ -package cc.iotkit.dao; - -import org.springframework.data.domain.Sort; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.Criteria; -import org.springframework.data.mongodb.core.query.Query; - -import java.util.List; - -import static org.springframework.data.mongodb.core.query.Criteria.where; -import static org.springframework.data.mongodb.core.query.Query.query; - -public class BaseDao { - - protected MongoTemplate mongoTemplate; - - private Class cls; - - public BaseDao(MongoTemplate mongoTemplate, Class cls) { - this.mongoTemplate = mongoTemplate; - this.cls = cls; - } - - public List find(Criteria condition) { - Query query = new Query(); - query.addCriteria(condition); - return mongoTemplate.find(query, cls); - } - - public List find(Criteria condition, long skip, int count, Sort.Order order) { - Query query = new Query(); - query.addCriteria(condition) - .with(Sort.by(order)) - .skip(skip) - .limit(count); - return mongoTemplate.find(query, cls); - } - - public long count(Criteria condition) { - Query query = new Query(); - query.addCriteria(condition); - return mongoTemplate.count(query, cls); - } - - public T save(String id, T entity) { - if (id == null) { - return mongoTemplate.save(entity); - } else { - mongoTemplate.updateFirst(query(where("_id").is(id)), - DaoTool.update(entity), entity.getClass()); - return (T) mongoTemplate.findById(id, entity.getClass()); - } - } - - public T save(T entity) { - return mongoTemplate.save(entity); - } - -} diff --git a/dao/src/main/java/cc/iotkit/dao/DeviceCache.java b/dao/src/main/java/cc/iotkit/dao/DeviceCache.java index 524487e4..7464b4fb 100755 --- a/dao/src/main/java/cc/iotkit/dao/DeviceCache.java +++ b/dao/src/main/java/cc/iotkit/dao/DeviceCache.java @@ -4,24 +4,14 @@ import cc.iotkit.common.Constants; import cc.iotkit.model.device.DeviceInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Repository; -import static org.springframework.data.mongodb.core.query.Criteria.where; -import static org.springframework.data.mongodb.core.query.Query.query; - @Repository -public class DeviceCache extends BaseDao { +public class DeviceCache { @Autowired private DeviceRepository deviceRepository; - @Autowired - public DeviceCache(MongoTemplate mongoTemplate) { - super(mongoTemplate, DeviceInfo.class); - } - @Cacheable(value = Constants.DEVICE_CACHE, key = "#pk+'_'+#dn") public DeviceInfo findByProductKeyAndDeviceName(String pk, String dn) { return deviceRepository.findByProductKeyAndDeviceName(pk, dn); diff --git a/dao/src/main/java/cc/iotkit/dao/DeviceDao.java b/dao/src/main/java/cc/iotkit/dao/DeviceDao.java new file mode 100644 index 00000000..dc281f01 --- /dev/null +++ b/dao/src/main/java/cc/iotkit/dao/DeviceDao.java @@ -0,0 +1,44 @@ +package cc.iotkit.dao; + +import cc.iotkit.model.Paging; +import cc.iotkit.model.device.DeviceInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Repository; + +import java.util.Map; + +@Repository +public class DeviceDao { + + @Autowired + private MongoTemplate mongoTemplate; + + public Paging find(Criteria condition, int size, int page) { + Query query = Query.query(condition); + return new Paging<>( + mongoTemplate.count(query, DeviceInfo.class), + mongoTemplate.find( + query.with(PageRequest.of(page-1, size, Sort.by(Sort.Order.desc("createAt")))) + , DeviceInfo.class) + ); + } + + /** + * 更新设备属性 + */ + public void updateProperties(String deviceId, Map properties) { + Query query = Query.query(new Criteria().and("deviceId").is(deviceId)); + Update update = new Update(); + for (String key : properties.keySet()) { + update.set("property." + key, properties.get(key)); + } + mongoTemplate.updateFirst(query, update, DeviceInfo.class); + } + +} diff --git a/dao/src/main/java/cc/iotkit/dao/DeviceEventDao.java b/dao/src/main/java/cc/iotkit/dao/DeviceEventDao.java deleted file mode 100755 index 15e9e56f..00000000 --- a/dao/src/main/java/cc/iotkit/dao/DeviceEventDao.java +++ /dev/null @@ -1,15 +0,0 @@ -package cc.iotkit.dao; - -import cc.iotkit.model.device.message.DeviceEvent; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.stereotype.Repository; - -@Repository -public class DeviceEventDao extends BaseDao { - - @Autowired - public DeviceEventDao(MongoTemplate mongoTemplate) { - super(mongoTemplate, DeviceEvent.class); - } -} diff --git a/dao/src/main/java/cc/iotkit/dao/DevicePropertyDao.java b/dao/src/main/java/cc/iotkit/dao/DevicePropertyDao.java new file mode 100644 index 00000000..91d1650a --- /dev/null +++ b/dao/src/main/java/cc/iotkit/dao/DevicePropertyDao.java @@ -0,0 +1,40 @@ +package cc.iotkit.dao; + +import cc.iotkit.model.device.message.DeviceProperty; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.sort.FieldSortBuilder; +import org.elasticsearch.search.sort.SortOrder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.SearchHit; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.stream.Collectors; + +@Repository +public class DevicePropertyDao { + + @Autowired + private ElasticsearchRestTemplate template; + + public List findDevicePropertyHistory(String deviceId, String name, long start, long end) { + NativeSearchQuery query = new NativeSearchQueryBuilder() + .withQuery( + QueryBuilders.boolQuery() + .must(QueryBuilders.termQuery("deviceId", deviceId)) + .must(QueryBuilders.termQuery("name", name)) + .must(QueryBuilders.rangeQuery("time") + .from(start, true).to(end, true)) + ) + .withSorts(new FieldSortBuilder("time").order(SortOrder.ASC)) + .build(); + SearchHits result = template.search(query, DeviceProperty.class); + return result.getSearchHits().stream() + .map(SearchHit::getContent).collect(Collectors.toList()); + } + +} diff --git a/dao/src/main/java/cc/iotkit/dao/DevicePropertyRepository.java b/dao/src/main/java/cc/iotkit/dao/DevicePropertyRepository.java new file mode 100755 index 00000000..3300b370 --- /dev/null +++ b/dao/src/main/java/cc/iotkit/dao/DevicePropertyRepository.java @@ -0,0 +1,11 @@ +package cc.iotkit.dao; + +import cc.iotkit.model.device.message.DeviceProperty; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface DevicePropertyRepository extends ElasticsearchRepository { + + +} diff --git a/dao/src/main/java/cc/iotkit/dao/DeviceRepository.java b/dao/src/main/java/cc/iotkit/dao/DeviceRepository.java index 334e0f3d..14a98cd2 100755 --- a/dao/src/main/java/cc/iotkit/dao/DeviceRepository.java +++ b/dao/src/main/java/cc/iotkit/dao/DeviceRepository.java @@ -4,6 +4,8 @@ import cc.iotkit.model.device.DeviceInfo; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface DeviceRepository extends MongoRepository { @@ -11,4 +13,6 @@ public interface DeviceRepository extends MongoRepository { DeviceInfo findByDeviceId(String deviceId); + List findByParentId(String parentId); + } diff --git a/dao/src/main/java/cc/iotkit/dao/ThingModelMessageDao.java b/dao/src/main/java/cc/iotkit/dao/ThingModelMessageDao.java new file mode 100644 index 00000000..2b06157f --- /dev/null +++ b/dao/src/main/java/cc/iotkit/dao/ThingModelMessageDao.java @@ -0,0 +1,45 @@ +package cc.iotkit.dao; + +import cc.iotkit.model.Paging; +import cc.iotkit.model.device.message.ThingModelMessage; +import org.apache.commons.lang3.StringUtils; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.SearchHit; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.stereotype.Repository; + +import java.util.stream.Collectors; + +@Repository +public class ThingModelMessageDao { + + @Autowired + private ElasticsearchRestTemplate template; + + public Paging findByTypeAndIdentifier(String deviceId, String type, + String identifier, + int page, int size) { + BoolQueryBuilder builder = QueryBuilders.boolQuery(); + builder.must(QueryBuilders.termQuery("deviceId", deviceId)); + if (StringUtils.isNotBlank(type)) { + builder.must(QueryBuilders.termQuery("type", type)); + } + if (StringUtils.isNotBlank(identifier)) { + builder.must(QueryBuilders.matchPhraseQuery("identifier", identifier)); + } + NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(builder) + .withPageable(PageRequest.of(page, size, Sort.by(Sort.Order.desc("time")))) + .build(); + SearchHits result = template.search(query, ThingModelMessage.class); + return new Paging<>(result.getTotalHits(), result.getSearchHits().stream() + .map(SearchHit::getContent).collect(Collectors.toList())); + } + +} diff --git a/dao/src/main/java/cc/iotkit/dao/ThingModelMessageRepository.java b/dao/src/main/java/cc/iotkit/dao/ThingModelMessageRepository.java index c865fbdd..5e95e53d 100755 --- a/dao/src/main/java/cc/iotkit/dao/ThingModelMessageRepository.java +++ b/dao/src/main/java/cc/iotkit/dao/ThingModelMessageRepository.java @@ -1,9 +1,14 @@ package cc.iotkit.dao; import cc.iotkit.model.device.message.ThingModelMessage; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; @Repository public interface ThingModelMessageRepository extends ElasticsearchRepository { + + Page findByTypeAndIdentifier(String type, String identifier, Pageable pageable); + } diff --git a/dao/src/main/java/cc/iotkit/dao/UserInfoDao.java b/dao/src/main/java/cc/iotkit/dao/UserInfoDao.java deleted file mode 100755 index 0b9b2151..00000000 --- a/dao/src/main/java/cc/iotkit/dao/UserInfoDao.java +++ /dev/null @@ -1,15 +0,0 @@ -package cc.iotkit.dao; - -import cc.iotkit.model.UserInfo; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.stereotype.Repository; - -@Repository -public class UserInfoDao extends BaseDao { - - @Autowired - public UserInfoDao(MongoTemplate mongoTemplate) { - super(mongoTemplate, UserInfo.class); - } -} diff --git a/device-server/.DS_Store b/device-server/.DS_Store deleted file mode 100755 index b021504d..00000000 Binary files a/device-server/.DS_Store and /dev/null differ diff --git a/device-server/device-api/pom.xml b/device-server/device-api/pom.xml deleted file mode 100755 index d10955a6..00000000 --- a/device-server/device-api/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - device-server - cc.iotkit - 0.0.1-SNAPSHOT - - 4.0.0 - - device-api - - - - - org.springframework.cloud - spring-cloud-openfeign-core - - - org.springframework - spring-web - - - org.projectlombok - lombok - compile - - - cc.iotkit - model - - - - \ No newline at end of file diff --git a/device-server/device-api/src/main/java/cc/iotkit/deviceapi/IDeviceManager.java b/device-server/device-api/src/main/java/cc/iotkit/deviceapi/IDeviceManager.java deleted file mode 100755 index 8e8087c7..00000000 --- a/device-server/device-api/src/main/java/cc/iotkit/deviceapi/IDeviceManager.java +++ /dev/null @@ -1,44 +0,0 @@ -package cc.iotkit.deviceapi; - -import cc.iotkit.model.device.DeviceInfo; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.*; - -import java.util.Map; - -@Component -@FeignClient(value = "iot-device-manager",url = "localhost:8091") -public interface IDeviceManager { - - /** - * 设备注册 - */ - @PostMapping("/register") - @ResponseBody - DeviceInfo register(@RequestParam("parentId") String parentId, - @RequestParam("productKey") String productKey, - @RequestParam("deviceName") String deviceName, - @RequestParam("model") String model); - - /** - * 解绑子设备 - */ - @PostMapping("/{deviceId}/unbind") - void unbind(@PathVariable("deviceId") String deviceId); - - /** - * 设置属性 - */ - @PostMapping("/{deviceId}/property/set") - String setProperty(@PathVariable("deviceId") String deviceId, - @RequestBody Map properties); - - /** - * 调用服务 - */ - @PostMapping("/{deviceId}/{identifier}/invoke") - String invokeService(@PathVariable("deviceId") String deviceId, - @PathVariable("identifier") String identifier, - @RequestBody Map properties); -} diff --git a/device-server/device-api/src/main/java/cc/iotkit/deviceapi/IDeviceService.java b/device-server/device-api/src/main/java/cc/iotkit/deviceapi/IDeviceService.java deleted file mode 100755 index d98a44b3..00000000 --- a/device-server/device-api/src/main/java/cc/iotkit/deviceapi/IDeviceService.java +++ /dev/null @@ -1,16 +0,0 @@ -package cc.iotkit.deviceapi; - -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.*; - -@Component -@FeignClient(value = "iot-device-service", url = "localhost:8091") -public interface IDeviceService { - - /** - * 调用服务 - */ - @PostMapping("/invoke") - String invoke(@RequestBody Service service); -} diff --git a/device-server/device-api/src/main/java/cc/iotkit/deviceapi/Service.java b/device-server/device-api/src/main/java/cc/iotkit/deviceapi/Service.java deleted file mode 100755 index 7501e1b8..00000000 --- a/device-server/device-api/src/main/java/cc/iotkit/deviceapi/Service.java +++ /dev/null @@ -1,31 +0,0 @@ -package cc.iotkit.deviceapi; - -import lombok.Data; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Data -public class Service { - - private String device; - - private String identifier; - - private List inputData; - - public Map parseInputData() { - Map data = new HashMap<>(); - for (Parameter p : inputData) { - data.put(p.getIdentifier(), p.getValue()); - } - return data; - } - - @Data - public static class Parameter { - private String identifier; - private Object value; - } -} diff --git a/device-server/mqtt-server/.DS_Store b/device-server/mqtt-server/.DS_Store deleted file mode 100755 index a3c148ab..00000000 Binary files a/device-server/mqtt-server/.DS_Store and /dev/null differ diff --git a/device-server/mqtt-server/pom.xml b/device-server/mqtt-server/pom.xml deleted file mode 100755 index 6289248d..00000000 --- a/device-server/mqtt-server/pom.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - device-server - cc.iotkit - 0.0.1-SNAPSHOT - - 4.0.0 - - mqtt-server - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.projectlombok - lombok - true - - - - commons-codec - commons-codec - - - - org.bouncycastle - bcprov-jdk15on - - - - org.eclipse.paho - org.eclipse.paho.client.mqttv3 - - - - cc.iotkit - model - - - - cc.iotkit - common - - - - cc.iotkit - device-api - - - - cc.iotkit - gateway-client - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - - - - \ No newline at end of file diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/Application.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/Application.java deleted file mode 100755 index 25c2b9fc..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/Application.java +++ /dev/null @@ -1,12 +0,0 @@ -package cc.iotkit.server.mqtt; - -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/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/config/AutobeanConfig.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/config/AutobeanConfig.java deleted file mode 100755 index 41fe6042..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/config/AutobeanConfig.java +++ /dev/null @@ -1,19 +0,0 @@ -package cc.iotkit.server.mqtt.config; - -import cc.iotkit.protocol.client.DeviceBehaviourClient; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class AutobeanConfig { - - @Value("${gateway.server:}") - private String gatewayServer; - - @Bean - public DeviceBehaviourClient getDeviceBehaviourClient() { - return new DeviceBehaviourClient(gatewayServer); - } - -} diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/DeviceController.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/DeviceController.java deleted file mode 100755 index e2e1b2b0..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/DeviceController.java +++ /dev/null @@ -1,47 +0,0 @@ -package cc.iotkit.server.mqtt.controller; - -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.protocol.DeviceGateway; -import cc.iotkit.protocol.DeviceMessage; -import cc.iotkit.protocol.OtaInfo; -import cc.iotkit.protocol.Result; -import cc.iotkit.server.mqtt.service.MqttManager; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RestController; - -@Slf4j -@RestController -public class DeviceController implements DeviceGateway { - - @Autowired - private MqttManager mqttManager; - - @Override - public Result sendMessage(DeviceMessage msg) { - try { - MqttMessage mqttMessage = JsonUtil.parse(msg.getContent(), MqttMessage.class); - mqttManager.sendMsg(mqttMessage.getTopic(), mqttMessage.getPayload()); - return new Result(true, ""); - } catch (Throwable e) { - log.error("send message error", e); - return new Result(false, e.getMessage()); - } - } - - @Override - public Result sendOta(OtaInfo ota) { - return null; - } - - @Data - public static class MqttMessage { - - private String topic; - - private String payload; - - } - -} diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/MqttAuthController.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/MqttAuthController.java deleted file mode 100755 index a9b82d6b..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/controller/MqttAuthController.java +++ /dev/null @@ -1,63 +0,0 @@ -package cc.iotkit.server.mqtt.controller; - - -import cc.iotkit.common.Constants; -import cc.iotkit.common.utils.CodecUtil; -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.server.mqtt.model.EmqAcl; -import cc.iotkit.server.mqtt.model.EmqAuthInfo; -import cc.iotkit.server.mqtt.service.DeviceAuthService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import javax.servlet.http.HttpServletResponse; - -@Slf4j -@RestController -public class MqttAuthController { - - @Autowired - private DeviceAuthService deviceAuthService; - - @PostMapping("/mqtt/auth") - public void auth(@RequestBody EmqAuthInfo auth) { - log.info("mqtt auth:" + JsonUtil.toJsonString(auth)); - String clientId = auth.getClientid(); - if (isSupperUser(clientId)) { - return; - } - deviceAuthService.auth(auth); - } - - @PostMapping("/mqtt/acl") - public void acl(@RequestBody EmqAcl acl) { - log.info("mqtt acl:{}", JsonUtil.toJsonString(acl)); - if (isSupperUser(acl.getClientid())) { - return; - } - deviceAuthService.acl(acl); - log.info("topic:{}, acl success", acl.getTopic()); - } - - @PostMapping("/mqtt/superuser") - public void superuser(@RequestBody EmqAcl acl, HttpServletResponse response) { - response.setStatus(HttpServletResponse.SC_BAD_GATEWAY); - } - - public boolean isSupperUser(String clientId) { - try { - if (!clientId.startsWith("su_")) { - return false; - } - clientId = clientId.replaceFirst("su_", ""); - return CodecUtil.aesDecrypt(clientId, Constants.PRODUCT_SECRET).startsWith("admin_"); - } catch (Throwable e) { - log.error("aesDecrypt error.", e); - return false; - } - } - -} diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/handler/DisconnectedHandler.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/handler/DisconnectedHandler.java deleted file mode 100755 index 4a9206ef..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/handler/DisconnectedHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -package cc.iotkit.server.mqtt.handler; - -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.protocol.client.DeviceBehaviourClient; -import com.fasterxml.jackson.core.type.TypeReference; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -public class DisconnectedHandler { - - @Autowired - private DeviceBehaviourClient behaviourClient; - - public void handler(String msg) { - Disconnected disconnected = JsonUtil.parse(msg, new TypeReference() { - }); - String clientId = disconnected.getClientid(); - String[] parts = clientId.split("_"); - if (parts.length < 2) { - return; - } - String pk = parts[0]; - String dn = parts[1]; - behaviourClient.offline(pk, dn); - log.info("client disconnected, offline,pk:{},dn:{}", pk, dn); - } - - @Data - private static class Disconnected { - private String reason; - private String clientid; - private String username; - private String peername; - private String sockname; - } - -} diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAcl.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAcl.java deleted file mode 100755 index f4cdbee4..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAcl.java +++ /dev/null @@ -1,19 +0,0 @@ -package cc.iotkit.server.mqtt.model; - -import lombok.Data; - -@Data -public class EmqAcl { - - private String access; - - private String username; - - private String clientid; - - private String ipaddr; - - private String protocol; - - private String topic; -} diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAuthInfo.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAuthInfo.java deleted file mode 100755 index 1ca3f4d5..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/EmqAuthInfo.java +++ /dev/null @@ -1,18 +0,0 @@ -package cc.iotkit.server.mqtt.model; - -import lombok.Data; - -@Data -public class EmqAuthInfo { - - private String clientid; - - private String password; - - private String username; - - private String ipaddress; - - private String protocol; - -} diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Request.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Request.java deleted file mode 100755 index 1b365b70..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Request.java +++ /dev/null @@ -1,17 +0,0 @@ -package cc.iotkit.server.mqtt.model; - - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@JsonIgnoreProperties(ignoreUnknown = true) -public class Request { - protected String id; - - protected T params; -} \ No newline at end of file diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Response.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Response.java deleted file mode 100755 index 5a9d9421..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/model/Response.java +++ /dev/null @@ -1,25 +0,0 @@ -package cc.iotkit.server.mqtt.model; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class Response { - - private String id; - - private int code; - - private T data; - - public static Empty empty() { - return new Empty(); - } - - @Data - public static class Empty { - } -} diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/DeviceAuthService.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/DeviceAuthService.java deleted file mode 100755 index b1fc8142..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/DeviceAuthService.java +++ /dev/null @@ -1,71 +0,0 @@ -package cc.iotkit.server.mqtt.service; - -import cc.iotkit.common.Constants; -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.protocol.RegisterInfo; -import cc.iotkit.protocol.Result; -import cc.iotkit.protocol.client.DeviceBehaviourClient; -import cc.iotkit.server.mqtt.model.EmqAcl; -import cc.iotkit.server.mqtt.model.EmqAuthInfo; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -public class DeviceAuthService { - - @Autowired - private DeviceBehaviourClient behaviourClient; - - public void auth(EmqAuthInfo auth) { - String clientId = auth.getClientid(); - String[] pkDnAndModel = getPkDnAndModel(clientId); - - String hmac = DigestUtils.md5Hex(Constants.PRODUCT_SECRET + clientId); - if (!hmac.equalsIgnoreCase(auth.getPassword())) { - throw new RuntimeException("password is illegal."); - } - - String pk = pkDnAndModel[0]; - String dn = pkDnAndModel[1]; - String model = pkDnAndModel[2]; - - Result result = behaviourClient.register(new RegisterInfo(pk, dn, model)); - log.info("register result:{}", JsonUtil.toJsonString(result)); - } - - public void acl(EmqAcl acl) { - String[] pkDn = getPkDnFromTopic(acl.getTopic()); - String pk = pkDn[2]; - String dn = pkDn[3]; - behaviourClient.online(pk, dn); - } - - private String[] getPkDnAndModel(String clientId) { - if (StringUtils.isBlank(clientId)) { - throw new RuntimeException("clientId is blank."); - } - clientId += "_"; - - String[] pkDnAndModel = clientId.split("_", -1); - if (pkDnAndModel.length < 3) { - throw new RuntimeException("clientId is illegal."); - } - return pkDnAndModel; - } - - private String[] getPkDnFromTopic(String topic) { - if (StringUtils.isBlank(topic)) { - throw new RuntimeException("topic is blank."); - } - - String[] pkDn = topic.split("/", -1); - if (pkDn.length < 4) { - throw new RuntimeException("topic is illegal."); - } - return pkDn; - } -} diff --git a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/MqttManager.java b/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/MqttManager.java deleted file mode 100755 index 5c9b6a3a..00000000 --- a/device-server/mqtt-server/src/main/java/cc/iotkit/server/mqtt/service/MqttManager.java +++ /dev/null @@ -1,256 +0,0 @@ -package cc.iotkit.server.mqtt.service; - -import cc.iotkit.common.Constants; -import cc.iotkit.common.utils.CodecUtil; -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.protocol.DeviceMessage; -import cc.iotkit.protocol.RegisterInfo; -import cc.iotkit.protocol.client.DeviceBehaviourClient; -import cc.iotkit.server.mqtt.handler.DisconnectedHandler; -import cc.iotkit.server.mqtt.model.Request; -import cc.iotkit.server.mqtt.model.Response; -import com.fasterxml.jackson.core.type.TypeReference; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.eclipse.paho.client.mqttv3.*; -import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.util.Collections; -import java.util.HashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -@Slf4j -@Component -public class MqttManager implements MqttCallback, IMqttMessageListener { - - @Value("${mqtt.url}") - private String url; - - @Value(("${spring.profiles.active:}")) - private String env; - - private MqttClient mqttClient; - - @Autowired - private DisconnectedHandler disconnectedHandler; - @Autowired - private DeviceBehaviourClient behaviourClient; - - public MqttManager() { - ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); - executorService.scheduleWithFixedDelay(this::createClient, 1, 3, TimeUnit.SECONDS); - } - - private MqttConnectOptions getMqttConnectOptions() { - MqttConnectOptions options = new MqttConnectOptions(); - // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录, - // 这里设置为true表示每次连接到服务器都以新的身份连接 - options.setCleanSession(true); - // 设置连接的用户名 - options.setUserName("admin"); - // 设置连接的密码 - options.setPassword("password".toCharArray()); - options.setServerURIs(StringUtils.split(url, ",")); - // 设置超时时间 单位为秒 - options.setConnectionTimeout(10); - // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送心跳判断客户端是否在线,但这个方法并没有重连的机制 - options.setKeepAliveInterval(20); - return options; - } - - @SneakyThrows - private void createClient() { - try { - if (mqttClient == null) { - MemoryPersistence persistence = new MemoryPersistence(); - String clientId = "mqtt-server-consumer-" + env; - clientId = "su_" + CodecUtil.aesEncrypt("admin_" + clientId, Constants.PRODUCT_SECRET); - mqttClient = new MqttClient(url, clientId, persistence); - mqttClient.setCallback(this); - } - if (mqttClient.isConnected()) { - return; - } - connect(); - } catch (Throwable e) { - log.error("create mqttClient error", e); - } - } - - private void connect() { - try { - log.info("Connecting to broker:{} ", url); - IMqttToken mqttToken = mqttClient.connectWithResult(getMqttConnectOptions()); - if (mqttToken.isComplete()) { - log.info("connect mqtt-broker success"); - } else { - log.error("connect mqtt-broker failed", mqttToken.getException()); - } - IMqttToken response = mqttClient.subscribeWithResponse( - new String[]{"/sys/+/+/s/#", "/sys/session/topic/unsubscribed", "/sys/client/disconnected"}); - if (response.isComplete()) { - log.info("subscribe topics success"); - } else { - log.error("subscribe topics failed", mqttToken.getException()); - } - } catch (Throwable e) { - log.error("connect to mqtt-broker error", e); - } - } - - @SneakyThrows - @Override - public void connectionLost(Throwable e) { - log.error("mqtt connection lost", e); - while (true) { - try { - Thread.sleep(1000); - if (mqttClient.isConnected()) { - mqttClient.disconnect(); - } - connect(); - break; - } catch (Throwable e1) { - log.error("connect error,retry...", e1); - } - } - } - - @Override - public void messageArrived(String topic, MqttMessage mqttMessage) { - handleMessage(topic, mqttMessage); - } - - @Override - public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { - } - - public void handleMessage(String topic, MqttMessage msg) { - log.info("receive msg,topic:{},msg:{}", topic, JsonUtil.toJsonString(msg)); - if (topic == null) { - log.error("message topic is null."); - return; - } - int code = 0; - String mid = ""; - - try { - String payload = new String(msg.getPayload()); - - //取消订阅 - if (topic.equals("/sys/session/topic/unsubscribed")) { - topicUnsubscribed(payload); - return; - } - - //连接断开 - if (topic.equals("/sys/client/disconnected")) { - disconnectedHandler.handler(payload); - return; - } - - String[] parts = topic.split("/"); - if (parts.length < 5) { - log.error("message topic is illegal."); - return; - } - String productKey = parts[2]; - String deviceName = parts[3]; - - //子设备注册 - if (topic.endsWith("/register")) { - RegisterRequest registerRequest = JsonUtil.parse(payload, RegisterRequest.class); - mid = registerRequest.getId(); - - RegisterInfo registerInfo = RegisterInfo.builder() - .productKey(productKey) - .deviceName(deviceName) - .subDevices(Collections.singletonList(registerRequest.getParams())) - .build(); - behaviourClient.register(registerInfo); - return; - } - - Request request = JsonUtil.parse(payload, Request.class); - mid = request.getId(); - MqtMsg mqtMsg = new MqtMsg(topic, request); - - behaviourClient.messageReport(DeviceMessage.builder() - .productKey(productKey) - .deviceName(deviceName) - .mid(request.getId()) - .content(JsonUtil.toJsonString(mqtMsg)) - .build()); - - } catch (Throwable e) { - log.error("message process error", e); - code = 500; - } finally { - reply(topic, mid, code); - } - - } - - @SneakyThrows - private void reply(String topic, String id, int code) { - //回复消息不需要再回复 - if (topic.endsWith("_reply")) { - return; - } - - topic = topic.replace("/s/", "/c/") + "_reply"; - String msg = JsonUtil.toJsonString(new Response<>(id, code, new HashMap<>())); - mqttClient.publish(topic, new MqttMessage(msg.getBytes())); - } - - private void topicUnsubscribed(String msg) { - Unsubscribed unsubscribed = JsonUtil.parse(msg, new TypeReference() { - }); - String topic = unsubscribed.getTopic(); - String[] parts = topic.split("/"); - if (parts.length < 4) { - return; - } - - log.info("device offline,pk:{},dn:{}", parts[2], parts[3]); - behaviourClient.offline(parts[2], parts[3]); - } - - @SneakyThrows - public void sendMsg(String topic, String msg) { - mqttClient.publish(topic, new MqttMessage(msg.getBytes())); - } - - @Data - private static class Unsubscribed { - private String clientid; - private String username; - private String topic; - private String peerhost; - } - - public static class RegisterRequest extends Request { - - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - private static class MqtMsg { - - private String topic; - - private Object payload; - - } - -} diff --git a/device-server/mqtt-server/src/main/resources/application-dev.yml b/device-server/mqtt-server/src/main/resources/application-dev.yml deleted file mode 100755 index 63e3cdec..00000000 --- a/device-server/mqtt-server/src/main/resources/application-dev.yml +++ /dev/null @@ -1,17 +0,0 @@ -server: - port: 8091 - -spring: - data: - mongodb: - uri: mongodb://填写mongodb地址/admin - database: iotkit - - cache: - cache-names: foo,bar - caffeine: - spec: maximumSize=5000,expireAfterAccess=120s - -mqtt: - url: tcp://填写mqtt连接地址 - diff --git a/device-server/mqtt-server/src/main/resources/application.yml b/device-server/mqtt-server/src/main/resources/application.yml deleted file mode 100755 index 5b877471..00000000 --- a/device-server/mqtt-server/src/main/resources/application.yml +++ /dev/null @@ -1,16 +0,0 @@ -server: - port: 8091 - -spring: - data: - mongodb: - uri: mongodb://填写mongodb地址/admin - database: iotkit - - cache: - cache-names: foo,bar - caffeine: - spec: maximumSize=5000,expireAfterAccess=120s - -mqtt: - url: tcp://填写mqtt连接地址 diff --git a/device-server/mqtt-server/src/main/resources/logback-spring.xml b/device-server/mqtt-server/src/main/resources/logback-spring.xml deleted file mode 100755 index 6322c4b5..00000000 --- a/device-server/mqtt-server/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - DEBUG - - - ${CONSOLE_LOG_PATTERN} - utf8 - - - - - - ${LOG_FILE}/info.log - - ${LOG_FILE}/info.%d{yyyy-MM-dd}.%i.gz - - 5 - - 20GB - - - 1GB - - - - ${CONSOLE_LOG_PATTERN} - utf8 - - - - - - ${LOG_FILE}/error.log - - ${LOG_FILE}/error.%d{yyyy-MM-dd}.%i.gz - - 5 - - 5GB - - - 1GB - - - - ${CONSOLE_LOG_PATTERN} - utf8 - - - ERROR - ACCEPT - DENY - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/device-server/pom.xml b/device-server/pom.xml deleted file mode 100755 index 6693a251..00000000 --- a/device-server/pom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - iotkit-parent - cc.iotkit - 0.0.1-SNAPSHOT - - 4.0.0 - - device-server - pom - - mqtt-server - device-api - mqtt-client-simulator - - - - \ No newline at end of file diff --git a/manager/pom.xml b/manager/pom.xml index f6678ab9..bd0aaef7 100755 --- a/manager/pom.xml +++ b/manager/pom.xml @@ -129,11 +129,6 @@ common - - cc.iotkit - device-api - - cc.iotkit rule-engine @@ -144,11 +139,6 @@ dao - - cc.iotkit - protocol-server - - cc.iotkit component-server diff --git a/manager/src/main/java/cc/iotkit/manager/controller/AppController.java b/manager/src/main/java/cc/iotkit/manager/controller/AppController.java index b9a16536..c54d5d98 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/AppController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/AppController.java @@ -5,9 +5,9 @@ import cc.iotkit.dao.CategoryRepository; import cc.iotkit.dao.ProductRepository; import cc.iotkit.manager.model.vo.AppDesignVo; import cc.iotkit.manager.service.DataOwnerService; +import cc.iotkit.model.Paging; import cc.iotkit.model.product.AppDesign; import cc.iotkit.model.product.Category; -import cc.iotkit.model.PagingData; import cc.iotkit.model.product.Product; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -37,7 +37,7 @@ public class AppController { private DataOwnerService dataOwnerService; @PostMapping("/designs") - public PagingData getDesigns() { + public Paging getDesigns() { List appDesignVos = new ArrayList<>(); List products = productRepository.findAll(Example @@ -64,7 +64,7 @@ public class AppController { } }); - return new PagingData<>(appDesignRepository.count(), + return new Paging<>(appDesignRepository.count(), appDesignVos); } diff --git a/manager/src/main/java/cc/iotkit/manager/controller/DbBaseController.java b/manager/src/main/java/cc/iotkit/manager/controller/DbBaseController.java deleted file mode 100755 index fdebab1d..00000000 --- a/manager/src/main/java/cc/iotkit/manager/controller/DbBaseController.java +++ /dev/null @@ -1,32 +0,0 @@ -package cc.iotkit.manager.controller; - -import org.springframework.data.mongodb.repository.MongoRepository; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; - -import java.util.List; - -public class DbBaseController, T> { - - protected final R repository; - - public DbBaseController(R r) { - this.repository = r; - } - - @GetMapping("/list") - public List list() { - return repository.findAll(); - } - - @PostMapping("/save") - public void save(T t) { - repository.save(t); - } - - @DeleteMapping("/delete") - public void delete(T t) { - repository.delete(t); - } -} 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 5d6359d4..b9adba84 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/DeviceController.java @@ -1,21 +1,18 @@ package cc.iotkit.manager.controller; -import cc.iotkit.dao.DeviceCache; -import cc.iotkit.dao.DeviceEventDao; -import cc.iotkit.dao.DeviceEventRepository; -import cc.iotkit.dao.DeviceRepository; +import cc.iotkit.dao.*; import cc.iotkit.manager.service.DataOwnerService; import cc.iotkit.manager.service.DeviceService; import cc.iotkit.manager.utils.AuthUtil; -import cc.iotkit.model.device.message.DeviceEvent; +import cc.iotkit.model.Paging; import cc.iotkit.model.device.DeviceInfo; -import cc.iotkit.model.PagingData; +import cc.iotkit.model.device.message.DeviceProperty; +import cc.iotkit.model.device.message.ThingModelMessage; import cc.iotkit.model.product.ThingModel; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; -import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.web.bind.annotation.*; @@ -32,15 +29,15 @@ public class DeviceController { @Autowired private DeviceRepository deviceRepository; @Autowired - private DeviceEventRepository deviceEventRepository; - @Autowired - private DeviceEventDao deviceEventDao; - @Autowired - private DeviceCache deviceCache; + private DeviceDao deviceDao; @Autowired private DataOwnerService dataOwnerService; @Autowired private ProductController productController; + @Autowired + private ThingModelMessageDao thingModelMessageDao; + @Autowired + private DevicePropertyDao devicePropertyDao; @PostMapping("/{deviceId}/service/{service}") public String invokeService(@PathVariable("deviceId") String deviceId, @@ -60,11 +57,11 @@ public class DeviceController { } @PostMapping("/list") - public PagingData getDevices(int page, - int limit, - String pk, - Boolean online, - String dn) { + public Paging getDevices(int page, + int size, + String pk, + Boolean online, + String dn) { Criteria condition = new Criteria(); if (!AuthUtil.isAdmin()) { condition.and("uid").is(AuthUtil.getUserId()); @@ -78,8 +75,8 @@ public class DeviceController { if (online != null) { condition.and("state.online").is(online); } - return new PagingData<>(deviceCache.count(condition), - deviceCache.find(condition, (page - 1) * limit, limit, Sort.Order.desc("createAt"))); + + return deviceDao.find(condition, size, page); } @GetMapping("/{deviceId}/children") @@ -112,29 +109,28 @@ public class DeviceController { deviceRepository.deleteById(deviceId); } - @PostMapping("/{deviceId}/events") - public PagingData events(@PathVariable("deviceId") String deviceId, - int page, - int limit, - String type, - String identifier) { - Criteria condition = Criteria.where("deviceId").is(deviceId); - if (StringUtils.isNotBlank(type)) { - condition.and("type").is(type); - } - if (StringUtils.isNotBlank(identifier)) { - condition.and("identifier").regex(".*" + identifier + ".*"); - } + @PostMapping("/{deviceId}/logs/{size}/{page}") + public Paging logs( + @PathVariable("deviceId") String deviceId, + @PathVariable("size") int size, + @PathVariable("page") int page, + String type, String identifier) { + return thingModelMessageDao.findByTypeAndIdentifier(deviceId, type, identifier, page, size); + } - return new PagingData<>(deviceEventDao.count(condition), - deviceEventDao.find(condition, - (page - 1) * limit, limit, Sort.Order.desc("createAt"))); + @GetMapping("/{deviceId}/property/{name}/{start}/{end}") + public List getPropertyHistory( + @PathVariable("deviceId") String deviceId, + @PathVariable("name") String name, + @PathVariable("start") long start, + @PathVariable("end") long end) { + return devicePropertyDao.findDevicePropertyHistory(deviceId, name, start, end); } @PostMapping("/{deviceId}/unbind") public void unbindDevice(@PathVariable("deviceId") String deviceId) { deviceId = getDetail(deviceId).getDeviceId(); - deviceService.unbindDevice(deviceId); +// deviceService.unbindDevice(deviceId); } @GetMapping("/{deviceId}/thingModel") diff --git a/manager/src/main/java/cc/iotkit/manager/controller/ProductController.java b/manager/src/main/java/cc/iotkit/manager/controller/ProductController.java index 005c46f2..1d7e28f5 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/ProductController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/ProductController.java @@ -6,8 +6,8 @@ import cc.iotkit.dao.ProductRepository; import cc.iotkit.dao.ThingModelRepository; import cc.iotkit.manager.config.AliyunConfig; import cc.iotkit.manager.service.DataOwnerService; +import cc.iotkit.model.Paging; import cc.iotkit.model.product.Category; -import cc.iotkit.model.PagingData; import cc.iotkit.model.product.Product; import cc.iotkit.model.product.ThingModel; import com.aliyun.oss.OSS; @@ -42,9 +42,9 @@ public class ProductController { private OSS ossClient; @PostMapping("/list") - public PagingData getProducts(Product form) { + public Paging getProducts(Product form) { form = dataOwnerService.wrapExample(form); - return new PagingData<>(productRepository.count(Example.of(form)), + return new Paging<>(productRepository.count(Example.of(form)), productRepository.findAll(Example.of(form))); } 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 7e1edd7f..03a02fdc 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/ProtocolController.java @@ -2,6 +2,7 @@ package cc.iotkit.manager.controller; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.utils.ReflectUtil; +import cc.iotkit.comp.CompConfig; import cc.iotkit.comp.mqtt.MqttComponent; import cc.iotkit.comps.ComponentManager; import cc.iotkit.converter.ScriptConverter; @@ -12,7 +13,6 @@ import cc.iotkit.manager.utils.AuthUtil; import cc.iotkit.model.Paging; import cc.iotkit.model.UserInfo; import cc.iotkit.model.protocol.ProtocolGateway; -import cc.iotkit.protocol.server.service.GatewayService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FileUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -22,7 +22,6 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.web.bind.annotation.*; -import javax.annotation.PostConstruct; import java.io.File; import java.io.IOException; import java.util.Optional; @@ -38,9 +37,6 @@ public class ProtocolController { @Autowired private ProtocolGatewayRepository gatewayRepository; - @Autowired - private GatewayService gatewayService; - @Autowired private DataOwnerService dataOwnerService; @@ -66,7 +62,6 @@ public class ProtocolController { gateway.setCreateAt(System.currentTimeMillis()); gateway.setUid(AuthUtil.getUserId()); gateway.setUuid(optUser.get().getUid()); - gatewayService.saveFunction(gateway.getUuid(), gateway.getId(), gateway.getScript(), functionJar); gatewayRepository.save(gateway); } catch (Throwable e) { throw new BizException("add protocol gateway error", e); @@ -89,7 +84,6 @@ public class ProtocolController { dataOwnerService.checkOwner(gateway); try { gatewayRepository.save(gateway); - gatewayService.saveFunction(gateway.getUuid(), gateway.getId(), gateway.getScript(), functionJar); } catch (Throwable e) { throw new BizException("add protocol gateway error", e); } @@ -105,8 +99,8 @@ public class ProtocolController { ProtocolGateway oldGateway = optGateway.get(); oldGateway.setScript(gateway.getScript()); try { - gatewayService.saveFunction(oldGateway.getUuid(), oldGateway.getId(), - "new (function (){" + oldGateway.getScript() + "})()", functionJar); +// gatewayService.saveFunction(oldGateway.getUuid(), oldGateway.getId(), +// "new (function (){" + oldGateway.getScript() + "})()", functionJar); gatewayRepository.save(oldGateway); } catch (Throwable e) { throw new BizException("save protocol gateway script error", e); @@ -118,7 +112,6 @@ public class ProtocolController { dataOwnerService.checkOwner(gatewayRepository, id); try { gatewayRepository.deleteById(id); - gatewayService.deleteFunction(AuthUtil.getUserId(), id); } catch (Throwable e) { throw new BizException("delete protocol gateway error", e); } @@ -136,7 +129,7 @@ public class ProtocolController { @GetMapping("/registerMqtt") public void registerMqtt() throws IOException { MqttComponent component = new MqttComponent(); - component.create("{\"port\":2883,\"ssl\":false}"); + component.create(new CompConfig(300, "{\"port\":2883,\"ssl\":false}")); ScriptConverter converter = new ScriptConverter(); converter.setScript(FileUtils.readFileToString(new File("/Users/sjg/home/gitee/open-source/converter.js"), "UTF-8")); component.setConverter(converter); diff --git a/manager/src/main/java/cc/iotkit/manager/controller/SpaceController.java b/manager/src/main/java/cc/iotkit/manager/controller/SpaceController.java index e95f07fd..fc63f838 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/SpaceController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/SpaceController.java @@ -23,8 +23,6 @@ import java.util.stream.Collectors; @RequestMapping("/space") public class SpaceController { - @Autowired - private UserInfoDao userInfoDao; @Autowired private SpaceDeviceRepository spaceDeviceRepository; @Autowired @@ -34,24 +32,24 @@ public class SpaceController { @Autowired private ProductCache productCache; - @PostMapping("/list") - public PagingData getDevices(int page, - int limit, - String address) { - Criteria condition = new Criteria(); - if (StringUtils.isNotBlank(address)) { - condition.and("address").regex(".*" + address + ".*"); - } - List userInfoList = userInfoDao.find(condition, (page - 1) * limit, - limit, Sort.Order.desc("createAt")); - - List spaces = userInfoList.stream().map((u -> - new SpaceInfo(u.getAddress(), u.getUid()))) - .collect(Collectors.toList()); - - return new PagingData<>(userInfoDao.count(condition), - spaces); - } +// @PostMapping("/list") +// public Paging getDevices(int page, +// int limit, +// String address) { +// Criteria condition = new Criteria(); +// if (StringUtils.isNotBlank(address)) { +// condition.and("address").regex(".*" + address + ".*"); +// } +// List userInfoList = userInfoDao.find(condition, (page - 1) * limit, +// limit, Sort.Order.desc("createAt")); +// +// List spaces = userInfoList.stream().map((u -> +// new SpaceInfo(u.getAddress(), u.getUid()))) +// .collect(Collectors.toList()); +// +// return new Paging<>(userInfoDao.count(condition), +// spaces); +// } @GetMapping("/{userId}/devices") public List getDevices(@PathVariable("userId") String userId) { @@ -65,7 +63,7 @@ public class SpaceController { .name(sd.getName()) .picUrl(product.getImg()) .spaceName(sd.getSpaceName()) - .online(deviceInfo.getState().getOnline()) + .online(deviceInfo.getState().isOnline()) .property(deviceInfo.getProperty()) .productKey(deviceInfo.getProductKey()) .build()); diff --git a/manager/src/main/java/cc/iotkit/manager/controller/UserAccountController.java b/manager/src/main/java/cc/iotkit/manager/controller/UserAccountController.java deleted file mode 100755 index 72a04306..00000000 --- a/manager/src/main/java/cc/iotkit/manager/controller/UserAccountController.java +++ /dev/null @@ -1,18 +0,0 @@ -package cc.iotkit.manager.controller; - -import cc.iotkit.dao.UserAccountRepository; -import cc.iotkit.model.UserAccount; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/userAccount") -public class UserAccountController extends DbBaseController { - - @Autowired - public UserAccountController(UserAccountRepository userAccountRepository) { - super(userAccountRepository); - } - -} diff --git a/manager/src/main/java/cc/iotkit/manager/controller/UserInfoController.java b/manager/src/main/java/cc/iotkit/manager/controller/UserInfoController.java index 07e1f132..ff2b1d81 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/UserInfoController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/UserInfoController.java @@ -4,7 +4,6 @@ import cc.iotkit.common.Constants; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.utils.ReflectUtil; import cc.iotkit.dao.UserInfoRepository; -import cc.iotkit.manager.service.AligenieService; import cc.iotkit.manager.service.KeycloakAdminService; import cc.iotkit.manager.service.PulsarAdminService; import cc.iotkit.manager.utils.AuthUtil; @@ -21,25 +20,21 @@ import java.util.UUID; @RestController @RequestMapping("/user") -public class UserInfoController extends DbBaseController { +public class UserInfoController { @Value("${app.systemRole}") private String systemRole; private final KeycloakAdminService keycloakAdminService; private final UserInfoRepository userInfoRepository; - private final AligenieService aligenieService; private final PulsarAdminService pulsarAdminService; @Autowired public UserInfoController(UserInfoRepository userInfoRepository, KeycloakAdminService keycloakAdminService, - AligenieService aligenieService, PulsarAdminService pulsarAdminService) { - super(userInfoRepository); this.keycloakAdminService = keycloakAdminService; this.userInfoRepository = userInfoRepository; - this.aligenieService = aligenieService; this.pulsarAdminService = pulsarAdminService; } @@ -113,11 +108,5 @@ public class UserInfoController extends DbBaseController { - - @Autowired - public AligenieDeviceController(AligenieDeviceRepository aligenieDeviceRepository) { - super(aligenieDeviceRepository); - } - -} diff --git a/manager/src/main/java/cc/iotkit/manager/controller/aligenie/AligenieProductController.java b/manager/src/main/java/cc/iotkit/manager/controller/aligenie/AligenieProductController.java index a14982da..8a5a62ce 100755 --- a/manager/src/main/java/cc/iotkit/manager/controller/aligenie/AligenieProductController.java +++ b/manager/src/main/java/cc/iotkit/manager/controller/aligenie/AligenieProductController.java @@ -1,14 +1,12 @@ package cc.iotkit.manager.controller.aligenie; -import cc.iotkit.dao.AligenieProductDao; import cc.iotkit.dao.AligenieProductRepository; import cc.iotkit.dao.ProductCache; -import cc.iotkit.manager.controller.DbBaseController; import cc.iotkit.manager.model.aligenie.AligenieProductVo; import cc.iotkit.manager.service.DataOwnerService; import cc.iotkit.manager.utils.AuthUtil; -import cc.iotkit.model.product.Product; import cc.iotkit.model.aligenie.AligenieProduct; +import cc.iotkit.model.product.Product; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Example; import org.springframework.web.bind.annotation.GetMapping; @@ -21,28 +19,20 @@ import java.util.List; @RestController @RequestMapping("/aligenie/product") -public class AligenieProductController extends DbBaseController { - - private final ProductCache productCache; - private final AligenieProductDao aligenieProductDao; - private final DataOwnerService dataOwnerService; - +public class AligenieProductController { @Autowired - public AligenieProductController(AligenieProductRepository aligenieProductRepository, - ProductCache productCache, - AligenieProductDao aligenieProductDao, - DataOwnerService dataOwnerService) { - super(aligenieProductRepository); - this.productCache = productCache; - this.aligenieProductDao = aligenieProductDao; - this.dataOwnerService = dataOwnerService; - } + private ProductCache productCache; + @Autowired + private DataOwnerService dataOwnerService; + @Autowired + private AligenieProductRepository aligenieProductRepository; + @GetMapping("/products") public List products() { List productVos = new ArrayList<>(); - List aligenieProducts = repository + List aligenieProducts = aligenieProductRepository .findAll(Example .of(AligenieProduct.builder() .uid(AuthUtil.getUserId()) @@ -61,7 +51,7 @@ public class AligenieProductController extends DbBaseController() : deviceInfo.getProperty()) .productKey(deviceInfo.getProductKey()) .build(); diff --git a/manager/src/main/java/cc/iotkit/manager/model/vo/DeviceLog.java b/manager/src/main/java/cc/iotkit/manager/model/vo/DeviceLog.java new file mode 100644 index 00000000..82a0b7cf --- /dev/null +++ b/manager/src/main/java/cc/iotkit/manager/model/vo/DeviceLog.java @@ -0,0 +1,9 @@ +package cc.iotkit.manager.model.vo; + +import lombok.Data; + +@Data +public class DeviceLog { + + +} diff --git a/manager/src/main/java/cc/iotkit/manager/service/AligenieService.java b/manager/src/main/java/cc/iotkit/manager/service/AligenieService.java deleted file mode 100755 index 6228bbbe..00000000 --- a/manager/src/main/java/cc/iotkit/manager/service/AligenieService.java +++ /dev/null @@ -1,90 +0,0 @@ -package cc.iotkit.manager.service; - -import cc.iotkit.dao.AligenieDeviceRepository; -import cc.iotkit.dao.AligenieProductDao; -import cc.iotkit.dao.DeviceCache; -import cc.iotkit.dao.SpaceDeviceRepository; -import cc.iotkit.model.device.DeviceInfo; -import cc.iotkit.model.space.SpaceDevice; -import cc.iotkit.model.UserInfo; -import cc.iotkit.model.aligenie.AligenieDevice; -import cc.iotkit.model.aligenie.AligenieProduct; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Example; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class AligenieService { - - @Autowired - private SpaceDeviceRepository spaceDeviceRepository; - - @Autowired - private AligenieDeviceRepository aligenieDeviceRepository; - - @Autowired - private AligenieProductDao aligenieProductDao; - - @Autowired - private DeviceCache deviceCache; - - public void syncDevice(UserInfo user) { - if (!user.getUsePlatforms().isAligenie()) { - //清空 - List aligenieDevices = aligenieDeviceRepository.findAll(Example.of( - AligenieDevice.builder() - .uid(user.getId()) - .build())); - for (AligenieDevice aligenieDevice : aligenieDevices) { - aligenieDeviceRepository.delete(aligenieDevice); - } - return; - } - - //找出用户空间下所有设备 - List spaceDeviceList = spaceDeviceRepository.findAll(Example.of( - SpaceDevice.builder().uid(user.getId()).build() - )); - - for (SpaceDevice spaceDevice : spaceDeviceList) { - AligenieDevice aligenieDevice = aligenieDeviceRepository.findOne(Example.of( - AligenieDevice.builder() - .deviceId(spaceDevice.getDeviceId()) - .uid(user.getId()) - .build() - )).orElse(null); - - //不存在设备,新增 - if (aligenieDevice == null) { - DeviceInfo deviceInfo = deviceCache.findByDeviceId(spaceDevice.getDeviceId()); - AligenieProduct aligenieProduct = aligenieProductDao.getAligenieProduct(deviceInfo.getProductKey()); - if(aligenieProduct==null){ - continue; - } - - aligenieDeviceRepository.save( - AligenieDevice.builder() - .uid(user.getId()) - .deviceId(spaceDevice.getDeviceId()) - .name(spaceDevice.getName()) - .spaceName(spaceDevice.getSpaceName()) - .productId(aligenieProduct.getProductId()) - .build() - ); - } else { - //存在,更新设备信息 - aligenieDeviceRepository.save( - AligenieDevice.builder() - .id(aligenieDevice.getId()) - .name(spaceDevice.getName()) - .spaceName(spaceDevice.getSpaceName()) - .build() - ); - } - - } - } - -} 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 70448a0f..14cdd9f2 100755 --- a/manager/src/main/java/cc/iotkit/manager/service/DeviceService.java +++ b/manager/src/main/java/cc/iotkit/manager/service/DeviceService.java @@ -1,48 +1,49 @@ package cc.iotkit.manager.service; +import cc.iotkit.common.exception.BizException; import cc.iotkit.common.exception.NotFoundException; -import cc.iotkit.dao.DeviceCache; -import cc.iotkit.dao.DeviceEventRepository; +import cc.iotkit.common.utils.UniqueIdUtil; +import cc.iotkit.comps.ComponentManager; +import cc.iotkit.converter.ThingService; import cc.iotkit.dao.DeviceRepository; -import cc.iotkit.dao.ThingModelRepository; -import cc.iotkit.deviceapi.IDeviceManager; import cc.iotkit.model.device.DeviceInfo; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; +import cc.iotkit.model.device.message.ThingModelMessage; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Example; import org.springframework.stereotype.Service; -import java.util.List; import java.util.Map; @Slf4j @Service public class DeviceService { - @Autowired - private DeviceCache deviceCache; @Autowired private DeviceRepository deviceRepository; @Autowired - private ThingModelRepository thingModelRepository; - @Autowired - private ThingModelService thingModelService; - @Autowired - private DeviceEventRepository deviceEventRepository; - @Autowired private DataOwnerService dataOwnerService; @Autowired - private IDeviceManager deviceManager; + private ComponentManager componentManager; public String invokeService(String deviceId, String service, Map args) { DeviceInfo device = deviceRepository.findById(deviceId) .orElseThrow(() -> new NotFoundException("device not found by deviceId")); dataOwnerService.checkOwner(device); - return this.deviceManager.invokeService(deviceId, service, args); + if (!device.getState().isOnline()) { + throw new BizException("device is offline"); + } + + ThingService thingService = ThingService.builder() + .mid(UniqueIdUtil.newRequestId()) + .productKey(device.getProductKey()) + .deviceName(device.getDeviceName()) + .type(ThingModelMessage.TYPE_SERVICE) + .identifier(service) + .params(args) + .build(); + componentManager.send(thingService); + return thingService.getMid(); } public String setProperty(String deviceId, Map properties) { @@ -50,26 +51,20 @@ public class DeviceService { .orElseThrow(() -> new NotFoundException("device not found by deviceId")); dataOwnerService.checkOwner(device); - return deviceManager.setProperty(deviceId, properties); + if (!device.getState().isOnline()) { + throw new BizException("device is offline"); + } + + ThingService thingService = ThingService.builder() + .mid(UniqueIdUtil.newRequestId()) + .productKey(device.getProductKey()) + .deviceName(device.getDeviceName()) + .type(ThingModelMessage.TYPE_PROPERTY) + .identifier("set") + .params(properties) + .build(); + componentManager.send(thingService); + return thingService.getMid(); } - public void unbindDevice(String deviceId) { - deviceManager.unbind(deviceId); - } - - public List findDevices(DeviceInfo form) { - return deviceRepository.findAll(Example.of(form)); - } - - public long count(DeviceInfo form) { - return deviceRepository.count(Example.of(form)); - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - private static class CmdRequest { - private String id; - private Object params; - } } diff --git a/manager/src/main/java/cc/iotkit/manager/service/SpaceDeviceService.java b/manager/src/main/java/cc/iotkit/manager/service/SpaceDeviceService.java index e450aac5..4bec68b2 100755 --- a/manager/src/main/java/cc/iotkit/manager/service/SpaceDeviceService.java +++ b/manager/src/main/java/cc/iotkit/manager/service/SpaceDeviceService.java @@ -41,7 +41,7 @@ public class SpaceDeviceService { .name(sd.getName()) .picUrl(product.getImg()) .spaceName(sd.getSpaceName()) - .online(deviceInfo.getState().getOnline()) + .online(deviceInfo.getState().isOnline()) .property(deviceInfo.getProperty()) .productKey(deviceInfo.getProductKey()) .build()); diff --git a/model/src/main/java/cc/iotkit/model/PagingData.java b/model/src/main/java/cc/iotkit/model/PagingData.java deleted file mode 100755 index 30637bf9..00000000 --- a/model/src/main/java/cc/iotkit/model/PagingData.java +++ /dev/null @@ -1,18 +0,0 @@ -package cc.iotkit.model; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class PagingData { - - private long count; - - private List data; - -} 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 4b1b01dc..d9babfa6 100755 --- a/model/src/main/java/cc/iotkit/model/device/DeviceInfo.java +++ b/model/src/main/java/cc/iotkit/model/device/DeviceInfo.java @@ -51,11 +51,12 @@ public class DeviceInfo implements Owned { @AllArgsConstructor public static class State { - private Boolean online; + private boolean online; private Long onlineTime; private Long offlineTime; } + } diff --git a/model/src/main/java/cc/iotkit/model/device/message/DeviceProperty.java b/model/src/main/java/cc/iotkit/model/device/message/DeviceProperty.java new file mode 100644 index 00000000..53acacf8 --- /dev/null +++ b/model/src/main/java/cc/iotkit/model/device/message/DeviceProperty.java @@ -0,0 +1,29 @@ +package cc.iotkit.model.device.message; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Document(indexName = "device_property") +public class DeviceProperty { + + @Id + private String mid; + + private String deviceId; + + private String name; + + private Object value; + + @Field(type = FieldType.Date) + private Long time; + +} diff --git a/model/src/main/java/cc/iotkit/model/device/message/ThingModelMessage.java b/model/src/main/java/cc/iotkit/model/device/message/ThingModelMessage.java index f984a941..937aa734 100755 --- a/model/src/main/java/cc/iotkit/model/device/message/ThingModelMessage.java +++ b/model/src/main/java/cc/iotkit/model/device/message/ThingModelMessage.java @@ -21,22 +21,28 @@ import java.util.Map; @Document(indexName = "thing_model_messages") public class ThingModelMessage { - public static final String TYPE_PROPERTY="property"; - public static final String TYPE_EVENT="event"; - public static final String TYPE_SERVICE="service"; + public static final String TYPE_LIFETIME = "lifetime"; + public static final String TYPE_STATE = "state"; + public static final String TYPE_PROPERTY = "property"; + public static final String TYPE_EVENT = "event"; + public static final String TYPE_SERVICE = "service"; - public static final String ID_PROPERTY_GET="get"; - public static final String ID_PROPERTY_SET="set"; + public static final String ID_PROPERTY_GET = "get"; + public static final String ID_PROPERTY_SET = "set"; @Id private String mid; + private String deviceId; + private String productKey; private String deviceName; /** * 消息类型 + * lifetime:生命周期 + * state:状态 * property:属性 * event:事件 * service:服务 @@ -45,13 +51,18 @@ public class ThingModelMessage { private String identifier; - private Map data; + /** + * 消息状态码 + */ + private int code; + + private Object data; /** * 时间戳,设备上的事件或数据产生的本地时间 */ @Field(type = FieldType.Date) - private Long occur; + private Long occurred; /** * 消息上报时间 diff --git a/pom.xml b/pom.xml index 14ab8abc..b9873bf3 100755 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,6 @@ 4.0.0 pom - device-server model rule-engine common @@ -181,13 +180,13 @@ io.vertx - vertx-web + vertx-mqtt 4.2.6 io.vertx - vertx-mqtt + vertx-web-proxy 4.2.6 @@ -209,36 +208,12 @@ ${project.version} - - cc.iotkit - device-api - ${project.version} - - cc.iotkit rule-engine ${project.version} - - cc.iotkit - gateway-client - ${project.version} - - - - cc.iotkit - decode-function - ${project.version} - - - - cc.iotkit - protocol-server - ${project.version} - - cc.iotkit component diff --git a/protocol-gateway/component-server/pom.xml b/protocol-gateway/component-server/pom.xml index 8def08ce..3fc4ffbb 100755 --- a/protocol-gateway/component-server/pom.xml +++ b/protocol-gateway/component-server/pom.xml @@ -3,10 +3,9 @@ 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 - ../../pom.xml 4.0.0 @@ -34,6 +33,15 @@ spring-context + + org.springframework.data + spring-data-redis + + + redis.clients + jedis + + org.slf4j slf4j-api 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/ComponentManager.java index 3662ffd6..2a60e15b 100755 --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentManager.java +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/ComponentManager.java @@ -1,14 +1,24 @@ package cc.iotkit.comps; +import cc.iotkit.common.exception.BizException; +import cc.iotkit.common.utils.JsonUtil; import cc.iotkit.comp.IComponent; +import cc.iotkit.comps.config.CacheKey; import cc.iotkit.comps.service.DeviceBehaviourService; +import cc.iotkit.converter.DeviceMessage; +import cc.iotkit.converter.ThingService; +import cc.iotkit.model.device.message.ThingModelMessage; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; +@Slf4j @Component public class ComponentManager { @@ -16,6 +26,8 @@ public class ComponentManager { @Autowired private DeviceBehaviourService deviceBehaviourService; + @Autowired + private StringRedisTemplate redisTemplate; public void register(String id, IComponent component) { components.put(id, component); @@ -31,8 +43,10 @@ public class ComponentManager { if (component == null) { return; } - component.setHandler(new MessageHandler(script, component.getConverter(), - deviceBehaviourService)); + component.setHandler( + new MessageHandler(this, component, + script, component.getConverter(), + deviceBehaviourService)); component.start(); } @@ -44,4 +58,42 @@ public class ComponentManager { component.stop(); } + public void send(ThingService service) { + log.info("start exec device service:{}", JsonUtil.toJsonString(service)); + if (components.size() == 0) { + throw new BizException("there is no components"); + } + + for (IComponent com : components.values()) { + if (com.exist(service.getProductKey(), service.getDeviceName())) { + DeviceMessage message = com.getConverter().encode(service, null); + if (message == null) { + throw new BizException("encode send message failed"); + } + //保存设备端mid与平台mid对应关系 + redisTemplate.opsForValue().set( + CacheKey.getKeyCmdMid(service.getDeviceName(), message.getMid()), + service.getMid(), com.getConfig().getCmdTimeout(), TimeUnit.SECONDS); + com.send(message); + + ThingModelMessage thingModelMessage = ThingModelMessage.builder() + .mid(service.getMid()) + .productKey(service.getProductKey()) + .deviceName(service.getDeviceName()) + .identifier(service.getIdentifier()) + .type(service.getType()) + .data(service.getParams()) + .build(); + deviceBehaviourService.reportMessage(thingModelMessage); + + return; + } + } + throw new BizException("send destination not found"); + } + + public String getPlatformMid(String deviceName, String mid) { + return redisTemplate.opsForValue().get(CacheKey.getKeyCmdMid(deviceName, mid)); + } + } 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/MessageHandler.java index b5393850..1c61dec1 100755 --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/MessageHandler.java +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/MessageHandler.java @@ -1,13 +1,18 @@ 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.IMessageHandler; -import cc.iotkit.comp.model.DeviceMessage; -import cc.iotkit.comps.model.AuthInfo; -import cc.iotkit.comps.model.DeviceState; -import cc.iotkit.comps.model.RegisterInfo; +import cc.iotkit.comp.model.AuthInfo; +import cc.iotkit.comp.model.ReceiveResult; +import cc.iotkit.comp.model.RegisterInfo; +import cc.iotkit.converter.DeviceMessage; +import cc.iotkit.comp.model.DeviceState; import cc.iotkit.comps.service.DeviceBehaviourService; import cc.iotkit.converter.IConverter; +import cc.iotkit.model.device.message.ThingModelMessage; import jdk.nashorn.api.scripting.NashornScriptEngine; import jdk.nashorn.api.scripting.ScriptObjectMirror; import lombok.Data; @@ -30,32 +35,32 @@ public class MessageHandler implements IMessageHandler { private final DeviceBehaviourService deviceBehaviourService; + private final ComponentManager componentManager; + + private final IComponent component; + @SneakyThrows - public MessageHandler(String script, IConverter converter, + public MessageHandler(ComponentManager componentManager, + IComponent component, + String script, IConverter converter, DeviceBehaviourService deviceBehaviourService) { + this.componentManager = componentManager; + this.component = component; this.converter = converter; this.deviceBehaviourService = deviceBehaviourService; scriptObj = engine.eval(script); } - public void register(Map head, String msg) { - } - - public void auth(Map head, String msg) { - } - - public void state(Map head, String msg) { - } - - public void onReceive(Map head, String type, String msg) { + public ReceiveResult onReceive(Map head, String type, String msg) { try { ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeMethod(scriptObj, "onReceive", head, type, msg); + log.info("onReceive script result:{}", JsonUtil.toJsonString(result)); Object rstType = result.get("type"); if (rstType == null) { - return; + return null; } //取脚本执行后返回的数据 - Object data = result.get("data"); + Object data = JsonUtil.toObject((ScriptObjectMirror) result.get("data")); if (!(data instanceof Map)) { throw new BizException("script result data is incorrect"); } @@ -63,24 +68,32 @@ public class MessageHandler implements IMessageHandler { if ("register".equals(rstType)) { //注册数据 - RegisterInfo regInfo = new RegisterInfo(); - BeanUtils.populate(regInfo, dataMap); + RegisterInfo regInfo = RegisterInfo.from(dataMap); + if (regInfo == null) { + return null; + } doRegister(regInfo); + return new ReceiveResult(regInfo.getProductKey(), regInfo.getDeviceName(), regInfo); } else if ("auth".equals(rstType)) { //设备认证 AuthInfo authInfo = new AuthInfo(); BeanUtils.populate(authInfo, dataMap); doAuth(authInfo); + return new ReceiveResult(authInfo.getProductKey(), authInfo.getDeviceName(), authInfo); } else if ("state".equals(rstType)) { //设备状态变更 - DeviceState state = new DeviceState(); - BeanUtils.populate(state, dataMap); + DeviceState state = DeviceState.from(dataMap); + if (state == null) { + return null; + } doStateChange(state); + return new ReceiveResult(state.getProductKey(), state.getDeviceName(), state); } else if ("report".equals(rstType)) { //上报数据 DeviceMessage message = new DeviceMessage(); BeanUtils.populate(message, dataMap); doReport(message); + return new ReceiveResult(message.getProductKey(), message.getDeviceName(), message); } } catch (BizException e) { @@ -88,6 +101,7 @@ public class MessageHandler implements IMessageHandler { } catch (Throwable e) { throw new BizException("receive component message error", e); } + return null; } private void doRegister(RegisterInfo reg) throws ScriptException, NoSuchMethodException { @@ -115,6 +129,7 @@ public class MessageHandler implements IMessageHandler { private void doStateChange(DeviceState state) { try { + component.onDeviceStateChange(state); deviceBehaviourService.deviceStateChange(state.getProductKey(), state.getDeviceName(), DeviceState.STATE_ONLINE.equals(state.getState())); @@ -124,10 +139,20 @@ public class MessageHandler implements IMessageHandler { } private void doReport(DeviceMessage message) { - try { - deviceBehaviourService.reportMessage(message); - } catch (Throwable e) { - log.error("report device message error", e); + ThingModelMessage thingModelMessage = converter.decode(message); + + //服务回复需要重新对应mid + if (thingModelMessage.getIdentifier().endsWith("_reply")) { + String platformMid = componentManager.getPlatformMid(message.getDeviceName(), message.getMid()); + if (platformMid == null) { + platformMid = UniqueIdUtil.newRequestId(); + } + thingModelMessage.setMid(platformMid); + } else { + //其它消息重新生成唯一MID + thingModelMessage.setMid(UniqueIdUtil.newRequestId()); } + + deviceBehaviourService.reportMessage(thingModelMessage); } } diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/config/CacheKey.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/config/CacheKey.java new file mode 100644 index 00000000..115cfe82 --- /dev/null +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/config/CacheKey.java @@ -0,0 +1,11 @@ +package cc.iotkit.comps.config; + +public class CacheKey { + + private static final String KEY_CMD_MID = "str:cmd:mid:%s:%s"; + + public static String getKeyCmdMid(String deviceName, String downMid) { + return String.format(KEY_CMD_MID, deviceName, downMid); + } + +} diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/model/AuthInfo.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/model/AuthInfo.java deleted file mode 100755 index cce5fc36..00000000 --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/model/AuthInfo.java +++ /dev/null @@ -1,15 +0,0 @@ -package cc.iotkit.comps.model; - -import lombok.Data; - -@Data -public class AuthInfo { - - private String productKey; - - private String deviceName; - - private String productSecret; - - private String deviceSecret; -} diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/model/DeviceState.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/model/DeviceState.java deleted file mode 100755 index 150ce9cb..00000000 --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/model/DeviceState.java +++ /dev/null @@ -1,17 +0,0 @@ -package cc.iotkit.comps.model; - -import lombok.Data; - -@Data -public class DeviceState { - - public static final String STATE_ONLINE = "online"; - public static final String STATE_OFFLINE = "offline"; - - private String productKey; - - private String deviceName; - - private String state; - -} diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/model/RegisterInfo.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/model/RegisterInfo.java deleted file mode 100755 index 0cc51c19..00000000 --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/model/RegisterInfo.java +++ /dev/null @@ -1,49 +0,0 @@ -package cc.iotkit.comps.model; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; -import java.util.Map; - -/** - * 注册信息 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class RegisterInfo { - - private String productKey; - - private String deviceName; - - private String model; - - private Map tag; - - private List subDevices; - - public RegisterInfo(String productKey, String deviceName, String model) { - this.productKey = productKey; - this.deviceName = deviceName; - this.model = model; - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class SubDevice { - - private String productKey; - - private String deviceName; - - private String model; - - private Map tag; - } -} diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java index ec5fd1c7..49adf445 100755 --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java @@ -3,12 +3,15 @@ package cc.iotkit.comps.service; import cc.iotkit.common.Constants; import cc.iotkit.common.exception.BizException; import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.comp.model.DeviceMessage; +import cc.iotkit.common.utils.UniqueIdUtil; +import cc.iotkit.comp.model.RegisterInfo; +import cc.iotkit.comp.model.DeviceState; import cc.iotkit.comps.config.ServerConfig; -import cc.iotkit.comps.model.RegisterInfo; +import cc.iotkit.dao.DeviceCache; import cc.iotkit.dao.DeviceRepository; import cc.iotkit.dao.ProductRepository; import cc.iotkit.model.device.DeviceInfo; +import cc.iotkit.model.device.message.ThingModelMessage; import cc.iotkit.model.product.Product; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomUtils; @@ -23,7 +26,6 @@ import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Optional; @Slf4j @@ -36,8 +38,12 @@ public class DeviceBehaviourService { private DeviceRepository deviceRepository; @Autowired private ServerConfig serverConfig; + @Autowired + private DeviceCache deviceCache; + @Autowired + private DeviceStateHolder deviceStateHolder; - private Producer deviceMessageProducer; + private Producer deviceMessageProducer; @PostConstruct public void init() throws PulsarClientException { @@ -45,13 +51,12 @@ public class DeviceBehaviourService { PulsarClient client = PulsarClient.builder() .serviceUrl(serverConfig.getPulsarBrokerUrl()) .build(); - deviceMessageProducer = client.newProducer(JSONSchema.of(DeviceMessage.class)) - .topic("persistent://public/default/device_raw") + deviceMessageProducer = client.newProducer(JSONSchema.of(ThingModelMessage.class)) + .topic("persistent://iotkit/default/device_thing") .create(); } - public void register(RegisterInfo info) { try { DeviceInfo deviceInfo = register(null, info); @@ -66,7 +71,17 @@ public class DeviceBehaviourService { subDevice.getTag(), null)); } } - //todo 产生设备注册事件 + + //设备注册消息 + ThingModelMessage modelMessage = new ThingModelMessage( + UniqueIdUtil.newRequestId(), "", + info.getProductKey(), info.getDeviceName(), + ThingModelMessage.TYPE_LIFETIME, "register", + 0, new HashMap<>(), System.currentTimeMillis(), + System.currentTimeMillis() + ); + + reportMessage(modelMessage); } catch (BizException e) { log.error("register device error", e); throw e; @@ -86,34 +101,20 @@ public class DeviceBehaviourService { DeviceInfo device = deviceRepository.findByProductKeyAndDeviceName(pk, info.getDeviceName()); if (device != null) { - //更新设备信息 - device.setParentId(parentId); - device.setUid(uid); - Map tag = info.getTag(); - Map oldTag = device.getTag(); - - if (oldTag == null) { - oldTag = new HashMap<>(); - } - - if (tag != null) { - oldTag.putAll(tag); - } - - device.setTag(oldTag); - } else { - //不存在,注册新设备 - device = new DeviceInfo(); - device.setId(newDeviceId(info.getDeviceName())); - device.setParentId(parentId); - device.setUid(uid); - device.setDeviceId(device.getId()); - device.setProductKey(pk); - device.setDeviceName(info.getDeviceName()); - device.setTag(info.getTag()); - device.setState(new DeviceInfo.State(false, null, null)); - device.setCreateAt(System.currentTimeMillis()); + log.info("device already registered."); + return device; } + //不存在,注册新设备 + device = new DeviceInfo(); + device.setId(newDeviceId(info.getDeviceName())); + device.setParentId(parentId); + device.setUid(uid); + device.setDeviceId(device.getId()); + device.setProductKey(pk); + device.setDeviceName(info.getDeviceName()); + device.setTag(info.getTag()); + device.setState(new DeviceInfo.State(false, null, null)); + device.setCreateAt(System.currentTimeMillis()); deviceRepository.save(device); log.info("device registered:{}", JsonUtil.toJsonString(device)); @@ -171,19 +172,60 @@ public class DeviceBehaviourService { if (device == null) { throw new BizException("device does not exist"); } + deviceStateChange(device, online); + //可能是父设备,父设备离线,子设备也要离线 + if (!online && device.getParentId() == null) { + List subDevices = deviceRepository.findByParentId(device.getDeviceId()); + for (DeviceInfo subDevice : subDevices) { + deviceStateChange(subDevice, false); + } + } + } + + private void deviceStateChange(DeviceInfo device, boolean online) { if (online) { device.getState().setOnline(true); device.getState().setOnlineTime(System.currentTimeMillis()); + deviceStateHolder.online(device.getDeviceId()); } else { device.getState().setOnline(false); device.getState().setOfflineTime(System.currentTimeMillis()); + deviceStateHolder.offline(device.getDeviceId()); } deviceRepository.save(device); - //todo 产生在离线事件 + + //设备状态变更消息 + ThingModelMessage modelMessage = new ThingModelMessage( + UniqueIdUtil.newRequestId(), "", + device.getProductKey(), device.getDeviceName(), + ThingModelMessage.TYPE_STATE, + online ? DeviceState.STATE_ONLINE : DeviceState.STATE_OFFLINE, + 0, + new HashMap<>(), System.currentTimeMillis(), + System.currentTimeMillis() + ); + + reportMessage(modelMessage); } - public void reportMessage(DeviceMessage message) throws PulsarClientException { - deviceMessageProducer.send(message); + public void reportMessage(ThingModelMessage message) { + try { + DeviceInfo device = deviceCache.findByProductKeyAndDeviceName(message.getProductKey(), + message.getDeviceName()); + if (device == null) { + return; + } + if (message.getOccurred() == null) { + message.setOccurred(System.currentTimeMillis()); + } + if (message.getTime() == null) { + message.setTime(System.currentTimeMillis()); + } + message.setDeviceId(device.getDeviceId()); + deviceMessageProducer.send(message); + } catch (PulsarClientException e) { + log.error("send thing model message error", e); + } } } diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceMessageConsumer.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceMessageConsumer.java index 8a90b95b..5a727588 100755 --- a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceMessageConsumer.java +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceMessageConsumer.java @@ -3,9 +3,12 @@ package cc.iotkit.comps.service; import cc.iotkit.common.Constants; import cc.iotkit.common.utils.JsonUtil; import cc.iotkit.comps.config.ServerConfig; +import cc.iotkit.dao.DeviceDao; +import cc.iotkit.dao.DevicePropertyRepository; import cc.iotkit.dao.ThingModelMessageRepository; import cc.iotkit.dao.UserInfoRepository; import cc.iotkit.model.UserInfo; +import cc.iotkit.model.device.message.DeviceProperty; import cc.iotkit.model.device.message.ThingModelMessage; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -14,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @Slf4j @@ -21,20 +25,21 @@ import java.util.stream.Collectors; public class DeviceMessageConsumer implements MessageListener { private final ServerConfig serverConfig; - private final ThingModelMessageRepository messageRepository; - - private final UserInfoRepository userInfoRepository; + private final DevicePropertyRepository propertyRepository; + private final DeviceDao deviceDao; @SneakyThrows @Autowired public DeviceMessageConsumer(ServerConfig serverConfig, ThingModelMessageRepository messageRepository, - UserInfoRepository userInfoRepository) { + UserInfoRepository userInfoRepository, + DevicePropertyRepository propertyRepository, + DeviceDao deviceDao) { this.serverConfig = serverConfig; this.messageRepository = messageRepository; - this.userInfoRepository = userInfoRepository; - + this.propertyRepository = propertyRepository; + this.deviceDao = deviceDao; PulsarClient client = PulsarClient.builder() .serviceUrl(this.serverConfig.getPulsarBrokerUrl()) .build(); @@ -56,14 +61,34 @@ public class DeviceMessageConsumer implements MessageListener @Override public void received(Consumer consumer, Message msg) { ThingModelMessage modelMessage = msg.getValue(); - log.info("receive message:{}", JsonUtil.toJsonString(modelMessage)); + String deviceId = modelMessage.getDeviceId(); + log.info("save message to es:{}", JsonUtil.toJsonString(modelMessage)); + //属性入库 + if (ThingModelMessage.TYPE_PROPERTY.equals(modelMessage.getType()) + && "report".equals(modelMessage.getIdentifier())) { + log.info("update device property,deviceId:{},property:{}", + deviceId, JsonUtil.toJsonString(modelMessage.getData())); + deviceDao.updateProperties(deviceId, (Map) modelMessage.getData()); + + //设备属性历史数据存储 + if (modelMessage.getData() instanceof Map) { + Map map = (Map) modelMessage.getData(); + for (Object key : map.keySet()) { + propertyRepository.save( + new DeviceProperty( + modelMessage.getMid(), + deviceId, + key.toString(), + map.get(key), + modelMessage.getOccurred() + ) + ); + } + } + } + //设备消息日志入库 messageRepository.save(modelMessage); - - messageRepository.findAll().forEach(m -> { - log.info(JsonUtil.toJsonString(m)); - }); - consumer.acknowledge(msg); } diff --git a/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceStateHolder.java b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceStateHolder.java new file mode 100644 index 00000000..95811205 --- /dev/null +++ b/protocol-gateway/component-server/src/main/java/cc/iotkit/comps/service/DeviceStateHolder.java @@ -0,0 +1,122 @@ +package cc.iotkit.comps.service; + +import cc.iotkit.common.utils.ThreadUtil; +import cc.iotkit.comps.config.ServerConfig; +import cc.iotkit.dao.DeviceRepository; +import cc.iotkit.model.device.DeviceInfo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.apache.pulsar.client.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * 设备状态维持,每1分钟更新一次心跳 + */ +@Slf4j +@Service +public class DeviceStateHolder implements MessageListener { + + private ScheduledThreadPoolExecutor stateHolderTask; + + private Set devices = new TreeSet<>(); + + @Autowired + private StringRedisTemplate redisTemplate; + @Autowired + private ServerConfig serverConfig; + @Autowired + private DeviceRepository deviceRepository; + + private Producer offlineMessageProducer; + + @PostConstruct + public void init() throws PulsarClientException { + stateHolderTask = ThreadUtil.newScheduled(4, "thread-device-state-holder"); + stateHolderTask.scheduleAtFixedRate(this::hold, 0, 1, TimeUnit.MINUTES); + + PulsarClient client = PulsarClient.builder() + .serviceUrl(this.serverConfig.getPulsarBrokerUrl()) + .build(); + + offlineMessageProducer = client.newProducer(Schema.JSON(OfflineMessage.class)) + .topic("persistent://iotkit/default/holder_offline") + .create(); + + client.newConsumer(Schema.JSON(OfflineMessage.class)) + .topic("persistent://iotkit/default/holder_offline") + .subscriptionName("holder_offline") + .consumerName("device-state-holder-consumer") + .messageListener(this).subscribe(); + } + + public void online(String deviceId) { + try { + devices.add(deviceId); + hold(deviceId); + //上线后先产生离线消息 + offlineMessageProducer.send(new OfflineMessage(deviceId)); + } catch (Throwable e) { + log.error("state holder online error", e); + } + } + + public void offline(String deviceId) { + devices.remove(deviceId); + } + + private void hold() { + //标识在线 + for (String deviceId : devices) { + hold(deviceId); + } + } + + private void hold(String deviceId) { + redisTemplate.opsForValue().set("str:device:state:holder:" + deviceId, + "1", 5, TimeUnit.SECONDS); + } + + @SneakyThrows + @Override + public void received(Consumer consumer, Message msg) { + String deviceId = msg.getValue().getDeviceId(); + //如果设备在线,不处理离线消息 + String hold = redisTemplate.opsForValue().get("str:device:state:holder:" + deviceId); + if (hold != null) { + return; + } + //如果设备不在线,则将设备更新为离线 + DeviceInfo device = deviceRepository.findByDeviceId(deviceId); + DeviceInfo.State state = device.getState(); + state.setOnline(false); + state.setOfflineTime(System.currentTimeMillis()); + deviceRepository.save(device); + log.info("device offline,deviceId:{}", deviceId); + + consumer.acknowledge(msg); + } + + @Override + public void reachedEndOfTopic(Consumer consumer) { + + } + + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class OfflineMessage { + private String deviceId; + } +} diff --git a/protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractComponent.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractComponent.java index da9714f4..81e7936f 100755 --- a/protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractComponent.java +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/AbstractComponent.java @@ -10,4 +10,15 @@ public abstract class AbstractComponent implements IComponent { protected IConverter converter; + protected CompConfig config; + + @Override + public void create(CompConfig config) { + this.config=config; + } + + @Override + public CompConfig getConfig() { + return config; + } } diff --git a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/Result.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/CompConfig.java old mode 100755 new mode 100644 similarity index 56% rename from protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/Result.java rename to protocol-gateway/component/src/main/java/cc/iotkit/comp/CompConfig.java index 10479669..724c7a85 --- a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/Result.java +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/CompConfig.java @@ -1,4 +1,4 @@ -package cc.iotkit.protocol; +package cc.iotkit.comp; import lombok.AllArgsConstructor; import lombok.Data; @@ -7,10 +7,10 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor -public class Result { +public class CompConfig { - private boolean success; + private long cmdTimeout; - private String content; + private String other; } 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 index 0d8b4f53..110e89c5 100755 --- 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,10 +1,13 @@ package cc.iotkit.comp; +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(String config); + void create(CompConfig config); void start(); @@ -12,10 +15,17 @@ public interface IComponent { void destroy(); + 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(); } diff --git a/protocol-gateway/component/src/main/java/cc/iotkit/comp/IMessageHandler.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/IMessageHandler.java index 54a7d4ec..e3eed223 100755 --- a/protocol-gateway/component/src/main/java/cc/iotkit/comp/IMessageHandler.java +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/IMessageHandler.java @@ -1,14 +1,10 @@ package cc.iotkit.comp; +import cc.iotkit.comp.model.ReceiveResult; + import java.util.Map; public interface IMessageHandler { - void register(Map head, String msg); - - void auth(Map head, String msg); - - void state(Map head, String msg); - - void onReceive(Map head, String type, String msg); + ReceiveResult onReceive(Map head, String type, String msg); } diff --git a/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/AuthInfo.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/AuthInfo.java index 4aae434a..29a61d53 100755 --- a/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/AuthInfo.java +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/AuthInfo.java @@ -9,4 +9,8 @@ public class AuthInfo { private String deviceName; + private String productSecret; + + private String deviceSecret; + } diff --git a/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/DeviceState.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/DeviceState.java new file mode 100755 index 00000000..bff86846 --- /dev/null +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/DeviceState.java @@ -0,0 +1,33 @@ +package cc.iotkit.comp.model; + +import cc.iotkit.common.utils.JsonUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.util.Map; + +@Data +@Slf4j +public class DeviceState { + + public static final String STATE_ONLINE = "online"; + public static final String STATE_OFFLINE = "offline"; + + private String productKey; + + private String deviceName; + + private String state; + + private Parent parent; + + public static DeviceState from(Map map) { + return JsonUtil.parse(JsonUtil.toJsonString(map), DeviceState.class); + } + + @Data + public static class Parent { + private String productKey; + private String deviceName; + } +} diff --git a/protocol-gateway/decode-function/src/main/java/cc/iotkit/protocol/function/DeviceMessage.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/ReceiveResult.java old mode 100755 new mode 100644 similarity index 53% rename from protocol-gateway/decode-function/src/main/java/cc/iotkit/protocol/function/DeviceMessage.java rename to protocol-gateway/component/src/main/java/cc/iotkit/comp/model/ReceiveResult.java index 1066d03d..3119ff7c --- a/protocol-gateway/decode-function/src/main/java/cc/iotkit/protocol/function/DeviceMessage.java +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/ReceiveResult.java @@ -1,25 +1,18 @@ -package cc.iotkit.protocol.function; +package cc.iotkit.comp.model; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -/** - * 设备消息 - */ @Data @NoArgsConstructor @AllArgsConstructor -@Builder -public class DeviceMessage { +public class ReceiveResult { private String productKey; private String deviceName; - private String mid; - - private String content; + private Object data; } diff --git a/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/RegisterInfo.java b/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/RegisterInfo.java index 84357c91..4decb820 100755 --- a/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/RegisterInfo.java +++ b/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/RegisterInfo.java @@ -4,13 +4,17 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.beanutils.BeanUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 注册信息 */ +@Slf4j @Data @NoArgsConstructor @AllArgsConstructor @@ -33,6 +37,38 @@ public class RegisterInfo { this.model = model; } + public RegisterInfo(String productKey, String deviceName, String subProductKey, String subDeviceName) { + this.productKey = productKey; + this.deviceName = deviceName; + if (subProductKey != null && subDeviceName != null) { + SubDevice subDevice = new SubDevice(subProductKey, subDeviceName, null, null); + subDevices = new ArrayList<>(); + subDevices.add(subDevice); + } + } + + public static RegisterInfo from(Map map) { + RegisterInfo bean = new RegisterInfo(); + try { + BeanUtils.populate(bean, map); + List subDevices = new ArrayList<>(); + List sourceSubDevices = (List) map.get("subDevices"); + if (sourceSubDevices == null) { + return bean; + } + for (Object sourceSubDevice : sourceSubDevices) { + SubDevice subDevice = new SubDevice(); + BeanUtils.populate(subDevice, (Map) sourceSubDevice); + subDevices.add(subDevice); + } + bean.setSubDevices(subDevices); + } catch (Throwable e) { + log.error("parse bean from map error", e); + return null; + } + return bean; + } + @Data @NoArgsConstructor @AllArgsConstructor @@ -46,4 +82,4 @@ public class RegisterInfo { private Map tag; } -} +} \ No newline at end of file diff --git a/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/DeviceMessage.java b/protocol-gateway/converter/src/main/java/cc/iotkit/converter/DeviceMessage.java similarity index 71% rename from protocol-gateway/component/src/main/java/cc/iotkit/comp/model/DeviceMessage.java rename to protocol-gateway/converter/src/main/java/cc/iotkit/converter/DeviceMessage.java index 3cc305c7..a5f3ce66 100755 --- a/protocol-gateway/component/src/main/java/cc/iotkit/comp/model/DeviceMessage.java +++ b/protocol-gateway/converter/src/main/java/cc/iotkit/converter/DeviceMessage.java @@ -1,4 +1,4 @@ -package cc.iotkit.comp.model; +package cc.iotkit.converter; import lombok.Data; @@ -11,5 +11,5 @@ public class DeviceMessage { private String mid; - private String content; + private Object content; } diff --git a/protocol-gateway/converter/src/main/java/cc/iotkit/converter/DeviceService.java b/protocol-gateway/converter/src/main/java/cc/iotkit/converter/DeviceService.java deleted file mode 100755 index efa87010..00000000 --- a/protocol-gateway/converter/src/main/java/cc/iotkit/converter/DeviceService.java +++ /dev/null @@ -1,20 +0,0 @@ -package cc.iotkit.converter; - -import lombok.Data; - -@Data -public class DeviceService { - - private String mid; - - private String productKey; - - private String deviceName; - - private String type; - - private String identifier; - - private T params; - -} diff --git a/protocol-gateway/converter/src/main/java/cc/iotkit/converter/IConverter.java b/protocol-gateway/converter/src/main/java/cc/iotkit/converter/IConverter.java index 93230295..d5c208da 100755 --- a/protocol-gateway/converter/src/main/java/cc/iotkit/converter/IConverter.java +++ b/protocol-gateway/converter/src/main/java/cc/iotkit/converter/IConverter.java @@ -6,8 +6,8 @@ public interface IConverter { void setScript(String script); - ThingModelMessage decode(String msg); + ThingModelMessage decode(DeviceMessage msg); - String encode(DeviceService service, Device device); + DeviceMessage encode(ThingService service, Device device); } diff --git a/protocol-gateway/converter/src/main/java/cc/iotkit/converter/ScriptConverter.java b/protocol-gateway/converter/src/main/java/cc/iotkit/converter/ScriptConverter.java index 75517bf5..8e7ec8fd 100755 --- a/protocol-gateway/converter/src/main/java/cc/iotkit/converter/ScriptConverter.java +++ b/protocol-gateway/converter/src/main/java/cc/iotkit/converter/ScriptConverter.java @@ -1,5 +1,6 @@ package cc.iotkit.converter; +import cc.iotkit.common.utils.JsonUtil; import cc.iotkit.model.device.message.ThingModelMessage; import jdk.nashorn.api.scripting.NashornScriptEngine; import jdk.nashorn.api.scripting.ScriptObjectMirror; @@ -9,26 +10,26 @@ import org.apache.commons.beanutils.BeanUtils; import javax.script.ScriptEngineManager; import javax.script.ScriptException; +import java.util.Map; @Slf4j @Data public class ScriptConverter implements IConverter { private final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn"); - private String script; + private Object scriptObj; public void setScript(String script) { - this.script = script; try { - engine.eval(script); + scriptObj = engine.eval(script); } catch (ScriptException e) { log.error("eval converter script error", e); } } - public ThingModelMessage decode(String msg) { + public ThingModelMessage decode(DeviceMessage msg) { try { - ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeFunction("decode", msg); + ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeMethod(scriptObj, "decode", msg); ThingModelMessage modelMessage = new ThingModelMessage(); BeanUtils.populate(modelMessage, result); return modelMessage; @@ -39,10 +40,13 @@ public class ScriptConverter implements IConverter { } @Override - public String encode(DeviceService service, Device device) { + public DeviceMessage encode(ThingService service, Device device) { try { - ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeFunction("encode", service, device); - return result.toString(); + ScriptObjectMirror result = (ScriptObjectMirror) engine.invokeMethod(scriptObj, "encode", service, device); + Map map = (Map) JsonUtil.toObject(result); + DeviceMessage message = new DeviceMessage(); + BeanUtils.populate(message, map); + return message; } catch (Throwable e) { log.error("execute encode script error", e); } diff --git a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeviceMessage.java b/protocol-gateway/converter/src/main/java/cc/iotkit/converter/ThingService.java similarity index 64% rename from protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeviceMessage.java rename to protocol-gateway/converter/src/main/java/cc/iotkit/converter/ThingService.java index cc2d18de..5f32c50f 100755 --- a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeviceMessage.java +++ b/protocol-gateway/converter/src/main/java/cc/iotkit/converter/ThingService.java @@ -1,25 +1,26 @@ -package cc.iotkit.protocol; +package cc.iotkit.converter; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -/** - * 设备消息 - */ @Data @NoArgsConstructor @AllArgsConstructor @Builder -public class DeviceMessage { +public class ThingService { + + private String mid; private String productKey; private String deviceName; - private String mid; + private String type; - private String content; + private String identifier; + + private T params; } diff --git a/protocol-gateway/decode-function/.DS_Store b/protocol-gateway/decode-function/.DS_Store deleted file mode 100755 index ee771938..00000000 Binary files a/protocol-gateway/decode-function/.DS_Store and /dev/null differ diff --git a/protocol-gateway/decode-function/pom.xml b/protocol-gateway/decode-function/pom.xml deleted file mode 100755 index abdc3fcb..00000000 --- a/protocol-gateway/decode-function/pom.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - iotkit-parent - cc.iotkit - 0.0.1-SNAPSHOT - ../../pom.xml - - 4.0.0 - - decode-function - - - - org.apache.pulsar - pulsar-functions-api - - - - org.projectlombok - lombok - - - - cc.iotkit - common - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.1.0 - - - - cc.iotkit.fun.TestFunction - - - - jar-with-dependencies - - - - - make-assembly - package - - single - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - - - \ No newline at end of file diff --git a/protocol-gateway/decode-function/src/main/java/cc/iotkit/protocol/function/DecodeFunction.java b/protocol-gateway/decode-function/src/main/java/cc/iotkit/protocol/function/DecodeFunction.java deleted file mode 100755 index dce944b0..00000000 --- a/protocol-gateway/decode-function/src/main/java/cc/iotkit/protocol/function/DecodeFunction.java +++ /dev/null @@ -1,51 +0,0 @@ -package cc.iotkit.protocol.function; - -import cc.iotkit.common.utils.JsonUtil; -import jdk.nashorn.api.scripting.NashornScriptEngine; -import org.apache.pulsar.functions.api.Context; -import org.apache.pulsar.functions.api.Function; - -import javax.script.*; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 上行消息转换函数 - */ -public class DecodeFunction implements Function { - - private static final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn"); - private static final Map compiledScripts = new ConcurrentHashMap<>(); - - @Override - public ThingModelMessage process(DeviceMessage msg, Context context) throws Exception { - Optional optGateway = context.getUserConfigValue("gateway"); - Optional optScript = context.getUserConfigValue("script"); - if (!optGateway.isPresent() || !optScript.isPresent()) { - return null; - } - - String gateway = optGateway.get().toString(); - compiledScripts.putIfAbsent(gateway, engine.compile(optScript.get() + ".decode(msg)")); - - CompiledScript script = compiledScripts.get(gateway); - context.getLogger().debug(script.toString()); - - Map data = new HashMap<>(); - data.putIfAbsent("msg", msg); - Bindings bindings = new SimpleBindings(data); - Object result = script.eval(bindings); - - if (result == null) { - context.getLogger().error("translate msg failed:{}", JsonUtil.toJsonString(msg)); - return null; - } - if (result instanceof Map) { - return ThingModelMessage.from((Map) result); - } - return null; - } - -} diff --git a/protocol-gateway/decode-function/src/main/java/cc/iotkit/protocol/function/ThingModelMessage.java b/protocol-gateway/decode-function/src/main/java/cc/iotkit/protocol/function/ThingModelMessage.java deleted file mode 100755 index 3904273b..00000000 --- a/protocol-gateway/decode-function/src/main/java/cc/iotkit/protocol/function/ThingModelMessage.java +++ /dev/null @@ -1,62 +0,0 @@ -package cc.iotkit.protocol.function; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.HashMap; -import java.util.Map; - -/** - * 物模型消息 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class ThingModelMessage { - - private String productKey; - - private String deviceName; - - private String mid; - - private String identifier; - - private Map data; - - /** - * 时间戳,设备上的事件或数据产生的本地时间 - */ - private Long occur; - - /** - * 消息上报时间 - */ - private Long time; - - public static ThingModelMessage from(Map map) { - ThingModelMessage message = new ThingModelMessage(); - message.setProductKey(getStr(map, "productKey")); - message.setDeviceName(getStr(map, "deviceName")); - message.setMid(getStr(map, "mid")); - message.setIdentifier(getStr(map, "identifier")); - Object data = map.get("data"); - if (data instanceof Map) { - message.setData((Map) data); - } else { - message.setData(new HashMap<>()); - } - return message; - } - - private static String getStr(Map map, String key) { - Object val = map.get(key); - if (val == null) { - return null; - } - return val.toString(); - } -} diff --git a/protocol-gateway/gateway-client/pom.xml b/protocol-gateway/emqx-component/pom.xml old mode 100755 new mode 100644 similarity index 57% rename from protocol-gateway/gateway-client/pom.xml rename to protocol-gateway/emqx-component/pom.xml index 9f54e7c2..55ea7dbc --- a/protocol-gateway/gateway-client/pom.xml +++ b/protocol-gateway/emqx-component/pom.xml @@ -9,33 +9,28 @@ 4.0.0 - gateway-client - - - 8 - 8 - + emqx-component - org.springframework - spring-web + io.vertx + vertx-core - com.squareup.okhttp3 - okhttp + io.vertx + vertx-web-proxy - org.apache.pulsar - pulsar-client + io.vertx + vertx-mqtt - org.projectlombok - lombok + cc.iotkit + model @@ -43,6 +38,11 @@ common + + cc.iotkit + component + + \ No newline at end of file diff --git a/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/AuthVerticle.java b/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/AuthVerticle.java new file mode 100644 index 00000000..9a89df27 --- /dev/null +++ b/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/AuthVerticle.java @@ -0,0 +1,70 @@ +package cc.iotkit.comp.emqx; + +import cc.iotkit.comp.IMessageHandler; +import io.vertx.core.AbstractVerticle; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpServer; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.Router; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class AuthVerticle extends AbstractVerticle { + + private HttpServer backendServer; + + private IMessageHandler executor; + + private EmqxConfig config; + + public void setExecutor(IMessageHandler executor) { + this.executor = executor; + } + + public AuthVerticle(EmqxConfig config) { + this.config = config; + } + + @Override + public void start() throws Exception { + backendServer = vertx.createHttpServer(); + Router backendRouter = Router.router(vertx); + + backendRouter.route(HttpMethod.POST, "/mqtt/auth").handler(rc -> { + JsonObject json = rc.getBodyAsJson(); + try { + executor.onReceive(new HashMap<>(), "auth", json.toString()); + rc.response().setStatusCode(200) + .end(); + } catch (Throwable e) { + rc.response().setStatusCode(500) + .end(); + log.error("mqtt auth failed", e); + } + }); + backendRouter.route(HttpMethod.POST, "/mqtt/acl").handler(rc -> { + JsonObject json = rc.getBodyAsJson(); + try { + Map head = new HashMap<>(); + head.put("topic", json.getString("topic")); + executor.onReceive(head, "subscribe", json.toString()); + rc.response().setStatusCode(200) + .end(); + } catch (Throwable e) { + rc.response().setStatusCode(500) + .end(); + log.error("mqtt acl failed", e); + } + }); + + backendServer.requestHandler(backendRouter).listen(config.getAuthPort()); + } + + @Override + public void stop() throws Exception { + backendServer.close(voidAsyncResult -> log.info("close emqx auth server...")); + } +} 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/EmqxComponent.java new file mode 100644 index 00000000..b698e745 --- /dev/null +++ b/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxComponent.java @@ -0,0 +1,147 @@ +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.CompConfig; +import cc.iotkit.comp.model.DeviceState; +import cc.iotkit.converter.DeviceMessage; +import io.vertx.core.Future; +import io.vertx.core.Vertx; +import io.vertx.mqtt.MqttClient; +import io.vertx.mqtt.MqttClientOptions; +import io.vertx.mqtt.messages.MqttConnAckMessage; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +@Slf4j +public class EmqxComponent extends AbstractComponent { + + private Vertx vertx; + private AuthVerticle authVerticle; + private CountDownLatch countDownLatch; + private String deployedId; + private EmqxConfig mqttConfig; + + public void create(CompConfig config) { + super.create(config); + vertx = Vertx.vertx(); + mqttConfig = JsonUtil.parse(config.getOther(), EmqxConfig.class); + authVerticle = new AuthVerticle(mqttConfig); + } + + @Override + public void start() { + try { + authVerticle.setExecutor(getHandler()); + countDownLatch = new CountDownLatch(1); + Future future = vertx.deployVerticle(authVerticle); + future.onSuccess((s -> { + deployedId = s; + countDownLatch.countDown(); + })); + future.onFailure((e) -> { + countDownLatch.countDown(); + log.error("start emqx auth component failed", e); + }); + countDownLatch.await(); + + MqttClientOptions options = new MqttClientOptions() + .setClientId(mqttConfig.getClientId()) + .setUsername(mqttConfig.getUsername()) + .setPassword(mqttConfig.getPassword()) + .setCleanSession(true) + .setKeepAliveInterval(60); + + if (mqttConfig.isSsl()) { + options.setSsl(true) + .setTrustAll(true); + } + MqttClient client = MqttClient.create(vertx, options); + + Future connFuture = + client.connect(mqttConfig.getPort(), mqttConfig.getBroker()); + connFuture.onSuccess(ack -> log.info("connect emqx broker success")) + .onFailure(e -> log.error("connect emqx broker failed", e)); + + List topics = mqttConfig.getSubscribeTopics(); + Map subscribes = new HashMap<>(); + for (String topic : topics) { + subscribes.put(topic, 1); + } + + client.publishHandler(s -> { + String topic = s.topicName(); + String payload = s.payload().toString(); + log.info("receive message,topic:{},payload:{}", topic, payload); + +// +// //取消订阅 +// if (topic.equals("/sys/session/topic/unsubscribed")) { +// topicUnsubscribed(payload); +// return; +// } +// +// //连接断开 +// if (topic.equals("/sys/client/disconnected")) { +// disconnectedHandler.handler(payload); +// return; +// } +// +// String[] parts = topic.split("/"); +// if (parts.length < 5) { +// log.error("message topic is illegal."); +// return; +// } +// String productKey = parts[2]; +// String deviceName = parts[3]; +// +// //子设备注册 +// if (topic.endsWith("/register")) { + + + Map head = new HashMap<>(); + head.put("topic", topic); + getHandler().onReceive(head, "", payload); + }).subscribe(subscribes).onSuccess(a -> log.info("subscribe topic success")) + .onFailure(e -> log.error("subscribe topic failed", e)); + + } catch (Throwable e) { + throw new BizException("start emqx auth component error", e); + } + } + + @SneakyThrows + @Override + public void stop() { + authVerticle.stop(); + Future future = vertx.undeploy(deployedId); + future.onSuccess(unused -> log.info("stop emqx auth component success")); + } + + @Override + public void destroy() { + + } + + @Override + public void onDeviceStateChange(DeviceState state) { + + } + + @Override + public void send(DeviceMessage message) { + + } + + @Override + public boolean exist(String productKey, String deviceName) { + return false; + } + +} diff --git a/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxConfig.java b/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxConfig.java new file mode 100644 index 00000000..4c3cf453 --- /dev/null +++ b/protocol-gateway/emqx-component/src/main/java/cc/iotkit/comp/emqx/EmqxConfig.java @@ -0,0 +1,25 @@ +package cc.iotkit.comp.emqx; + +import lombok.Data; + +import java.util.List; + +@Data +public class EmqxConfig { + + private int authPort; + + private String broker; + + private int port; + + private boolean ssl; + + private String clientId; + + private String username; + + private String password; + + private List subscribeTopics; +} diff --git a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeregisterInfo.java b/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeregisterInfo.java deleted file mode 100755 index 4e8f03ed..00000000 --- a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeregisterInfo.java +++ /dev/null @@ -1,17 +0,0 @@ -package cc.iotkit.protocol; - -import lombok.Data; - - -/** - * 注销信息 - */ -@Data -public class DeregisterInfo { - - private String productKey; - - private String deviceName; - - private boolean cascade; -} diff --git a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeviceBehaviour.java b/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeviceBehaviour.java deleted file mode 100755 index f4e944a6..00000000 --- a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeviceBehaviour.java +++ /dev/null @@ -1,34 +0,0 @@ -package cc.iotkit.protocol; - - -/** - * 设备行为接口 - */ -public interface DeviceBehaviour { - - /** - * 设备注册 - */ - Result register(RegisterInfo info); - - /** - * 设备上线 - */ - Result online(String productKey, String deviceName); - - /** - * 设备离线 - */ - Result offline(String productKey, String deviceName); - - /** - * 设备消息上报 - */ - void messageReport(DeviceMessage msg); - - /** - * OTA消息上报 - */ - void otaProgressReport(OtaMessage msg); - -} diff --git a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeviceGateway.java b/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeviceGateway.java deleted file mode 100755 index d9e125af..00000000 --- a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/DeviceGateway.java +++ /dev/null @@ -1,23 +0,0 @@ -package cc.iotkit.protocol; - - -import org.springframework.web.bind.annotation.RequestMapping; - -/** - * 设备网关接口 - */ -public interface DeviceGateway { - - /** - * 指令下发 - */ - @RequestMapping("/sendMessage") - Result sendMessage(DeviceMessage msg); - - /** - * OTA升级任务下发 - */ - @RequestMapping("/sendOta") - Result sendOta(OtaInfo ota); - -} diff --git a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/OtaInfo.java b/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/OtaInfo.java deleted file mode 100755 index d064e65e..00000000 --- a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/OtaInfo.java +++ /dev/null @@ -1,7 +0,0 @@ -package cc.iotkit.protocol; - -import lombok.Data; - -@Data -public class OtaInfo { -} diff --git a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/OtaMessage.java b/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/OtaMessage.java deleted file mode 100755 index 65ad1be2..00000000 --- a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/OtaMessage.java +++ /dev/null @@ -1,30 +0,0 @@ -package cc.iotkit.protocol; - -import lombok.Data; - -/** - * OTA消息 - */ -@Data -public class OtaMessage { - - private final String TYPE_PROGRESS="progress"; - private final String TYPE_RESULT="result"; - - private final String PROGRESS_DOWNLOADING="downloading"; - private final String PROGRESS_DOWNLOADED="downloaded"; - private final String PROGRESS_UPGRADING="upgrading"; - private final String PROGRESS_UPGRADED="upgraded"; - - private String productKey; - - private String deviceName; - - private String type; - - private String jobId; - - private String progress; - - private String result; -} diff --git a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/RegisterInfo.java b/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/RegisterInfo.java deleted file mode 100755 index 7fd26c75..00000000 --- a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/RegisterInfo.java +++ /dev/null @@ -1,49 +0,0 @@ -package cc.iotkit.protocol; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; -import java.util.Map; - -/** - * 注册信息 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class RegisterInfo { - - private String productKey; - - private String deviceName; - - private String model; - - private Map tag; - - private List subDevices; - - public RegisterInfo(String productKey, String deviceName, String model) { - this.productKey = productKey; - this.deviceName = deviceName; - this.model = model; - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class SubDevice { - - private String productKey; - - private String deviceName; - - private String model; - - private Map tag; - } -} diff --git a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/client/DeviceBehaviourClient.java b/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/client/DeviceBehaviourClient.java deleted file mode 100755 index b1976e89..00000000 --- a/protocol-gateway/gateway-client/src/main/java/cc/iotkit/protocol/client/DeviceBehaviourClient.java +++ /dev/null @@ -1,151 +0,0 @@ -package cc.iotkit.protocol.client; - -import cc.iotkit.common.exception.BizException; -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.protocol.*; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.SneakyThrows; -import okhttp3.*; -import org.apache.pulsar.client.api.Producer; -import org.apache.pulsar.client.api.PulsarClient; -import org.apache.pulsar.client.impl.schema.JSONSchema; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -public class DeviceBehaviourClient implements DeviceBehaviour { - - public final String gatewayServer; - - private GatewayConfig gatewayConfig; - - private final OkHttpClient httpClient; - - private Producer deviceMessageProducer; - - private Producer otaMessageProducer; - - - @SneakyThrows - public DeviceBehaviourClient(String server) { - //初始化协议网关http客户端 - this.gatewayServer = server.replaceAll("/$", ""); - httpClient = new OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(30, TimeUnit.SECONDS) - .build(); - - //获取协议网关配置 - getConfig(); - - //初始化pulsar客户端 - PulsarClient client = PulsarClient.builder() - .serviceUrl(gatewayConfig.getMqServiceUrl()) - .build(); - - deviceMessageProducer = client.newProducer(JSONSchema.of(DeviceMessage.class)) - .topic("persistent://public/default/device_raw") - .create(); - - otaMessageProducer = client.newProducer(JSONSchema.of(OtaMessage.class)) - .topic("persistent://public/default/device_ota") - .create(); - } - - public Request buildRequest(String url, String method, String type, Map data) { - Request.Builder requestBuilder = new Request.Builder() - .url(url); - - RequestBody requestBody; - if ("json".equals(type)) { - requestBody = RequestBody.create(MediaType.get("application/json; charset=utf-8"), - JsonUtil.toJsonString(data)); - } else { - FormBody.Builder builder = new FormBody.Builder(); - data.forEach((key, val) -> builder.add(key, val.toString())); - requestBody = builder.build(); - } - requestBuilder.method(method.toUpperCase(), requestBody); - return requestBuilder.build(); - } - - - private Result invoke(String path, T data) { - return invoke(path, "form", data); - } - - private Result invokeJson(String path, T data) { - return invoke(path, "json", data); - } - - private Result invoke(String path, String type, T data) { - Request request = buildRequest(gatewayServer + path, "post", type, - (data instanceof Map) ? (Map) data : - JsonUtil.parse(JsonUtil.toJsonString(data), Map.class)); - - Call call = httpClient.newCall(request); - try { - Response response = call.execute(); - if (!response.isSuccessful() || response.body() == null) { - return new Result(false, "Remote interface call failed:" + response.body().string()); - } - String content = response.body().string(); - return JsonUtil.parse(content, Result.class); - } catch (Throwable e) { - return new Result(false, "Interface call failed:" + e.getMessage()); - } - } - - private void getConfig() { - if (this.gatewayConfig == null) { - Result result = invoke("/getConfig", new HashMap<>()); - if (!result.isSuccess()) { - throw new BizException("get gateway config failed"); - } - this.gatewayConfig = JsonUtil.parse(result.getContent(), GatewayConfig.class); - } - } - - @Override - public Result register(RegisterInfo info) { - return invokeJson("/register", info); - } - - @Override - public Result online(String productKey, String deviceName) { - Map data = new HashMap<>(); - data.put("productKey", productKey); - data.put("deviceName", deviceName); - return invoke("/online", data); - } - - @Override - public Result offline(String productKey, String deviceName) { - Map data = new HashMap<>(); - data.put("productKey", productKey); - data.put("deviceName", deviceName); - return invoke("/offline", data); - } - - @SneakyThrows - @Override - public void messageReport(DeviceMessage msg) { - deviceMessageProducer.send(msg); - } - - @Override - public void otaProgressReport(OtaMessage msg) { - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class GatewayConfig { - - private String mqServiceUrl; - - } -} diff --git a/device-server/mqtt-client-simulator/.DS_Store b/protocol-gateway/mqtt-client-simulator/.DS_Store similarity index 100% rename from device-server/mqtt-client-simulator/.DS_Store rename to protocol-gateway/mqtt-client-simulator/.DS_Store diff --git a/device-server/mqtt-client-simulator/pom.xml b/protocol-gateway/mqtt-client-simulator/pom.xml similarity index 97% rename from device-server/mqtt-client-simulator/pom.xml rename to protocol-gateway/mqtt-client-simulator/pom.xml index 989e1f3b..72a6fe2b 100755 --- a/device-server/mqtt-client-simulator/pom.xml +++ b/protocol-gateway/mqtt-client-simulator/pom.xml @@ -3,7 +3,7 @@ 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"> - device-server + protocol-gateway cc.iotkit 0.0.1-SNAPSHOT diff --git a/device-server/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/Application.java b/protocol-gateway/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/Application.java similarity index 100% rename from device-server/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/Application.java rename to protocol-gateway/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/Application.java diff --git a/device-server/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/config/Mqtt.java b/protocol-gateway/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/config/Mqtt.java similarity index 100% rename from device-server/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/config/Mqtt.java rename to protocol-gateway/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/config/Mqtt.java diff --git a/device-server/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/service/Device.java b/protocol-gateway/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/service/Device.java similarity index 100% rename from device-server/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/service/Device.java rename to protocol-gateway/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/service/Device.java diff --git a/device-server/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/service/Gateway.java b/protocol-gateway/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/service/Gateway.java similarity index 100% rename from device-server/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/service/Gateway.java rename to protocol-gateway/mqtt-client-simulator/src/main/java/cc/iotkit/simulator/service/Gateway.java diff --git a/protocol-gateway/mqtt-component/pom.xml b/protocol-gateway/mqtt-component/pom.xml index 21e910b6..9119c3b3 100755 --- a/protocol-gateway/mqtt-component/pom.xml +++ b/protocol-gateway/mqtt-component/pom.xml @@ -3,10 +3,9 @@ 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 - ../../pom.xml 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/MqttComponent.java index a64a4638..d7c1505b 100755 --- 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/MqttComponent.java @@ -3,12 +3,17 @@ 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.IMessageHandler; +import cc.iotkit.comp.CompConfig; +import cc.iotkit.comp.model.DeviceState; +import cc.iotkit.converter.DeviceMessage; import io.vertx.core.Future; import io.vertx.core.Vertx; -import lombok.SneakyThrows; +import lombok.*; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.beanutils.BeanUtils; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CountDownLatch; @Slf4j @@ -18,10 +23,12 @@ public class MqttComponent extends AbstractComponent { private CountDownLatch countDownLatch; private String deployedId; private MqttVerticle mqttVerticle; + private Map deviceChildToParent = new HashMap<>(); - public void create(String config) { + public void create(CompConfig config) { + super.create(config); vertx = Vertx.vertx(); - MqttConfig mqttConfig = JsonUtil.parse(config, MqttConfig.class); + MqttConfig mqttConfig = JsonUtil.parse(config.getOther(), MqttConfig.class); mqttVerticle = new MqttVerticle(mqttConfig); } @@ -55,4 +62,79 @@ public class MqttComponent extends AbstractComponent { public void destroy() { } + @Override + public void onDeviceStateChange(DeviceState state) { + DeviceState.Parent parent = state.getParent(); + if (parent == null) { + return; + } + Device device = new Device(state.getProductKey(), state.getDeviceName()); + + if (DeviceState.STATE_ONLINE.equals(state.getState())) { + //保存子设备所属父设备 + deviceChildToParent.put(device.toString(), + new Device(parent.getProductKey(), parent.getDeviceName()) + ); + } else { + //删除关系 + deviceChildToParent.remove(device.toString()); + } + + } + + @Override + public void send(DeviceMessage message) { + Device child = new Device(message.getProductKey(), message.getDeviceName()); + //作为子设备查找父设备 + Device parent = deviceChildToParent.get(child.toString()); + if (parent == null) { + parent = child; + } + + Object obj = message.getContent(); + if (!(obj instanceof Map)) { + throw new BizException("message content is not Map"); + } + Message msg = new Message(); + try { + BeanUtils.populate(msg, (Map) obj); + } catch (Throwable e) { + throw new BizException("message content is incorrect"); + } + + mqttVerticle.publish(parent.getProductKey(), parent.getDeviceName(), + msg.getTopic(), msg.getPayload()); + } + + @Override + public boolean exist(String productKey, String deviceName) { + //先作为子设备查找是否存在父设备 + Device device = deviceChildToParent.get(new Device(productKey, deviceName).toString()); + if (device != null) { + return true; + } + + return mqttVerticle.exist(productKey, deviceName); + } + + @Override + public CompConfig getConfig() { + return config; + } + + @Data + public static class Message { + private String topic; + private String payload; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + @ToString + public static class Device { + private String productKey; + private String deviceName; + } + } diff --git a/protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttVerticle.java b/protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttVerticle.java index ff73ae1e..85102aba 100755 --- a/protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttVerticle.java +++ b/protocol-gateway/mqtt-component/src/main/java/cc/iotkit/comp/mqtt/MqttVerticle.java @@ -1,15 +1,17 @@ package cc.iotkit.comp.mqtt; +import cc.iotkit.common.exception.BizException; import cc.iotkit.comp.IMessageHandler; +import cc.iotkit.comp.model.ReceiveResult; import io.netty.handler.codec.mqtt.MqttConnectReturnCode; import io.netty.handler.codec.mqtt.MqttProperties; import io.netty.handler.codec.mqtt.MqttQoS; import io.vertx.core.AbstractVerticle; +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.core.buffer.Buffer; import io.vertx.core.net.PemKeyCertOptions; -import io.vertx.mqtt.MqttAuth; -import io.vertx.mqtt.MqttServer; -import io.vertx.mqtt.MqttServerOptions; -import io.vertx.mqtt.MqttTopicSubscription; +import io.vertx.mqtt.*; import io.vertx.mqtt.messages.codes.MqttSubAckReasonCode; import lombok.extern.slf4j.Slf4j; @@ -28,6 +30,8 @@ public class MqttVerticle extends AbstractVerticle { private IMessageHandler executor; + private Map endpointMap = new HashMap<>(); + public MqttVerticle(MqttConfig config) { this.config = config; } @@ -56,12 +60,15 @@ public class MqttVerticle extends AbstractVerticle { return; } + String clientId = endpoint.clientIdentifier(); String authJson = auth.toJson() - .put("clientid", endpoint.clientIdentifier()).toString(); + .put("clientid", clientId).toString(); log.info("MQTT client auth,username:{},password:{}", auth.getUsername(), auth.getPassword()); try { - executor.onReceive(new HashMap<>(), "auth", authJson); + ReceiveResult result = executor.onReceive(new HashMap<>(), "auth", authJson); + //保存设备与连接关系 + endpointMap.put(getEndpointKey(result), endpoint); } catch (Throwable e) { log.error("auth failed", e); endpoint.reject(MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED); @@ -73,13 +80,17 @@ public class MqttVerticle extends AbstractVerticle { endpoint.accept(false); endpoint.disconnectMessageHandler(disconnectMessage -> { log.info("Received disconnect from client, reason code = {}", disconnectMessage.code()); - executor.onReceive(new HashMap<>(), "disconnect", authJson); + ReceiveResult result = executor.onReceive(new HashMap<>(), "disconnect", clientId); + //删除设备与连接关系 + endpointMap.remove(getEndpointKey(result)); }).subscribeHandler(subscribe -> { List reasonCodes = new ArrayList<>(); for (MqttTopicSubscription s : subscribe.topicSubscriptions()) { log.info("Subscription for {},with QoS {}", s.topicName(), s.qualityOfService()); try { - executor.onReceive(new HashMap<>(), "subscribe", s.topicName()); + Map head = new HashMap<>(); + head.put("topic", s.topicName()); + executor.onReceive(head, "subscribe", clientId); reasonCodes.add(MqttSubAckReasonCode.qosGranted(s.qualityOfService())); } catch (Throwable e) { log.error("subscribe failed,topic:" + s.topicName(), e); @@ -93,7 +104,9 @@ public class MqttVerticle extends AbstractVerticle { for (String t : unsubscribe.topics()) { log.info("Unsubscription for {}", t); try { - executor.onReceive(new HashMap<>(), "unsubscribe", t); + Map head = new HashMap<>(); + head.put("topic", t); + executor.onReceive(head, "unsubscribe", clientId); } catch (Throwable e) { log.error("unsubscribe failed,topic:" + t, e); } @@ -108,15 +121,14 @@ public class MqttVerticle extends AbstractVerticle { Map head = new HashMap<>(); head.put("topic", message.topicName()); executor.onReceive(head, "", payload); + if (message.qosLevel() == MqttQoS.AT_LEAST_ONCE) { + endpoint.publishAcknowledge(message.messageId()); + } else if (message.qosLevel() == MqttQoS.EXACTLY_ONCE) { + endpoint.publishReceived(message.messageId()); + } } catch (Throwable e) { log.error("handler message failed,topic:" + message.topicName(), e); } - - if (message.qosLevel() == MqttQoS.AT_LEAST_ONCE) { - endpoint.publishAcknowledge(message.messageId()); - } else if (message.qosLevel() == MqttQoS.EXACTLY_ONCE) { - endpoint.publishReceived(message.messageId()); - } }).publishReleaseHandler(endpoint::publishComplete); }).listen(ar -> { if (ar.succeeded()) { @@ -129,6 +141,34 @@ public class MqttVerticle extends AbstractVerticle { @Override public void stop() throws Exception { + for (MqttEndpoint endpoint : endpointMap.values()) { + executor.onReceive(new HashMap<>(), "disconnect", endpoint.clientIdentifier()); + } mqttServer.close(voidAsyncResult -> log.info("close mqtt server...")); } + + private String getEndpointKey(ReceiveResult result) { + return getEndpointKey(result.getProductKey(), result.getDeviceName()); + } + + private String getEndpointKey(String productKey, String deviceName) { + return String.format("%s_%s", productKey, deviceName); + } + + public boolean exist(String productKey, String deviceName) { + return endpointMap.containsKey(getEndpointKey(productKey, deviceName)); + } + + public void publish(String productKey, String deviceName, String topic, String msg) { + MqttEndpoint endpoint = endpointMap.get(getEndpointKey(productKey, deviceName)); + if (endpoint == null) { + throw new BizException("endpoint does not exist"); + } + Future result = endpoint.publish(topic, Buffer.buffer(msg), + MqttQoS.AT_LEAST_ONCE, false, false); + result.onFailure(e -> log.error("public topic failed", e)); + result.onSuccess(integer -> { + log.info("publish success,topic:{},payload:{}", topic, msg); + }); + } } diff --git a/protocol-gateway/pom.xml b/protocol-gateway/pom.xml index f53cf12b..71ac04b7 100755 --- a/protocol-gateway/pom.xml +++ b/protocol-gateway/pom.xml @@ -12,12 +12,10 @@ protocol-gateway pom - gateway-client - protocol-server - decode-function component-server converter mqtt-component + emqx-component component diff --git a/protocol-gateway/protocol-server/.DS_Store b/protocol-gateway/protocol-server/.DS_Store deleted file mode 100755 index 7a073db3..00000000 Binary files a/protocol-gateway/protocol-server/.DS_Store and /dev/null differ diff --git a/protocol-gateway/protocol-server/fun-test/.DS_Store b/protocol-gateway/protocol-server/fun-test/.DS_Store deleted file mode 100755 index fc5ea607..00000000 Binary files a/protocol-gateway/protocol-server/fun-test/.DS_Store and /dev/null differ diff --git a/protocol-gateway/protocol-server/fun-test/pom.xml b/protocol-gateway/protocol-server/fun-test/pom.xml deleted file mode 100755 index 0e12c219..00000000 --- a/protocol-gateway/protocol-server/fun-test/pom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - iotkit-parent - cc.iotkit - 0.0.1-SNAPSHOT - ../../../pom.xml - - 4.0.0 - - fun-test - - - - org.apache.pulsar - pulsar-functions-api - 2.6.0 - - - - cc.iotkit - common - - - - cc.iotkit - gateway-client - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.1.0 - - - - cc.iotkit.fun.TestFunction - - - - jar-with-dependencies - - - - - make-assembly - package - - single - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - - - \ No newline at end of file diff --git a/protocol-gateway/protocol-server/fun-test/src/main/java/cc/iotkit/fun/TestFunction.java b/protocol-gateway/protocol-server/fun-test/src/main/java/cc/iotkit/fun/TestFunction.java deleted file mode 100755 index 282853b2..00000000 --- a/protocol-gateway/protocol-server/fun-test/src/main/java/cc/iotkit/fun/TestFunction.java +++ /dev/null @@ -1,50 +0,0 @@ -package cc.iotkit.fun; - -import cc.iotkit.common.utils.JsonUtil; -import jdk.nashorn.api.scripting.NashornScriptEngine; -import org.apache.pulsar.functions.api.Context; -import org.apache.pulsar.functions.api.Function; - -import javax.script.Bindings; -import javax.script.CompiledScript; -import javax.script.ScriptEngineManager; -import javax.script.SimpleBindings; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; - -public class TestFunction implements Function { - - private static final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn"); - private static final Map compiledScripts = new ConcurrentHashMap<>(); - - @Override - public byte[] process(byte[] bs, Context context) throws Exception { - Optional objPk = context.getUserConfigValue("pk"); - Optional objTrans = context.getUserConfigValue("transform"); - if (!objPk.isPresent() || !objTrans.isPresent()) { - return null; - } - String s = new String(bs); - String pk = objPk.get().toString(); - compiledScripts.putIfAbsent(pk, engine.compile(objTrans.get().toString())); - - CompiledScript script = compiledScripts.get(pk); - context.getLogger().debug(script.toString()); - - Map data = new HashMap<>(); - data.putIfAbsent("msg", s); - Bindings bindings = new SimpleBindings(data); - Object result = script.eval(bindings); - - if (result == null) { - context.getLogger().error("translate failed:" + s); - return null; - } - s = JsonUtil.toJsonString(result); - return s.getBytes(); - } - - -} diff --git a/protocol-gateway/protocol-server/pom.xml b/protocol-gateway/protocol-server/pom.xml deleted file mode 100755 index 822782c0..00000000 --- a/protocol-gateway/protocol-server/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - protocol-gateway - cc.iotkit - 0.0.1-SNAPSHOT - - 4.0.0 - - protocol-server - - - 8 - 8 - - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.apache.pulsar - pulsar-client-all - - - - org.springframework.boot - spring-boot-starter-data-elasticsearch - - - - cc.iotkit - gateway-client - - - - cc.iotkit - model - - - - cc.iotkit - dao - - - - org.projectlombok - lombok - - - - cc.iotkit - decode-function - - - - - \ No newline at end of file diff --git a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/Application.java b/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/Application.java deleted file mode 100755 index c154603c..00000000 --- a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/Application.java +++ /dev/null @@ -1,12 +0,0 @@ -package cc.iotkit.protocol; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication(scanBasePackages = {"cc.iotkit.protocol", "cc.iotkit.dao"}) -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} diff --git a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/Test1.java b/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/Test1.java deleted file mode 100755 index 08e2ebf3..00000000 --- a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/Test1.java +++ /dev/null @@ -1,86 +0,0 @@ -package cc.iotkit.protocol.server; - -import cc.iotkit.protocol.DeviceMessage; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.SneakyThrows; -import org.apache.pulsar.client.admin.PulsarAdmin; -import org.apache.pulsar.client.admin.PulsarAdminException; -import org.apache.pulsar.client.api.*; -import org.apache.pulsar.client.impl.schema.JSONSchema; -import org.apache.pulsar.common.functions.FunctionConfig; - -import java.util.Set; -import java.util.regex.Pattern; - -public class Test1 { - - public static void main(String[] args) throws PulsarClientException, InterruptedException, PulsarAdminException { - -// PulsarAdmin admin = PulsarAdmin.builder() -// .serviceHttpUrl("http://localhost:8080") -// .build(); -// -// FunctionConfig functionConfig = new FunctionConfig(); -// functionConfig.setTenant("tenant"); -// functionConfig.setNamespace("namespace"); -// functionConfig.setName("functionName"); -// functionConfig.setRuntime(FunctionConfig.Runtime.JAVA); -// functionConfig.setParallelism(1); -// functionConfig.setClassName("org.apache.pulsar.functions.api.examples.ExclamationFunction"); -// functionConfig.setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.ATLEAST_ONCE); -// functionConfig.setTopicsPattern("persistent://public/default/test.*"); -// functionConfig.setSubName("fun-test1"); -// functionConfig.setAutoAck(true); -// functionConfig.setOutput("persistent://public/default/fun_out"); -// admin.functions().createFunction(functionConfig, "/examples/api-examples.jar"); - - - PulsarClient client = PulsarClient.builder() - .serviceUrl("pulsar://192.168.0.112:6650") - .build(); - - client.newConsumer(JSONSchema.of(DeviceMessage.class)) - .topicsPattern(Pattern.compile("persistent://public/default/device_raw")) - .subscriptionName("test1") - .consumerName("test1") - .messageListener((MessageListener) (consumer, msg) -> { - try { - DeviceMessage m = msg.getValue(); - System.out.printf("==============received:%s,%s%n", m.getMid(), m.getContent()); - consumer.acknowledge(msg); - } catch (Throwable e) { - e.printStackTrace(); - } - }).subscribe(); - - -// for (int i = 0; i < 3; i++) { -// Producer producer = client.newProducer(JSONSchema.of(Msg.class)) -// .topic("test_" + i) -// .create(); -// for (int j = 0; j < 10; j++) { -// producer.newMessage() -// .value(new Msg("QQQQQ" + i, "id_test_" + i + "_" + j)) -// .property("aa", "1") -// .send(); -// } -// Thread.sleep(100); -// } - - - } - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class Msg { - - private String identifier; - - private String deviceId; - - } - -} diff --git a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/Test3.java b/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/Test3.java deleted file mode 100755 index b1b7a766..00000000 --- a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/Test3.java +++ /dev/null @@ -1,40 +0,0 @@ -package cc.iotkit.protocol.server; - -import cc.iotkit.common.utils.JsonUtil; -import jdk.nashorn.api.scripting.NashornScriptEngine; - -import javax.script.*; -import java.util.HashMap; -import java.util.Map; - -public class Test3 { - private static final NashornScriptEngine engine = (NashornScriptEngine) (new ScriptEngineManager()).getEngineByName("nashorn"); - - - public static void main(String[] args) throws ScriptException { - - Map data = new HashMap<>(); - data.putIfAbsent("msg", "aaa"); - CompiledScript script = engine.compile("a={data:msg+'===111',b:2}"); - Bindings bindings = new SimpleBindings(data); - Object result = script.eval(bindings); - System.out.println(JsonUtil.toJsonString(result)); - - script = engine.compile("new (function() {\n" + - " function add(n){\n" + - " return n+1;\n" + - " }\n" + - " this.decode = function(msg) {\n" + - " return \"=>decode:\"+add(msg);\n" + - " };\n" + - "})().decode(color)"); - - for (int i = 0; i < 100; i++) { - data.put("color", "black" + i); - bindings = new SimpleBindings(data); - result = script.eval(bindings); - System.out.println(result); - } - - } -} diff --git a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/TestFunction.java b/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/TestFunction.java deleted file mode 100755 index af8923aa..00000000 --- a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/TestFunction.java +++ /dev/null @@ -1,88 +0,0 @@ -package cc.iotkit.protocol.server; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.apache.pulsar.client.admin.PulsarAdmin; -import org.apache.pulsar.client.admin.PulsarAdminException; -import org.apache.pulsar.client.api.MessageListener; -import org.apache.pulsar.client.api.PulsarClient; -import org.apache.pulsar.client.api.PulsarClientException; -import org.apache.pulsar.client.impl.schema.JSONSchema; -import org.apache.pulsar.common.functions.FunctionConfig; - -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Pattern; - -public class TestFunction { - - public static void main(String[] args) throws PulsarClientException, InterruptedException, PulsarAdminException { - - PulsarAdmin admin = PulsarAdmin.builder() - .serviceHttpUrl("http://192.168.0.112:8080") - .build(); - - String gatewayName = "test3"; - String tenant = "public"; - String namespace = "default"; - String inputTopicsPattern = "device_raw"; - String fullInputTopic = String.format("persistent://%s/%s/%s", tenant, namespace, inputTopicsPattern); - String outputTopic = "device_thing"; - String transform = "new (function() {\n this.decode=function(msg){\n //对msg进行解析,并返回物模型数据\n var mqttMsg=JSON.parse(msg.content);\n var topic=mqttMsg.topic;\n var payload=mqttMsg.payload;\n\n if(topic.endWith(\"/property/post\")){\n //属性上报\n return {\n \"mid\":msg.mid,\n \"productKey\":msg.productKey, //可根据消息内容判断填写不同产品\n \"deviceName\":msg.deviceName,\n \"identifier\":\"propertyReport\", //属性上报\n \"occur\":new Date().getTime(), //时间戳,设备上的事件或数据产生的本地时间\n \"time\":new Date().getTime(), //时间戳,消息上报时间\n \"data\":payload.params\n }\n }else if(topic.indexOf(\"/event/\")>0){\n var identifier=topic.substring(topic.lastIndexOf(\"/\")+1);\n //事件上报\n return {\n \"mid\":msg.mid,\n \"productKey\":msg.productKey,\n \"deviceName\":msg.deviceName,\n \"identifier\":identifier,\n \"occur\":new Date().getTime(),\n \"time\":new Date().getTime(),\n \"data\":payload.params\n }\n }else if(topic.endWith(\"_reply\")){\n var identifier=topic.substring(topic.lastIndexOf(\"/\")+1);\n //服务回复\n return {\n \"mid\":msg.mid,\n \"productKey\":msg.productKey,\n \"deviceName\":msg.deviceName,\n \"identifier\":identifier.replace(\"_reply\",\"Reply\"),\n \"occur\":new Date().getTime(),\n \"time\":new Date().getTime(),\n \"code\":payload.code,\n \"data\":payload.data\n } \n }\n return null;\n }\n\n})().decode(msg)"; - String functionClass = "cc.iotkit.protocol.function.UplinkTranslateFunction"; - String jarFile = "/Users/sjg/home/gitee/open-source/iotkit-parent/protocol-gateway/protocol-function/target/protocol-function-0.0.1-SNAPSHOT-jar-with-dependencies.jar"; - - FunctionConfig functionConfig = new FunctionConfig(); - functionConfig.setTenant(tenant); - functionConfig.setNamespace(namespace); - functionConfig.setName("UplinkTranslateFunction_" + gatewayName); - functionConfig.setRuntime(FunctionConfig.Runtime.JAVA); - functionConfig.setParallelism(1); - functionConfig.setClassName(functionClass); - functionConfig.setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.ATLEAST_ONCE); - functionConfig.setTopicsPattern(fullInputTopic); - functionConfig.setSubName(functionConfig.getName()); - functionConfig.setAutoAck(true); - functionConfig.setOutput(String.format("persistent://%s/%s/%s", tenant, namespace, outputTopic)); - Map userConfig = new HashMap<>(); - userConfig.put("script", transform); - functionConfig.setUserConfig(userConfig); - for (String function : admin.functions().getFunctions(tenant, namespace)) { - System.out.println(function); - if (function.contains("test")) { - admin.functions().deleteFunction(tenant, namespace, function); - } - } -// if (admin.functions().getFunction(tenant, namespace, functionConfig.getName()) != null) { -// admin.functions().updateFunction(functionConfig, jarFile); -// } else { -// admin.functions().createFunction(functionConfig, jarFile); -// } - -// admin.functions().stopFunction("public", "default", "fun_4", 0); -// admin.functions().startFunction("public", "default", "fun_4", 0); - -// -// PulsarClient client = PulsarClient.builder() -// .serviceUrl("pulsar://localhost:6650") -// .build(); -// -// client.newConsumer() -// .topicsPattern(Pattern.compile("persistent://public/default/fun_out.*")) -// .subscriptionName("test1") -// .consumerName("test-fun-1") -// .messageListener((MessageListener) (consumer, msg) -> { -// try { -// System.out.printf("==============received:%s\n", new String(msg.getValue())); -// consumer.acknowledge(msg); -// } catch (Throwable e) { -// e.printStackTrace(); -// } -// }).subscribe(); - - - } - - -} diff --git a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/config/ProtocolConfig.java b/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/config/ProtocolConfig.java deleted file mode 100755 index 275a3443..00000000 --- a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/config/ProtocolConfig.java +++ /dev/null @@ -1,17 +0,0 @@ -package cc.iotkit.protocol.server.config; - -import lombok.Data; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; - -@Configuration -@Data -public class ProtocolConfig { - - @Value("${pulsar.broker}") - private String pulsarBrokerUrl; - - @Value("${pulsar.service}") - private String pulsarServiceUrl; - -} diff --git a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/controller/DeviceBehaviourController.java b/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/controller/DeviceBehaviourController.java deleted file mode 100755 index 1b4d76d4..00000000 --- a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/controller/DeviceBehaviourController.java +++ /dev/null @@ -1,59 +0,0 @@ -package cc.iotkit.protocol.server.controller; - -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.protocol.*; -import cc.iotkit.protocol.client.DeviceBehaviourClient; -import cc.iotkit.protocol.server.config.ProtocolConfig; -import cc.iotkit.protocol.server.service.BehaviourService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - -@Slf4j -@RestController -@RequestMapping("/device_behaviour") -public class DeviceBehaviourController implements DeviceBehaviour { - - @Autowired - private ProtocolConfig serverConfig; - - @Autowired - private BehaviourService behaviourService; - - - @Override - @PostMapping("/register") - public Result register(@RequestBody RegisterInfo info) { - return behaviourService.register(info); - } - - @Override - @PostMapping("/online") - public Result online(String productKey, String deviceName) { - return behaviourService.deviceStateChange(productKey, deviceName, true); - } - - @Override - @PostMapping("/offline") - public Result offline(String productKey, String deviceName) { - return behaviourService.deviceStateChange(productKey, deviceName, false); - } - - @PostMapping("/getConfig") - public Result getConfig() { - return new Result(true, JsonUtil.toJsonString( - new DeviceBehaviourClient.GatewayConfig(serverConfig.getPulsarBrokerUrl()))); - } - - @Override - public void messageReport(DeviceMessage msg) { - throw new UnsupportedOperationException(); - } - - @Override - public void otaProgressReport(OtaMessage msg) { - throw new UnsupportedOperationException(); - } - - -} diff --git a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/service/BehaviourService.java b/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/service/BehaviourService.java deleted file mode 100755 index 8a4ca0a8..00000000 --- a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/service/BehaviourService.java +++ /dev/null @@ -1,142 +0,0 @@ -package cc.iotkit.protocol.server.service; - -import cc.iotkit.common.exception.BizException; -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.dao.DeviceRepository; -import cc.iotkit.dao.ProductRepository; -import cc.iotkit.model.device.DeviceInfo; -import cc.iotkit.model.product.Product; -import cc.iotkit.protocol.RegisterInfo; -import cc.iotkit.protocol.Result; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.RandomUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -@Slf4j -@Service -public class BehaviourService { - - @Autowired - private ProductRepository productRepository; - @Autowired - private DeviceRepository deviceRepository; - - - public Result register(RegisterInfo info) { - try { - DeviceInfo deviceInfo = register(null, info); - //子设备注册 - List subDevices = info.getSubDevices(); - if (subDevices != null && subDevices.size() != 0) { - for (RegisterInfo.SubDevice subDevice : subDevices) { - register(deviceInfo.getDeviceId(), - new RegisterInfo(subDevice.getProductKey(), - subDevice.getDeviceName(), - subDevice.getModel(), - subDevice.getTag(), null)); - } - } - //todo 产生设备注册事件 - } catch (BizException e) { - log.error("register device error", e); - return new Result(false, e.getMessage()); - } catch (Throwable e) { - log.error("register device error", e); - return new Result(false, "unknown error:" + e.getMessage()); - } - - return new Result(true, ""); - } - - public DeviceInfo register(String parentId, RegisterInfo info) { - String pk = info.getProductKey(); - Optional optProduct = productRepository.findById(pk); - if (!optProduct.isPresent()) { - throw new BizException("Product does not exist"); - } - String uid = optProduct.get().getUid(); - DeviceInfo device = deviceRepository.findByProductKeyAndDeviceName(pk, info.getDeviceName()); - - if (device != null) { - //更新设备信息 - device.setParentId(parentId); - device.setUid(uid); - Map tag = info.getTag(); - Map oldTag = device.getTag(); - - if (oldTag == null) { - oldTag = new HashMap<>(); - } - - if (tag != null) { - oldTag.putAll(tag); - } - - device.setTag(oldTag); - } else { - //不存在,注册新设备 - device = new DeviceInfo(); - device.setParentId(parentId); - device.setUid(uid); - device.setDeviceId(newDeviceId(info.getDeviceName())); - device.setProductKey(info.getProductKey()); - device.setDeviceName(info.getDeviceName()); - device.setTag(info.getTag()); - device.setState(new DeviceInfo.State(false, null, null)); - device.setCreateAt(System.currentTimeMillis()); - } - - deviceRepository.save(device); - log.info("device registered:{}", JsonUtil.toJsonString(device)); - - return device; - } - - /** - * 1-13位 时间戳 - * 14-29位 deviceNae,去除非字母和数字,不足16位补0,超过16位的mac取后16位,共16位 - * 30-31位 mac长度,共2位 - * 32位 随机一个0-f字符 - */ - public static String newDeviceId(String deviceNae) { - int maxDnLen = 16; - String dn = deviceNae.replaceAll("[^0-9A-Za-z]", ""); - if (dn.length() > maxDnLen) { - dn = dn.substring(dn.length() - maxDnLen); - } else { - dn = (dn + "00000000000000000000").substring(0, maxDnLen); - } - String len = StringUtils.leftPad(deviceNae.length() + "", 2, '0'); - String rnd = Integer.toHexString(RandomUtils.nextInt(0, 16)); - return (System.currentTimeMillis() + "0" + dn + len + rnd).toLowerCase(); - } - - public Result deviceStateChange(String productKey, - String deviceName, - boolean online) { - DeviceInfo device = deviceRepository.findByProductKeyAndDeviceName(productKey, deviceName); - if (device == null) { - return new Result(false, "device does not exist"); - } - - if (online) { - device.getState().setOnline(true); - device.getState().setOnlineTime(System.currentTimeMillis()); - } else { - device.getState().setOnline(false); - device.getState().setOfflineTime(System.currentTimeMillis()); - } - deviceRepository.save(device); - //todo 产生在离线事件 - - return new Result(true, ""); - } - -} diff --git a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/service/DeviceMessageConsumer.java b/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/service/DeviceMessageConsumer.java deleted file mode 100755 index 04364c8d..00000000 --- a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/service/DeviceMessageConsumer.java +++ /dev/null @@ -1,75 +0,0 @@ -package cc.iotkit.protocol.server.service; - -import cc.iotkit.common.Constants; -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.dao.ThingModelMessageRepository; -import cc.iotkit.dao.UserInfoRepository; -import cc.iotkit.model.UserInfo; -import cc.iotkit.model.device.message.ThingModelMessage; -import cc.iotkit.protocol.server.config.ProtocolConfig; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.apache.pulsar.client.api.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.stream.Collectors; - -@Slf4j -//@Service -public class DeviceMessageConsumer implements MessageListener { - - private final ProtocolConfig serverConfig; - - private final ThingModelMessageRepository messageRepository; - - private final UserInfoRepository userInfoRepository; - - @SneakyThrows - @Autowired - public DeviceMessageConsumer(ProtocolConfig serverConfig, - ThingModelMessageRepository messageRepository, - UserInfoRepository userInfoRepository) { - this.serverConfig = serverConfig; - this.messageRepository = messageRepository; - this.userInfoRepository = userInfoRepository; - - PulsarClient client = PulsarClient.builder() - .serviceUrl(this.serverConfig.getPulsarBrokerUrl()) - .build(); - - String topicFormat = "persistent://%s/default/" + Constants.THING_MODEL_MESSAGE_TOPIC; - List platformUsers = userInfoRepository.findByType(UserInfo.USER_TYPE_PLATFORM); - List topics = platformUsers.stream().map(u -> String.format(topicFormat, u.getUid())) - .collect(Collectors.toList()); - log.info("subscribe device_thing topic:{}", JsonUtil.toJsonString(topics)); - - client.newConsumer(Schema.JSON(ThingModelMessage.class)) - .topics(topics) - .subscriptionName("thing-model-message") - .consumerName("thing-model-message-consumer") - .messageListener(this).subscribe(); - } - - @SneakyThrows - @Override - public void received(Consumer consumer, Message msg) { - ThingModelMessage modelMessage = msg.getValue(); - log.info("receive message:{}", JsonUtil.toJsonString(modelMessage)); - //设备消息日志入库 - messageRepository.save(modelMessage); - - messageRepository.findAll().forEach(m -> { - log.info(JsonUtil.toJsonString(m)); - }); - - consumer.acknowledge(msg); - } - - @Override - public void reachedEndOfTopic(Consumer consumer) { - - } - -} diff --git a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/service/GatewayService.java b/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/service/GatewayService.java deleted file mode 100755 index c00faf9d..00000000 --- a/protocol-gateway/protocol-server/src/main/java/cc/iotkit/protocol/server/service/GatewayService.java +++ /dev/null @@ -1,98 +0,0 @@ -package cc.iotkit.protocol.server.service; - -import cc.iotkit.common.Constants; -import cc.iotkit.common.utils.JsonUtil; -import cc.iotkit.protocol.function.DecodeFunction; -import cc.iotkit.protocol.server.config.ProtocolConfig; -import lombok.extern.slf4j.Slf4j; -import org.apache.pulsar.client.admin.PulsarAdmin; -import org.apache.pulsar.client.admin.PulsarAdminException; -import org.apache.pulsar.client.api.PulsarClientException; -import org.apache.pulsar.common.functions.FunctionConfig; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.HashMap; -import java.util.Map; - -@Slf4j -@Service -public class GatewayService { - - private PulsarAdmin pulsarAdmin; - - @Autowired - private ProtocolConfig serverConfig; - - private PulsarAdmin getPulsarAdmin() throws PulsarClientException { - if (pulsarAdmin == null) { - pulsarAdmin = PulsarAdmin.builder() - .serviceHttpUrl(serverConfig.getPulsarServiceUrl()) - .build(); - } - return pulsarAdmin; - } - - public void saveFunction(String tenant, String gatewayId, String script, - String jarFile) throws PulsarClientException, PulsarAdminException { - saveFunction(tenant, gatewayId, "default", script, jarFile); - } - - public void saveFunction(String tenant, String gatewayId, - String namespace, String script, - String jarFile) throws PulsarClientException, PulsarAdminException { - PulsarAdmin pulsarAdmin = getPulsarAdmin(); - -// String gatewayName = ""; -// String tenant = "public"; -// String namespace = "default"; -// String inputTopicsPattern = ""; - String fullInputTopic = String.format("persistent://%s/%s/%s", - tenant, namespace, Constants.DEVICE_RAW_MESSAGE_TOPIC); -// String outputTopic = ""; -// String transform = ""; -// String functionClass = "cc.iotkit.protocol.function.UplinkTranslateFunction"; -// String jarFile = "/Users/sjg/home/gitee/open-source/iotkit-parent/protocol-gateway/gateway-server/fun-test/target/fun-test-0.0.1-SNAPSHOT-jar-with-dependencies.jar"; - - String functionClass = DecodeFunction.class.getName(); - String functionName = functionClass.substring(functionClass.lastIndexOf(".") + 1) + "_" + gatewayId; - - FunctionConfig functionConfig = new FunctionConfig(); - functionConfig.setTenant(tenant); - functionConfig.setNamespace(namespace); - functionConfig.setName(functionName); - functionConfig.setRuntime(FunctionConfig.Runtime.JAVA); - functionConfig.setParallelism(1); - functionConfig.setClassName(functionClass); - functionConfig.setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.ATLEAST_ONCE); - functionConfig.setTopicsPattern(fullInputTopic); - functionConfig.setSubName(functionConfig.getName()); - functionConfig.setAutoAck(true); - functionConfig.setOutput(String.format("persistent://%s/%s/%s", tenant, - namespace, Constants.THING_MODEL_MESSAGE_TOPIC)); - log.info("creating function:{}", JsonUtil.toJsonString(functionConfig)); - - Map userConfig = new HashMap<>(); - userConfig.put("script", script); - userConfig.put("gateway", gatewayId); - functionConfig.setUserConfig(userConfig); - - if (pulsarAdmin.functions().getFunctions(tenant, namespace).contains(functionName)) { - pulsarAdmin.functions().updateFunction(functionConfig, jarFile); - } else { - pulsarAdmin.functions().createFunction(functionConfig, jarFile); - } - } - - public void deleteFunction(String tenant, String gatewayId) throws PulsarClientException, PulsarAdminException { - String namespace = "default"; - String functionClass = DecodeFunction.class.getName(); - String functionName = functionClass.substring(functionClass.lastIndexOf(".") + 1) + "_" + gatewayId; - PulsarAdmin pulsarAdmin = getPulsarAdmin(); - if (!pulsarAdmin.functions().getFunctions(tenant, namespace).contains(functionName)) { - log.warn("function does not found,delete success."); - return; - } - pulsarAdmin.functions().deleteFunction(tenant, namespace, functionName); - } -} diff --git a/protocol-gateway/protocol-server/src/main/resources/logback-spring.xml b/protocol-gateway/protocol-server/src/main/resources/logback-spring.xml deleted file mode 100755 index 6322c4b5..00000000 --- a/protocol-gateway/protocol-server/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - DEBUG - - - ${CONSOLE_LOG_PATTERN} - utf8 - - - - - - ${LOG_FILE}/info.log - - ${LOG_FILE}/info.%d{yyyy-MM-dd}.%i.gz - - 5 - - 20GB - - - 1GB - - - - ${CONSOLE_LOG_PATTERN} - utf8 - - - - - - ${LOG_FILE}/error.log - - ${LOG_FILE}/error.%d{yyyy-MM-dd}.%i.gz - - 5 - - 5GB - - - 1GB - - - - ${CONSOLE_LOG_PATTERN} - utf8 - - - ERROR - ACCEPT - DENY - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/protocol-gateway/protocol-server/src/main/resources/spring.factories b/protocol-gateway/protocol-server/src/main/resources/spring.factories deleted file mode 100755 index ae3134d9..00000000 --- a/protocol-gateway/protocol-server/src/main/resources/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration= cc.iotkit.protocol.config.GatewayConfig \ No newline at end of file diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index d911db84..81b00ac8 100755 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -58,12 +58,12 @@ cc.iotkit - device-api + dao cc.iotkit - dao + component-server diff --git a/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceAction.java b/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceAction.java index f0c020ac..3876a679 100755 --- a/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceAction.java +++ b/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceAction.java @@ -1,7 +1,5 @@ package cc.iotkit.ruleengine.action; -import cc.iotkit.deviceapi.IDeviceService; -import cc.iotkit.deviceapi.Service; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -11,15 +9,15 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @Data -public class DeviceAction implements Action { +public class DeviceAction implements Action { public static final String TYPE = "device"; private String type; - private List services; + private List services; - private IDeviceService deviceService; + private DeviceActionService deviceActionService; @Override public String getType() { @@ -28,8 +26,8 @@ public class DeviceAction implements Action { @Override public void execute() { - for (Service service : services) { - deviceService.invoke(service); + for (DeviceActionService.Service service : services) { + deviceActionService.invoke(service); } } diff --git a/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceActionExecutor.java b/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceActionExecutor.java index 2e9f3c59..3a076772 100755 --- a/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceActionExecutor.java +++ b/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceActionExecutor.java @@ -2,8 +2,6 @@ package cc.iotkit.ruleengine.action; import cc.iotkit.common.utils.JsonUtil; import cc.iotkit.dao.DeviceCache; -import cc.iotkit.deviceapi.IDeviceService; -import cc.iotkit.deviceapi.Service; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -16,11 +14,11 @@ import org.springframework.stereotype.Component; @Component public class DeviceActionExecutor implements ActionExecutor { - @Autowired - private IDeviceService deviceService; - @Autowired private DeviceCache deviceCache; + @Autowired + private DeviceActionService deviceActionService; + @Override public String getName() { @@ -36,8 +34,8 @@ public class DeviceActionExecutor implements ActionExecutor { //将执行的数据转换为动作配置 DeviceAction action = JsonUtil.parse(config, DeviceAction.class); log.info("start device service invoke,{}", JsonUtil.toJsonString(action)); - for (Service service : action.getServices()) { - deviceService.invoke(service); + for (DeviceActionService.Service service : action.getServices()) { + deviceActionService.invoke(service); } } } 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 new file mode 100644 index 00000000..c06f9283 --- /dev/null +++ b/rule-engine/src/main/java/cc/iotkit/ruleengine/action/DeviceActionService.java @@ -0,0 +1,56 @@ +package cc.iotkit.ruleengine.action; + +import cc.iotkit.common.utils.UniqueIdUtil; +import cc.iotkit.comps.ComponentManager; +import cc.iotkit.converter.ThingService; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class DeviceActionService { + + @Autowired + private ComponentManager componentManager; + + public String invoke(Service service) { + String[] pkDn = service.getDevice().split("/"); + ThingService> thingService = new ThingService<>(); + thingService.setMid(UniqueIdUtil.newRequestId()); + thingService.setProductKey(pkDn[0]); + thingService.setDeviceName(pkDn[1]); + thingService.setIdentifier(service.getIdentifier()); + thingService.setParams(service.parseInputData()); + componentManager.send(thingService); + return thingService.getMid(); + } + + @Data + public static class Service { + + private String device; + + private String identifier; + + private List inputData; + + public Map parseInputData() { + Map data = new HashMap<>(); + for (Parameter p : inputData) { + data.put(p.getIdentifier(), p.getValue()); + } + return data; + } + + @Data + public static class Parameter { + private String identifier; + private Object value; + } + } + +} diff --git a/rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceCondition.java b/rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceCondition.java index 778d0d00..df10e052 100755 --- a/rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceCondition.java +++ b/rule-engine/src/main/java/cc/iotkit/ruleengine/filter/DeviceCondition.java @@ -31,7 +31,7 @@ public class DeviceCondition { left = properties.get(identifier); } else if ("state".equals(type)) { DeviceInfo.State state = deviceInfo.getState(); - left = state != null && state.getOnline(); + left = state != null && state.isOnline(); } return Expression.eval(comparator, left, value); } diff --git a/rule-engine/src/main/java/cc/iotkit/ruleengine/scene/SceneManager.java b/rule-engine/src/main/java/cc/iotkit/ruleengine/scene/SceneManager.java index cd4aaafc..3cb79b59 100755 --- a/rule-engine/src/main/java/cc/iotkit/ruleengine/scene/SceneManager.java +++ b/rule-engine/src/main/java/cc/iotkit/ruleengine/scene/SceneManager.java @@ -3,11 +3,11 @@ package cc.iotkit.ruleengine.scene; import cc.iotkit.common.utils.JsonUtil; import cc.iotkit.dao.DeviceCache; import cc.iotkit.dao.SceneInfoRepository; -import cc.iotkit.deviceapi.IDeviceService; import cc.iotkit.model.rule.RuleAction; import cc.iotkit.model.rule.SceneInfo; import cc.iotkit.ruleengine.action.Action; import cc.iotkit.ruleengine.action.DeviceAction; +import cc.iotkit.ruleengine.action.DeviceActionService; import cc.iotkit.ruleengine.config.RuleConfiguration; import cc.iotkit.ruleengine.filter.DeviceFilter; import cc.iotkit.ruleengine.filter.Filter; @@ -46,7 +46,7 @@ public class SceneManager { private DeviceCache deviceCache; @Autowired - private IDeviceService deviceService; + private DeviceActionService deviceActionService; public SceneManager() { ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); @@ -165,7 +165,7 @@ public class SceneManager { private Action parseAction(String type, String config) { if (DeviceAction.TYPE.equals(type)) { DeviceAction action = parse(config, DeviceAction.class); - action.setDeviceService(deviceService); + action.setDeviceActionService(deviceActionService); return action; } return null;