Commit 1b59aa9ccb26822b48fc0e4bab13ac6b44461ad6
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 | 28 | <artifactId>yudao-module-iot-api</artifactId> |
| 29 | 29 | <version>${revision}</version> |
| 30 | 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 | 37 | <!-- IoT 协议模块 --> |
| 32 | 38 | <dependency> |
| 33 | 39 | <groupId>cn.iocoder.boot</groupId> |
| ... | ... | @@ -80,10 +86,11 @@ |
| 80 | 86 | </dependency> |
| 81 | 87 | |
| 82 | 88 | <!-- 消息队列相关 --> |
| 89 | + <!-- TODO @芋艿:临时打开 --> | |
| 83 | 90 | <dependency> |
| 84 | 91 | <groupId>org.apache.rocketmq</groupId> |
| 85 | 92 | <artifactId>rocketmq-spring-boot-starter</artifactId> |
| 86 | - <optional>true</optional> | |
| 93 | +<!-- <optional>true</optional>--> | |
| 87 | 94 | </dependency> |
| 88 | 95 | <dependency> |
| 89 | 96 | <groupId>org.springframework.kafka</groupId> |
| ... | ... | @@ -147,8 +154,6 @@ |
| 147 | 154 | <!-- <artifactId>yudao-module-iot-script</artifactId>--> |
| 148 | 155 | <!-- <version>${revision}</version>--> |
| 149 | 156 | <!-- </dependency>--> |
| 150 | - | |
| 151 | - | |
| 152 | 157 | </dependencies> |
| 153 | 158 | |
| 154 | 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 | 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 | 6 | import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService; |
| 7 | +import jakarta.annotation.PostConstruct; | |
| 5 | 8 | import jakarta.annotation.Resource; |
| 6 | 9 | import lombok.extern.slf4j.Slf4j; |
| 7 | -import org.springframework.context.event.EventListener; | |
| 8 | -import org.springframework.scheduling.annotation.Async; | |
| 9 | 10 | import org.springframework.stereotype.Component; |
| 10 | 11 | |
| 11 | 12 | /** |
| ... | ... | @@ -15,16 +16,34 @@ import org.springframework.stereotype.Component; |
| 15 | 16 | */ |
| 16 | 17 | @Component |
| 17 | 18 | @Slf4j |
| 18 | -public class IotDeviceLogMessageConsumer { | |
| 19 | +public class IotDeviceLogMessageBusSubscriber implements IotMessageBusSubscriber<IotDeviceMessage> { | |
| 20 | + | |
| 21 | + @Resource | |
| 22 | + private IotMessageBus messageBus; | |
| 19 | 23 | |
| 20 | 24 | @Resource |
| 21 | 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 | 44 | public void onMessage(IotDeviceMessage message) { |
| 26 | 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 | 1 | package cn.iocoder.yudao.module.iot.core.mq.message; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.util.IdUtil; | |
| 3 | 4 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageIdentifierEnum; |
| 4 | 5 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageTypeEnum; |
| 5 | 6 | import lombok.AllArgsConstructor; |
| ... | ... | @@ -8,6 +9,7 @@ import lombok.Data; |
| 8 | 9 | import lombok.NoArgsConstructor; |
| 9 | 10 | |
| 10 | 11 | import java.time.LocalDateTime; |
| 12 | +import java.util.Map; | |
| 11 | 13 | |
| 12 | 14 | // TODO @芋艿:参考阿里云的物模型,优化 IoT 上下行消息的设计,尽量保持一致(渐进式,不要一口气)! |
| 13 | 15 | |
| ... | ... | @@ -21,6 +23,18 @@ import java.time.LocalDateTime; |
| 21 | 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 | 40 | private String requestId; |
| ... | ... | @@ -70,8 +84,41 @@ public class IotDeviceMessage { |
| 70 | 84 | private LocalDateTime reportTime; |
| 71 | 85 | |
| 72 | 86 | /** |
| 87 | + * 服务编号,该消息由哪个消息发送 | |
| 88 | + */ | |
| 89 | + private String serverId; | |
| 90 | + | |
| 91 | + /** | |
| 73 | 92 | * 租户编号 |
| 74 | 93 | */ |
| 75 | 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 | 12 | @RequiredArgsConstructor |
| 13 | 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 | 15 | private final IotMessageBus messageBus; |
| 28 | 16 | |
| 29 | 17 | /** |
| ... | ... | @@ -32,17 +20,17 @@ public class IotDeviceMessageProducer { |
| 32 | 20 | * @param message 设备消息 |
| 33 | 21 | */ |
| 34 | 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 | 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
yudao-module-iot/yudao-module-iot-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
0 → 100644
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/pom.xml
| ... | ... | @@ -24,6 +24,12 @@ |
| 24 | 24 | <version>${revision}</version> |
| 25 | 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 | 33 | <!-- IoT 协议模块 --> |
| 28 | 34 | <dependency> |
| 29 | 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 | 2 | |
| 3 | 3 | import cn.hutool.system.SystemUtil; |
| 4 | 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 | 6 | import cn.iocoder.yudao.module.iot.net.component.core.config.IotNetComponentCommonProperties; |
| 8 | 7 | import cn.iocoder.yudao.module.iot.net.component.core.downstream.IotDeviceDownstreamHandler; |
| 9 | 8 | import cn.iocoder.yudao.module.iot.net.component.core.heartbeat.IotNetComponentRegistry; |
| 10 | 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 | 12 | import io.vertx.core.Vertx; |
| 12 | 13 | import lombok.extern.slf4j.Slf4j; |
| 13 | 14 | import org.springframework.beans.factory.annotation.Qualifier; |
| ... | ... | @@ -15,7 +16,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 15 | 16 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| 16 | 17 | import org.springframework.boot.context.event.ApplicationStartedEvent; |
| 17 | 18 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 18 | -import org.springframework.context.ApplicationContext; | |
| 19 | 19 | import org.springframework.context.annotation.Bean; |
| 20 | 20 | import org.springframework.context.annotation.ComponentScan; |
| 21 | 21 | import org.springframework.context.annotation.Lazy; |
| ... | ... | @@ -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 | 90 | @Bean(name = "httpDeviceUpstreamServer", initMethod = "start", destroyMethod = "stop") |
| 97 | 91 | public IotDeviceUpstreamServer deviceUpstreamServer( |
| 98 | 92 | @Lazy @Qualifier("httpVertx") Vertx vertx, |
| 99 | 93 | IotDeviceUpstreamApi deviceUpstreamApi, |
| 100 | 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 | 1 | package cn.iocoder.yudao.module.iot.net.component.http.upstream; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; |
| 4 | +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; | |
| 4 | 5 | import cn.iocoder.yudao.module.iot.net.component.http.config.IotNetComponentHttpProperties; |
| 5 | 6 | import cn.iocoder.yudao.module.iot.net.component.http.upstream.router.IotDeviceUpstreamVertxHandler; |
| 6 | 7 | import io.vertx.core.AbstractVerticle; |
| ... | ... | @@ -8,9 +9,8 @@ import io.vertx.core.Promise; |
| 8 | 9 | import io.vertx.core.Vertx; |
| 9 | 10 | import io.vertx.ext.web.Router; |
| 10 | 11 | import io.vertx.ext.web.handler.BodyHandler; |
| 12 | +import lombok.RequiredArgsConstructor; | |
| 11 | 13 | import lombok.extern.slf4j.Slf4j; |
| 12 | -import org.springframework.context.ApplicationContext; | |
| 13 | -import org.springframework.context.annotation.Lazy; | |
| 14 | 14 | |
| 15 | 15 | /** |
| 16 | 16 | * IoT 设备上行服务器 |
| ... | ... | @@ -19,48 +19,24 @@ import org.springframework.context.annotation.Lazy; |
| 19 | 19 | * |
| 20 | 20 | * @author 芋道源码 |
| 21 | 21 | */ |
| 22 | +@RequiredArgsConstructor | |
| 22 | 23 | @Slf4j |
| 23 | 24 | public class IotDeviceUpstreamServer extends AbstractVerticle { |
| 24 | 25 | |
| 25 | - /** | |
| 26 | - * Vert.x 实例 | |
| 27 | - */ | |
| 28 | 26 | private final Vertx vertx; |
| 29 | 27 | |
| 30 | - /** | |
| 31 | - * HTTP 组件配置属性 | |
| 32 | - */ | |
| 33 | 28 | private final IotNetComponentHttpProperties httpProperties; |
| 34 | 29 | |
| 35 | - /** | |
| 36 | - * 设备上行 API | |
| 37 | - */ | |
| 38 | 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 | 40 | @Override |
| 65 | 41 | public void start(Promise<Void> startPromise) { |
| 66 | 42 | // 创建路由 |
| ... | ... | @@ -69,7 +45,7 @@ public class IotDeviceUpstreamServer extends AbstractVerticle { |
| 69 | 45 | |
| 70 | 46 | // 创建处理器 |
| 71 | 47 | IotDeviceUpstreamVertxHandler upstreamHandler = new IotDeviceUpstreamVertxHandler( |
| 72 | - deviceUpstreamApi, applicationContext); | |
| 48 | + deviceUpstreamApi, deviceMessageProducer); | |
| 73 | 49 | |
| 74 | 50 | // 添加路由处理器 |
| 75 | 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 | 8 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 9 | 9 | import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; |
| 10 | 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 | 13 | import cn.iocoder.yudao.module.iot.net.component.core.constants.IotDeviceTopicEnum; |
| 15 | 14 | import cn.iocoder.yudao.module.iot.net.component.core.pojo.IotStandardResponse; |
| 16 | 15 | import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils; |
| 17 | 16 | import io.vertx.core.Handler; |
| 18 | 17 | import io.vertx.core.json.JsonObject; |
| 19 | 18 | import io.vertx.ext.web.RoutingContext; |
| 19 | +import lombok.RequiredArgsConstructor; | |
| 20 | 20 | import lombok.extern.slf4j.Slf4j; |
| 21 | -import org.springframework.context.ApplicationContext; | |
| 22 | 21 | |
| 23 | 22 | import java.time.LocalDateTime; |
| 24 | 23 | import java.util.Map; |
| ... | ... | @@ -33,6 +32,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC |
| 33 | 32 | * |
| 34 | 33 | * @author 芋道源码 |
| 35 | 34 | */ |
| 35 | +@RequiredArgsConstructor | |
| 36 | 36 | @Slf4j |
| 37 | 37 | public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { |
| 38 | 38 | |
| ... | ... | @@ -70,17 +70,10 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { |
| 70 | 70 | * 设备上行 API |
| 71 | 71 | */ |
| 72 | 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 | 78 | @Override |
| 86 | 79 | public void handle(RoutingContext routingContext) { |
| ... | ... | @@ -170,18 +163,17 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { |
| 170 | 163 | */ |
| 171 | 164 | private void handlePropertyPost(RoutingContext routingContext, String productKey, String deviceName, |
| 172 | 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<RoutingContext> { |
| 200 | 192 | IotDeviceEventReportReqDTO reportReqDTO = parseEventReportRequest(productKey, deviceName, identifier, |
| 201 | 193 | requestId, body); |
| 202 | 194 | |
| 203 | - // 设备上线 | |
| 204 | - updateDeviceState(reportReqDTO.getProductKey(), reportReqDTO.getDeviceName()); | |
| 205 | - | |
| 206 | 195 | // 事件上报 |
| 207 | 196 | CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO); |
| 208 | 197 | String method = EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX; |
| ... | ... | @@ -221,8 +210,11 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { |
| 221 | 210 | */ |
| 222 | 211 | private void sendResponse(RoutingContext routingContext, String requestId, String method, |
| 223 | 212 | CommonResult<Boolean> result) { |
| 213 | + // TODO @芋艿:后续再优化 | |
| 224 | 214 | IotStandardResponse response; |
| 225 | - if (result.isSuccess()) { | |
| 215 | + if (result == null ) { | |
| 216 | + response = IotStandardResponse.success(requestId, method, null); | |
| 217 | + } else if (result.isSuccess()) { | |
| 226 | 218 | response = IotStandardResponse.success(requestId, method, result.getData()); |
| 227 | 219 | } else { |
| 228 | 220 | response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg()); |
| ... | ... | @@ -265,45 +257,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { |
| 265 | 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 | 50 | <version>${revision}</version> |
| 51 | 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 | 59 | </dependencies> |
| 54 | 60 | |
| 55 | 61 | <build> |
| ... | ... | @@ -72,4 +78,4 @@ |
| 72 | 78 | </plugins> |
| 73 | 79 | </build> |
| 74 | 80 | |
| 75 | -</project> | |
| 76 | 81 | \ No newline at end of file |
| 82 | +</project> | |
| 77 | 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 | 26 | upstream-url: http://127.0.0.1:48080 # 主程序 API 地址 |
| 27 | 27 | upstream-connect-timeout: 30s # 连接超时 |
| 28 | 28 | upstream-read-timeout: 30s # 读取超时 |
| 29 | - | |
| 29 | + | |
| 30 | 30 | # 下行通信配置,用于接收主程序的控制指令 |
| 31 | 31 | downstream-port: 18888 # 下行服务器端口 |
| 32 | - | |
| 32 | + | |
| 33 | 33 | # 组件服务唯一标识 |
| 34 | 34 | server-key: yudao-module-iot-net-component-server |
| 35 | - | |
| 35 | + | |
| 36 | 36 | # 心跳频率,单位:毫秒 |
| 37 | 37 | heartbeat-interval: 30000 |
| 38 | 38 | |
| ... | ... | @@ -50,15 +50,26 @@ yudao: |
| 50 | 50 | enabled: true # 启用EMQX组件 |
| 51 | 51 | mqtt-host: 127.0.0.1 # MQTT服务器主机地址 |
| 52 | 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 | 55 | mqtt-ssl: false # 是否启用SSL |
| 56 | 56 | mqtt-topics: # 订阅的主题列表 |
| 57 | 57 | - "/sys/#" |
| 58 | 58 | auth-port: 8101 # 认证端口 |
| 59 | + message-bus: | |
| 60 | + type: rocketmq # 消息总线的类型 | |
| 59 | 61 | |
| 60 | 62 | # 日志配置 |
| 61 | 63 | logging: |
| 62 | 64 | level: |
| 63 | 65 | cn.iocoder.yudao: INFO |
| 64 | - root: INFO | |
| 65 | 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