Commit c3485a3f3daa2dbcdb03c6c0484afefb8ae655ee

Authored by YunaiV
1 parent 81cbc61f

reactor:【IoT 物联网】将 http component 合并到 gateway 里

Showing 46 changed files with 524 additions and 922 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDO.java
@@ -33,6 +33,7 @@ public class IotDeviceDO extends TenantBaseDO { @@ -33,6 +33,7 @@ public class IotDeviceDO extends TenantBaseDO {
33 */ 33 */
34 @TableId 34 @TableId
35 private Long id; 35 private Long id;
  36 + // TODO @芋艿:看看怎么弱化 deviceKey
36 /** 37 /**
37 * 设备唯一标识符,全局唯一,用于识别设备 38 * 设备唯一标识符,全局唯一,用于识别设备
38 * 39 *
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
9 */ 9 */
10 public interface RedisKeyConstants { 10 public interface RedisKeyConstants {
11 11
  12 + // TODO @芋艿:弱化 deviceKey;使用 product_key + device_name 替代
12 /** 13 /**
13 * 设备属性的数据缓存,采用 HASH 结构 14 * 设备属性的数据缓存,采用 HASH 结构
14 * <p> 15 * <p>
@@ -18,6 +19,7 @@ public interface RedisKeyConstants { @@ -18,6 +19,7 @@ public interface RedisKeyConstants {
18 */ 19 */
19 String DEVICE_PROPERTY = "iot:device_property:%s"; 20 String DEVICE_PROPERTY = "iot:device_property:%s";
20 21
  22 + // TODO @芋艿:弱化 deviceKey;使用 product_key + device_name 替代
21 /** 23 /**
22 * 设备的最后上报时间,采用 ZSET 结构 24 * 设备的最后上报时间,采用 ZSET 结构
23 * 25 *
@@ -29,7 +31,7 @@ public interface RedisKeyConstants { @@ -29,7 +31,7 @@ public interface RedisKeyConstants {
29 /** 31 /**
30 * 设备信息的数据缓存,使用 Spring Cache 操作(忽略租户) 32 * 设备信息的数据缓存,使用 Spring Cache 操作(忽略租户)
31 * 33 *
32 - * KEY 格式:device_${productKey}_${deviceKey} 34 + * KEY 格式:device_${productKey}_${deviceName}
33 * VALUE 数据类型:String(JSON) 35 * VALUE 数据类型:String(JSON)
34 */ 36 */
35 String DEVICE = "iot:device"; 37 String DEVICE = "iot:device";
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageBusSubscriber.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageSubscriber.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.core.messagebus.core.IotMessageBus; 3 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
4 -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; 4 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
6 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; 7 import jakarta.annotation.PostConstruct;
@@ -16,7 +16,7 @@ import org.springframework.stereotype.Component; @@ -16,7 +16,7 @@ import org.springframework.stereotype.Component;
16 */ 16 */
17 @Component 17 @Component
18 @Slf4j 18 @Slf4j
19 -public class IotDeviceLogMessageBusSubscriber implements IotMessageBusSubscriber<IotDeviceMessage> { 19 +public class IotDeviceLogMessageSubscriber implements IotMessageSubscriber<IotDeviceMessage> {
20 20
21 @Resource 21 @Resource
22 private IotMessageBus messageBus; 22 private IotMessageBus messageBus;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java
@@ -20,7 +20,6 @@ import jakarta.annotation.Resource; @@ -20,7 +20,6 @@ import jakarta.annotation.Resource;
20 import lombok.extern.slf4j.Slf4j; 20 import lombok.extern.slf4j.Slf4j;
21 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
22 import org.springframework.validation.annotation.Validated; 22 import org.springframework.validation.annotation.Validated;
23 -import org.springframework.web.client.RestTemplate;  
24 23
25 import java.time.LocalDateTime; 24 import java.time.LocalDateTime;
26 import java.util.List; 25 import java.util.List;
@@ -45,9 +44,6 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic @@ -45,9 +44,6 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
45 private IotDeviceService deviceService; 44 private IotDeviceService deviceService;
46 45
47 @Resource 46 @Resource
48 - private RestTemplate restTemplate;  
49 -  
50 - @Resource  
51 private IotDeviceProducer deviceProducer; 47 private IotDeviceProducer deviceProducer;
52 @Resource 48 @Resource
53 private IotDeviceMessageProducer deviceMessageProducer; 49 private IotDeviceMessageProducer deviceMessageProducer;
@@ -156,7 +152,7 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic @@ -156,7 +152,7 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
156 cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage message = cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage 152 cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage message = cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage
157 .of(getProductKey(device, parentDevice), getDeviceName(device, parentDevice), deviceName, 153 .of(getProductKey(device, parentDevice), getDeviceName(device, parentDevice), deviceName,
158 null, tenantId); 154 null, tenantId);
159 - String serverId = "yy"; 155 + String serverId = "192_168_64_1_8092";
160 deviceMessageProducer.sendGatewayDeviceMessage(serverId, message); 156 deviceMessageProducer.sendGatewayDeviceMessage(serverId, message);
161 // TODO @芋艿:后续可以清理掉 157 // TODO @芋艿:后续可以清理掉
162 return null; 158 return null;
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageBus.java
@@ -22,6 +22,6 @@ public interface IotMessageBus { @@ -22,6 +22,6 @@ public interface IotMessageBus {
22 * 22 *
23 * @param subscriber 订阅者 23 * @param subscriber 订阅者
24 */ 24 */
25 - void register(IotMessageBusSubscriber<?> subscriber); 25 + void register(IotMessageSubscriber<?> subscriber);
26 26
27 } 27 }
28 \ No newline at end of file 28 \ No newline at end of file
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageBusSubscriber.java renamed to yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageSubscriber.java
@@ -7,7 +7,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core; @@ -7,7 +7,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core;
7 * 7 *
8 * @author 芋道源码 8 * @author 芋道源码
9 */ 9 */
10 -public interface IotMessageBusSubscriber<T> { 10 +public interface IotMessageSubscriber<T> {
11 11
12 /** 12 /**
13 * @return 主题 13 * @return 主题
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBus.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core.local; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core.local;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; 4 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
5 -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; 5 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
6 import lombok.RequiredArgsConstructor; 6 import lombok.RequiredArgsConstructor;
7 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
8 import org.springframework.context.ApplicationContext; 8 import org.springframework.context.ApplicationContext;
@@ -30,7 +30,7 @@ public class LocalIotMessageBus implements IotMessageBus { @@ -30,7 +30,7 @@ public class LocalIotMessageBus implements IotMessageBus {
30 * 订阅者映射表 30 * 订阅者映射表
31 * Key: topic 31 * Key: topic
32 */ 32 */
33 - private final Map<String, List<IotMessageBusSubscriber<?>>> subscribers = new HashMap<>(); 33 + private final Map<String, List<IotMessageSubscriber<?>>> subscribers = new HashMap<>();
34 34
35 @Override 35 @Override
36 public void post(String topic, Object message) { 36 public void post(String topic, Object message) {
@@ -38,9 +38,9 @@ public class LocalIotMessageBus implements IotMessageBus { @@ -38,9 +38,9 @@ public class LocalIotMessageBus implements IotMessageBus {
38 } 38 }
39 39
40 @Override 40 @Override
41 - public void register(IotMessageBusSubscriber<?> subscriber) { 41 + public void register(IotMessageSubscriber<?> subscriber) {
42 String topic = subscriber.getTopic(); 42 String topic = subscriber.getTopic();
43 - List<IotMessageBusSubscriber<?>> topicSubscribers = subscribers.computeIfAbsent(topic, k -> new ArrayList<>()); 43 + List<IotMessageSubscriber<?>> topicSubscribers = subscribers.computeIfAbsent(topic, k -> new ArrayList<>());
44 topicSubscribers.add(subscriber); 44 topicSubscribers.add(subscriber);
45 log.info("[register][topic({}/{}) 注册消费者({})成功]", 45 log.info("[register][topic({}/{}) 注册消费者({})成功]",
46 topic, subscriber.getGroup(), subscriber.getClass().getName()); 46 topic, subscriber.getGroup(), subscriber.getClass().getName());
@@ -50,11 +50,11 @@ public class LocalIotMessageBus implements IotMessageBus { @@ -50,11 +50,11 @@ public class LocalIotMessageBus implements IotMessageBus {
50 @SuppressWarnings({"unchecked", "rawtypes"}) 50 @SuppressWarnings({"unchecked", "rawtypes"})
51 public void onMessage(LocalIotMessage message) { 51 public void onMessage(LocalIotMessage message) {
52 String topic = message.getTopic(); 52 String topic = message.getTopic();
53 - List<IotMessageBusSubscriber<?>> topicSubscribers = subscribers.get(topic); 53 + List<IotMessageSubscriber<?>> topicSubscribers = subscribers.get(topic);
54 if (CollUtil.isEmpty(topicSubscribers)) { 54 if (CollUtil.isEmpty(topicSubscribers)) {
55 return; 55 return;
56 } 56 }
57 - for (IotMessageBusSubscriber subscriber : topicSubscribers) { 57 + for (IotMessageSubscriber subscriber : topicSubscribers) {
58 try { 58 try {
59 subscriber.onMessage(message.getMessage()); 59 subscriber.onMessage(message.getMessage());
60 } catch (Exception ex) { 60 } catch (Exception ex) {
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBus.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core.rocketmq; @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core.rocketmq;
3 import cn.hutool.core.util.TypeUtil; 3 import cn.hutool.core.util.TypeUtil;
4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
5 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; 5 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
6 -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; 6 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
7 import lombok.RequiredArgsConstructor; 7 import lombok.RequiredArgsConstructor;
8 import lombok.SneakyThrows; 8 import lombok.SneakyThrows;
9 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
@@ -47,7 +47,7 @@ public class RocketMQIotMessageBus implements IotMessageBus { @@ -47,7 +47,7 @@ public class RocketMQIotMessageBus implements IotMessageBus {
47 47
48 @Override 48 @Override
49 @SneakyThrows 49 @SneakyThrows
50 - public void register(IotMessageBusSubscriber<?> subscriber) { 50 + public void register(IotMessageSubscriber<?> subscriber) {
51 Type type = TypeUtil.getTypeArgument(subscriber.getClass(), 0); 51 Type type = TypeUtil.getTypeArgument(subscriber.getClass(), 0);
52 if (type == null) { 52 if (type == null) {
53 throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName())); 53 throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName()));
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;  
4 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageIdentifierEnum; 3 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageIdentifierEnum;
5 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageTypeEnum; 4 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageTypeEnum;
  5 +import cn.iocoder.yudao.module.iot.core.util.IotCoreUtils;
6 import lombok.AllArgsConstructor; 6 import lombok.AllArgsConstructor;
7 import lombok.Builder; 7 import lombok.Builder;
8 import lombok.Data; 8 import lombok.Data;
@@ -119,7 +119,7 @@ public class IotDeviceMessage { @@ -119,7 +119,7 @@ public class IotDeviceMessage {
119 String requestId, LocalDateTime reportTime, 119 String requestId, LocalDateTime reportTime,
120 String serverId, Long tenantId) { 120 String serverId, Long tenantId) {
121 if (requestId == null) { 121 if (requestId == null) {
122 - requestId = IdUtil.fastSimpleUUID(); 122 + requestId = IotCoreUtils.generateRequestId();
123 } 123 }
124 if (reportTime == null) { 124 if (reportTime == null) {
125 reportTime = LocalDateTime.now(); 125 reportTime = LocalDateTime.now();
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotCoreUtils.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.core.util;
  2 +
  3 +import cn.hutool.core.util.IdUtil;
  4 +import cn.hutool.system.SystemUtil;
  5 +
  6 +/**
  7 + * IoT 核心模块的工具类
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +public class IotCoreUtils {
  12 +
  13 + /**
  14 + * 生成服务器编号
  15 + *
  16 + * @param serverPort 服务器端口
  17 + * @return 服务器编号
  18 + */
  19 + public static String generateServerId(Integer serverPort) {
  20 + String serverId = String.format("%s.%d", SystemUtil.getHostInfo().getAddress(), serverPort);
  21 + // 避免一些场景无法使用 . 符号,例如说 RocketMQ Topic
  22 + return serverId.replaceAll("\\.", "_");
  23 + }
  24 +
  25 + public static String generateRequestId() {
  26 + return IdUtil.fastSimpleUUID();
  27 + }
  28 +
  29 +}
0 \ No newline at end of file 30 \ No newline at end of file
yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBusIntegrationTest.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core.local; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core.local;
2 2
3 import cn.iocoder.yudao.module.iot.core.messagebus.config.IotMessageBusAutoConfiguration; 3 import cn.iocoder.yudao.module.iot.core.messagebus.config.IotMessageBusAutoConfiguration;
4 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; 4 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
5 -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; 5 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
6 import jakarta.annotation.Resource; 6 import jakarta.annotation.Resource;
7 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
8 import org.junit.jupiter.api.Test; 8 import org.junit.jupiter.api.Test;
@@ -47,7 +47,7 @@ public class LocalIotMessageBusIntegrationTest { @@ -47,7 +47,7 @@ public class LocalIotMessageBusIntegrationTest {
47 AtomicInteger subscriber2Count = new AtomicInteger(0); 47 AtomicInteger subscriber2Count = new AtomicInteger(0);
48 48
49 // 创建第一个订阅者 49 // 创建第一个订阅者
50 - IotMessageBusSubscriber<String> subscriber1 = new IotMessageBusSubscriber<>() { 50 + IotMessageSubscriber<String> subscriber1 = new IotMessageSubscriber<>() {
51 51
52 @Override 52 @Override
53 public String getTopic() { 53 public String getTopic() {
@@ -69,7 +69,7 @@ public class LocalIotMessageBusIntegrationTest { @@ -69,7 +69,7 @@ public class LocalIotMessageBusIntegrationTest {
69 69
70 }; 70 };
71 // 创建第二个订阅者 71 // 创建第二个订阅者
72 - IotMessageBusSubscriber<String> subscriber2 = new IotMessageBusSubscriber<>() { 72 + IotMessageSubscriber<String> subscriber2 = new IotMessageSubscriber<>() {
73 73
74 @Override 74 @Override
75 public String getTopic() { 75 public String getTopic() {
@@ -120,7 +120,7 @@ public class LocalIotMessageBusIntegrationTest { @@ -120,7 +120,7 @@ public class LocalIotMessageBusIntegrationTest {
120 CountDownLatch latch = new CountDownLatch(2); 120 CountDownLatch latch = new CountDownLatch(2);
121 121
122 // 创建订阅者 1 - 只订阅设备状态 122 // 创建订阅者 1 - 只订阅设备状态
123 - IotMessageBusSubscriber<String> statusSubscriber = new IotMessageBusSubscriber<>() { 123 + IotMessageSubscriber<String> statusSubscriber = new IotMessageSubscriber<>() {
124 124
125 @Override 125 @Override
126 public String getTopic() { 126 public String getTopic() {
@@ -141,7 +141,7 @@ public class LocalIotMessageBusIntegrationTest { @@ -141,7 +141,7 @@ public class LocalIotMessageBusIntegrationTest {
141 141
142 }; 142 };
143 // 创建订阅者 2 - 只订阅设备数据 143 // 创建订阅者 2 - 只订阅设备数据
144 - IotMessageBusSubscriber<String> dataSubscriber = new IotMessageBusSubscriber<>() { 144 + IotMessageSubscriber<String> dataSubscriber = new IotMessageSubscriber<>() {
145 145
146 @Override 146 @Override
147 public String getTopic() { 147 public String getTopic() {
yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBusTest.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core.rocketmq; @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.core.messagebus.core.rocketmq;
3 import cn.hutool.core.util.IdUtil; 3 import cn.hutool.core.util.IdUtil;
4 import cn.iocoder.yudao.module.iot.core.messagebus.config.IotMessageBusAutoConfiguration; 4 import cn.iocoder.yudao.module.iot.core.messagebus.config.IotMessageBusAutoConfiguration;
5 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; 5 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
6 -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; 6 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
7 import cn.iocoder.yudao.module.iot.core.messagebus.core.TestMessage; 7 import cn.iocoder.yudao.module.iot.core.messagebus.core.TestMessage;
8 import jakarta.annotation.Resource; 8 import jakarta.annotation.Resource;
9 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
@@ -59,7 +59,7 @@ public class RocketMQIotMessageBusTest { @@ -59,7 +59,7 @@ public class RocketMQIotMessageBusTest {
59 messageBus.post(topic, testMessage); 59 messageBus.post(topic, testMessage);
60 60
61 // 创建订阅者 61 // 创建订阅者
62 - IotMessageBusSubscriber<String> subscriber1 = new IotMessageBusSubscriber<>() { 62 + IotMessageSubscriber<String> subscriber1 = new IotMessageSubscriber<>() {
63 63
64 @Override 64 @Override
65 public String getTopic() { 65 public String getTopic() {
@@ -117,7 +117,7 @@ public class RocketMQIotMessageBusTest { @@ -117,7 +117,7 @@ public class RocketMQIotMessageBusTest {
117 messageBus.post(topic, testMessage); 117 messageBus.post(topic, testMessage);
118 118
119 // 创建第一个订阅者 119 // 创建第一个订阅者
120 - IotMessageBusSubscriber<TestMessage> subscriber1 = new IotMessageBusSubscriber<>() { 120 + IotMessageSubscriber<TestMessage> subscriber1 = new IotMessageSubscriber<>() {
121 121
122 @Override 122 @Override
123 public String getTopic() { 123 public String getTopic() {
@@ -141,7 +141,7 @@ public class RocketMQIotMessageBusTest { @@ -141,7 +141,7 @@ public class RocketMQIotMessageBusTest {
141 141
142 }; 142 };
143 // 创建第二个订阅者 143 // 创建第二个订阅者
144 - IotMessageBusSubscriber<TestMessage> subscriber2 = new IotMessageBusSubscriber<>() { 144 + IotMessageSubscriber<TestMessage> subscriber2 = new IotMessageSubscriber<>() {
145 145
146 @Override 146 @Override
147 public String getTopic() { 147 public String getTopic() {
@@ -204,7 +204,7 @@ public class RocketMQIotMessageBusTest { @@ -204,7 +204,7 @@ public class RocketMQIotMessageBusTest {
204 messageBus.post(topic2, message2); 204 messageBus.post(topic2, message2);
205 205
206 // 创建订阅者 1 - 只订阅设备状态 206 // 创建订阅者 1 - 只订阅设备状态
207 - IotMessageBusSubscriber<String> statusSubscriber = new IotMessageBusSubscriber<>() { 207 + IotMessageSubscriber<String> statusSubscriber = new IotMessageSubscriber<>() {
208 208
209 @Override 209 @Override
210 public String getTopic() { 210 public String getTopic() {
@@ -227,7 +227,7 @@ public class RocketMQIotMessageBusTest { @@ -227,7 +227,7 @@ public class RocketMQIotMessageBusTest {
227 227
228 }; 228 };
229 // 创建订阅者 2 - 只订阅设备数据 229 // 创建订阅者 2 - 只订阅设备数据
230 - IotMessageBusSubscriber<String> dataSubscriber = new IotMessageBusSubscriber<>() { 230 + IotMessageSubscriber<String> dataSubscriber = new IotMessageSubscriber<>() {
231 231
232 @Override 232 @Override
233 public String getTopic() { 233 public String getTopic() {
yudao-module-iot/yudao-module-iot-gateway/pom.xml
@@ -16,4 +16,46 @@ @@ -16,4 +16,46 @@
16 ② 功能二:接收来自消息网关的消息(由 iot-biz 发送),并进行编码(encode)后,发送给设备 16 ② 功能二:接收来自消息网关的消息(由 iot-biz 发送),并进行编码(encode)后,发送给设备
17 </description> 17 </description>
18 18
  19 + <dependencies>
  20 + <dependency>
  21 + <groupId>cn.iocoder.boot</groupId>
  22 + <artifactId>yudao-module-iot-core</artifactId>
  23 + <version>${revision}</version>
  24 + </dependency>
  25 +
  26 + <!-- 消息队列相关 -->
  27 + <dependency>
  28 + <groupId>org.apache.rocketmq</groupId>
  29 + <artifactId>rocketmq-spring-boot-starter</artifactId>
  30 + <!-- TODO @芋艿:消息队列,后续可能去掉,默认不使用 rocketmq -->
  31 +<!-- <optional>true</optional> -->
  32 + </dependency>
  33 +
  34 + <!-- 工具类相关 -->
  35 + <dependency>
  36 + <groupId>io.vertx</groupId>
  37 + <artifactId>vertx-web</artifactId>
  38 + </dependency>
  39 + </dependencies>
  40 +
  41 + <build>
  42 + <!-- 设置构建的 jar 包名 -->
  43 + <finalName>${project.artifactId}</finalName>
  44 + <plugins>
  45 + <!-- 打包 -->
  46 + <plugin>
  47 + <groupId>org.springframework.boot</groupId>
  48 + <artifactId>spring-boot-maven-plugin</artifactId>
  49 + <version>${spring.boot.version}</version>
  50 + <executions>
  51 + <execution>
  52 + <goals>
  53 + <goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
  54 + </goals>
  55 + </execution>
  56 + </executions>
  57 + </plugin>
  58 + </plugins>
  59 + </build>
  60 +
19 </project> 61 </project>
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/IotGatewayServerApplication.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.gateway;
  2 +
  3 +import org.springframework.boot.SpringApplication;
  4 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  5 +
  6 +@SpringBootApplication
  7 +public class IotGatewayServerApplication {
  8 +
  9 + public static void main(String[] args) {
  10 + SpringApplication.run(IotGatewayServerApplication.class, args);
  11 + }
  12 +
  13 +}
0 \ No newline at end of file 14 \ No newline at end of file
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/codec/package-info.java
  1 +/**
  2 + * 提供设备接入的各种数据(请求、响应)的编解码
  3 + */
1 package cn.iocoder.yudao.module.iot.gateway.codec; 4 package cn.iocoder.yudao.module.iot.gateway.codec;
2 \ No newline at end of file 5 \ No newline at end of file
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.gateway.config;
  2 +
  3 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
  4 +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
  5 +import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpDownstreamSubscriber;
  6 +import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpUpstreamProtocol;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  9 +import org.springframework.boot.context.properties.EnableConfigurationProperties;
  10 +import org.springframework.context.annotation.Bean;
  11 +import org.springframework.context.annotation.Configuration;
  12 +
  13 +@Configuration
  14 +@EnableConfigurationProperties(IotGatewayProperties.class)
  15 +@Slf4j
  16 +public class IotGatewayConfiguration {
  17 +
  18 + /**
  19 + * IoT 网关 HTTP 协议配置类
  20 + */
  21 + @Configuration
  22 + @ConditionalOnProperty(prefix = "yudao.iot.gateway.protocol.http", name = "enabled", havingValue = "true")
  23 + @Slf4j
  24 + public static class HttpProtocolConfiguration {
  25 +
  26 + @Bean
  27 + public IotHttpUpstreamProtocol iotHttpUpstreamProtocol(IotGatewayProperties gatewayProperties,
  28 + IotDeviceMessageProducer deviceMessageProducer) {
  29 + return new IotHttpUpstreamProtocol(gatewayProperties.getProtocol().getHttp(), deviceMessageProducer);
  30 + }
  31 +
  32 + @Bean
  33 + public IotHttpDownstreamSubscriber iotHttpDownstreamSubscriber(IotHttpUpstreamProtocol httpUpstreamProtocol,
  34 + IotMessageBus messageBus) {
  35 + return new IotHttpDownstreamSubscriber(httpUpstreamProtocol,messageBus);
  36 + }
  37 + }
  38 +
  39 +}
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayProperties.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.gateway.config;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.boot.context.properties.ConfigurationProperties;
  5 +import org.springframework.validation.annotation.Validated;
  6 +
  7 +import java.util.List;
  8 +
  9 +@ConfigurationProperties(prefix = "yudao.iot.gateway")
  10 +@Validated
  11 +@Data
  12 +public class IotGatewayProperties {
  13 +
  14 + /**
  15 + * 设备 RPC 服务配置
  16 + */
  17 + private RpcProperties rpc;
  18 +
  19 + /**
  20 + * 协议配置
  21 + */
  22 + private ProtocolProperties protocol;
  23 +
  24 + @Data
  25 + public static class RpcProperties {
  26 +
  27 + /**
  28 + * 主程序 API 地址
  29 + */
  30 + private String url;
  31 + /**
  32 + * 连接超时时间
  33 + */
  34 + private String connectTimeout;
  35 + /**
  36 + * 读取超时时间
  37 + */
  38 + private String readTimeout;
  39 +
  40 + }
  41 +
  42 + @Data
  43 + public static class ProtocolProperties {
  44 +
  45 + /**
  46 + * HTTP 组件配置
  47 + */
  48 + private HttpProperties http;
  49 +
  50 + /**
  51 + * EMQX 组件配置
  52 + */
  53 + private EmqxProperties emqx;
  54 +
  55 + }
  56 +
  57 + @Data
  58 + public static class HttpProperties {
  59 +
  60 + /**
  61 + * 是否开启
  62 + */
  63 + private Boolean enabled;
  64 + /**
  65 + * 服务端口
  66 + */
  67 + private Integer serverPort;
  68 +
  69 + }
  70 +
  71 + @Data
  72 + public static class EmqxProperties {
  73 +
  74 + /**
  75 + * 是否开启
  76 + */
  77 + private Boolean enabled;
  78 + /**
  79 + * MQTT 服务器地址
  80 + */
  81 + private String mqttHost;
  82 + /**
  83 + * MQTT 服务器端口
  84 + */
  85 + private Integer mqttPort;
  86 + /**
  87 + * MQTT 用户名
  88 + */
  89 + private String mqttUsername;
  90 + /**
  91 + * MQTT 密码
  92 + */
  93 + private String mqttPassword;
  94 + /**
  95 + * MQTT 是否开启 SSL
  96 + */
  97 + private Boolean mqttSsl;
  98 + /**
  99 + * MQTT 主题
  100 + */
  101 + private List<String> mqttTopics;
  102 + /**
  103 + * 认证端口
  104 + */
  105 + private Integer authPort;
  106 +
  107 + }
  108 +
  109 +}
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/constants/IotDeviceTopicEnum.java renamed to yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/enums/IotDeviceTopicEnum.java
1 -package cn.iocoder.yudao.module.iot.net.component.core.constants; 1 +package cn.iocoder.yudao.module.iot.gateway.enums;
2 2
3 import lombok.Getter; 3 import lombok.Getter;
  4 +import lombok.RequiredArgsConstructor;
4 5
5 -// TODO @haohao:要不放到 enums 包下;  
6 /** 6 /**
7 * IoT 设备主题枚举 7 * IoT 设备主题枚举
8 * <p> 8 * <p>
@@ -10,6 +10,7 @@ import lombok.Getter; @@ -10,6 +10,7 @@ import lombok.Getter;
10 * 10 *
11 * @author haohao 11 * @author haohao
12 */ 12 */
  13 +@RequiredArgsConstructor
13 @Getter 14 @Getter
14 public enum IotDeviceTopicEnum { 15 public enum IotDeviceTopicEnum {
15 16
@@ -27,36 +28,36 @@ public enum IotDeviceTopicEnum { @@ -27,36 +28,36 @@ public enum IotDeviceTopicEnum {
27 // TODO @haohao:注释时,中英文之间,有个空格; 28 // TODO @haohao:注释时,中英文之间,有个空格;
28 /** 29 /**
29 * 设备属性设置主题 30 * 设备属性设置主题
30 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/set  
31 - * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/property/set_reply 31 + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/service/property/set
  32 + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/service/property/set_reply
32 */ 33 */
33 PROPERTY_SET_TOPIC("/thing/service/property/set", "设备属性设置主题"), 34 PROPERTY_SET_TOPIC("/thing/service/property/set", "设备属性设置主题"),
34 35
35 /** 36 /**
36 * 设备属性获取主题 37 * 设备属性获取主题
37 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/get  
38 - * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/property/get_reply 38 + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/service/property/get
  39 + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/service/property/get_reply
39 */ 40 */
40 PROPERTY_GET_TOPIC("/thing/service/property/get", "设备属性获取主题"), 41 PROPERTY_GET_TOPIC("/thing/service/property/get", "设备属性获取主题"),
41 42
42 /** 43 /**
43 * 设备配置设置主题 44 * 设备配置设置主题
44 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/config/set  
45 - * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/config/set_reply 45 + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/service/config/set
  46 + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/service/config/set_reply
46 */ 47 */
47 CONFIG_SET_TOPIC("/thing/service/config/set", "设备配置设置主题"), 48 CONFIG_SET_TOPIC("/thing/service/config/set", "设备配置设置主题"),
48 49
49 /** 50 /**
50 * 设备OTA升级主题 51 * 设备OTA升级主题
51 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade  
52 - * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade_reply 52 + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade
  53 + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade_reply
53 */ 54 */
54 OTA_UPGRADE_TOPIC("/thing/service/ota/upgrade", "设备OTA升级主题"), 55 OTA_UPGRADE_TOPIC("/thing/service/ota/upgrade", "设备OTA升级主题"),
55 56
56 /** 57 /**
57 * 设备属性上报主题 58 * 设备属性上报主题
58 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/event/property/post  
59 - * 响应Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply 59 + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post
  60 + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply
60 */ 61 */
61 PROPERTY_POST_TOPIC("/thing/event/property/post", "设备属性上报主题"), 62 PROPERTY_POST_TOPIC("/thing/event/property/post", "设备属性上报主题"),
62 63
@@ -78,12 +79,6 @@ public enum IotDeviceTopicEnum { @@ -78,12 +79,6 @@ public enum IotDeviceTopicEnum {
78 private final String topic; 79 private final String topic;
79 private final String description; 80 private final String description;
80 81
81 - // TODO @haohao:使用 lombok 去除  
82 - IotDeviceTopicEnum(String topic, String description) {  
83 - this.topic = topic;  
84 - this.description = description;  
85 - }  
86 -  
87 /** 82 /**
88 * 构建设备服务调用主题 83 * 构建设备服务调用主题
89 * 84 *
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/package-info.java deleted
1 -package cn.iocoder.yudao.module.iot.gateway;  
2 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpDownstreamSubscriber.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.gateway.protocol.http;
  2 +
  3 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
  4 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
  5 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  6 +import jakarta.annotation.PostConstruct;
  7 +import lombok.RequiredArgsConstructor;
  8 +import lombok.extern.slf4j.Slf4j;
  9 +
  10 +/**
  11 + * IoT 网关 HTTP 订阅者:接收下行给设备的消息
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@RequiredArgsConstructor
  16 +@Slf4j
  17 +public class IotHttpDownstreamSubscriber implements IotMessageSubscriber<IotDeviceMessage> {
  18 +
  19 + private final IotHttpUpstreamProtocol protocol;
  20 +
  21 + private final IotMessageBus messageBus;
  22 +
  23 + @PostConstruct
  24 + public void init() {
  25 + messageBus.register(this);
  26 + }
  27 +
  28 + @Override
  29 + public String getTopic() {
  30 + return IotDeviceMessage.buildMessageBusGatewayDeviceMessageTopic(protocol.getServerId());
  31 + }
  32 +
  33 + @Override
  34 + public String getGroup() {
  35 + // 保证点对点消费,需要保证独立的 Group,所以使用 Topic 作为 Group
  36 + return getTopic();
  37 + }
  38 +
  39 + @Override
  40 + public void onMessage(IotDeviceMessage message) {
  41 + log.error("[onMessage][IoT 网关 HTTP 协议不支持下行消息,忽略消息:{}]", message);
  42 + }
  43 +
  44 +}
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpUpstreamProtocol.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.gateway.protocol.http;
  2 +
  3 +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
  4 +import cn.iocoder.yudao.module.iot.core.util.IotCoreUtils;
  5 +import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties;
  6 +import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpUpstreamHandler;
  7 +import io.vertx.core.AbstractVerticle;
  8 +import io.vertx.core.Vertx;
  9 +import io.vertx.core.http.HttpServer;
  10 +import io.vertx.ext.web.Router;
  11 +import io.vertx.ext.web.handler.BodyHandler;
  12 +import jakarta.annotation.PostConstruct;
  13 +import jakarta.annotation.PreDestroy;
  14 +import lombok.RequiredArgsConstructor;
  15 +import lombok.extern.slf4j.Slf4j;
  16 +
  17 +/**
  18 + * IoT 网关 HTTP 协议:接收设备上行消息
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +@RequiredArgsConstructor
  23 +@Slf4j
  24 +public class IotHttpUpstreamProtocol extends AbstractVerticle {
  25 +
  26 + private final IotGatewayProperties.HttpProperties httpProperties;
  27 +
  28 + private final IotDeviceMessageProducer deviceMessageProducer;
  29 +
  30 + private HttpServer httpServer;
  31 +
  32 + @Override
  33 + @PostConstruct
  34 + public void start() {
  35 + // 创建路由
  36 + Vertx vertx = Vertx.vertx();
  37 + Router router = Router.router(vertx);
  38 + router.route().handler(BodyHandler.create());
  39 +
  40 + // 创建处理器,添加路由处理器
  41 + IotHttpUpstreamHandler upstreamHandler = new IotHttpUpstreamHandler(
  42 + this, deviceMessageProducer);
  43 + router.post(IotHttpUpstreamHandler.PROPERTY_PATH).handler(upstreamHandler);
  44 + router.post(IotHttpUpstreamHandler.EVENT_PATH).handler(upstreamHandler);
  45 +
  46 + // 启动 HTTP 服务器
  47 + try {
  48 + httpServer = vertx.createHttpServer()
  49 + .requestHandler(router)
  50 + .listen(httpProperties.getServerPort())
  51 + .result();
  52 + log.info("[start][IoT 网关 HTTP 协议启动成功,端口:{}]", httpProperties.getServerPort());
  53 + } catch (Exception e) {
  54 + log.error("[start][IoT 网关 HTTP 协议启动失败]", e);
  55 + throw e;
  56 + }
  57 + }
  58 +
  59 + @Override
  60 + @PreDestroy
  61 + public void stop() {
  62 + if (httpServer != null) {
  63 + try {
  64 + httpServer.close().result();
  65 + log.info("[stop][IoT 网关 HTTP 协议已停止]");
  66 + } catch (Exception e) {
  67 + log.error("[stop][IoT 网关 HTTP 协议停止失败]", e);
  68 + }
  69 + }
  70 + }
  71 +
  72 + public String getServerId() {
  73 + return IotCoreUtils.generateServerId(httpProperties.getServerPort());
  74 + }
  75 +
  76 +}
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/package-info.java deleted
1 -package cn.iocoder.yudao.module.iot.gateway.protocol.http;  
2 \ No newline at end of file 0 \ No newline at end of file
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 renamed to yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/router/IotHttpUpstreamHandler.java
1 -package cn.iocoder.yudao.module.iot.net.component.http.upstream.router; 1 +package cn.iocoder.yudao.module.iot.gateway.protocol.http.router;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.map.MapUtil; 4 import cn.hutool.core.map.MapUtil;
@@ -6,13 +6,10 @@ import cn.hutool.core.util.IdUtil; @@ -6,13 +6,10 @@ import cn.hutool.core.util.IdUtil;
6 import cn.hutool.core.util.ObjUtil; 6 import cn.hutool.core.util.ObjUtil;
7 import cn.hutool.core.util.StrUtil; 7 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;  
10 -import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO;  
11 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 9 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
12 import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; 10 import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
13 -import cn.iocoder.yudao.module.iot.net.component.core.constants.IotDeviceTopicEnum;  
14 -import cn.iocoder.yudao.module.iot.net.component.core.pojo.IotStandardResponse;  
15 -import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils; 11 +import cn.iocoder.yudao.module.iot.gateway.enums.IotDeviceTopicEnum;
  12 +import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpUpstreamProtocol;
16 import io.vertx.core.Handler; 13 import io.vertx.core.Handler;
17 import io.vertx.core.json.JsonObject; 14 import io.vertx.core.json.JsonObject;
18 import io.vertx.ext.web.RoutingContext; 15 import io.vertx.ext.web.RoutingContext;
@@ -26,15 +23,13 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -26,15 +23,13 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
26 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; 23 import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
27 24
28 /** 25 /**
29 - * IoT 设备上行统一处理的 Vert.x Handler  
30 - * <p>  
31 - * 统一处理设备属性上报和事件上报的请求。 26 + * IoT 网关 HTTP 协议的处理器
32 * 27 *
33 * @author 芋道源码 28 * @author 芋道源码
34 */ 29 */
35 @RequiredArgsConstructor 30 @RequiredArgsConstructor
36 @Slf4j 31 @Slf4j
37 -public class IotDeviceUpstreamVertxHandler implements Handler<RoutingContext> { 32 +public class IotHttpUpstreamHandler implements Handler<RoutingContext> {
38 33
39 // TODO @haohao:你说,咱要不要把 "/sys/:productKey/:deviceName" 34 // TODO @haohao:你说,咱要不要把 "/sys/:productKey/:deviceName"
40 // + IotDeviceTopicEnum.PROPERTY_POST_TOPIC.getTopic(),也抽到 IotDeviceTopicEnum 的 build 这种?尽量都收敛掉? 35 // + IotDeviceTopicEnum.PROPERTY_POST_TOPIC.getTopic(),也抽到 IotDeviceTopicEnum 的 build 这种?尽量都收敛掉?
@@ -52,11 +47,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -52,11 +47,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
52 + IotDeviceTopicEnum.EVENT_POST_TOPIC_SUFFIX.getTopic(); 47 + IotDeviceTopicEnum.EVENT_POST_TOPIC_SUFFIX.getTopic();
53 48
54 /** 49 /**
55 - * 属性上报方法标识  
56 - */  
57 - private static final String PROPERTY_METHOD = "thing.event.property.post";  
58 -  
59 - /**  
60 * 事件上报方法前缀 50 * 事件上报方法前缀
61 */ 51 */
62 private static final String EVENT_METHOD_PREFIX = "thing.event."; 52 private static final String EVENT_METHOD_PREFIX = "thing.event.";
@@ -66,10 +56,11 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -66,10 +56,11 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
66 */ 56 */
67 private static final String EVENT_METHOD_SUFFIX = ".post"; 57 private static final String EVENT_METHOD_SUFFIX = ".post";
68 58
69 - /**  
70 - * 设备上行 API  
71 - */  
72 - private final IotDeviceUpstreamApi deviceUpstreamApi; 59 + private final IotHttpUpstreamProtocol protocol;
  60 +// /**
  61 +// * 设备上行 API
  62 +// */
  63 +// private final IotDeviceUpstreamApi deviceUpstreamApi;
73 /** 64 /**
74 * 设备消息生产者 65 * 设备消息生产者
75 */ 66 */
@@ -167,13 +158,14 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -167,13 +158,14 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
167 String deviceKey = "xxx"; // TODO @芋艿:待支持 158 String deviceKey = "xxx"; // TODO @芋艿:待支持
168 Long tenantId = 1L; // TODO @芋艿:待支持 159 Long tenantId = 1L; // TODO @芋艿:待支持
169 IotDeviceMessage message = IotDeviceMessage.of(productKey, deviceName, deviceKey, 160 IotDeviceMessage message = IotDeviceMessage.of(productKey, deviceName, deviceKey,
170 - requestId, LocalDateTime.now(), IotNetComponentCommonUtils.getProcessId(), tenantId) 161 + requestId, LocalDateTime.now(),
  162 + protocol.getServerId(), tenantId)
171 .ofPropertyReport(parsePropertiesFromBody(body)); 163 .ofPropertyReport(parsePropertiesFromBody(body));
172 // 1.2 发送消息 164 // 1.2 发送消息
173 deviceMessageProducer.sendDeviceMessage(message); 165 deviceMessageProducer.sendDeviceMessage(message);
174 166
175 // 2. 返回响应 167 // 2. 返回响应
176 - sendResponse(routingContext, requestId, PROPERTY_METHOD, null); 168 + sendResponse(routingContext, requestId, null, null);
177 } 169 }
178 170
179 /** 171 /**
@@ -188,16 +180,16 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -188,16 +180,16 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
188 */ 180 */
189 private void handleEventPost(RoutingContext routingContext, String productKey, String deviceName, 181 private void handleEventPost(RoutingContext routingContext, String productKey, String deviceName,
190 String identifier, String requestId, JsonObject body) { 182 String identifier, String requestId, JsonObject body) {
191 - // 处理事件上报  
192 - IotDeviceEventReportReqDTO reportReqDTO = parseEventReportRequest(productKey, deviceName, identifier,  
193 - requestId, body);  
194 -  
195 - // 事件上报  
196 - CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO);  
197 - String method = EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX;  
198 -  
199 - // 返回响应  
200 - sendResponse(routingContext, requestId, method, result); 183 +// // 处理事件上报
  184 +// IotDeviceEventReportReqDTO reportReqDTO = parseEventReportRequest(productKey, deviceName, identifier,
  185 +// requestId, body);
  186 +//
  187 +// // 事件上报
  188 +// CommonResult<Boolean> result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO);
  189 +// String method = EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX;
  190 +//
  191 +// // 返回响应
  192 +// sendResponse(routingContext, requestId, method, result);
201 } 193 }
202 194
203 /** 195 /**
@@ -210,16 +202,16 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -210,16 +202,16 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
210 */ 202 */
211 private void sendResponse(RoutingContext routingContext, String requestId, String method, 203 private void sendResponse(RoutingContext routingContext, String requestId, String method,
212 CommonResult<Boolean> result) { 204 CommonResult<Boolean> result) {
213 - // TODO @芋艿:后续再优化  
214 - IotStandardResponse response;  
215 - if (result == null ) {  
216 - response = IotStandardResponse.success(requestId, method, null);  
217 - } else if (result.isSuccess()) {  
218 - response = IotStandardResponse.success(requestId, method, result.getData());  
219 - } else {  
220 - response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg());  
221 - }  
222 - IotNetComponentCommonUtils.writeJsonResponse(routingContext, response); 205 +// // TODO @芋艿:后续再优化
  206 +// IotStandardResponse response;
  207 +// if (result == null ) {
  208 +// response = IotStandardResponse.success(requestId, method, null);
  209 +// } else if (result.isSuccess()) {
  210 +// response = IotStandardResponse.success(requestId, method, result.getData());
  211 +// } else {
  212 +// response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg());
  213 +// }
  214 +// IotNetComponentCommonUtils.writeJsonResponse(routingContext, response);
223 } 215 }
224 216
225 /** 217 /**
@@ -233,8 +225,8 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -233,8 +225,8 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
233 */ 225 */
234 private void sendErrorResponse(RoutingContext routingContext, String requestId, String method, Integer code, 226 private void sendErrorResponse(RoutingContext routingContext, String requestId, String method, Integer code,
235 String message) { 227 String message) {
236 - IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method, code, message);  
237 - IotNetComponentCommonUtils.writeJsonResponse(routingContext, errorResponse); 228 +// IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method, code, message);
  229 +// IotNetComponentCommonUtils.writeJsonResponse(routingContext, errorResponse);
238 } 230 }
239 231
240 /** 232 /**
@@ -246,7 +238,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -246,7 +238,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
246 */ 238 */
247 private String determineMethodFromPath(String path, RoutingContext routingContext) { 239 private String determineMethodFromPath(String path, RoutingContext routingContext) {
248 if (StrUtil.contains(path, "/property/")) { 240 if (StrUtil.contains(path, "/property/")) {
249 - return PROPERTY_METHOD; 241 + return null;
250 } 242 }
251 243
252 return EVENT_METHOD_PREFIX 244 return EVENT_METHOD_PREFIX
@@ -285,29 +277,29 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; { @@ -285,29 +277,29 @@ public class IotDeviceUpstreamVertxHandler implements Handler&lt;RoutingContext&gt; {
285 return properties; 277 return properties;
286 } 278 }
287 279
288 - /**  
289 - * 解析事件上报请求  
290 - *  
291 - * @param productKey 产品 Key  
292 - * @param deviceName 设备名称  
293 - * @param identifier 事件标识符  
294 - * @param requestId 请求 ID  
295 - * @param body 请求体  
296 - * @return 事件上报请求 DTO  
297 - */  
298 - private IotDeviceEventReportReqDTO parseEventReportRequest(String productKey, String deviceName, String identifier,  
299 - String requestId, JsonObject body) {  
300 - // 解析参数  
301 - Map<String, Object> params = parseParamsFromBody(body);  
302 -  
303 - // 构建事件上报请求 DTO  
304 - return ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO()  
305 - .setRequestId(requestId)  
306 - .setProcessId(IotNetComponentCommonUtils.getProcessId())  
307 - .setReportTime(LocalDateTime.now())  
308 - .setProductKey(productKey)  
309 - .setDeviceName(deviceName)).setIdentifier(identifier).setParams(params);  
310 - } 280 +// /**
  281 +// * 解析事件上报请求
  282 +// *
  283 +// * @param productKey 产品 Key
  284 +// * @param deviceName 设备名称
  285 +// * @param identifier 事件标识符
  286 +// * @param requestId 请求 ID
  287 +// * @param body 请求体
  288 +// * @return 事件上报请求 DTO
  289 +// */
  290 +// private IotDeviceEventReportReqDTO parseEventReportRequest(String productKey, String deviceName, String identifier,
  291 +// String requestId, JsonObject body) {
  292 +// // 解析参数
  293 +// Map<String, Object> params = parseParamsFromBody(body);
  294 +//
  295 +// // 构建事件上报请求 DTO
  296 +// return ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO()
  297 +// .setRequestId(requestId)
  298 +// .setProcessId(IotNetComponentCommonUtils.getProcessId())
  299 +// .setReportTime(LocalDateTime.now())
  300 +// .setProductKey(productKey)
  301 +// .setDeviceName(deviceName)).setIdentifier(identifier).setParams(params);
  302 +// }
311 303
312 /** 304 /**
313 * 从请求体解析参数 305 * 从请求体解析参数
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/package-info.java
1 /** 1 /**
2 - * TODO 占位 2 + * 提供设备接入的各种协议的实现
3 */ 3 */
4 package cn.iocoder.yudao.module.iot.gateway.protocol; 4 package cn.iocoder.yudao.module.iot.gateway.protocol;
5 \ No newline at end of file 5 \ No newline at end of file
yudao-module-iot/yudao-module-iot-gateway/src/main/resources/application.yaml 0 → 100644
  1 +spring:
  2 + application:
  3 + name: iot-gateway-server
  4 +
  5 +--- #################### 消息队列相关 ####################
  6 +
  7 +# rocketmq 配置项,对应 RocketMQProperties 配置类
  8 +rocketmq:
  9 + name-server: 127.0.0.1:9876 # RocketMQ Namesrv
  10 + # Producer 配置项
  11 + producer:
  12 + group: ${spring.application.name}_PRODUCER # 生产者分组
  13 +
  14 +--- #################### 芋道相关配置 ####################
  15 +
  16 +yudao:
  17 + iot:
  18 + # 网关配置
  19 + gateway:
  20 + # 设备 RPC 配置
  21 + rpc:
  22 + url: http://127.0.0.1:48080 # 主程序 API 地址
  23 + connect-timeout: 30s
  24 + read-timeout: 30s
  25 +
  26 + # 协议配置
  27 + protocol:
  28 + # ====================================
  29 + # 针对引入的 HTTP 组件的配置
  30 + # ====================================
  31 + http:
  32 + enabled: true
  33 + server-port: 8092
  34 + # ====================================
  35 + # 针对引入的 EMQX 组件的配置
  36 + # ====================================
  37 + emqx:
  38 + enabled: true
  39 + mqtt-host: 127.0.0.1
  40 + mqtt-port: 1883
  41 + mqtt-username: admin
  42 + mqtt-password: admin123
  43 + mqtt-ssl: false
  44 + mqtt-topics:
  45 + - "/sys/#"
  46 + auth-port: 8101
  47 +
  48 + # 消息总线配置
  49 + message-bus:
  50 + type: rocketmq # 消息总线的类型
  51 +
  52 +# 日志配置
  53 +# TODO 芋艿:是不是可以删除
  54 +logging:
  55 + level:
  56 + cn.iocoder.yudao: INFO
  57 + root: INFO
yudao-module-iot/yudao-module-iot-net-components/README.md deleted
1 -# IOT 组件使用说明  
2 -  
3 -## 组件介绍  
4 -  
5 -该模块包含多个 IoT 设备连接组件,提供不同的通信协议支持:  
6 -  
7 -- `yudao-module-iot-net-component-core`: 核心接口和通用类  
8 -- `yudao-module-iot-net-component-http`: 基于 HTTP 协议的设备通信组件  
9 -- `yudao-module-iot-net-component-emqx`: 基于 MQTT/EMQX 的设备通信组件  
10 -  
11 -## 组件架构  
12 -  
13 -### 架构设计  
14 -  
15 -各组件采用统一的架构设计和命名规范:  
16 -  
17 -- 配置类: `IotComponentXxxAutoConfiguration` - 提供Bean定义和组件初始化逻辑  
18 -- 属性类: `IotComponentXxxProperties` - 定义组件的配置属性  
19 -- 下行接口: `*DownstreamHandler` - 处理从平台到设备的下行通信  
20 -- 上行接口: `*UpstreamServer` - 处理从设备到平台的上行通信  
21 -  
22 -### Bean 命名规范  
23 -  
24 -为避免 Bean 冲突,各个组件中的 Bean 已添加特定前缀:  
25 -  
26 -- HTTP 组件: `httpDeviceUpstreamServer`, `httpDeviceDownstreamHandler`  
27 -- EMQX 组件: `emqxDeviceUpstreamServer`, `emqxDeviceDownstreamHandler`  
28 -  
29 -### 组件启用规则  
30 -  
31 -现在系统支持同时使用多个组件,但有以下规则:  
32 -  
33 -1. 当`yudao.iot.component.emqx.enabled=true`时,核心模块将优先使用EMQX组件  
34 -2. 如果同时启用了多个组件,需要在业务代码中使用`@Qualifier`指定要使用的具体实现  
35 -  
36 -> **重要提示:**  
37 -> 1. 组件库内部的默认配置文件**不会**被自动加载。必须将上述配置添加到主应用的配置文件中。  
38 -> 2. 所有配置项现在都已增加空值处理,配置缺失时将使用合理的默认值  
39 -> 3. `mqtt-host` 是唯一必须配置的参数,其他参数均有默认值  
40 -> 4. `mqtt-ssl` 和 `auth-port` 缺失时的默认值分别为 `false` 和 `8080`  
41 -> 5. `mqtt-topics` 缺失时将使用默认主题 `/device/#`  
42 -  
43 -### 如何引用特定的 Bean  
44 -  
45 -在其他组件中引用这些 Bean 时,需要使用 `@Qualifier` 注解指定 Bean 名称:  
46 -  
47 -```java  
48 -import org.springframework.beans.factory.annotation.Autowired;  
49 -import org.springframework.beans.factory.annotation.Qualifier;  
50 -import cn.iocoder.yudao.module.iot.component.core.downstream.IotDeviceDownstreamHandler;  
51 -  
52 -@Service  
53 -public class YourServiceClass {  
54 -  
55 - // 注入 HTTP 组件的下行处理器  
56 - @Autowired  
57 - @Qualifier("httpDeviceDownstreamHandler")  
58 - private IotDeviceDownstreamHandler httpDeviceDownstreamHandler;  
59 -  
60 - // 注入 EMQX 组件的下行处理器  
61 - @Autowired  
62 - @Qualifier("emqxDeviceDownstreamHandler")  
63 - private IotDeviceDownstreamHandler emqxDeviceDownstreamHandler;  
64 -  
65 - // 使用示例  
66 - public void example() {  
67 - // 使用 HTTP 组件  
68 - httpDeviceDownstreamHandler.invokeDeviceService(...);  
69 -  
70 - // 使用 EMQX 组件  
71 - emqxDeviceDownstreamHandler.invokeDeviceService(...);  
72 - }  
73 -}  
74 -```  
75 -  
76 -### 组件选择指南  
77 -  
78 -- **HTTP 组件**:适用于简单场景,设备通过 HTTP 接口与平台通信  
79 -- **EMQX 组件**:适用于实时性要求高的场景,基于 MQTT 协议,支持发布/订阅模式  
80 -  
81 -## 常见问题  
82 -  
83 -### 1. 配置未加载问题  
84 -  
85 -如果遇到以下日志:  
86 -  
87 -```  
88 -MQTT配置: host=null, port=null, username=null, ssl=null  
89 -[connectMqtt][MQTT Host为null,无法连接]  
90 -```  
91 -  
92 -这表明配置没有被正确加载。请确保:  
93 -  
94 -1. 在主应用的配置文件中(如 `application.yml` 或 `application-dev.yml`)添加了必要的 EMQX 配置  
95 -2. 配置前缀正确:`yudao.iot.component.emqx`  
96 -3. 配置了必要的 `mqtt-host` 属性  
97 -  
98 -### 2. mqttSsl 空指针异常  
99 -  
100 -如果遇到以下错误:  
101 -  
102 -```  
103 -Cannot invoke "java.lang.Boolean.booleanValue()" because the return value of "cn.iocoder.yudao.module.iot.component.emqx.config.IotEmqxComponentProperties.getMqttSsl()" is null  
104 -```  
105 -  
106 -此问题已通过代码修复,现在会自动使用默认值 `false`。同样适用于其他配置项的空值问题。  
107 -  
108 -### 3. authPort 空指针异常  
109 -  
110 -如果遇到以下错误:  
111 -  
112 -```  
113 -Cannot invoke "java.lang.Integer.intValue()" because the return value of "cn.iocoder.yudao.module.iot.component.emqx.config.IotEmqxComponentProperties.getAuthPort()" is null  
114 -```  
115 -  
116 -此问题已通过代码修复,现在会自动使用默认值 `8080`。  
117 -  
118 -### 4. Bean注入问题  
119 -  
120 -如果遇到以下错误:  
121 -  
122 -```  
123 -Parameter 1 of method deviceDownstreamServer in IotPluginCommonAutoConfiguration required a single bean, but 2 were found  
124 -```  
125 -  
126 -此问题已通过修改核心配置类来解决。现在系统会根据组件的启用状态自动选择合适的实现:  
127 -  
128 -1. 优先使用EMQX组件(当`yudao.iot.component.emqx.enabled=true`时)  
129 -2. 如果EMQX未启用,则使用HTTP组件(当`yudao.iot.component.http.enabled=true`时)  
130 -  
131 -如果需要同时使用两个组件,业务代码中必须使用`@Qualifier`明确指定要使用的Bean。  
132 -  
133 -### 5. 使用默认配置  
134 -  
135 -组件现已加入完善的默认配置和空值处理机制,使配置更加灵活。但需要注意的是,这些默认配置值必须通过在主应用配置文件中设置相应的属性才能生效。  
136 -  
137 -// TODO 芋艿:后续继续完善 README.md  
138 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/pom.xml
@@ -18,9 +18,8 @@ @@ -18,9 +18,8 @@
18 18
19 <modules> 19 <modules>
20 <module>yudao-module-iot-net-component-core</module> 20 <module>yudao-module-iot-net-component-core</module>
21 - <module>yudao-module-iot-net-component-http</module>  
22 <module>yudao-module-iot-net-component-emqx</module> 21 <module>yudao-module-iot-net-component-emqx</module>
23 <module>yudao-module-iot-net-component-server</module> 22 <module>yudao-module-iot-net-component-server</module>
24 </modules> 23 </modules>
25 24
26 -</project>  
27 \ No newline at end of file 25 \ No newline at end of file
  26 +</project>
28 \ No newline at end of file 27 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/config/IotNetComponentCommonAutoConfiguration.java
@@ -11,9 +11,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @@ -11,9 +11,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
11 * 11 *
12 * @author haohao 12 * @author haohao
13 */ 13 */
14 -@AutoConfiguration  
15 @EnableConfigurationProperties(IotNetComponentCommonProperties.class) 14 @EnableConfigurationProperties(IotNetComponentCommonProperties.class)
16 -@EnableScheduling // 开启定时任务,因为 IotNetComponentInstanceHeartbeatJob 是一个定时任务  
17 public class IotNetComponentCommonAutoConfiguration { 15 public class IotNetComponentCommonAutoConfiguration {
18 16
19 /** 17 /**
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/config/IotNetComponentCommonProperties.java deleted
1 -package cn.iocoder.yudao.module.iot.net.component.core.config;  
2 -  
3 -import lombok.Data;  
4 -import org.springframework.boot.context.properties.ConfigurationProperties;  
5 -import org.springframework.validation.annotation.Validated;  
6 -  
7 -/**  
8 - * IoT 网络组件通用配置属性  
9 - *  
10 - * @author haohao  
11 - */  
12 -@ConfigurationProperties(prefix = "yudao.iot.component")  
13 -@Validated  
14 -@Data  
15 -public class IotNetComponentCommonProperties {  
16 -  
17 - /**  
18 - * 组件的唯一标识  
19 - * <p>  
20 - * 注意:该值将在运行时由各组件设置,不再从配置读取  
21 - */  
22 - private String pluginKey;  
23 -  
24 -}  
25 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/pojo/IotStandardResponse.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.iot.net.component.core.pojo; @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.iot.net.component.core.pojo;
2 2
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 import lombok.Data; 4 import lombok.Data;
5 -import lombok.experimental.Accessors;  
6 5
7 /** 6 /**
8 * IoT 标准协议响应实体类 7 * IoT 标准协议响应实体类
@@ -12,7 +11,6 @@ import lombok.experimental.Accessors; @@ -12,7 +11,6 @@ import lombok.experimental.Accessors;
12 * @author haohao 11 * @author haohao
13 */ 12 */
14 @Data 13 @Data
15 -@Accessors(chain = true) // TODO @haohao:貌似不用写 @Accessors(chain = true),我全局加啦,可见 lombok.config  
16 public class IotStandardResponse { 14 public class IotStandardResponse {
17 15
18 /** 16 /**
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-core/src/main/java/cn/iocoder/yudao/module/iot/net/component/core/util/IotNetComponentCommonUtils.java
1 package cn.iocoder.yudao.module.iot.net.component.core.util; 1 package cn.iocoder.yudao.module.iot.net.component.core.util;
2 2
3 -import cn.hutool.core.util.IdUtil;  
4 -import cn.hutool.core.util.StrUtil;  
5 -import cn.hutool.system.SystemUtil;  
6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
7 import cn.iocoder.yudao.module.iot.net.component.core.pojo.IotStandardResponse; 4 import cn.iocoder.yudao.module.iot.net.component.core.pojo.IotStandardResponse;
8 import io.vertx.core.http.HttpHeaders; 5 import io.vertx.core.http.HttpHeaders;
@@ -17,40 +14,6 @@ import org.springframework.http.MediaType; @@ -17,40 +14,6 @@ import org.springframework.http.MediaType;
17 public class IotNetComponentCommonUtils { 14 public class IotNetComponentCommonUtils {
18 15
19 /** 16 /**
20 - * 流程实例的进程编号  
21 - */  
22 - private static String processId;  
23 -  
24 - /**  
25 - * 获取进程ID  
26 - *  
27 - * @return 进程ID  
28 - */  
29 - public static String getProcessId() {  
30 - if (StrUtil.isEmpty(processId)) {  
31 - initProcessId();  
32 - }  
33 - return processId;  
34 - }  
35 -  
36 - /**  
37 - * 初始化进程ID  
38 - */  
39 - private synchronized static void initProcessId() {  
40 - processId = String.format("%s@%d@%s", // IP@PID@${uuid}  
41 - SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID(), IdUtil.fastSimpleUUID());  
42 - }  
43 -  
44 - /**  
45 - * 生成请求ID  
46 - *  
47 - * @return 生成的唯一请求ID  
48 - */  
49 - public static String generateRequestId() {  
50 - return IdUtil.fastSimpleUUID();  
51 - }  
52 -  
53 - /**  
54 * 将对象转换为JSON字符串后写入HTTP响应 17 * 将对象转换为JSON字符串后写入HTTP响应
55 * 18 *
56 * @param routingContext 路由上下文 19 * @param routingContext 路由上下文
@@ -89,4 +52,5 @@ public class IotNetComponentCommonUtils { @@ -89,4 +52,5 @@ public class IotNetComponentCommonUtils {
89 .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) 52 .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
90 .end(JsonUtils.toJsonString(response)); 53 .end(JsonUtils.toJsonString(response));
91 } 54 }
  55 +
92 } 56 }
93 \ No newline at end of file 57 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/pom.xml deleted
1 -<?xml version="1.0" encoding="UTF-8"?>  
2 -<project xmlns="http://maven.apache.org/POM/4.0.0"  
3 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
5 - <parent>  
6 - <artifactId>yudao-module-iot-net-components</artifactId>  
7 - <groupId>cn.iocoder.boot</groupId>  
8 - <version>${revision}</version>  
9 - </parent>  
10 - <modelVersion>4.0.0</modelVersion>  
11 - <artifactId>yudao-module-iot-net-component-http</artifactId>  
12 - <packaging>jar</packaging>  
13 -  
14 - <name>${project.artifactId}</name>  
15 - <description>  
16 - 物联网网络组件 HTTP 模块  
17 - </description>  
18 -  
19 - <dependencies>  
20 - <dependency>  
21 - <groupId>cn.iocoder.boot</groupId>  
22 - <artifactId>yudao-module-iot-net-component-core</artifactId>  
23 - <version>${revision}</version>  
24 - </dependency>  
25 -  
26 - <!-- 脚本解析相关 -->  
27 - <!-- <dependency>-->  
28 - <!-- <groupId>cn.iocoder.boot</groupId>-->  
29 - <!-- <artifactId>yudao-module-iot-plugin-script</artifactId>-->  
30 - <!-- <version>${revision}</version>-->  
31 - <!-- </dependency>-->  
32 -  
33 - <!-- 工具类相关 -->  
34 - <dependency>  
35 - <groupId>io.vertx</groupId>  
36 - <artifactId>vertx-web</artifactId>  
37 - </dependency>  
38 -  
39 - <!-- 参数校验 -->  
40 - <dependency>  
41 - <groupId>org.springframework.boot</groupId>  
42 - <artifactId>spring-boot-starter-validation</artifactId>  
43 - <optional>true</optional>  
44 - </dependency>  
45 - </dependencies>  
46 -  
47 -</project>  
48 \ No newline at end of file 0 \ No newline at end of file
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 deleted
1 -package cn.iocoder.yudao.module.iot.net.component.http.config;  
2 -  
3 -import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;  
4 -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;  
5 -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber;  
6 -import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;  
7 -import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;  
8 -import cn.iocoder.yudao.module.iot.net.component.http.upstream.IotDeviceUpstreamServer;  
9 -import io.vertx.core.Vertx;  
10 -import lombok.extern.slf4j.Slf4j;  
11 -import org.springframework.beans.factory.annotation.Qualifier;  
12 -import org.springframework.boot.autoconfigure.AutoConfiguration;  
13 -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;  
14 -import org.springframework.boot.context.event.ApplicationStartedEvent;  
15 -import org.springframework.boot.context.properties.EnableConfigurationProperties;  
16 -import org.springframework.context.annotation.Bean;  
17 -import org.springframework.context.annotation.ComponentScan;  
18 -import org.springframework.context.annotation.Lazy;  
19 -import org.springframework.context.event.EventListener;  
20 -  
21 -/**  
22 - * IoT 网络组件 HTTP 的自动配置类  
23 - *  
24 - * @author haohao  
25 - */  
26 -@Slf4j  
27 -@AutoConfiguration  
28 -@EnableConfigurationProperties(IotNetComponentHttpProperties.class)  
29 -@ConditionalOnProperty(prefix = "yudao.iot.component.http", name = "enabled", havingValue = "true", matchIfMissing = false)  
30 -@ComponentScan(basePackages = {  
31 - "cn.iocoder.yudao.module.iot.net.component.http" // 只扫描 HTTP 组件包  
32 -})  
33 -public class IotNetComponentHttpAutoConfiguration {  
34 -  
35 - /**  
36 - * 初始化 HTTP 组件  
37 - *  
38 - * @param event 应用启动事件  
39 - */  
40 - @EventListener(ApplicationStartedEvent.class)  
41 - public void initialize(ApplicationStartedEvent event) {  
42 - log.info("[IotNetComponentHttpAutoConfiguration][开始初始化]");  
43 -  
44 - // TODO @芋艿:临时处理  
45 - IotMessageBus messageBus = event.getApplicationContext()  
46 - .getBean(IotMessageBus.class);  
47 - messageBus.register(new IotMessageBusSubscriber<IotDeviceMessage>() {  
48 -  
49 - @Override  
50 - public String getTopic() {  
51 - return IotDeviceMessage.buildMessageBusGatewayDeviceMessageTopic("yy");  
52 - }  
53 -  
54 - @Override  
55 - public String getGroup() {  
56 - return "test";  
57 - }  
58 -  
59 - @Override  
60 - public void onMessage(IotDeviceMessage message) {  
61 - System.out.println(message);  
62 - }  
63 -  
64 - });  
65 - }  
66 -  
67 - // TODO @芋艿:貌似这里不用注册 bean?  
68 - /**  
69 - * 创建 Vert.x 实例  
70 - *  
71 - * @return Vert.x 实例  
72 - */  
73 - @Bean(name = "httpVertx")  
74 - public Vertx vertx() {  
75 - return Vertx.vertx();  
76 - }  
77 -  
78 - /**  
79 - * 创建设备上行服务器  
80 - */  
81 - @Bean(name = "httpDeviceUpstreamServer", initMethod = "start", destroyMethod = "stop")  
82 - public IotDeviceUpstreamServer deviceUpstreamServer(  
83 - @Lazy @Qualifier("httpVertx") Vertx vertx,  
84 - IotDeviceUpstreamApi deviceUpstreamApi,  
85 - IotNetComponentHttpProperties properties,  
86 - IotDeviceMessageProducer deviceMessageProducer) {  
87 - return new IotDeviceUpstreamServer(vertx, properties, deviceUpstreamApi, deviceMessageProducer);  
88 - }  
89 -  
90 -}  
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/IotNetComponentHttpProperties.java deleted
1 -package cn.iocoder.yudao.module.iot.net.component.http.config;  
2 -  
3 -import lombok.Data;  
4 -import org.springframework.boot.context.properties.ConfigurationProperties;  
5 -import org.springframework.validation.annotation.Validated;  
6 -  
7 -/**  
8 - * IoT HTTP 网络组件配置属性  
9 - *  
10 - * @author haohao  
11 - */  
12 -@ConfigurationProperties(prefix = "yudao.iot.component.http")  
13 -@Validated  
14 -@Data  
15 -public class IotNetComponentHttpProperties {  
16 -  
17 - /**  
18 - * 是否启用 HTTP 组件  
19 - */  
20 - private Boolean enabled;  
21 -  
22 - /**  
23 - * HTTP 服务端口  
24 - */  
25 - private Integer serverPort;  
26 -  
27 - /**  
28 - * 连接超时时间(毫秒)  
29 - * <p>  
30 - * 默认值:10000 毫秒  
31 - */  
32 - private Integer connectionTimeoutMs = 10000;  
33 -}  
34 \ No newline at end of file 0 \ No newline at end of file
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/downstream/IotDeviceDownstreamHandlerImpl.java deleted
1 -package cn.iocoder.yudao.module.iot.net.component.http.downstream;  
2 -  
3 -// TODO @芋艿:实现下;  
4 -///**  
5 -// * HTTP 网络组件的 {@link IotDeviceDownstreamHandler} 实现类  
6 -// * <p>  
7 -// * 但是:由于设备通过 HTTP 短链接接入,导致其实无法下行指导给 device 设备,所以基本都是直接返回失败!!!  
8 -// * 类似 MQTT、WebSocket、TCP 网络组件,是可以实现下行指令的。  
9 -// *  
10 -// * @author 芋道源码  
11 -// */  
12 -//@Slf4j  
13 -//public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandler {  
14 -//  
15 -// /**  
16 -// * 不支持的错误消息  
17 -// */  
18 -// private static final String NOT_SUPPORTED_MSG = "HTTP 不支持设备下行通信";  
19 -//  
20 -// @Override  
21 -// public CommonResult<Boolean> invokeDeviceService(IotDeviceServiceInvokeReqDTO invokeReqDTO) {  
22 -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG);  
23 -// }  
24 -//  
25 -// @Override  
26 -// public CommonResult<Boolean> getDeviceProperty(IotDevicePropertyGetReqDTO getReqDTO) {  
27 -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG);  
28 -// }  
29 -//  
30 -// @Override  
31 -// public CommonResult<Boolean> setDeviceProperty(IotDevicePropertySetReqDTO setReqDTO) {  
32 -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG);  
33 -// }  
34 -//  
35 -// @Override  
36 -// public CommonResult<Boolean> setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO) {  
37 -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG);  
38 -// }  
39 -//  
40 -// @Override  
41 -// public CommonResult<Boolean> upgradeDeviceOta(IotDeviceOtaUpgradeReqDTO upgradeReqDTO) {  
42 -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG);  
43 -// }  
44 -//}  
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 deleted
1 -package cn.iocoder.yudao.module.iot.net.component.http.upstream;  
2 -  
3 -import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;  
4 -import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;  
5 -import cn.iocoder.yudao.module.iot.net.component.http.config.IotNetComponentHttpProperties;  
6 -import cn.iocoder.yudao.module.iot.net.component.http.upstream.router.IotDeviceUpstreamVertxHandler;  
7 -import io.vertx.core.AbstractVerticle;  
8 -import io.vertx.core.Promise;  
9 -import io.vertx.core.Vertx;  
10 -import io.vertx.ext.web.Router;  
11 -import io.vertx.ext.web.handler.BodyHandler;  
12 -import lombok.RequiredArgsConstructor;  
13 -import lombok.extern.slf4j.Slf4j;  
14 -  
15 -/**  
16 - * IoT 设备上行服务器  
17 - * <p>  
18 - * 处理设备通过 HTTP 方式接入的上行消息  
19 - *  
20 - * @author 芋道源码  
21 - */  
22 -@RequiredArgsConstructor  
23 -@Slf4j  
24 -public class IotDeviceUpstreamServer extends AbstractVerticle {  
25 -  
26 - private final Vertx vertx;  
27 -  
28 - private final IotNetComponentHttpProperties httpProperties;  
29 -  
30 - private final IotDeviceUpstreamApi deviceUpstreamApi;  
31 -  
32 - private final IotDeviceMessageProducer deviceMessageProducer;  
33 -  
34 - @Override  
35 - public void start() {  
36 - start(Promise.promise());  
37 - }  
38 -  
39 - // TODO @haohao:这样貌似初始化不到;我临时拷贝上去了  
40 - @Override  
41 - public void start(Promise<Void> startPromise) {  
42 - // 创建路由  
43 - Router router = Router.router(vertx);  
44 - router.route().handler(BodyHandler.create());  
45 -  
46 - // 创建处理器  
47 - IotDeviceUpstreamVertxHandler upstreamHandler = new IotDeviceUpstreamVertxHandler(  
48 - deviceUpstreamApi, deviceMessageProducer);  
49 -  
50 - // 添加路由处理器  
51 - router.post(IotDeviceUpstreamVertxHandler.PROPERTY_PATH).handler(upstreamHandler::handle);  
52 - router.post(IotDeviceUpstreamVertxHandler.EVENT_PATH).handler(upstreamHandler::handle);  
53 -  
54 - // 启动 HTTP 服务器  
55 - vertx.createHttpServer()  
56 - .requestHandler(router)  
57 - .listen(httpProperties.getServerPort(), result -> {  
58 - if (result.succeeded()) {  
59 - log.info("[start][IoT 设备上行服务器启动成功,端口:{}]", httpProperties.getServerPort());  
60 - startPromise.complete();  
61 - } else {  
62 - log.error("[start][IoT 设备上行服务器启动失败]", result.cause());  
63 - startPromise.fail(result.cause());  
64 - }  
65 - });  
66 - }  
67 -  
68 - @Override  
69 - public void stop(Promise<Void> stopPromise) {  
70 - log.info("[stop][IoT 设备上行服务器已停止]");  
71 - stopPromise.complete();  
72 - }  
73 -}  
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/auth/IotDeviceAuthProvider.java deleted
1 -package cn.iocoder.yudao.module.iot.net.component.http.upstream.auth;  
2 -  
3 -import io.vertx.core.Future;  
4 -import io.vertx.ext.web.RoutingContext;  
5 -import lombok.extern.slf4j.Slf4j;  
6 -import org.springframework.context.ApplicationContext;  
7 -  
8 -// TODO @haohao:待实现,或者不需要?  
9 -/**  
10 - * IoT 设备认证提供者  
11 - * <p>  
12 - * 用于 HTTP 设备接入时的身份认证  
13 - *  
14 - * @author haohao  
15 - */  
16 -@Slf4j  
17 -public class IotDeviceAuthProvider {  
18 -  
19 - private final ApplicationContext applicationContext;  
20 -  
21 - /**  
22 - * 构造函数  
23 - *  
24 - * @param applicationContext Spring 应用上下文  
25 - */  
26 - public IotDeviceAuthProvider(ApplicationContext applicationContext) {  
27 - this.applicationContext = applicationContext;  
28 - }  
29 -  
30 - /**  
31 - * 认证设备  
32 - *  
33 - * @param context 路由上下文  
34 - * @param clientId 设备唯一标识  
35 - * @return 认证结果 Future 对象  
36 - */  
37 - public Future<Void> authenticate(RoutingContext context, String clientId) {  
38 - if (clientId == null || clientId.isEmpty()) {  
39 - return Future.failedFuture("clientId 不能为空");  
40 - }  
41 -  
42 - try {  
43 - log.info("[authenticate][设备认证成功,clientId={}]", clientId);  
44 - return Future.succeededFuture();  
45 - } catch (Exception e) {  
46 - log.error("[authenticate][设备认证异常,clientId={}]", clientId, e);  
47 - return Future.failedFuture(e);  
48 - }  
49 - }  
50 -}  
51 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted
1 -cn.iocoder.yudao.module.iot.net.component.http.config.IotNetComponentHttpAutoConfiguration  
2 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/resources/application.yml deleted
1 -# HTTP组件默认配置  
2 -yudao:  
3 - iot:  
4 - component:  
5 - core:  
6 - plugin-key: http # 插件的唯一标识  
7 -# http:  
8 -# enabled: true # 是否启用HTTP组件,默认启用  
9 -# server-port: 8092  
10 -  
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/pom.xml
@@ -17,32 +17,12 @@ @@ -17,32 +17,12 @@
17 </description> 17 </description>
18 18
19 <dependencies> 19 <dependencies>
20 - <!-- Spring Boot 核心 -->  
21 - <dependency>  
22 - <groupId>org.springframework.boot</groupId>  
23 - <artifactId>spring-boot-starter</artifactId>  
24 - </dependency>  
25 -  
26 <!-- Web 相关 --> 20 <!-- Web 相关 -->
27 <dependency> 21 <dependency>
28 <groupId>org.springframework.boot</groupId> 22 <groupId>org.springframework.boot</groupId>
29 <artifactId>spring-boot-starter-web</artifactId> 23 <artifactId>spring-boot-starter-web</artifactId>
30 </dependency> 24 </dependency>
31 25
32 - <!-- Net Component 核心 -->  
33 - <dependency>  
34 - <groupId>cn.iocoder.boot</groupId>  
35 - <artifactId>yudao-module-iot-net-component-core</artifactId>  
36 - <version>${revision}</version>  
37 - </dependency>  
38 -  
39 - <!-- Net Component HTTP -->  
40 - <dependency>  
41 - <groupId>cn.iocoder.boot</groupId>  
42 - <artifactId>yudao-module-iot-net-component-http</artifactId>  
43 - <version>${revision}</version>  
44 - </dependency>  
45 -  
46 <!-- Net Component EMQX --> 26 <!-- Net Component EMQX -->
47 <dependency> 27 <dependency>
48 <groupId>cn.iocoder.boot</groupId> 28 <groupId>cn.iocoder.boot</groupId>
@@ -50,32 +30,8 @@ @@ -50,32 +30,8 @@
50 <version>${revision}</version> 30 <version>${revision}</version>
51 </dependency> 31 </dependency>
52 32
53 - <!-- TODO @芋艿:消息队列,后续可能去掉,默认不使用 rocketmq -->  
54 - <dependency>  
55 - <groupId>org.apache.rocketmq</groupId>  
56 - <artifactId>rocketmq-spring-boot-starter</artifactId>  
57 - </dependency>  
58 33
59 - </dependencies>  
60 34
61 - <build>  
62 - <!-- 设置构建的 jar 包名 -->  
63 - <finalName>${project.artifactId}</finalName>  
64 - <plugins>  
65 - <!-- 打包 -->  
66 - <plugin>  
67 - <groupId>org.springframework.boot</groupId>  
68 - <artifactId>spring-boot-maven-plugin</artifactId>  
69 - <version>${spring.boot.version}</version> <!-- 需要确认父 POM 中有定义 -->  
70 - <executions>  
71 - <execution>  
72 - <goals>  
73 - <goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->  
74 - </goals>  
75 - </execution>  
76 - </executions>  
77 - </plugin>  
78 - </plugins>  
79 - </build> 35 + </dependencies>
80 36
81 </project> 37 </project>
82 \ No newline at end of file 38 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/NetComponentServerApplication.java deleted
1 -package cn.iocoder.yudao.module.iot.net.component.server;  
2 -  
3 -import org.springframework.boot.SpringApplication;  
4 -import org.springframework.boot.autoconfigure.SpringBootApplication;  
5 -  
6 -/**  
7 - * IoT 网络组件聚合启动服务  
8 - *  
9 - * @author haohao  
10 - */  
11 -@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}.module.iot.net.component"})  
12 -public class NetComponentServerApplication {  
13 -  
14 - public static void main(String[] args) {  
15 - SpringApplication.run(NetComponentServerApplication.class, args);  
16 - }  
17 -  
18 -}  
19 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/config/IotNetComponentServerConfiguration.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.iot.net.component.server.config; @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.iot.net.component.server.config;
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.net.component.server.upstream.IotComponentUpstreamClient; 4 import cn.iocoder.yudao.module.iot.net.component.server.upstream.IotComponentUpstreamClient;
5 -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;  
6 import org.springframework.boot.context.properties.EnableConfigurationProperties; 5 import org.springframework.boot.context.properties.EnableConfigurationProperties;
7 import org.springframework.boot.web.client.RestTemplateBuilder; 6 import org.springframework.boot.web.client.RestTemplateBuilder;
8 import org.springframework.context.annotation.Bean; 7 import org.springframework.context.annotation.Bean;
@@ -50,28 +49,4 @@ public class IotNetComponentServerConfiguration { @@ -50,28 +49,4 @@ public class IotNetComponentServerConfiguration {
50 return new IotComponentUpstreamClient(properties, restTemplate); 49 return new IotComponentUpstreamClient(properties, restTemplate);
51 } 50 }
52 51
53 - /**  
54 - * 配置默认的设备上行客户端,避免在独立运行模式下的循环依赖问题  
55 - *  
56 - * @return 设备上行客户端  
57 - */  
58 - @Bean  
59 - @ConditionalOnMissingBean(name = "serverDeviceUpstreamClient")  
60 - public Object serverDeviceUpstreamClient() {  
61 - // 返回一个空对象,避免找不到类的问题  
62 - return new Object();  
63 - }  
64 -  
65 - // TODO @haohao:这个是不是木有用呀?  
66 - /**  
67 - * 配置默认的组件实例注册客户端  
68 - *  
69 - * @return 插件实例注册客户端  
70 - */  
71 - @Bean  
72 - @ConditionalOnMissingBean(name = "serverPluginInstanceRegistryClient")  
73 - public Object serverPluginInstanceRegistryClient() {  
74 - // 返回一个空对象,避免找不到类的问题  
75 - return new Object();  
76 - }  
77 } 52 }
78 \ No newline at end of file 53 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/config/IotNetComponentServerProperties.java
@@ -18,8 +18,6 @@ public class IotNetComponentServerProperties { @@ -18,8 +18,6 @@ public class IotNetComponentServerProperties {
18 18
19 /** 19 /**
20 * 上行 URL,用于向主应用程序上报数据 20 * 上行 URL,用于向主应用程序上报数据
21 - * <p>  
22 - * 默认:http://127.0.0.1:48080  
23 */ 21 */
24 private String upstreamUrl = "http://127.0.0.1:48080"; 22 private String upstreamUrl = "http://127.0.0.1:48080";
25 23
@@ -33,18 +31,4 @@ public class IotNetComponentServerProperties { @@ -33,18 +31,4 @@ public class IotNetComponentServerProperties {
33 */ 31 */
34 private Duration upstreamReadTimeout = Duration.ofSeconds(30); 32 private Duration upstreamReadTimeout = Duration.ofSeconds(30);
35 33
36 - /**  
37 - * 下行服务端口,用于接收主应用程序的请求  
38 - * <p>  
39 - * 默认:18888  
40 - */  
41 - private Integer downstreamPort = 18888;  
42 -  
43 - /**  
44 - * 组件服务器唯一标识  
45 - * <p>  
46 - * 默认:yudao-module-iot-net-component-server  
47 - */  
48 - private String serverKey = "yudao-module-iot-net-component-server";  
49 -  
50 } 34 }
51 \ No newline at end of file 35 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/controller/HealthController.java deleted
1 -package cn.iocoder.yudao.module.iot.net.component.server.controller;  
2 -  
3 -import org.springframework.web.bind.annotation.GetMapping;  
4 -import org.springframework.web.bind.annotation.RequestMapping;  
5 -import org.springframework.web.bind.annotation.RestController;  
6 -  
7 -import java.util.HashMap;  
8 -import java.util.Map;  
9 -  
10 -// TODO @haohao:这个是必须的哇?可以考虑基于 spring boot actuator;  
11 -/**  
12 - * 健康检查接口  
13 - *  
14 - * @author haohao  
15 - */  
16 -@RestController  
17 -@RequestMapping("/health")  
18 -public class HealthController {  
19 -  
20 - /**  
21 - * 健康检查接口  
22 - *  
23 - * @return 返回服务状态信息  
24 - */  
25 - @GetMapping("/status")  
26 - public Map<String, Object> status() {  
27 - Map<String, Object> result = new HashMap<>();  
28 - result.put("status", "UP");  
29 - result.put("message", "IoT 网络组件服务运行正常");  
30 - result.put("timestamp", System.currentTimeMillis());  
31 - return result;  
32 - }  
33 -}  
34 \ No newline at end of file 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/java/cn/iocoder/yudao/module/iot/net/component/server/upstream/IotComponentUpstreamClient.java
1 package cn.iocoder.yudao.module.iot.net.component.server.upstream; 1 package cn.iocoder.yudao.module.iot.net.component.server.upstream;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 -import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;  
5 -import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.*;  
6 import cn.iocoder.yudao.module.iot.net.component.server.config.IotNetComponentServerProperties; 4 import cn.iocoder.yudao.module.iot.net.component.server.config.IotNetComponentServerProperties;
7 import lombok.RequiredArgsConstructor; 5 import lombok.RequiredArgsConstructor;
8 import lombok.extern.slf4j.Slf4j; 6 import lombok.extern.slf4j.Slf4j;
@@ -19,7 +17,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC @@ -19,7 +17,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
19 */ 17 */
20 @RequiredArgsConstructor 18 @RequiredArgsConstructor
21 @Slf4j 19 @Slf4j
22 -public class IotComponentUpstreamClient implements IotDeviceUpstreamApi { 20 +public class IotComponentUpstreamClient {
23 21
24 public static final String URL_PREFIX = "/rpc-api/iot/device/upstream"; 22 public static final String URL_PREFIX = "/rpc-api/iot/device/upstream";
25 23
@@ -27,47 +25,11 @@ public class IotComponentUpstreamClient implements IotDeviceUpstreamApi { @@ -27,47 +25,11 @@ public class IotComponentUpstreamClient implements IotDeviceUpstreamApi {
27 25
28 private final RestTemplate restTemplate; 26 private final RestTemplate restTemplate;
29 27
30 - @Override  
31 - public CommonResult<Boolean> updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {  
32 - String url = properties.getUpstreamUrl() + URL_PREFIX + "/update-state";  
33 - return doPost(url, updateReqDTO);  
34 - }  
35 -  
36 - @Override  
37 - public CommonResult<Boolean> reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {  
38 - String url = properties.getUpstreamUrl() + URL_PREFIX + "/report-event";  
39 - return doPost(url, reportReqDTO);  
40 - }  
41 -  
42 - @Override  
43 - public CommonResult<Boolean> registerDevice(IotDeviceRegisterReqDTO registerReqDTO) {  
44 - String url = properties.getUpstreamUrl() + URL_PREFIX + "/register-device";  
45 - return doPost(url, registerReqDTO);  
46 - }  
47 -  
48 - @Override  
49 - public CommonResult<Boolean> registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) {  
50 - String url = properties.getUpstreamUrl() + URL_PREFIX + "/register-sub-device";  
51 - return doPost(url, registerReqDTO);  
52 - }  
53 -  
54 - @Override  
55 - public CommonResult<Boolean> addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) {  
56 - String url = properties.getUpstreamUrl() + URL_PREFIX + "/add-device-topology";  
57 - return doPost(url, addReqDTO);  
58 - }  
59 -  
60 - @Override  
61 - public CommonResult<Boolean> authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) {  
62 - String url = properties.getUpstreamUrl() + URL_PREFIX + "/authenticate-emqx-connection";  
63 - return doPost(url, authReqDTO);  
64 - }  
65 -  
66 - @Override  
67 - public CommonResult<Boolean> reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {  
68 - String url = properties.getUpstreamUrl() + URL_PREFIX + "/report-property";  
69 - return doPost(url, reportReqDTO);  
70 - } 28 +// @Override
  29 +// public CommonResult<Boolean> updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {
  30 +// String url = properties.getUpstreamUrl() + URL_PREFIX + "/update-state";
  31 +// return doPost(url, updateReqDTO);
  32 +// }
71 33
72 @SuppressWarnings("unchecked") 34 @SuppressWarnings("unchecked")
73 private <T> CommonResult<Boolean> doPost(String url, T requestBody) { 35 private <T> CommonResult<Boolean> doPost(String url, T requestBody) {
yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/resources/application.yml deleted
1 -# 服务器配置  
2 -server:  
3 - port: 18080 # 修改端口,避免与主应用的8080端口冲突  
4 -  
5 -# Spring 配置  
6 -spring:  
7 - application:  
8 - name: iot-component-server  
9 - # 允许循环引用  
10 - main:  
11 - allow-circular-references: true  
12 - allow-bean-definition-overriding: true  
13 -  
14 -# Yudao 配置  
15 -yudao:  
16 - info:  
17 - base-package: cn.iocoder.yudao # 主项目包路径,确保正确  
18 - iot:  
19 - component:  
20 -  
21 - # 网络组件服务器专用配置  
22 - server:  
23 - # 上行通信配置,用于向主程序上报数据  
24 - upstream-url: http://127.0.0.1:48080 # 主程序 API 地址  
25 - upstream-connect-timeout: 30s # 连接超时  
26 - upstream-read-timeout: 30s # 读取超时  
27 -  
28 - # 下行通信配置,用于接收主程序的控制指令  
29 - downstream-port: 18888 # 下行服务器端口  
30 -  
31 - # 组件服务唯一标识  
32 - server-key: yudao-module-iot-net-component-server  
33 -  
34 - # ====================================  
35 - # 针对引入的 HTTP 组件的配置  
36 - # ====================================  
37 - http:  
38 - enabled: true # 启用HTTP组件  
39 - server-port: 8092 # HTTP组件服务端口  
40 -  
41 - # ====================================  
42 - # 针对引入的 EMQX 组件的配置  
43 - # ====================================  
44 - emqx:  
45 - enabled: true # 启用EMQX组件  
46 - mqtt-host: 127.0.0.1 # MQTT服务器主机地址  
47 - mqtt-port: 1883 # MQTT服务器端口  
48 - mqtt-username: admin # MQTT服务器用户名  
49 - mqtt-password: admin123 # MQTT服务器密码  
50 - mqtt-ssl: false # 是否启用SSL  
51 - mqtt-topics: # 订阅的主题列表  
52 - - "/sys/#"  
53 - auth-port: 8101 # 认证端口  
54 - message-bus:  
55 - type: rocketmq # 消息总线的类型  
56 -  
57 -# 日志配置  
58 -logging:  
59 - level:  
60 - cn.iocoder.yudao: INFO  
61 - root: INFO  
62 -  
63 ---- #################### 消息队列相关 ####################  
64 -  
65 -# rocketmq 配置项,对应 RocketMQProperties 配置类  
66 -rocketmq:  
67 - name-server: 127.0.0.1:9876 # RocketMQ Namesrv  
68 - # Producer 配置项  
69 - producer:  
70 - group: ${spring.application.name}_PRODUCER # 生产者分组