Commit 1b59aa9ccb26822b48fc0e4bab13ac6b44461ad6

Authored by YunaiV
1 parent 385cea8d

reactor:【IoT 物联网】增加 http 网络组件,接入 rocketmq 消息总线

Showing 13 changed files with 155 additions and 152 deletions
yudao-module-iot/yudao-module-iot-biz/pom.xml
@@ -28,6 +28,12 @@ @@ -28,6 +28,12 @@
28 <artifactId>yudao-module-iot-api</artifactId> 28 <artifactId>yudao-module-iot-api</artifactId>
29 <version>${revision}</version> 29 <version>${revision}</version>
30 </dependency> 30 </dependency>
  31 + <dependency>
  32 + <groupId>cn.iocoder.boot</groupId>
  33 + <artifactId>yudao-module-iot-core</artifactId>
  34 + <version>${revision}</version>
  35 + </dependency>
  36 +
31 <!-- IoT 协议模块 --> 37 <!-- IoT 协议模块 -->
32 <dependency> 38 <dependency>
33 <groupId>cn.iocoder.boot</groupId> 39 <groupId>cn.iocoder.boot</groupId>
@@ -80,10 +86,11 @@ @@ -80,10 +86,11 @@
80 </dependency> 86 </dependency>
81 87
82 <!-- 消息队列相关 --> 88 <!-- 消息队列相关 -->
  89 + <!-- TODO @芋艿:临时打开 -->
83 <dependency> 90 <dependency>
84 <groupId>org.apache.rocketmq</groupId> 91 <groupId>org.apache.rocketmq</groupId>
85 <artifactId>rocketmq-spring-boot-starter</artifactId> 92 <artifactId>rocketmq-spring-boot-starter</artifactId>
86 - <optional>true</optional> 93 +<!-- <optional>true</optional>-->
87 </dependency> 94 </dependency>
88 <dependency> 95 <dependency>
89 <groupId>org.springframework.kafka</groupId> 96 <groupId>org.springframework.kafka</groupId>
@@ -147,8 +154,6 @@ @@ -147,8 +154,6 @@
147 <!-- <artifactId>yudao-module-iot-script</artifactId>--> 154 <!-- <artifactId>yudao-module-iot-script</artifactId>-->
148 <!-- <version>${revision}</version>--> 155 <!-- <version>${revision}</version>-->
149 <!-- </dependency>--> 156 <!-- </dependency>-->
150 -  
151 -  
152 </dependencies> 157 </dependencies>
153 158
154 </project> 159 </project>
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageConsumer.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageBusSubscriber.java
1 package cn.iocoder.yudao.module.iot.mq.consumer.device; 1 package cn.iocoder.yudao.module.iot.mq.consumer.device;
2 2
3 -import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 3 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
  4 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber;
  5 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService; 6 import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService;
  7 +import jakarta.annotation.PostConstruct;
5 import jakarta.annotation.Resource; 8 import jakarta.annotation.Resource;
6 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
7 -import org.springframework.context.event.EventListener;  
8 -import org.springframework.scheduling.annotation.Async;  
9 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
10 11
11 /** 12 /**
@@ -15,16 +16,34 @@ import org.springframework.stereotype.Component; @@ -15,16 +16,34 @@ import org.springframework.stereotype.Component;
15 */ 16 */
16 @Component 17 @Component
17 @Slf4j 18 @Slf4j
18 -public class IotDeviceLogMessageConsumer { 19 +public class IotDeviceLogMessageBusSubscriber implements IotMessageBusSubscriber<IotDeviceMessage> {
  20 +
  21 + @Resource
  22 + private IotMessageBus messageBus;
19 23
20 @Resource 24 @Resource
21 private IotDeviceLogService deviceLogService; 25 private IotDeviceLogService deviceLogService;
22 26
23 - @EventListener  
24 - @Async 27 + @PostConstruct
  28 + public void init() {
  29 + messageBus.register(this);
  30 + }
  31 +
  32 + @Override
  33 + public String getTopic() {
  34 + return IotDeviceMessage.MESSAGE_BUS_DEVICE_MESSAGE_TOPIC;
  35 + }
  36 +
  37 + @Override
  38 + public String getGroup() {
  39 + return "iot_device_log_consumer";
  40 + }
  41 +
  42 + // TODO @芋艿:后续再对接这个细节逻辑;
  43 + @Override
25 public void onMessage(IotDeviceMessage message) { 44 public void onMessage(IotDeviceMessage message) {
26 log.info("[onMessage][消息内容({})]", message); 45 log.info("[onMessage][消息内容({})]", message);
27 - deviceLogService.createDeviceLog(message); 46 +// deviceLogService.createDeviceLog(message);
28 } 47 }
29 48
30 } 49 }
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/mq/message/IotDeviceMessage.java
1 package cn.iocoder.yudao.module.iot.core.mq.message; 1 package cn.iocoder.yudao.module.iot.core.mq.message;
2 2
  3 +import cn.hutool.core.util.IdUtil;
3 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageIdentifierEnum; 4 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageIdentifierEnum;
4 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageTypeEnum; 5 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageTypeEnum;
5 import lombok.AllArgsConstructor; 6 import lombok.AllArgsConstructor;
@@ -8,6 +9,7 @@ import lombok.Data; @@ -8,6 +9,7 @@ import lombok.Data;
8 import lombok.NoArgsConstructor; 9 import lombok.NoArgsConstructor;
9 10
10 import java.time.LocalDateTime; 11 import java.time.LocalDateTime;
  12 +import java.util.Map;
11 13
12 // TODO @芋艿:参考阿里云的物模型,优化 IoT 上下行消息的设计,尽量保持一致(渐进式,不要一口气)! 14 // TODO @芋艿:参考阿里云的物模型,优化 IoT 上下行消息的设计,尽量保持一致(渐进式,不要一口气)!
13 15
@@ -21,6 +23,18 @@ import java.time.LocalDateTime; @@ -21,6 +23,18 @@ import java.time.LocalDateTime;
21 public class IotDeviceMessage { 23 public class IotDeviceMessage {
22 24
23 /** 25 /**
  26 + * 【消息总线】应用的设备消息 Topic,由 iot-gateway 发给 iot-biz 进行消费
  27 + */
  28 + public static final String MESSAGE_BUS_DEVICE_MESSAGE_TOPIC = "iot_device_message";
  29 +
  30 + /**
  31 + * 【消息总线】设备消息 Topic,由 iot-biz 发送给 iot-gateway 的某个 “server”(protocol) 进行消费
  32 + *
  33 + * 其中,%s 就是该“server”(protocol) 的标识
  34 + */
  35 + public static final String MESSAGE_BUS_GATEWAY_DEVICE_MESSAGE_TOPIC = MESSAGE_BUS_DEVICE_MESSAGE_TOPIC + "/%s";
  36 +
  37 + /**
24 * 请求编号 38 * 请求编号
25 */ 39 */
26 private String requestId; 40 private String requestId;
@@ -70,8 +84,41 @@ public class IotDeviceMessage { @@ -70,8 +84,41 @@ public class IotDeviceMessage {
70 private LocalDateTime reportTime; 84 private LocalDateTime reportTime;
71 85
72 /** 86 /**
  87 + * 服务编号,该消息由哪个消息发送
  88 + */
  89 + private String serverId;
  90 +
  91 + /**
73 * 租户编号 92 * 租户编号
74 */ 93 */
75 private Long tenantId; 94 private Long tenantId;
76 95
  96 + public IotDeviceMessage ofPropertyReport(Map<String, Object> properties) {
  97 + this.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
  98 + this.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier());
  99 + this.setData(properties);
  100 + return this;
  101 + }
  102 +
  103 + public static IotDeviceMessage of(String productKey, String deviceName, String deviceKey,
  104 + String requestId, LocalDateTime reportTime,
  105 + String serverId, Long tenantId) {
  106 + if (requestId == null) {
  107 + requestId = IdUtil.fastSimpleUUID();
  108 + }
  109 + if (reportTime == null) {
  110 + reportTime = LocalDateTime.now();
  111 + }
  112 + return IotDeviceMessage.builder()
  113 + .requestId(requestId).reportTime(reportTime)
  114 + .productKey(productKey).deviceName(deviceName).deviceKey(deviceKey)
  115 + .serverId(serverId).tenantId(tenantId).build();
  116 + }
  117 +
  118 + // ========== Topic 相关 ==========
  119 +
  120 + public static String getMessageBusGatewayDeviceMessageTopic(String serverId) {
  121 + return String.format(MESSAGE_BUS_GATEWAY_DEVICE_MESSAGE_TOPIC, serverId);
  122 + }
  123 +
77 } 124 }
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/mq/producer/IotDeviceMessageProducer.java
@@ -12,18 +12,6 @@ import lombok.RequiredArgsConstructor; @@ -12,18 +12,6 @@ import lombok.RequiredArgsConstructor;
12 @RequiredArgsConstructor 12 @RequiredArgsConstructor
13 public class IotDeviceMessageProducer { 13 public class IotDeviceMessageProducer {
14 14
15 - /**  
16 - * 【消息总线】应用的设备消息 Topic,由 iot-gateway 发给 iot-biz 进行消费  
17 - */  
18 - private static final String MESSAGE_BUS_DEVICE_MESSAGE_TOPIC = "iot_device_message";  
19 -  
20 - /**  
21 - * 【消息总线】设备消息 Topic,由 iot-biz 发送给 iot-gateway 的某个 “server”(protocol) 进行消费  
22 - *  
23 - * 其中,%s 就是该“server”(protocol) 的标识  
24 - */  
25 - private static final String MESSAGE_BUS_GATEWAY_DEVICE_MESSAGE_TOPIC = MESSAGE_BUS_DEVICE_MESSAGE_TOPIC + "/%s";  
26 -  
27 private final IotMessageBus messageBus; 15 private final IotMessageBus messageBus;
28 16
29 /** 17 /**
@@ -32,17 +20,17 @@ public class IotDeviceMessageProducer { @@ -32,17 +20,17 @@ public class IotDeviceMessageProducer {
32 * @param message 设备消息 20 * @param message 设备消息
33 */ 21 */
34 public void sendDeviceMessage(IotDeviceMessage message) { 22 public void sendDeviceMessage(IotDeviceMessage message) {
35 - messageBus.post(MESSAGE_BUS_DEVICE_MESSAGE_TOPIC, message); 23 + messageBus.post(IotDeviceMessage.MESSAGE_BUS_DEVICE_MESSAGE_TOPIC, message);
36 } 24 }
37 25
38 /** 26 /**
39 * 发送网关设备消息 27 * 发送网关设备消息
40 * 28 *
41 - * @param server 网关的 server 标识 29 + * @param serverId 网关的 serverId 标识
42 * @param message 设备消息 30 * @param message 设备消息
43 */ 31 */
44 - public void sendGatewayDeviceMessage(String server, Object message) {  
45 - messageBus.post(String.format(MESSAGE_BUS_GATEWAY_DEVICE_MESSAGE_TOPIC, server), message); 32 + public void sendGatewayDeviceMessage(String serverId, Object message) {
  33 + messageBus.post(IotDeviceMessage.getMessageBusGatewayDeviceMessageTopic(serverId), message);
46 } 34 }
47 35
48 } 36 }
yudao-module-iot/yudao-module-iot-core/src/main/resources/META-INF/spring.factories deleted
1 -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\  
2 -cn.iocoder.yudao.module.iot.core.messagebus.config.IotMessageBusAutoConfiguration  
3 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 0 → 100644
  1 +cn.iocoder.yudao.module.iot.core.messagebus.config.IotMessageBusAutoConfiguration
0 \ No newline at end of file 2 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/pom.xml
@@ -24,6 +24,12 @@ @@ -24,6 +24,12 @@
24 <version>${revision}</version> 24 <version>${revision}</version>
25 </dependency> 25 </dependency>
26 26
  27 + <dependency>
  28 + <groupId>cn.iocoder.boot</groupId>
  29 + <artifactId>yudao-module-iot-core</artifactId>
  30 + <version>${revision}</version>
  31 + </dependency>
  32 +
27 <!-- IoT 协议模块 --> 33 <!-- IoT 协议模块 -->
28 <dependency> 34 <dependency>
29 <groupId>cn.iocoder.boot</groupId> 35 <groupId>cn.iocoder.boot</groupId>
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/java/cn/iocoder/yudao/module/iot/net/component/http/config/IotNetComponentHttpAutoConfiguration.java
@@ -2,12 +2,13 @@ package cn.iocoder.yudao.module.iot.net.component.http.config; @@ -2,12 +2,13 @@ package cn.iocoder.yudao.module.iot.net.component.http.config;
2 2
3 import cn.hutool.system.SystemUtil; 3 import cn.hutool.system.SystemUtil;
4 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; 4 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
5 -import cn.iocoder.yudao.module.iot.net.component.http.downstream.IotDeviceDownstreamHandlerImpl;  
6 -import cn.iocoder.yudao.module.iot.net.component.http.upstream.IotDeviceUpstreamServer; 5 +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
7 import cn.iocoder.yudao.module.iot.net.component.core.config.IotNetComponentCommonProperties; 6 import cn.iocoder.yudao.module.iot.net.component.core.config.IotNetComponentCommonProperties;
8 import cn.iocoder.yudao.module.iot.net.component.core.downstream.IotDeviceDownstreamHandler; 7 import cn.iocoder.yudao.module.iot.net.component.core.downstream.IotDeviceDownstreamHandler;
9 import cn.iocoder.yudao.module.iot.net.component.core.heartbeat.IotNetComponentRegistry; 8 import cn.iocoder.yudao.module.iot.net.component.core.heartbeat.IotNetComponentRegistry;
10 import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils; 9 import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils;
  10 +import cn.iocoder.yudao.module.iot.net.component.http.downstream.IotDeviceDownstreamHandlerImpl;
  11 +import cn.iocoder.yudao.module.iot.net.component.http.upstream.IotDeviceUpstreamServer;
11 import io.vertx.core.Vertx; 12 import io.vertx.core.Vertx;
12 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
13 import org.springframework.beans.factory.annotation.Qualifier; 14 import org.springframework.beans.factory.annotation.Qualifier;
@@ -15,7 +16,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -15,7 +16,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
15 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 16 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
16 import org.springframework.boot.context.event.ApplicationStartedEvent; 17 import org.springframework.boot.context.event.ApplicationStartedEvent;
17 import org.springframework.boot.context.properties.EnableConfigurationProperties; 18 import org.springframework.boot.context.properties.EnableConfigurationProperties;
18 -import org.springframework.context.ApplicationContext;  
19 import org.springframework.context.annotation.Bean; 19 import org.springframework.context.annotation.Bean;
20 import org.springframework.context.annotation.ComponentScan; 20 import org.springframework.context.annotation.ComponentScan;
21 import org.springframework.context.annotation.Lazy; 21 import org.springframework.context.annotation.Lazy;
@@ -86,25 +86,14 @@ public class IotNetComponentHttpAutoConfiguration { @@ -86,25 +86,14 @@ public class IotNetComponentHttpAutoConfiguration {
86 86
87 /** 87 /**
88 * 创建设备上行服务器 88 * 创建设备上行服务器
89 - *  
90 - * @param vertx Vert.x 实例  
91 - * @param deviceUpstreamApi 设备上行 API  
92 - * @param properties HTTP 组件配置属性  
93 - * @param applicationContext 应用上下文  
94 - * @return 设备上行服务器  
95 */ 89 */
96 @Bean(name = "httpDeviceUpstreamServer", initMethod = "start", destroyMethod = "stop") 90 @Bean(name = "httpDeviceUpstreamServer", initMethod = "start", destroyMethod = "stop")
97 public IotDeviceUpstreamServer deviceUpstreamServer( 91 public IotDeviceUpstreamServer deviceUpstreamServer(
98 @Lazy @Qualifier("httpVertx") Vertx vertx, 92 @Lazy @Qualifier("httpVertx") Vertx vertx,
99 IotDeviceUpstreamApi deviceUpstreamApi, 93 IotDeviceUpstreamApi deviceUpstreamApi,
100 IotNetComponentHttpProperties properties, 94 IotNetComponentHttpProperties properties,
101 - ApplicationContext applicationContext) {  
102 - if (log.isDebugEnabled()) {  
103 - log.debug("HTTP 服务器配置: port={}", properties.getServerPort());  
104 - } else {  
105 - log.info("HTTP 服务器将监听端口: {}", properties.getServerPort());  
106 - }  
107 - return new IotDeviceUpstreamServer(vertx, properties, deviceUpstreamApi, applicationContext); 95 + IotDeviceMessageProducer deviceMessageProducer) {
  96 + return new IotDeviceUpstreamServer(vertx, properties, deviceUpstreamApi, deviceMessageProducer);
108 } 97 }
109 98
110 /** 99 /**
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/java/cn/iocoder/yudao/module/iot/net/component/http/upstream/IotDeviceUpstreamServer.java
1 package cn.iocoder.yudao.module.iot.net.component.http.upstream; 1 package cn.iocoder.yudao.module.iot.net.component.http.upstream;
2 2
3 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; 3 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
  4 +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
4 import cn.iocoder.yudao.module.iot.net.component.http.config.IotNetComponentHttpProperties; 5 import cn.iocoder.yudao.module.iot.net.component.http.config.IotNetComponentHttpProperties;
5 import cn.iocoder.yudao.module.iot.net.component.http.upstream.router.IotDeviceUpstreamVertxHandler; 6 import cn.iocoder.yudao.module.iot.net.component.http.upstream.router.IotDeviceUpstreamVertxHandler;
6 import io.vertx.core.AbstractVerticle; 7 import io.vertx.core.AbstractVerticle;
@@ -8,9 +9,8 @@ import io.vertx.core.Promise; @@ -8,9 +9,8 @@ import io.vertx.core.Promise;
8 import io.vertx.core.Vertx; 9 import io.vertx.core.Vertx;
9 import io.vertx.ext.web.Router; 10 import io.vertx.ext.web.Router;
10 import io.vertx.ext.web.handler.BodyHandler; 11 import io.vertx.ext.web.handler.BodyHandler;
  12 +import lombok.RequiredArgsConstructor;
11 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
12 -import org.springframework.context.ApplicationContext;  
13 -import org.springframework.context.annotation.Lazy;  
14 14
15 /** 15 /**
16 * IoT 设备上行服务器 16 * IoT 设备上行服务器
@@ -19,48 +19,24 @@ import org.springframework.context.annotation.Lazy; @@ -19,48 +19,24 @@ import org.springframework.context.annotation.Lazy;
19 * 19 *
20 * @author 芋道源码 20 * @author 芋道源码
21 */ 21 */
  22 +@RequiredArgsConstructor
22 @Slf4j 23 @Slf4j
23 public class IotDeviceUpstreamServer extends AbstractVerticle { 24 public class IotDeviceUpstreamServer extends AbstractVerticle {
24 25
25 - /**  
26 - * Vert.x 实例  
27 - */  
28 private final Vertx vertx; 26 private final Vertx vertx;
29 27
30 - /**  
31 - * HTTP 组件配置属性  
32 - */  
33 private final IotNetComponentHttpProperties httpProperties; 28 private final IotNetComponentHttpProperties httpProperties;
34 29
35 - /**  
36 - * 设备上行 API  
37 - */  
38 private final IotDeviceUpstreamApi deviceUpstreamApi; 30 private final IotDeviceUpstreamApi deviceUpstreamApi;
39 31
40 - /**  
41 - * Spring 应用上下文  
42 - */  
43 - private final ApplicationContext applicationContext; 32 + private final IotDeviceMessageProducer deviceMessageProducer;
44 33
45 - /**  
46 - * 构造函数  
47 - *  
48 - * @param vertx Vert.x 实例  
49 - * @param httpProperties HTTP 组件配置属性  
50 - * @param deviceUpstreamApi 设备上行 API  
51 - * @param applicationContext Spring 应用上下文  
52 - */  
53 - public IotDeviceUpstreamServer(  
54 - @Lazy Vertx vertx,  
55 - IotNetComponentHttpProperties httpProperties,  
56 - IotDeviceUpstreamApi deviceUpstreamApi,  
57 - ApplicationContext applicationContext) {  
58 - this.vertx = vertx;  
59 - this.httpProperties = httpProperties;  
60 - this.deviceUpstreamApi = deviceUpstreamApi;  
61 - this.applicationContext = applicationContext; 34 + @Override
  35 + public void start() throws Exception {
  36 + start(Promise.promise());
62 } 37 }
63 38
  39 + // TODO @haohao:这样貌似初始化不到;我临时拷贝上去了
64 @Override 40 @Override
65 public void start(Promise<Void> startPromise) { 41 public void start(Promise<Void> startPromise) {
66 // 创建路由 42 // 创建路由
@@ -69,7 +45,7 @@ public class IotDeviceUpstreamServer extends AbstractVerticle { @@ -69,7 +45,7 @@ public class IotDeviceUpstreamServer extends AbstractVerticle {
69 45
70 // 创建处理器 46 // 创建处理器
71 IotDeviceUpstreamVertxHandler upstreamHandler = new IotDeviceUpstreamVertxHandler( 47 IotDeviceUpstreamVertxHandler upstreamHandler = new IotDeviceUpstreamVertxHandler(
72 - deviceUpstreamApi, applicationContext); 48 + deviceUpstreamApi, deviceMessageProducer);
73 49
74 // 添加路由处理器 50 // 添加路由处理器
75 router.post(IotDeviceUpstreamVertxHandler.PROPERTY_PATH).handler(upstreamHandler::handle); 51 router.post(IotDeviceUpstreamVertxHandler.PROPERTY_PATH).handler(upstreamHandler::handle);
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/java/cn/iocoder/yudao/module/iot/net/component/http/upstream/router/IotDeviceUpstreamVertxHandler.java
@@ -8,17 +8,16 @@ import cn.hutool.core.util.StrUtil; @@ -8,17 +8,16 @@ import cn.hutool.core.util.StrUtil;
8 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 8 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
9 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; 9 import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
10 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO; 10 import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO;
11 -import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO;  
12 -import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO;  
13 -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; 11 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  12 +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
14 import cn.iocoder.yudao.module.iot.net.component.core.constants.IotDeviceTopicEnum; 13 import cn.iocoder.yudao.module.iot.net.component.core.constants.IotDeviceTopicEnum;
15 import cn.iocoder.yudao.module.iot.net.component.core.pojo.IotStandardResponse; 14 import cn.iocoder.yudao.module.iot.net.component.core.pojo.IotStandardResponse;
16 import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils; 15 import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils;
17 import io.vertx.core.Handler; 16 import io.vertx.core.Handler;
18 import io.vertx.core.json.JsonObject; 17 import io.vertx.core.json.JsonObject;
19 import io.vertx.ext.web.RoutingContext; 18 import io.vertx.ext.web.RoutingContext;
  19 +import lombok.RequiredArgsConstructor;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
21 -import org.springframework.context.ApplicationContext;  
22 21
23 import java.time.LocalDateTime; 22 import java.time.LocalDateTime;
24 import java.util.Map; 23 import java.util.Map;
@@ -33,6 +32,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -33,6 +32,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
33 * 32 *
34 * @author 芋道源码 33 * @author 芋道源码
35 */ 34 */
  35 +@RequiredArgsConstructor
36 @Slf4j 36 @Slf4j
37 public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { 37 public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> {
38 38
@@ -70,17 +70,10 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -70,17 +70,10 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
70 * 设备上行 API 70 * 设备上行 API
71 */ 71 */
72 private final IotDeviceUpstreamApi deviceUpstreamApi; 72 private final IotDeviceUpstreamApi deviceUpstreamApi;
73 -  
74 /** 73 /**
75 - * 构造函数  
76 - *  
77 - * @param deviceUpstreamApi 设备上行 API  
78 - * @param applicationContext 应用上下文 74 + * 设备消息生产者
79 */ 75 */
80 - public IotDeviceUpstreamVertxHandler(IotDeviceUpstreamApi deviceUpstreamApi,  
81 - ApplicationContext applicationContext) {  
82 - this.deviceUpstreamApi = deviceUpstreamApi;  
83 - } 76 + private final IotDeviceMessageProducer deviceMessageProducer;
84 77
85 @Override 78 @Override
86 public void handle(RoutingContext routingContext) { 79 public void handle(RoutingContext routingContext) {
@@ -170,18 +163,17 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -170,18 +163,17 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
170 */ 163 */
171 private void handlePropertyPost(RoutingContext routingContext, String productKey, String deviceName, 164 private void handlePropertyPost(RoutingContext routingContext, String productKey, String deviceName,
172 String requestId, JsonObject body) { 165 String requestId, JsonObject body) {
173 - // 处理属性上报  
174 - IotDevicePropertyReportReqDTO reportReqDTO = parsePropertyReportRequest(productKey, deviceName,  
175 - requestId, body);  
176 -  
177 - // 设备上线  
178 - updateDeviceState(reportReqDTO.getProductKey(), reportReqDTO.getDeviceName());  
179 -  
180 - // 属性上报  
181 - CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceProperty(reportReqDTO);  
182 -  
183 - // 返回响应  
184 - sendResponse(routingContext, requestId, PROPERTY_METHOD, result); 166 + // 1.1 构建设备消息
  167 + String deviceKey = "xxx"; // TODO @芋艿:待支持
  168 + Long tenantId = 1L; // TODO @芋艿:待支持
  169 + IotDeviceMessage message = IotDeviceMessage.of(productKey, deviceName, deviceKey,
  170 + requestId, LocalDateTime.now(), IotNetComponentCommonUtils.getProcessId(), tenantId)
  171 + .ofPropertyReport(parsePropertiesFromBody(body));
  172 + // 1.2 发送消息
  173 + deviceMessageProducer.sendDeviceMessage(message);
  174 +
  175 + // 2. 返回响应
  176 + sendResponse(routingContext, requestId, PROPERTY_METHOD, null);
185 } 177 }
186 178
187 /** 179 /**
@@ -200,9 +192,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -200,9 +192,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
200 IotDeviceEventReportReqDTO reportReqDTO = parseEventReportRequest(productKey, deviceName, identifier, 192 IotDeviceEventReportReqDTO reportReqDTO = parseEventReportRequest(productKey, deviceName, identifier,
201 requestId, body); 193 requestId, body);
202 194
203 - // 设备上线  
204 - updateDeviceState(reportReqDTO.getProductKey(), reportReqDTO.getDeviceName());  
205 -  
206 // 事件上报 195 // 事件上报
207 CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO); 196 CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO);
208 String method = EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX; 197 String method = EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX;
@@ -221,8 +210,11 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -221,8 +210,11 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
221 */ 210 */
222 private void sendResponse(RoutingContext routingContext, String requestId, String method, 211 private void sendResponse(RoutingContext routingContext, String requestId, String method,
223 CommonResult<Boolean> result) { 212 CommonResult<Boolean> result) {
  213 + // TODO @芋艿:后续再优化
224 IotStandardResponse response; 214 IotStandardResponse response;
225 - if (result.isSuccess()) { 215 + if (result == null ) {
  216 + response = IotStandardResponse.success(requestId, method, null);
  217 + } else if (result.isSuccess()) {
226 response = IotStandardResponse.success(requestId, method, result.getData()); 218 response = IotStandardResponse.success(requestId, method, result.getData());
227 } else { 219 } else {
228 response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg()); 220 response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg());
@@ -265,45 +257,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -265,45 +257,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
265 EVENT_METHOD_SUFFIX; 257 EVENT_METHOD_SUFFIX;
266 } 258 }
267 259
268 - /**  
269 - * 更新设备状态  
270 - *  
271 - * @param productKey 产品 Key  
272 - * @param deviceName 设备名称  
273 - */  
274 - private void updateDeviceState(String productKey, String deviceName) {  
275 - IotDeviceStateUpdateReqDTO reqDTO = ((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO()  
276 - .setRequestId(IdUtil.fastSimpleUUID())  
277 - .setProcessId(IotNetComponentCommonUtils.getProcessId())  
278 - .setReportTime(LocalDateTime.now())  
279 - .setProductKey(productKey)  
280 - .setDeviceName(deviceName)).setState(IotDeviceStateEnum.ONLINE.getState());  
281 - deviceUpstreamApi.updateDeviceState(reqDTO);  
282 - }  
283 -  
284 - /**  
285 - * 解析属性上报请求  
286 - *  
287 - * @param productKey 产品 Key  
288 - * @param deviceName 设备名称  
289 - * @param requestId 请求 ID  
290 - * @param body 请求体  
291 - * @return 属性上报请求 DTO  
292 - */  
293 - private IotDevicePropertyReportReqDTO parsePropertyReportRequest(String productKey, String deviceName,  
294 - String requestId, JsonObject body) {  
295 - // 解析属性  
296 - Map<String, Object> properties = parsePropertiesFromBody(body);  
297 -  
298 - // 构建属性上报请求 DTO  
299 - return ((IotDevicePropertyReportReqDTO) new IotDevicePropertyReportReqDTO()  
300 - .setRequestId(requestId)  
301 - .setProcessId(IotNetComponentCommonUtils.getProcessId())  
302 - .setReportTime(LocalDateTime.now())  
303 - .setProductKey(productKey)  
304 - .setDeviceName(deviceName)).setProperties(properties);  
305 - }  
306 - 260 + // TODO @芋艿:这块在看看
307 /** 261 /**
308 * 从请求体解析属性 262 * 从请求体解析属性
309 * 263 *
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/pom.xml
@@ -50,6 +50,12 @@ @@ -50,6 +50,12 @@
50 <version>${revision}</version> 50 <version>${revision}</version>
51 </dependency> 51 </dependency>
52 52
  53 + <!-- TODO @芋艿:消息队列,后续可能去掉,默认不使用 rocketmq -->
  54 + <dependency>
  55 + <groupId>org.apache.rocketmq</groupId>
  56 + <artifactId>rocketmq-spring-boot-starter</artifactId>
  57 + </dependency>
  58 +
53 </dependencies> 59 </dependencies>
54 60
55 <build> 61 <build>
@@ -72,4 +78,4 @@ @@ -72,4 +78,4 @@
72 </plugins> 78 </plugins>
73 </build> 79 </build>
74 80
75 -</project>  
76 \ No newline at end of file 81 \ No newline at end of file
  82 +</project>
77 \ No newline at end of file 83 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/resources/application.yml
@@ -26,13 +26,13 @@ yudao: @@ -26,13 +26,13 @@ yudao:
26 upstream-url: http://127.0.0.1:48080 # 主程序 API 地址 26 upstream-url: http://127.0.0.1:48080 # 主程序 API 地址
27 upstream-connect-timeout: 30s # 连接超时 27 upstream-connect-timeout: 30s # 连接超时
28 upstream-read-timeout: 30s # 读取超时 28 upstream-read-timeout: 30s # 读取超时
29 - 29 +
30 # 下行通信配置,用于接收主程序的控制指令 30 # 下行通信配置,用于接收主程序的控制指令
31 downstream-port: 18888 # 下行服务器端口 31 downstream-port: 18888 # 下行服务器端口
32 - 32 +
33 # 组件服务唯一标识 33 # 组件服务唯一标识
34 server-key: yudao-module-iot-net-component-server 34 server-key: yudao-module-iot-net-component-server
35 - 35 +
36 # 心跳频率,单位:毫秒 36 # 心跳频率,单位:毫秒
37 heartbeat-interval: 30000 37 heartbeat-interval: 30000
38 38
@@ -50,15 +50,26 @@ yudao: @@ -50,15 +50,26 @@ yudao:
50 enabled: true # 启用EMQX组件 50 enabled: true # 启用EMQX组件
51 mqtt-host: 127.0.0.1 # MQTT服务器主机地址 51 mqtt-host: 127.0.0.1 # MQTT服务器主机地址
52 mqtt-port: 1883 # MQTT服务器端口 52 mqtt-port: 1883 # MQTT服务器端口
53 - mqtt-username: yudao # MQTT服务器用户名  
54 - mqtt-password: 123456 # MQTT服务器密码 53 + mqtt-username: admin # MQTT服务器用户名
  54 + mqtt-password: admin123 # MQTT服务器密码
55 mqtt-ssl: false # 是否启用SSL 55 mqtt-ssl: false # 是否启用SSL
56 mqtt-topics: # 订阅的主题列表 56 mqtt-topics: # 订阅的主题列表
57 - "/sys/#" 57 - "/sys/#"
58 auth-port: 8101 # 认证端口 58 auth-port: 8101 # 认证端口
  59 + message-bus:
  60 + type: rocketmq # 消息总线的类型
59 61
60 # 日志配置 62 # 日志配置
61 logging: 63 logging:
62 level: 64 level:
63 cn.iocoder.yudao: INFO 65 cn.iocoder.yudao: INFO
64 - root: INFO  
65 \ No newline at end of file 66 \ No newline at end of file
  67 + root: INFO
  68 +
  69 +--- #################### 消息队列相关 ####################
  70 +
  71 +# rocketmq 配置项,对应 RocketMQProperties 配置类
  72 +rocketmq:
  73 + name-server: 127.0.0.1:9876 # RocketMQ Namesrv
  74 + # Producer 配置项
  75 + producer:
  76 + group: ${spring.application.name}_PRODUCER # 生产者分组
yudao-server/src/main/resources/application.yaml
@@ -311,6 +311,9 @@ yudao: @@ -311,6 +311,9 @@ yudao:
311 kd100: 311 kd100:
312 key: pLXUGAwK5305 312 key: pLXUGAwK5305
313 customer: E77DF18BE109F454A5CD319E44BF5177 313 customer: E77DF18BE109F454A5CD319E44BF5177
  314 + iot:
  315 + message-bus:
  316 + type: rocketmq # 消息总线的类型
314 317
315 debug: false 318 debug: false
316 # 插件配置 TODO 芋艿:【IOT】需要处理下 319 # 插件配置 TODO 芋艿:【IOT】需要处理下