diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDO.java index 9633d2febe..714775ce22 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDO.java +++ b/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 { */ @TableId private Long id; + // TODO @芋艿:看看怎么弱化 deviceKey /** * 设备唯一标识符,全局唯一,用于识别设备 * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java index 0c267517ef..d31096b118 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java +++ b/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; */ public interface RedisKeyConstants { + // TODO @芋艿:弱化 deviceKey;使用 product_key + device_name 替代 /** * 设备属性的数据缓存,采用 HASH 结构 *

@@ -18,6 +19,7 @@ public interface RedisKeyConstants { */ String DEVICE_PROPERTY = "iot:device_property:%s"; + // TODO @芋艿:弱化 deviceKey;使用 product_key + device_name 替代 /** * 设备的最后上报时间,采用 ZSET 结构 * @@ -29,7 +31,7 @@ public interface RedisKeyConstants { /** * 设备信息的数据缓存,使用 Spring Cache 操作(忽略租户) * - * KEY 格式:device_${productKey}_${deviceKey} + * KEY 格式:device_${productKey}_${deviceName} * VALUE 数据类型:String(JSON) */ String DEVICE = "iot:device"; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageBusSubscriber.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageSubscriber.java similarity index 91% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageBusSubscriber.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageSubscriber.java index 4b42781acc..279e422d7e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageBusSubscriber.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageSubscriber.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.iot.mq.consumer.device; import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService; import jakarta.annotation.PostConstruct; @@ -16,7 +16,7 @@ import org.springframework.stereotype.Component; */ @Component @Slf4j -public class IotDeviceLogMessageBusSubscriber implements IotMessageBusSubscriber { +public class IotDeviceLogMessageSubscriber implements IotMessageSubscriber { @Resource private IotMessageBus messageBus; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java index d568d7a42b..511585a099 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java +++ b/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; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import org.springframework.web.client.RestTemplate; import java.time.LocalDateTime; import java.util.List; @@ -44,9 +43,6 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic @Resource private IotDeviceService deviceService; - @Resource - private RestTemplate restTemplate; - @Resource private IotDeviceProducer deviceProducer; @Resource @@ -156,7 +152,7 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage message = cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage .of(getProductKey(device, parentDevice), getDeviceName(device, parentDevice), deviceName, null, tenantId); - String serverId = "yy"; + String serverId = "192_168_64_1_8092"; deviceMessageProducer.sendGatewayDeviceMessage(serverId, message); // TODO @芋艿:后续可以清理掉 return null; diff --git a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageBus.java b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageBus.java index b032298795..c621467610 100644 --- a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageBus.java +++ b/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 { * * @param subscriber 订阅者 */ - void register(IotMessageBusSubscriber subscriber); + void register(IotMessageSubscriber subscriber); } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageBusSubscriber.java b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageSubscriber.java similarity index 90% rename from yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageBusSubscriber.java rename to yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageSubscriber.java index 631fa88e5e..23a055325c 100644 --- a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/IotMessageBusSubscriber.java +++ b/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; * * @author 芋道源码 */ -public interface IotMessageBusSubscriber { +public interface IotMessageSubscriber { /** * @return 主题 diff --git a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBus.java b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBus.java index af73547200..76bd6a493e 100644 --- a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBus.java +++ b/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; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationContext; @@ -30,7 +30,7 @@ public class LocalIotMessageBus implements IotMessageBus { * 订阅者映射表 * Key: topic */ - private final Map>> subscribers = new HashMap<>(); + private final Map>> subscribers = new HashMap<>(); @Override public void post(String topic, Object message) { @@ -38,9 +38,9 @@ public class LocalIotMessageBus implements IotMessageBus { } @Override - public void register(IotMessageBusSubscriber subscriber) { + public void register(IotMessageSubscriber subscriber) { String topic = subscriber.getTopic(); - List> topicSubscribers = subscribers.computeIfAbsent(topic, k -> new ArrayList<>()); + List> topicSubscribers = subscribers.computeIfAbsent(topic, k -> new ArrayList<>()); topicSubscribers.add(subscriber); log.info("[register][topic({}/{}) 注册消费者({})成功]", topic, subscriber.getGroup(), subscriber.getClass().getName()); @@ -50,11 +50,11 @@ public class LocalIotMessageBus implements IotMessageBus { @SuppressWarnings({"unchecked", "rawtypes"}) public void onMessage(LocalIotMessage message) { String topic = message.getTopic(); - List> topicSubscribers = subscribers.get(topic); + List> topicSubscribers = subscribers.get(topic); if (CollUtil.isEmpty(topicSubscribers)) { return; } - for (IotMessageBusSubscriber subscriber : topicSubscribers) { + for (IotMessageSubscriber subscriber : topicSubscribers) { try { subscriber.onMessage(message.getMessage()); } catch (Exception ex) { diff --git a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBus.java b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBus.java index a304ef4597..68d2ce9102 100644 --- a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBus.java +++ b/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; import cn.hutool.core.util.TypeUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -47,7 +47,7 @@ public class RocketMQIotMessageBus implements IotMessageBus { @Override @SneakyThrows - public void register(IotMessageBusSubscriber subscriber) { + public void register(IotMessageSubscriber subscriber) { Type type = TypeUtil.getTypeArgument(subscriber.getClass(), 0); if (type == null) { throw new IllegalStateException(String.format("类型(%s) 需要设置消息类型", getClass().getName())); diff --git a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/mq/message/IotDeviceMessage.java b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/mq/message/IotDeviceMessage.java index da829b14f1..3d9cc2d16a 100644 --- a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/mq/message/IotDeviceMessage.java +++ b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/mq/message/IotDeviceMessage.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.iot.core.mq.message; -import cn.hutool.core.util.IdUtil; import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageIdentifierEnum; import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageTypeEnum; +import cn.iocoder.yudao.module.iot.core.util.IotCoreUtils; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -119,7 +119,7 @@ public class IotDeviceMessage { String requestId, LocalDateTime reportTime, String serverId, Long tenantId) { if (requestId == null) { - requestId = IdUtil.fastSimpleUUID(); + requestId = IotCoreUtils.generateRequestId(); } if (reportTime == null) { reportTime = LocalDateTime.now(); diff --git a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotCoreUtils.java b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotCoreUtils.java new file mode 100644 index 0000000000..10d9769178 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotCoreUtils.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.iot.core.util; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.system.SystemUtil; + +/** + * IoT 核心模块的工具类 + * + * @author 芋道源码 + */ +public class IotCoreUtils { + + /** + * 生成服务器编号 + * + * @param serverPort 服务器端口 + * @return 服务器编号 + */ + public static String generateServerId(Integer serverPort) { + String serverId = String.format("%s.%d", SystemUtil.getHostInfo().getAddress(), serverPort); + // 避免一些场景无法使用 . 符号,例如说 RocketMQ Topic + return serverId.replaceAll("\\.", "_"); + } + + public static String generateRequestId() { + return IdUtil.fastSimpleUUID(); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBusIntegrationTest.java b/yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBusIntegrationTest.java index de757dd71e..341ad891c2 100644 --- a/yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/local/LocalIotMessageBusIntegrationTest.java +++ b/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; import cn.iocoder.yudao.module.iot.core.messagebus.config.IotMessageBusAutoConfiguration; import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; @@ -47,7 +47,7 @@ public class LocalIotMessageBusIntegrationTest { AtomicInteger subscriber2Count = new AtomicInteger(0); // 创建第一个订阅者 - IotMessageBusSubscriber subscriber1 = new IotMessageBusSubscriber<>() { + IotMessageSubscriber subscriber1 = new IotMessageSubscriber<>() { @Override public String getTopic() { @@ -69,7 +69,7 @@ public class LocalIotMessageBusIntegrationTest { }; // 创建第二个订阅者 - IotMessageBusSubscriber subscriber2 = new IotMessageBusSubscriber<>() { + IotMessageSubscriber subscriber2 = new IotMessageSubscriber<>() { @Override public String getTopic() { @@ -120,7 +120,7 @@ public class LocalIotMessageBusIntegrationTest { CountDownLatch latch = new CountDownLatch(2); // 创建订阅者 1 - 只订阅设备状态 - IotMessageBusSubscriber statusSubscriber = new IotMessageBusSubscriber<>() { + IotMessageSubscriber statusSubscriber = new IotMessageSubscriber<>() { @Override public String getTopic() { @@ -141,7 +141,7 @@ public class LocalIotMessageBusIntegrationTest { }; // 创建订阅者 2 - 只订阅设备数据 - IotMessageBusSubscriber dataSubscriber = new IotMessageBusSubscriber<>() { + IotMessageSubscriber dataSubscriber = new IotMessageSubscriber<>() { @Override public String getTopic() { diff --git a/yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBusTest.java b/yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBusTest.java index babd3b252e..01b97ce780 100644 --- a/yudao-module-iot/yudao-module-iot-core/src/test/java/cn/iocoder/yudao/module/iot/core/messagebus/core/rocketmq/RocketMQIotMessageBusTest.java +++ b/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; import cn.hutool.core.util.IdUtil; import cn.iocoder.yudao.module.iot.core.messagebus.config.IotMessageBusAutoConfiguration; import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber; import cn.iocoder.yudao.module.iot.core.messagebus.core.TestMessage; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -59,7 +59,7 @@ public class RocketMQIotMessageBusTest { messageBus.post(topic, testMessage); // 创建订阅者 - IotMessageBusSubscriber subscriber1 = new IotMessageBusSubscriber<>() { + IotMessageSubscriber subscriber1 = new IotMessageSubscriber<>() { @Override public String getTopic() { @@ -117,7 +117,7 @@ public class RocketMQIotMessageBusTest { messageBus.post(topic, testMessage); // 创建第一个订阅者 - IotMessageBusSubscriber subscriber1 = new IotMessageBusSubscriber<>() { + IotMessageSubscriber subscriber1 = new IotMessageSubscriber<>() { @Override public String getTopic() { @@ -141,7 +141,7 @@ public class RocketMQIotMessageBusTest { }; // 创建第二个订阅者 - IotMessageBusSubscriber subscriber2 = new IotMessageBusSubscriber<>() { + IotMessageSubscriber subscriber2 = new IotMessageSubscriber<>() { @Override public String getTopic() { @@ -204,7 +204,7 @@ public class RocketMQIotMessageBusTest { messageBus.post(topic2, message2); // 创建订阅者 1 - 只订阅设备状态 - IotMessageBusSubscriber statusSubscriber = new IotMessageBusSubscriber<>() { + IotMessageSubscriber statusSubscriber = new IotMessageSubscriber<>() { @Override public String getTopic() { @@ -227,7 +227,7 @@ public class RocketMQIotMessageBusTest { }; // 创建订阅者 2 - 只订阅设备数据 - IotMessageBusSubscriber dataSubscriber = new IotMessageBusSubscriber<>() { + IotMessageSubscriber dataSubscriber = new IotMessageSubscriber<>() { @Override public String getTopic() { diff --git a/yudao-module-iot/yudao-module-iot-gateway/pom.xml b/yudao-module-iot/yudao-module-iot-gateway/pom.xml index 1355f51913..83eae1f603 100644 --- a/yudao-module-iot/yudao-module-iot-gateway/pom.xml +++ b/yudao-module-iot/yudao-module-iot-gateway/pom.xml @@ -16,4 +16,46 @@ ② 功能二:接收来自消息网关的消息(由 iot-biz 发送),并进行编码(encode)后,发送给设备 + + + cn.iocoder.boot + yudao-module-iot-core + ${revision} + + + + + org.apache.rocketmq + rocketmq-spring-boot-starter + + + + + + + io.vertx + vertx-web + + + + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/IotGatewayServerApplication.java b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/IotGatewayServerApplication.java new file mode 100644 index 0000000000..e9c4578850 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/IotGatewayServerApplication.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.iot.gateway; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class IotGatewayServerApplication { + + public static void main(String[] args) { + SpringApplication.run(IotGatewayServerApplication.class, args); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/codec/package-info.java b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/codec/package-info.java index b922a07095..e1dae7707a 100644 --- a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/codec/package-info.java +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/codec/package-info.java @@ -1 +1,4 @@ +/** + * 提供设备接入的各种数据(请求、响应)的编解码 + */ package cn.iocoder.yudao.module.iot.gateway.codec; \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayConfiguration.java b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayConfiguration.java new file mode 100644 index 0000000000..cd0e6ac8a8 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayConfiguration.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.iot.gateway.config; + +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; +import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpDownstreamSubscriber; +import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpUpstreamProtocol; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(IotGatewayProperties.class) +@Slf4j +public class IotGatewayConfiguration { + + /** + * IoT 网关 HTTP 协议配置类 + */ + @Configuration + @ConditionalOnProperty(prefix = "yudao.iot.gateway.protocol.http", name = "enabled", havingValue = "true") + @Slf4j + public static class HttpProtocolConfiguration { + + @Bean + public IotHttpUpstreamProtocol iotHttpUpstreamProtocol(IotGatewayProperties gatewayProperties, + IotDeviceMessageProducer deviceMessageProducer) { + return new IotHttpUpstreamProtocol(gatewayProperties.getProtocol().getHttp(), deviceMessageProducer); + } + + @Bean + public IotHttpDownstreamSubscriber iotHttpDownstreamSubscriber(IotHttpUpstreamProtocol httpUpstreamProtocol, + IotMessageBus messageBus) { + return new IotHttpDownstreamSubscriber(httpUpstreamProtocol,messageBus); + } + } + +} diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayProperties.java b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayProperties.java new file mode 100644 index 0000000000..9e83a36024 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayProperties.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.iot.gateway.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +@ConfigurationProperties(prefix = "yudao.iot.gateway") +@Validated +@Data +public class IotGatewayProperties { + + /** + * 设备 RPC 服务配置 + */ + private RpcProperties rpc; + + /** + * 协议配置 + */ + private ProtocolProperties protocol; + + @Data + public static class RpcProperties { + + /** + * 主程序 API 地址 + */ + private String url; + /** + * 连接超时时间 + */ + private String connectTimeout; + /** + * 读取超时时间 + */ + private String readTimeout; + + } + + @Data + public static class ProtocolProperties { + + /** + * HTTP 组件配置 + */ + private HttpProperties http; + + /** + * EMQX 组件配置 + */ + private EmqxProperties emqx; + + } + + @Data + public static class HttpProperties { + + /** + * 是否开启 + */ + private Boolean enabled; + /** + * 服务端口 + */ + private Integer serverPort; + + } + + @Data + public static class EmqxProperties { + + /** + * 是否开启 + */ + private Boolean enabled; + /** + * MQTT 服务器地址 + */ + private String mqttHost; + /** + * MQTT 服务器端口 + */ + private Integer mqttPort; + /** + * MQTT 用户名 + */ + private String mqttUsername; + /** + * MQTT 密码 + */ + private String mqttPassword; + /** + * MQTT 是否开启 SSL + */ + private Boolean mqttSsl; + /** + * MQTT 主题 + */ + private List mqttTopics; + /** + * 认证端口 + */ + private Integer authPort; + + } + +} diff --git a/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 b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/enums/IotDeviceTopicEnum.java similarity index 81% rename from 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 rename to yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/enums/IotDeviceTopicEnum.java index 9429133a5f..543b307f27 100644 --- a/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 +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/enums/IotDeviceTopicEnum.java @@ -1,8 +1,8 @@ -package cn.iocoder.yudao.module.iot.net.component.core.constants; +package cn.iocoder.yudao.module.iot.gateway.enums; import lombok.Getter; +import lombok.RequiredArgsConstructor; -// TODO @haohao:要不放到 enums 包下; /** * IoT 设备主题枚举 *

@@ -10,6 +10,7 @@ import lombok.Getter; * * @author haohao */ +@RequiredArgsConstructor @Getter public enum IotDeviceTopicEnum { @@ -27,36 +28,36 @@ public enum IotDeviceTopicEnum { // TODO @haohao:注释时,中英文之间,有个空格; /** * 设备属性设置主题 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/set - * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/property/set_reply + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/service/property/set + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/service/property/set_reply */ PROPERTY_SET_TOPIC("/thing/service/property/set", "设备属性设置主题"), /** * 设备属性获取主题 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/get - * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/property/get_reply + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/service/property/get + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/service/property/get_reply */ PROPERTY_GET_TOPIC("/thing/service/property/get", "设备属性获取主题"), /** * 设备配置设置主题 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/config/set - * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/config/set_reply + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/service/config/set + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/service/config/set_reply */ CONFIG_SET_TOPIC("/thing/service/config/set", "设备配置设置主题"), /** * 设备OTA升级主题 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade - * 响应Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade_reply + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade_reply */ OTA_UPGRADE_TOPIC("/thing/service/ota/upgrade", "设备OTA升级主题"), /** * 设备属性上报主题 - * 请求Topic:/sys/${productKey}/${deviceName}/thing/event/property/post - * 响应Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply + * 请求 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post + * 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply */ PROPERTY_POST_TOPIC("/thing/event/property/post", "设备属性上报主题"), @@ -78,12 +79,6 @@ public enum IotDeviceTopicEnum { private final String topic; private final String description; - // TODO @haohao:使用 lombok 去除 - IotDeviceTopicEnum(String topic, String description) { - this.topic = topic; - this.description = description; - } - /** * 构建设备服务调用主题 * diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/package-info.java b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/package-info.java deleted file mode 100644 index 7de19cf5d5..0000000000 --- a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.iot.gateway; \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpDownstreamSubscriber.java b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpDownstreamSubscriber.java new file mode 100644 index 0000000000..046095e3df --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpDownstreamSubscriber.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.iot.gateway.protocol.http; + +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber; +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * IoT 网关 HTTP 订阅者:接收下行给设备的消息 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Slf4j +public class IotHttpDownstreamSubscriber implements IotMessageSubscriber { + + private final IotHttpUpstreamProtocol protocol; + + private final IotMessageBus messageBus; + + @PostConstruct + public void init() { + messageBus.register(this); + } + + @Override + public String getTopic() { + return IotDeviceMessage.buildMessageBusGatewayDeviceMessageTopic(protocol.getServerId()); + } + + @Override + public String getGroup() { + // 保证点对点消费,需要保证独立的 Group,所以使用 Topic 作为 Group + return getTopic(); + } + + @Override + public void onMessage(IotDeviceMessage message) { + log.error("[onMessage][IoT 网关 HTTP 协议不支持下行消息,忽略消息:{}]", message); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpUpstreamProtocol.java b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpUpstreamProtocol.java new file mode 100644 index 0000000000..4ddc79f0a8 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpUpstreamProtocol.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.iot.gateway.protocol.http; + +import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; +import cn.iocoder.yudao.module.iot.core.util.IotCoreUtils; +import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties; +import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpUpstreamHandler; +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Vertx; +import io.vertx.core.http.HttpServer; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.handler.BodyHandler; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * IoT 网关 HTTP 协议:接收设备上行消息 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Slf4j +public class IotHttpUpstreamProtocol extends AbstractVerticle { + + private final IotGatewayProperties.HttpProperties httpProperties; + + private final IotDeviceMessageProducer deviceMessageProducer; + + private HttpServer httpServer; + + @Override + @PostConstruct + public void start() { + // 创建路由 + Vertx vertx = Vertx.vertx(); + Router router = Router.router(vertx); + router.route().handler(BodyHandler.create()); + + // 创建处理器,添加路由处理器 + IotHttpUpstreamHandler upstreamHandler = new IotHttpUpstreamHandler( + this, deviceMessageProducer); + router.post(IotHttpUpstreamHandler.PROPERTY_PATH).handler(upstreamHandler); + router.post(IotHttpUpstreamHandler.EVENT_PATH).handler(upstreamHandler); + + // 启动 HTTP 服务器 + try { + httpServer = vertx.createHttpServer() + .requestHandler(router) + .listen(httpProperties.getServerPort()) + .result(); + log.info("[start][IoT 网关 HTTP 协议启动成功,端口:{}]", httpProperties.getServerPort()); + } catch (Exception e) { + log.error("[start][IoT 网关 HTTP 协议启动失败]", e); + throw e; + } + } + + @Override + @PreDestroy + public void stop() { + if (httpServer != null) { + try { + httpServer.close().result(); + log.info("[stop][IoT 网关 HTTP 协议已停止]"); + } catch (Exception e) { + log.error("[stop][IoT 网关 HTTP 协议停止失败]", e); + } + } + } + + public String getServerId() { + return IotCoreUtils.generateServerId(httpProperties.getServerPort()); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/package-info.java b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/package-info.java deleted file mode 100644 index ed889b81ec..0000000000 --- a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.iot.gateway.protocol.http; \ No newline at end of file diff --git a/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 b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/router/IotHttpUpstreamHandler.java similarity index 73% rename from 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 rename to yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/router/IotHttpUpstreamHandler.java index 47e90e0d46..2c626d6000 100644 --- a/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 +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/router/IotHttpUpstreamHandler.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.net.component.http.upstream.router; +package cn.iocoder.yudao.module.iot.gateway.protocol.http.router; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; @@ -6,13 +6,10 @@ import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; -import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; -import cn.iocoder.yudao.module.iot.net.component.core.constants.IotDeviceTopicEnum; -import cn.iocoder.yudao.module.iot.net.component.core.pojo.IotStandardResponse; -import cn.iocoder.yudao.module.iot.net.component.core.util.IotNetComponentCommonUtils; +import cn.iocoder.yudao.module.iot.gateway.enums.IotDeviceTopicEnum; +import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpUpstreamProtocol; import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.RoutingContext; @@ -26,15 +23,13 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; /** - * IoT 设备上行统一处理的 Vert.x Handler - *

- * 统一处理设备属性上报和事件上报的请求。 + * IoT 网关 HTTP 协议的处理器 * * @author 芋道源码 */ @RequiredArgsConstructor @Slf4j -public class IotDeviceUpstreamVertxHandler implements Handler { +public class IotHttpUpstreamHandler implements Handler { // TODO @haohao:你说,咱要不要把 "/sys/:productKey/:deviceName" // + IotDeviceTopicEnum.PROPERTY_POST_TOPIC.getTopic(),也抽到 IotDeviceTopicEnum 的 build 这种?尽量都收敛掉? @@ -51,11 +46,6 @@ public class IotDeviceUpstreamVertxHandler implements Handler { + IotDeviceTopicEnum.EVENT_POST_TOPIC_PREFIX.getTopic() + ":identifier" + IotDeviceTopicEnum.EVENT_POST_TOPIC_SUFFIX.getTopic(); - /** - * 属性上报方法标识 - */ - private static final String PROPERTY_METHOD = "thing.event.property.post"; - /** * 事件上报方法前缀 */ @@ -66,10 +56,11 @@ public class IotDeviceUpstreamVertxHandler implements Handler { */ private static final String EVENT_METHOD_SUFFIX = ".post"; - /** - * 设备上行 API - */ - private final IotDeviceUpstreamApi deviceUpstreamApi; + private final IotHttpUpstreamProtocol protocol; +// /** +// * 设备上行 API +// */ +// private final IotDeviceUpstreamApi deviceUpstreamApi; /** * 设备消息生产者 */ @@ -167,13 +158,14 @@ public class IotDeviceUpstreamVertxHandler implements Handler { String deviceKey = "xxx"; // TODO @芋艿:待支持 Long tenantId = 1L; // TODO @芋艿:待支持 IotDeviceMessage message = IotDeviceMessage.of(productKey, deviceName, deviceKey, - requestId, LocalDateTime.now(), IotNetComponentCommonUtils.getProcessId(), tenantId) + requestId, LocalDateTime.now(), + protocol.getServerId(), tenantId) .ofPropertyReport(parsePropertiesFromBody(body)); // 1.2 发送消息 deviceMessageProducer.sendDeviceMessage(message); // 2. 返回响应 - sendResponse(routingContext, requestId, PROPERTY_METHOD, null); + sendResponse(routingContext, requestId, null, null); } /** @@ -188,16 +180,16 @@ public class IotDeviceUpstreamVertxHandler implements Handler { */ private void handleEventPost(RoutingContext routingContext, String productKey, String deviceName, String identifier, String requestId, JsonObject body) { - // 处理事件上报 - IotDeviceEventReportReqDTO reportReqDTO = parseEventReportRequest(productKey, deviceName, identifier, - requestId, body); - - // 事件上报 - CommonResult result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO); - String method = EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX; - - // 返回响应 - sendResponse(routingContext, requestId, method, result); +// // 处理事件上报 +// IotDeviceEventReportReqDTO reportReqDTO = parseEventReportRequest(productKey, deviceName, identifier, +// requestId, body); +// +// // 事件上报 +// CommonResult result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO); +// String method = EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX; +// +// // 返回响应 +// sendResponse(routingContext, requestId, method, result); } /** @@ -210,16 +202,16 @@ public class IotDeviceUpstreamVertxHandler implements Handler { */ private void sendResponse(RoutingContext routingContext, String requestId, String method, CommonResult result) { - // TODO @芋艿:后续再优化 - IotStandardResponse response; - if (result == null ) { - response = IotStandardResponse.success(requestId, method, null); - } else if (result.isSuccess()) { - response = IotStandardResponse.success(requestId, method, result.getData()); - } else { - response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg()); - } - IotNetComponentCommonUtils.writeJsonResponse(routingContext, response); +// // TODO @芋艿:后续再优化 +// IotStandardResponse response; +// if (result == null ) { +// response = IotStandardResponse.success(requestId, method, null); +// } else if (result.isSuccess()) { +// response = IotStandardResponse.success(requestId, method, result.getData()); +// } else { +// response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg()); +// } +// IotNetComponentCommonUtils.writeJsonResponse(routingContext, response); } /** @@ -233,8 +225,8 @@ public class IotDeviceUpstreamVertxHandler implements Handler { */ private void sendErrorResponse(RoutingContext routingContext, String requestId, String method, Integer code, String message) { - IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method, code, message); - IotNetComponentCommonUtils.writeJsonResponse(routingContext, errorResponse); +// IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method, code, message); +// IotNetComponentCommonUtils.writeJsonResponse(routingContext, errorResponse); } /** @@ -246,7 +238,7 @@ public class IotDeviceUpstreamVertxHandler implements Handler { */ private String determineMethodFromPath(String path, RoutingContext routingContext) { if (StrUtil.contains(path, "/property/")) { - return PROPERTY_METHOD; + return null; } return EVENT_METHOD_PREFIX @@ -285,29 +277,29 @@ public class IotDeviceUpstreamVertxHandler implements Handler { return properties; } - /** - * 解析事件上报请求 - * - * @param productKey 产品 Key - * @param deviceName 设备名称 - * @param identifier 事件标识符 - * @param requestId 请求 ID - * @param body 请求体 - * @return 事件上报请求 DTO - */ - private IotDeviceEventReportReqDTO parseEventReportRequest(String productKey, String deviceName, String identifier, - String requestId, JsonObject body) { - // 解析参数 - Map params = parseParamsFromBody(body); - - // 构建事件上报请求 DTO - return ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO() - .setRequestId(requestId) - .setProcessId(IotNetComponentCommonUtils.getProcessId()) - .setReportTime(LocalDateTime.now()) - .setProductKey(productKey) - .setDeviceName(deviceName)).setIdentifier(identifier).setParams(params); - } +// /** +// * 解析事件上报请求 +// * +// * @param productKey 产品 Key +// * @param deviceName 设备名称 +// * @param identifier 事件标识符 +// * @param requestId 请求 ID +// * @param body 请求体 +// * @return 事件上报请求 DTO +// */ +// private IotDeviceEventReportReqDTO parseEventReportRequest(String productKey, String deviceName, String identifier, +// String requestId, JsonObject body) { +// // 解析参数 +// Map params = parseParamsFromBody(body); +// +// // 构建事件上报请求 DTO +// return ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO() +// .setRequestId(requestId) +// .setProcessId(IotNetComponentCommonUtils.getProcessId()) +// .setReportTime(LocalDateTime.now()) +// .setProductKey(productKey) +// .setDeviceName(deviceName)).setIdentifier(identifier).setParams(params); +// } /** * 从请求体解析参数 diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/package-info.java b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/package-info.java index 4920c11422..6eb414ee9f 100644 --- a/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/package-info.java +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/package-info.java @@ -1,4 +1,4 @@ /** - * TODO 占位 + * 提供设备接入的各种协议的实现 */ package cn.iocoder.yudao.module.iot.gateway.protocol; \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-gateway/src/main/resources/application.yaml b/yudao-module-iot/yudao-module-iot-gateway/src/main/resources/application.yaml new file mode 100644 index 0000000000..9cc438720e --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-gateway/src/main/resources/application.yaml @@ -0,0 +1,57 @@ +spring: + application: + name: iot-gateway-server + +--- #################### 消息队列相关 #################### + +# rocketmq 配置项,对应 RocketMQProperties 配置类 +rocketmq: + name-server: 127.0.0.1:9876 # RocketMQ Namesrv + # Producer 配置项 + producer: + group: ${spring.application.name}_PRODUCER # 生产者分组 + +--- #################### 芋道相关配置 #################### + +yudao: + iot: + # 网关配置 + gateway: + # 设备 RPC 配置 + rpc: + url: http://127.0.0.1:48080 # 主程序 API 地址 + connect-timeout: 30s + read-timeout: 30s + + # 协议配置 + protocol: + # ==================================== + # 针对引入的 HTTP 组件的配置 + # ==================================== + http: + enabled: true + server-port: 8092 + # ==================================== + # 针对引入的 EMQX 组件的配置 + # ==================================== + emqx: + enabled: true + mqtt-host: 127.0.0.1 + mqtt-port: 1883 + mqtt-username: admin + mqtt-password: admin123 + mqtt-ssl: false + mqtt-topics: + - "/sys/#" + auth-port: 8101 + + # 消息总线配置 + message-bus: + type: rocketmq # 消息总线的类型 + +# 日志配置 +# TODO 芋艿:是不是可以删除 +logging: + level: + cn.iocoder.yudao: INFO + root: INFO diff --git a/yudao-module-iot/yudao-module-iot-net-components/README.md b/yudao-module-iot/yudao-module-iot-net-components/README.md deleted file mode 100644 index d60c0dd93d..0000000000 --- a/yudao-module-iot/yudao-module-iot-net-components/README.md +++ /dev/null @@ -1,137 +0,0 @@ -# IOT 组件使用说明 - -## 组件介绍 - -该模块包含多个 IoT 设备连接组件,提供不同的通信协议支持: - -- `yudao-module-iot-net-component-core`: 核心接口和通用类 -- `yudao-module-iot-net-component-http`: 基于 HTTP 协议的设备通信组件 -- `yudao-module-iot-net-component-emqx`: 基于 MQTT/EMQX 的设备通信组件 - -## 组件架构 - -### 架构设计 - -各组件采用统一的架构设计和命名规范: - -- 配置类: `IotComponentXxxAutoConfiguration` - 提供Bean定义和组件初始化逻辑 -- 属性类: `IotComponentXxxProperties` - 定义组件的配置属性 -- 下行接口: `*DownstreamHandler` - 处理从平台到设备的下行通信 -- 上行接口: `*UpstreamServer` - 处理从设备到平台的上行通信 - -### Bean 命名规范 - -为避免 Bean 冲突,各个组件中的 Bean 已添加特定前缀: - -- HTTP 组件: `httpDeviceUpstreamServer`, `httpDeviceDownstreamHandler` -- EMQX 组件: `emqxDeviceUpstreamServer`, `emqxDeviceDownstreamHandler` - -### 组件启用规则 - -现在系统支持同时使用多个组件,但有以下规则: - -1. 当`yudao.iot.component.emqx.enabled=true`时,核心模块将优先使用EMQX组件 -2. 如果同时启用了多个组件,需要在业务代码中使用`@Qualifier`指定要使用的具体实现 - -> **重要提示:** -> 1. 组件库内部的默认配置文件**不会**被自动加载。必须将上述配置添加到主应用的配置文件中。 -> 2. 所有配置项现在都已增加空值处理,配置缺失时将使用合理的默认值 -> 3. `mqtt-host` 是唯一必须配置的参数,其他参数均有默认值 -> 4. `mqtt-ssl` 和 `auth-port` 缺失时的默认值分别为 `false` 和 `8080` -> 5. `mqtt-topics` 缺失时将使用默认主题 `/device/#` - -### 如何引用特定的 Bean - -在其他组件中引用这些 Bean 时,需要使用 `@Qualifier` 注解指定 Bean 名称: - -```java -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import cn.iocoder.yudao.module.iot.component.core.downstream.IotDeviceDownstreamHandler; - -@Service -public class YourServiceClass { - - // 注入 HTTP 组件的下行处理器 - @Autowired - @Qualifier("httpDeviceDownstreamHandler") - private IotDeviceDownstreamHandler httpDeviceDownstreamHandler; - - // 注入 EMQX 组件的下行处理器 - @Autowired - @Qualifier("emqxDeviceDownstreamHandler") - private IotDeviceDownstreamHandler emqxDeviceDownstreamHandler; - - // 使用示例 - public void example() { - // 使用 HTTP 组件 - httpDeviceDownstreamHandler.invokeDeviceService(...); - - // 使用 EMQX 组件 - emqxDeviceDownstreamHandler.invokeDeviceService(...); - } -} -``` - -### 组件选择指南 - -- **HTTP 组件**:适用于简单场景,设备通过 HTTP 接口与平台通信 -- **EMQX 组件**:适用于实时性要求高的场景,基于 MQTT 协议,支持发布/订阅模式 - -## 常见问题 - -### 1. 配置未加载问题 - -如果遇到以下日志: - -``` -MQTT配置: host=null, port=null, username=null, ssl=null -[connectMqtt][MQTT Host为null,无法连接] -``` - -这表明配置没有被正确加载。请确保: - -1. 在主应用的配置文件中(如 `application.yml` 或 `application-dev.yml`)添加了必要的 EMQX 配置 -2. 配置前缀正确:`yudao.iot.component.emqx` -3. 配置了必要的 `mqtt-host` 属性 - -### 2. mqttSsl 空指针异常 - -如果遇到以下错误: - -``` -Cannot invoke "java.lang.Boolean.booleanValue()" because the return value of "cn.iocoder.yudao.module.iot.component.emqx.config.IotEmqxComponentProperties.getMqttSsl()" is null -``` - -此问题已通过代码修复,现在会自动使用默认值 `false`。同样适用于其他配置项的空值问题。 - -### 3. authPort 空指针异常 - -如果遇到以下错误: - -``` -Cannot invoke "java.lang.Integer.intValue()" because the return value of "cn.iocoder.yudao.module.iot.component.emqx.config.IotEmqxComponentProperties.getAuthPort()" is null -``` - -此问题已通过代码修复,现在会自动使用默认值 `8080`。 - -### 4. Bean注入问题 - -如果遇到以下错误: - -``` -Parameter 1 of method deviceDownstreamServer in IotPluginCommonAutoConfiguration required a single bean, but 2 were found -``` - -此问题已通过修改核心配置类来解决。现在系统会根据组件的启用状态自动选择合适的实现: - -1. 优先使用EMQX组件(当`yudao.iot.component.emqx.enabled=true`时) -2. 如果EMQX未启用,则使用HTTP组件(当`yudao.iot.component.http.enabled=true`时) - -如果需要同时使用两个组件,业务代码中必须使用`@Qualifier`明确指定要使用的Bean。 - -### 5. 使用默认配置 - -组件现已加入完善的默认配置和空值处理机制,使配置更加灵活。但需要注意的是,这些默认配置值必须通过在主应用配置文件中设置相应的属性才能生效。 - -// TODO 芋艿:后续继续完善 README.md \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-net-components/pom.xml b/yudao-module-iot/yudao-module-iot-net-components/pom.xml index 6147006f50..d90f4a55e4 100644 --- a/yudao-module-iot/yudao-module-iot-net-components/pom.xml +++ b/yudao-module-iot/yudao-module-iot-net-components/pom.xml @@ -18,9 +18,8 @@ yudao-module-iot-net-component-core - yudao-module-iot-net-component-http yudao-module-iot-net-component-emqx yudao-module-iot-net-component-server - \ No newline at end of file + \ No newline at end of file diff --git a/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 b/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 index 714b39e647..7c28ee65fc 100644 --- a/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 +++ b/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; * * @author haohao */ -@AutoConfiguration @EnableConfigurationProperties(IotNetComponentCommonProperties.class) -@EnableScheduling // 开启定时任务,因为 IotNetComponentInstanceHeartbeatJob 是一个定时任务 public class IotNetComponentCommonAutoConfiguration { /** diff --git a/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 b/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 file mode 100644 index 99312994f8..0000000000 --- a/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 +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.iot.net.component.core.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -/** - * IoT 网络组件通用配置属性 - * - * @author haohao - */ -@ConfigurationProperties(prefix = "yudao.iot.component") -@Validated -@Data -public class IotNetComponentCommonProperties { - - /** - * 组件的唯一标识 - *

- * 注意:该值将在运行时由各组件设置,不再从配置读取 - */ - private String pluginKey; - -} \ No newline at end of file diff --git a/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 b/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 index 5959072a4e..ce5adc36af 100644 --- a/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 +++ b/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; import cn.hutool.core.util.StrUtil; import lombok.Data; -import lombok.experimental.Accessors; /** * IoT 标准协议响应实体类 @@ -12,7 +11,6 @@ import lombok.experimental.Accessors; * @author haohao */ @Data -@Accessors(chain = true) // TODO @haohao:貌似不用写 @Accessors(chain = true),我全局加啦,可见 lombok.config public class IotStandardResponse { /** diff --git a/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 b/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 index 9e432af320..5598c29d6e 100644 --- a/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 +++ b/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,8 +1,5 @@ package cn.iocoder.yudao.module.iot.net.component.core.util; -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.system.SystemUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.iot.net.component.core.pojo.IotStandardResponse; import io.vertx.core.http.HttpHeaders; @@ -16,40 +13,6 @@ import org.springframework.http.MediaType; */ public class IotNetComponentCommonUtils { - /** - * 流程实例的进程编号 - */ - private static String processId; - - /** - * 获取进程ID - * - * @return 进程ID - */ - public static String getProcessId() { - if (StrUtil.isEmpty(processId)) { - initProcessId(); - } - return processId; - } - - /** - * 初始化进程ID - */ - private synchronized static void initProcessId() { - processId = String.format("%s@%d@%s", // IP@PID@${uuid} - SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID(), IdUtil.fastSimpleUUID()); - } - - /** - * 生成请求ID - * - * @return 生成的唯一请求ID - */ - public static String generateRequestId() { - return IdUtil.fastSimpleUUID(); - } - /** * 将对象转换为JSON字符串后写入HTTP响应 * @@ -89,4 +52,5 @@ public class IotNetComponentCommonUtils { .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) .end(JsonUtils.toJsonString(response)); } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/pom.xml b/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/pom.xml deleted file mode 100644 index cb71977f43..0000000000 --- a/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - yudao-module-iot-net-components - cn.iocoder.boot - ${revision} - - 4.0.0 - yudao-module-iot-net-component-http - jar - - ${project.artifactId} - - 物联网网络组件 HTTP 模块 - - - - - cn.iocoder.boot - yudao-module-iot-net-component-core - ${revision} - - - - - - - - - - - - io.vertx - vertx-web - - - - - org.springframework.boot - spring-boot-starter-validation - true - - - - \ No newline at end of file diff --git a/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 b/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 file mode 100644 index d65a5025e5..0000000000 --- a/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 +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.yudao.module.iot.net.component.http.config; - -import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBusSubscriber; -import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; -import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; -import cn.iocoder.yudao.module.iot.net.component.http.upstream.IotDeviceUpstreamServer; -import io.vertx.core.Vertx; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.event.ApplicationStartedEvent; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Lazy; -import org.springframework.context.event.EventListener; - -/** - * IoT 网络组件 HTTP 的自动配置类 - * - * @author haohao - */ -@Slf4j -@AutoConfiguration -@EnableConfigurationProperties(IotNetComponentHttpProperties.class) -@ConditionalOnProperty(prefix = "yudao.iot.component.http", name = "enabled", havingValue = "true", matchIfMissing = false) -@ComponentScan(basePackages = { - "cn.iocoder.yudao.module.iot.net.component.http" // 只扫描 HTTP 组件包 -}) -public class IotNetComponentHttpAutoConfiguration { - - /** - * 初始化 HTTP 组件 - * - * @param event 应用启动事件 - */ - @EventListener(ApplicationStartedEvent.class) - public void initialize(ApplicationStartedEvent event) { - log.info("[IotNetComponentHttpAutoConfiguration][开始初始化]"); - - // TODO @芋艿:临时处理 - IotMessageBus messageBus = event.getApplicationContext() - .getBean(IotMessageBus.class); - messageBus.register(new IotMessageBusSubscriber() { - - @Override - public String getTopic() { - return IotDeviceMessage.buildMessageBusGatewayDeviceMessageTopic("yy"); - } - - @Override - public String getGroup() { - return "test"; - } - - @Override - public void onMessage(IotDeviceMessage message) { - System.out.println(message); - } - - }); - } - - // TODO @芋艿:貌似这里不用注册 bean? - /** - * 创建 Vert.x 实例 - * - * @return Vert.x 实例 - */ - @Bean(name = "httpVertx") - public Vertx vertx() { - return Vertx.vertx(); - } - - /** - * 创建设备上行服务器 - */ - @Bean(name = "httpDeviceUpstreamServer", initMethod = "start", destroyMethod = "stop") - public IotDeviceUpstreamServer deviceUpstreamServer( - @Lazy @Qualifier("httpVertx") Vertx vertx, - IotDeviceUpstreamApi deviceUpstreamApi, - IotNetComponentHttpProperties properties, - IotDeviceMessageProducer deviceMessageProducer) { - return new IotDeviceUpstreamServer(vertx, properties, deviceUpstreamApi, deviceMessageProducer); - } - -} diff --git a/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 b/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 file mode 100644 index 02bbca2d2e..0000000000 --- a/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 +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.iot.net.component.http.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -/** - * IoT HTTP 网络组件配置属性 - * - * @author haohao - */ -@ConfigurationProperties(prefix = "yudao.iot.component.http") -@Validated -@Data -public class IotNetComponentHttpProperties { - - /** - * 是否启用 HTTP 组件 - */ - private Boolean enabled; - - /** - * HTTP 服务端口 - */ - private Integer serverPort; - - /** - * 连接超时时间(毫秒) - *

- * 默认值:10000 毫秒 - */ - private Integer connectionTimeoutMs = 10000; -} \ No newline at end of file diff --git a/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 b/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 file mode 100644 index f0994036f5..0000000000 --- a/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 +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.iot.net.component.http.downstream; - -// TODO @芋艿:实现下; -///** -// * HTTP 网络组件的 {@link IotDeviceDownstreamHandler} 实现类 -// *

-// * 但是:由于设备通过 HTTP 短链接接入,导致其实无法下行指导给 device 设备,所以基本都是直接返回失败!!! -// * 类似 MQTT、WebSocket、TCP 网络组件,是可以实现下行指令的。 -// * -// * @author 芋道源码 -// */ -//@Slf4j -//public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandler { -// -// /** -// * 不支持的错误消息 -// */ -// private static final String NOT_SUPPORTED_MSG = "HTTP 不支持设备下行通信"; -// -// @Override -// public CommonResult invokeDeviceService(IotDeviceServiceInvokeReqDTO invokeReqDTO) { -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG); -// } -// -// @Override -// public CommonResult getDeviceProperty(IotDevicePropertyGetReqDTO getReqDTO) { -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG); -// } -// -// @Override -// public CommonResult setDeviceProperty(IotDevicePropertySetReqDTO setReqDTO) { -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG); -// } -// -// @Override -// public CommonResult setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO) { -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG); -// } -// -// @Override -// public CommonResult upgradeDeviceOta(IotDeviceOtaUpgradeReqDTO upgradeReqDTO) { -// return CommonResult.error(NOT_IMPLEMENTED.getCode(), NOT_SUPPORTED_MSG); -// } -//} diff --git a/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 b/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 file mode 100644 index e9e40f7cfd..0000000000 --- a/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 +++ /dev/null @@ -1,73 +0,0 @@ -package cn.iocoder.yudao.module.iot.net.component.http.upstream; - -import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; -import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; -import cn.iocoder.yudao.module.iot.net.component.http.config.IotNetComponentHttpProperties; -import cn.iocoder.yudao.module.iot.net.component.http.upstream.router.IotDeviceUpstreamVertxHandler; -import io.vertx.core.AbstractVerticle; -import io.vertx.core.Promise; -import io.vertx.core.Vertx; -import io.vertx.ext.web.Router; -import io.vertx.ext.web.handler.BodyHandler; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -/** - * IoT 设备上行服务器 - *

- * 处理设备通过 HTTP 方式接入的上行消息 - * - * @author 芋道源码 - */ -@RequiredArgsConstructor -@Slf4j -public class IotDeviceUpstreamServer extends AbstractVerticle { - - private final Vertx vertx; - - private final IotNetComponentHttpProperties httpProperties; - - private final IotDeviceUpstreamApi deviceUpstreamApi; - - private final IotDeviceMessageProducer deviceMessageProducer; - - @Override - public void start() { - start(Promise.promise()); - } - - // TODO @haohao:这样貌似初始化不到;我临时拷贝上去了 - @Override - public void start(Promise startPromise) { - // 创建路由 - Router router = Router.router(vertx); - router.route().handler(BodyHandler.create()); - - // 创建处理器 - IotDeviceUpstreamVertxHandler upstreamHandler = new IotDeviceUpstreamVertxHandler( - deviceUpstreamApi, deviceMessageProducer); - - // 添加路由处理器 - router.post(IotDeviceUpstreamVertxHandler.PROPERTY_PATH).handler(upstreamHandler::handle); - router.post(IotDeviceUpstreamVertxHandler.EVENT_PATH).handler(upstreamHandler::handle); - - // 启动 HTTP 服务器 - vertx.createHttpServer() - .requestHandler(router) - .listen(httpProperties.getServerPort(), result -> { - if (result.succeeded()) { - log.info("[start][IoT 设备上行服务器启动成功,端口:{}]", httpProperties.getServerPort()); - startPromise.complete(); - } else { - log.error("[start][IoT 设备上行服务器启动失败]", result.cause()); - startPromise.fail(result.cause()); - } - }); - } - - @Override - public void stop(Promise stopPromise) { - log.info("[stop][IoT 设备上行服务器已停止]"); - stopPromise.complete(); - } -} diff --git a/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 b/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 file mode 100644 index 10b00cd6b1..0000000000 --- a/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 +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.iot.net.component.http.upstream.auth; - -import io.vertx.core.Future; -import io.vertx.ext.web.RoutingContext; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.ApplicationContext; - -// TODO @haohao:待实现,或者不需要? -/** - * IoT 设备认证提供者 - *

- * 用于 HTTP 设备接入时的身份认证 - * - * @author haohao - */ -@Slf4j -public class IotDeviceAuthProvider { - - private final ApplicationContext applicationContext; - - /** - * 构造函数 - * - * @param applicationContext Spring 应用上下文 - */ - public IotDeviceAuthProvider(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } - - /** - * 认证设备 - * - * @param context 路由上下文 - * @param clientId 设备唯一标识 - * @return 认证结果 Future 对象 - */ - public Future authenticate(RoutingContext context, String clientId) { - if (clientId == null || clientId.isEmpty()) { - return Future.failedFuture("clientId 不能为空"); - } - - try { - log.info("[authenticate][设备认证成功,clientId={}]", clientId); - return Future.succeededFuture(); - } catch (Exception e) { - log.error("[authenticate][设备认证异常,clientId={}]", clientId, e); - return Future.failedFuture(e); - } - } -} \ No newline at end of file diff --git a/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 b/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 file mode 100644 index 9d3b4057c0..0000000000 --- a/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 +++ /dev/null @@ -1 +0,0 @@ -cn.iocoder.yudao.module.iot.net.component.http.config.IotNetComponentHttpAutoConfiguration \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/resources/application.yml b/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/resources/application.yml deleted file mode 100644 index bdb6b74970..0000000000 --- a/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-http/src/main/resources/application.yml +++ /dev/null @@ -1,10 +0,0 @@ -# HTTP组件默认配置 -yudao: - iot: - component: - core: - plugin-key: http # 插件的唯一标识 -# http: -# enabled: true # 是否启用HTTP组件,默认启用 -# server-port: 8092 - diff --git a/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/pom.xml b/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/pom.xml index eaf000ef50..457feee683 100644 --- a/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/pom.xml +++ b/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/pom.xml @@ -17,32 +17,12 @@ - - - org.springframework.boot - spring-boot-starter - - org.springframework.boot spring-boot-starter-web - - - cn.iocoder.boot - yudao-module-iot-net-component-core - ${revision} - - - - - cn.iocoder.boot - yudao-module-iot-net-component-http - ${revision} - - cn.iocoder.boot @@ -50,32 +30,8 @@ ${revision} - - - org.apache.rocketmq - rocketmq-spring-boot-starter - + - - - ${project.artifactId} - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - - repackage - - - - - - - \ No newline at end of file diff --git a/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 b/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 file mode 100644 index 0d40edb725..0000000000 --- a/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 +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.iot.net.component.server; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * IoT 网络组件聚合启动服务 - * - * @author haohao - */ -@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}.module.iot.net.component"}) -public class NetComponentServerApplication { - - public static void main(String[] args) { - SpringApplication.run(NetComponentServerApplication.class, args); - } - -} \ No newline at end of file diff --git a/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 b/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 index 33fd957993..7d646c5343 100644 --- a/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 +++ b/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; import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; import cn.iocoder.yudao.module.iot.net.component.server.upstream.IotComponentUpstreamClient; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; @@ -50,28 +49,4 @@ public class IotNetComponentServerConfiguration { return new IotComponentUpstreamClient(properties, restTemplate); } - /** - * 配置默认的设备上行客户端,避免在独立运行模式下的循环依赖问题 - * - * @return 设备上行客户端 - */ - @Bean - @ConditionalOnMissingBean(name = "serverDeviceUpstreamClient") - public Object serverDeviceUpstreamClient() { - // 返回一个空对象,避免找不到类的问题 - return new Object(); - } - - // TODO @haohao:这个是不是木有用呀? - /** - * 配置默认的组件实例注册客户端 - * - * @return 插件实例注册客户端 - */ - @Bean - @ConditionalOnMissingBean(name = "serverPluginInstanceRegistryClient") - public Object serverPluginInstanceRegistryClient() { - // 返回一个空对象,避免找不到类的问题 - return new Object(); - } } \ No newline at end of file diff --git a/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 b/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 index bb5a9731c9..bc0a65a6dc 100644 --- a/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 +++ b/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 { /** * 上行 URL,用于向主应用程序上报数据 - *

- * 默认:http://127.0.0.1:48080 */ private String upstreamUrl = "http://127.0.0.1:48080"; @@ -33,18 +31,4 @@ public class IotNetComponentServerProperties { */ private Duration upstreamReadTimeout = Duration.ofSeconds(30); - /** - * 下行服务端口,用于接收主应用程序的请求 - *

- * 默认:18888 - */ - private Integer downstreamPort = 18888; - - /** - * 组件服务器唯一标识 - *

- * 默认:yudao-module-iot-net-component-server - */ - private String serverKey = "yudao-module-iot-net-component-server"; - } \ No newline at end of file diff --git a/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 b/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 file mode 100644 index 4f652dae96..0000000000 --- a/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 +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.iot.net.component.server.controller; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.HashMap; -import java.util.Map; - -// TODO @haohao:这个是必须的哇?可以考虑基于 spring boot actuator; -/** - * 健康检查接口 - * - * @author haohao - */ -@RestController -@RequestMapping("/health") -public class HealthController { - - /** - * 健康检查接口 - * - * @return 返回服务状态信息 - */ - @GetMapping("/status") - public Map status() { - Map result = new HashMap<>(); - result.put("status", "UP"); - result.put("message", "IoT 网络组件服务运行正常"); - result.put("timestamp", System.currentTimeMillis()); - return result; - } -} \ No newline at end of file diff --git a/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 b/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 index 53ea8f15b7..7959c5b670 100644 --- a/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 +++ b/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,8 +1,6 @@ package cn.iocoder.yudao.module.iot.net.component.server.upstream; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi; -import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.*; import cn.iocoder.yudao.module.iot.net.component.server.config.IotNetComponentServerProperties; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,7 +17,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC */ @RequiredArgsConstructor @Slf4j -public class IotComponentUpstreamClient implements IotDeviceUpstreamApi { +public class IotComponentUpstreamClient { public static final String URL_PREFIX = "/rpc-api/iot/device/upstream"; @@ -27,47 +25,11 @@ public class IotComponentUpstreamClient implements IotDeviceUpstreamApi { private final RestTemplate restTemplate; - @Override - public CommonResult updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) { - String url = properties.getUpstreamUrl() + URL_PREFIX + "/update-state"; - return doPost(url, updateReqDTO); - } - - @Override - public CommonResult reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) { - String url = properties.getUpstreamUrl() + URL_PREFIX + "/report-event"; - return doPost(url, reportReqDTO); - } - - @Override - public CommonResult registerDevice(IotDeviceRegisterReqDTO registerReqDTO) { - String url = properties.getUpstreamUrl() + URL_PREFIX + "/register-device"; - return doPost(url, registerReqDTO); - } - - @Override - public CommonResult registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) { - String url = properties.getUpstreamUrl() + URL_PREFIX + "/register-sub-device"; - return doPost(url, registerReqDTO); - } - - @Override - public CommonResult addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) { - String url = properties.getUpstreamUrl() + URL_PREFIX + "/add-device-topology"; - return doPost(url, addReqDTO); - } - - @Override - public CommonResult authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) { - String url = properties.getUpstreamUrl() + URL_PREFIX + "/authenticate-emqx-connection"; - return doPost(url, authReqDTO); - } - - @Override - public CommonResult reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) { - String url = properties.getUpstreamUrl() + URL_PREFIX + "/report-property"; - return doPost(url, reportReqDTO); - } +// @Override +// public CommonResult updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) { +// String url = properties.getUpstreamUrl() + URL_PREFIX + "/update-state"; +// return doPost(url, updateReqDTO); +// } @SuppressWarnings("unchecked") private CommonResult doPost(String url, T requestBody) { diff --git a/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/resources/application.yml b/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/resources/application.yml deleted file mode 100644 index f1b104bb9c..0000000000 --- a/yudao-module-iot/yudao-module-iot-net-components/yudao-module-iot-net-component-server/src/main/resources/application.yml +++ /dev/null @@ -1,70 +0,0 @@ -# 服务器配置 -server: - port: 18080 # 修改端口,避免与主应用的8080端口冲突 - -# Spring 配置 -spring: - application: - name: iot-component-server - # 允许循环引用 - main: - allow-circular-references: true - allow-bean-definition-overriding: true - -# Yudao 配置 -yudao: - info: - base-package: cn.iocoder.yudao # 主项目包路径,确保正确 - iot: - component: - - # 网络组件服务器专用配置 - server: - # 上行通信配置,用于向主程序上报数据 - upstream-url: http://127.0.0.1:48080 # 主程序 API 地址 - upstream-connect-timeout: 30s # 连接超时 - upstream-read-timeout: 30s # 读取超时 - - # 下行通信配置,用于接收主程序的控制指令 - downstream-port: 18888 # 下行服务器端口 - - # 组件服务唯一标识 - server-key: yudao-module-iot-net-component-server - - # ==================================== - # 针对引入的 HTTP 组件的配置 - # ==================================== - http: - enabled: true # 启用HTTP组件 - server-port: 8092 # HTTP组件服务端口 - - # ==================================== - # 针对引入的 EMQX 组件的配置 - # ==================================== - emqx: - enabled: true # 启用EMQX组件 - mqtt-host: 127.0.0.1 # MQTT服务器主机地址 - mqtt-port: 1883 # MQTT服务器端口 - mqtt-username: admin # MQTT服务器用户名 - mqtt-password: admin123 # MQTT服务器密码 - mqtt-ssl: false # 是否启用SSL - mqtt-topics: # 订阅的主题列表 - - "/sys/#" - auth-port: 8101 # 认证端口 - message-bus: - type: rocketmq # 消息总线的类型 - -# 日志配置 -logging: - level: - cn.iocoder.yudao: INFO - root: INFO - ---- #################### 消息队列相关 #################### - -# rocketmq 配置项,对应 RocketMQProperties 配置类 -rocketmq: - name-server: 127.0.0.1:9876 # RocketMQ Namesrv - # Producer 配置项 - producer: - group: ${spring.application.name}_PRODUCER # 生产者分组