Commit 4319220750a142bf62c5ae42baa99472708be047
1 parent
e275cb57
feat(iot):【协议改造】modbus-tcp:改造新的协议方式
Showing
11 changed files
with
300 additions
and
323 deletions
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayConfiguration.java
| 1 | package cn.iocoder.yudao.module.iot.gateway.config; | 1 | package cn.iocoder.yudao.module.iot.gateway.config; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; | ||
| 4 | import cn.iocoder.yudao.module.iot.gateway.protocol.IotProtocolManager; | 3 | import cn.iocoder.yudao.module.iot.gateway.protocol.IotProtocolManager; |
| 5 | -import cn.iocoder.yudao.module.iot.gateway.protocol.emqx.IotEmqxAuthEventProtocol; | ||
| 6 | -import cn.iocoder.yudao.module.iot.gateway.protocol.emqx.IotEmqxDownstreamSubscriber; | ||
| 7 | -import cn.iocoder.yudao.module.iot.gateway.protocol.emqx.IotEmqxUpstreamProtocol; | ||
| 8 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.*; | ||
| 9 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.client.IotModbusTcpClient; | ||
| 10 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.codec.IotModbusDataConverter; | ||
| 11 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConfigCacheService; | ||
| 12 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConnectionManager; | ||
| 13 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpPollScheduler; | ||
| 14 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.router.IotModbusTcpDownstreamHandler; | ||
| 15 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.router.IotModbusTcpUpstreamHandler; | ||
| 16 | -import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttDownstreamSubscriber; | ||
| 17 | -import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttUpstreamProtocol; | ||
| 18 | -import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.manager.IotMqttConnectionManager; | ||
| 19 | -import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.router.IotMqttDownstreamHandler; | ||
| 20 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.IotModbusTcpDownstreamSubscriber; | ||
| 21 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.IotModbusTcpUpstreamProtocol; | ||
| 22 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.client.IotModbusTcpClient; | ||
| 23 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.codec.IotModbusDataConverter; | ||
| 24 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConfigCacheService; | ||
| 25 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConnectionManager; | ||
| 26 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpPollScheduler; | ||
| 27 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.router.IotModbusTcpDownstreamHandler; | ||
| 28 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.router.IotModbusTcpUpstreamHandler; | ||
| 29 | import cn.iocoder.yudao.module.iot.gateway.serialize.IotMessageSerializerManager; | 4 | import cn.iocoder.yudao.module.iot.gateway.serialize.IotMessageSerializerManager; |
| 30 | -import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService; | ||
| 31 | -import io.vertx.core.Vertx; | ||
| 32 | -import lombok.extern.slf4j.Slf4j; | ||
| 33 | -import org.redisson.api.RedissonClient; | ||
| 34 | -import org.springframework.beans.factory.annotation.Qualifier; | ||
| 35 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 36 | -import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService; | ||
| 37 | -import io.vertx.core.Vertx; | ||
| 38 | -import lombok.extern.slf4j.Slf4j; | ||
| 39 | -import org.redisson.api.RedissonClient; | ||
| 40 | -import org.springframework.beans.factory.annotation.Qualifier; | ||
| 41 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 42 | import org.springframework.boot.context.properties.EnableConfigurationProperties; | 5 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 43 | import org.springframework.context.annotation.Bean; | 6 | import org.springframework.context.annotation.Bean; |
| 44 | import org.springframework.context.annotation.Configuration; | 7 | import org.springframework.context.annotation.Configuration; |
| 45 | 8 | ||
| 9 | +/** | ||
| 10 | + * IoT 网关配置类 | ||
| 11 | + * | ||
| 12 | + * @author 芋道源码 | ||
| 13 | + */ | ||
| 46 | @Configuration | 14 | @Configuration |
| 47 | @EnableConfigurationProperties(IotGatewayProperties.class) | 15 | @EnableConfigurationProperties(IotGatewayProperties.class) |
| 48 | public class IotGatewayConfiguration { | 16 | public class IotGatewayConfiguration { |
| @@ -57,86 +25,4 @@ public class IotGatewayConfiguration { | @@ -57,86 +25,4 @@ public class IotGatewayConfiguration { | ||
| 57 | return new IotProtocolManager(gatewayProperties); | 25 | return new IotProtocolManager(gatewayProperties); |
| 58 | } | 26 | } |
| 59 | 27 | ||
| 60 | - /** | ||
| 61 | - * IoT 网关 Modbus TCP 协议配置类 | ||
| 62 | - */ | ||
| 63 | - @Configuration | ||
| 64 | - @ConditionalOnProperty(prefix = "yudao.iot.gateway.protocol.modbus-tcp", name = "enabled", havingValue = "true") | ||
| 65 | - @Slf4j | ||
| 66 | - public static class ModbusTcpProtocolConfiguration { | ||
| 67 | - | ||
| 68 | - @Bean(name = "modbusTcpVertx", destroyMethod = "close") | ||
| 69 | - public Vertx modbusTcpVertx() { | ||
| 70 | - return Vertx.vertx(); | ||
| 71 | - } | ||
| 72 | - | ||
| 73 | - @Bean | ||
| 74 | - public IotModbusDataConverter iotModbusDataConverter() { | ||
| 75 | - return new IotModbusDataConverter(); | ||
| 76 | - } | ||
| 77 | - | ||
| 78 | - @Bean | ||
| 79 | - public IotModbusTcpClient iotModbusTcpClient() { | ||
| 80 | - return new IotModbusTcpClient(); | ||
| 81 | - } | ||
| 82 | - | ||
| 83 | - @Bean | ||
| 84 | - public IotModbusTcpConnectionManager iotModbusTcpConnectionManager( | ||
| 85 | - RedissonClient redissonClient, | ||
| 86 | - @Qualifier("modbusTcpVertx") Vertx modbusTcpVertx) { | ||
| 87 | - return new IotModbusTcpConnectionManager(redissonClient, modbusTcpVertx); | ||
| 88 | - } | ||
| 89 | - | ||
| 90 | - @Bean | ||
| 91 | - public IotModbusTcpConfigCacheService iotModbusTcpConfigCacheService( | ||
| 92 | - cn.iocoder.yudao.module.iot.core.biz.IotDeviceCommonApi deviceApi) { | ||
| 93 | - return new IotModbusTcpConfigCacheService(deviceApi); | ||
| 94 | - } | ||
| 95 | - | ||
| 96 | - @Bean | ||
| 97 | - public IotModbusTcpUpstreamHandler iotModbusTcpUpstreamHandler( | ||
| 98 | - IotDeviceMessageService messageService, | ||
| 99 | - IotModbusDataConverter dataConverter) { | ||
| 100 | - return new IotModbusTcpUpstreamHandler(messageService, dataConverter); | ||
| 101 | - } | ||
| 102 | - | ||
| 103 | - @Bean | ||
| 104 | - public IotModbusTcpPollScheduler iotModbusTcpPollScheduler( | ||
| 105 | - @Qualifier("modbusTcpVertx") Vertx modbusTcpVertx, | ||
| 106 | - IotModbusTcpConnectionManager connectionManager, | ||
| 107 | - IotModbusTcpClient modbusClient, | ||
| 108 | - IotModbusTcpUpstreamHandler upstreamHandler) { | ||
| 109 | - return new IotModbusTcpPollScheduler(modbusTcpVertx, connectionManager, modbusClient, upstreamHandler); | ||
| 110 | - } | ||
| 111 | - | ||
| 112 | - @Bean | ||
| 113 | - public IotModbusTcpDownstreamHandler iotModbusTcpDownstreamHandler( | ||
| 114 | - IotModbusTcpConnectionManager connectionManager, | ||
| 115 | - IotModbusTcpClient modbusClient, | ||
| 116 | - IotModbusDataConverter dataConverter, | ||
| 117 | - IotModbusTcpConfigCacheService configCacheService) { | ||
| 118 | - return new IotModbusTcpDownstreamHandler(connectionManager, modbusClient, dataConverter, configCacheService); | ||
| 119 | - } | ||
| 120 | - | ||
| 121 | - @Bean | ||
| 122 | - public IotModbusTcpUpstreamProtocol iotModbusTcpUpstreamProtocol(IotGatewayProperties gatewayProperties, | ||
| 123 | - IotDeviceMessageService messageService, | ||
| 124 | - IotModbusTcpConnectionManager connectionManager, | ||
| 125 | - IotModbusTcpPollScheduler pollScheduler, | ||
| 126 | - IotModbusTcpConfigCacheService configCacheService, | ||
| 127 | - IotModbusTcpUpstreamHandler upstreamHandler, | ||
| 128 | - @Qualifier("modbusTcpVertx") Vertx modbusTcpVertx) { | ||
| 129 | - return new IotModbusTcpUpstreamProtocol(gatewayProperties.getProtocol().getModbusTcp(), | ||
| 130 | - messageService, connectionManager, pollScheduler, configCacheService, upstreamHandler, modbusTcpVertx); | ||
| 131 | - } | ||
| 132 | - | ||
| 133 | - @Bean | ||
| 134 | - public IotModbusTcpDownstreamSubscriber iotModbusTcpDownstreamSubscriber(IotModbusTcpUpstreamProtocol upstreamProtocol, | ||
| 135 | - IotModbusTcpDownstreamHandler downstreamHandler, | ||
| 136 | - IotMessageBus messageBus) { | ||
| 137 | - return new IotModbusTcpDownstreamSubscriber(upstreamProtocol, downstreamHandler, messageBus); | ||
| 138 | - } | ||
| 139 | - | ||
| 140 | - } | ||
| 141 | - | ||
| 142 | } | 28 | } |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayProperties.java
| @@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.iot.core.enums.IotProtocolTypeEnum; | @@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.iot.core.enums.IotProtocolTypeEnum; | ||
| 4 | import cn.iocoder.yudao.module.iot.gateway.protocol.coap.IotCoapConfig; | 4 | import cn.iocoder.yudao.module.iot.gateway.protocol.coap.IotCoapConfig; |
| 5 | import cn.iocoder.yudao.module.iot.gateway.protocol.emqx.IotEmqxConfig; | 5 | import cn.iocoder.yudao.module.iot.gateway.protocol.emqx.IotEmqxConfig; |
| 6 | import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpConfig; | 6 | import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpConfig; |
| 7 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.IotModbusTcpConfig; | ||
| 7 | import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttConfig; | 8 | import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttConfig; |
| 8 | import cn.iocoder.yudao.module.iot.gateway.protocol.tcp.IotTcpConfig; | 9 | import cn.iocoder.yudao.module.iot.gateway.protocol.tcp.IotTcpConfig; |
| 9 | import cn.iocoder.yudao.module.iot.gateway.protocol.udp.IotUdpConfig; | 10 | import cn.iocoder.yudao.module.iot.gateway.protocol.udp.IotUdpConfig; |
| @@ -166,6 +167,12 @@ public class IotGatewayProperties { | @@ -166,6 +167,12 @@ public class IotGatewayProperties { | ||
| 166 | @Valid | 167 | @Valid |
| 167 | private IotEmqxConfig emqx; | 168 | private IotEmqxConfig emqx; |
| 168 | 169 | ||
| 170 | + /** | ||
| 171 | + * Modbus TCP 协议配置 | ||
| 172 | + */ | ||
| 173 | + @Valid | ||
| 174 | + private IotModbusTcpConfig modbusTcp; | ||
| 175 | + | ||
| 169 | } | 176 | } |
| 170 | 177 | ||
| 171 | /** | 178 | /** |
| @@ -216,31 +223,4 @@ public class IotGatewayProperties { | @@ -216,31 +223,4 @@ public class IotGatewayProperties { | ||
| 216 | 223 | ||
| 217 | } | 224 | } |
| 218 | 225 | ||
| 219 | - @Data | ||
| 220 | - public static class ProtocolProperties { | ||
| 221 | - | ||
| 222 | - /** | ||
| 223 | - * Modbus TCP 组件配置 | ||
| 224 | - */ | ||
| 225 | - private ModbusTcpProperties modbusTcp; | ||
| 226 | - | ||
| 227 | - } | ||
| 228 | - | ||
| 229 | - @Data | ||
| 230 | - public static class ModbusTcpProperties { | ||
| 231 | - | ||
| 232 | - /** | ||
| 233 | - * 是否开启 | ||
| 234 | - */ | ||
| 235 | - @NotNull(message = "是否开启不能为空") | ||
| 236 | - private Boolean enabled; | ||
| 237 | - | ||
| 238 | - /** | ||
| 239 | - * 配置刷新间隔(秒) | ||
| 240 | - */ | ||
| 241 | - @NotNull(message = "配置刷新间隔不能为空") | ||
| 242 | - private Integer configRefreshInterval = 30; | ||
| 243 | - | ||
| 244 | - } | ||
| 245 | - | ||
| 246 | } | 226 | } |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/IotProtocolManager.java
| @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties; | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties; | ||
| 7 | import cn.iocoder.yudao.module.iot.gateway.protocol.coap.IotCoapProtocol; | 7 | import cn.iocoder.yudao.module.iot.gateway.protocol.coap.IotCoapProtocol; |
| 8 | import cn.iocoder.yudao.module.iot.gateway.protocol.emqx.IotEmqxProtocol; | 8 | import cn.iocoder.yudao.module.iot.gateway.protocol.emqx.IotEmqxProtocol; |
| 9 | import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpProtocol; | 9 | import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpProtocol; |
| 10 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.IotModbusTcpProtocol; | ||
| 10 | import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttProtocol; | 11 | import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttProtocol; |
| 11 | import cn.iocoder.yudao.module.iot.gateway.protocol.tcp.IotTcpProtocol; | 12 | import cn.iocoder.yudao.module.iot.gateway.protocol.tcp.IotTcpProtocol; |
| 12 | import cn.iocoder.yudao.module.iot.gateway.protocol.udp.IotUdpProtocol; | 13 | import cn.iocoder.yudao.module.iot.gateway.protocol.udp.IotUdpProtocol; |
| @@ -112,6 +113,8 @@ public class IotProtocolManager implements SmartLifecycle { | @@ -112,6 +113,8 @@ public class IotProtocolManager implements SmartLifecycle { | ||
| 112 | return createMqttProtocol(config); | 113 | return createMqttProtocol(config); |
| 113 | case EMQX: | 114 | case EMQX: |
| 114 | return createEmqxProtocol(config); | 115 | return createEmqxProtocol(config); |
| 116 | + case MODBUS_TCP: | ||
| 117 | + return createModbusTcpProtocol(config); | ||
| 115 | default: | 118 | default: |
| 116 | throw new IllegalArgumentException(String.format( | 119 | throw new IllegalArgumentException(String.format( |
| 117 | "[createProtocol][协议实例 %s 的协议类型 %s 暂不支持]", config.getId(), protocolType)); | 120 | "[createProtocol][协议实例 %s 的协议类型 %s 暂不支持]", config.getId(), protocolType)); |
| @@ -188,4 +191,14 @@ public class IotProtocolManager implements SmartLifecycle { | @@ -188,4 +191,14 @@ public class IotProtocolManager implements SmartLifecycle { | ||
| 188 | return new IotEmqxProtocol(config); | 191 | return new IotEmqxProtocol(config); |
| 189 | } | 192 | } |
| 190 | 193 | ||
| 194 | + /** | ||
| 195 | + * 创建 Modbus TCP 协议实例 | ||
| 196 | + * | ||
| 197 | + * @param config 协议实例配置 | ||
| 198 | + * @return Modbus TCP 协议实例 | ||
| 199 | + */ | ||
| 200 | + private IotModbusTcpProtocol createModbusTcpProtocol(IotGatewayProperties.ProtocolProperties config) { | ||
| 201 | + return new IotModbusTcpProtocol(config); | ||
| 202 | + } | ||
| 203 | + | ||
| 191 | } | 204 | } |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/IotModbusTcpConfig.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp; | ||
| 2 | + | ||
| 3 | +import jakarta.validation.constraints.Min; | ||
| 4 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * IoT Modbus TCP 协议配置 | ||
| 9 | + * | ||
| 10 | + * @author 芋道源码 | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +public class IotModbusTcpConfig { | ||
| 14 | + | ||
| 15 | + /** | ||
| 16 | + * 配置刷新间隔(秒) | ||
| 17 | + */ | ||
| 18 | + @NotNull(message = "配置刷新间隔不能为空") | ||
| 19 | + @Min(value = 1, message = "配置刷新间隔不能小于 1 秒") | ||
| 20 | + private Integer configRefreshInterval = 30; | ||
| 21 | + | ||
| 22 | +} |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/IotModbusTcpProtocol.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.lang.Assert; | ||
| 4 | +import cn.hutool.extra.spring.SpringUtil; | ||
| 5 | +import cn.iocoder.yudao.module.iot.core.biz.IotDeviceCommonApi; | ||
| 6 | +import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO; | ||
| 7 | +import cn.iocoder.yudao.module.iot.core.enums.IotProtocolTypeEnum; | ||
| 8 | +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; | ||
| 9 | +import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; | ||
| 10 | +import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties.ProtocolProperties; | ||
| 11 | +import cn.iocoder.yudao.module.iot.gateway.protocol.IotProtocol; | ||
| 12 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.client.IotModbusTcpClient; | ||
| 13 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.codec.IotModbusDataConverter; | ||
| 14 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.handler.downstream.IotModbusTcpDownstreamHandler; | ||
| 15 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.handler.downstream.IotModbusTcpDownstreamSubscriber; | ||
| 16 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.handler.upstream.IotModbusTcpUpstreamHandler; | ||
| 17 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConfigCacheService; | ||
| 18 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConnectionManager; | ||
| 19 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpPollScheduler; | ||
| 20 | +import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService; | ||
| 21 | +import io.vertx.core.Vertx; | ||
| 22 | +import lombok.Getter; | ||
| 23 | +import lombok.extern.slf4j.Slf4j; | ||
| 24 | +import org.redisson.api.RedissonClient; | ||
| 25 | + | ||
| 26 | +import java.util.List; | ||
| 27 | +import java.util.concurrent.TimeUnit; | ||
| 28 | + | ||
| 29 | +/** | ||
| 30 | + * IoT 网关 Modbus TCP 协议:主动轮询 Modbus 从站设备数据 | ||
| 31 | + * | ||
| 32 | + * @author 芋道源码 | ||
| 33 | + */ | ||
| 34 | +@Slf4j | ||
| 35 | +public class IotModbusTcpProtocol implements IotProtocol { | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 协议配置 | ||
| 39 | + */ | ||
| 40 | + private final ProtocolProperties properties; | ||
| 41 | + /** | ||
| 42 | + * 服务器 ID(用于消息追踪,全局唯一) | ||
| 43 | + */ | ||
| 44 | + @Getter | ||
| 45 | + private final String serverId; | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * 运行状态 | ||
| 49 | + */ | ||
| 50 | + @Getter | ||
| 51 | + private volatile boolean running = false; | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * Vert.x 实例 | ||
| 55 | + */ | ||
| 56 | + private final Vertx vertx; | ||
| 57 | + /** | ||
| 58 | + * 配置刷新定时器 ID | ||
| 59 | + */ | ||
| 60 | + private Long configRefreshTimerId; | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * 连接管理器 | ||
| 64 | + */ | ||
| 65 | + private final IotModbusTcpConnectionManager connectionManager; | ||
| 66 | + /** | ||
| 67 | + * 下行消息订阅者 | ||
| 68 | + */ | ||
| 69 | + private final IotModbusTcpDownstreamSubscriber downstreamSubscriber; | ||
| 70 | + | ||
| 71 | + private final IotModbusTcpConfigCacheService configCacheService; | ||
| 72 | + private final IotModbusTcpPollScheduler pollScheduler; | ||
| 73 | + | ||
| 74 | + public IotModbusTcpProtocol(ProtocolProperties properties) { | ||
| 75 | + IotModbusTcpConfig modbusTcpConfig = properties.getModbusTcp(); | ||
| 76 | + Assert.notNull(modbusTcpConfig, "Modbus TCP 协议配置(modbusTcp)不能为空"); | ||
| 77 | + this.properties = properties; | ||
| 78 | + this.serverId = IotDeviceMessageUtils.generateServerId(properties.getPort()); | ||
| 79 | + | ||
| 80 | + // 初始化 Vertx | ||
| 81 | + this.vertx = Vertx.vertx(); | ||
| 82 | + | ||
| 83 | + // 初始化 Manager | ||
| 84 | + RedissonClient redissonClient = SpringUtil.getBean(RedissonClient.class); | ||
| 85 | + IotDeviceCommonApi deviceApi = SpringUtil.getBean(IotDeviceCommonApi.class); | ||
| 86 | + this.connectionManager = new IotModbusTcpConnectionManager(redissonClient, vertx); | ||
| 87 | + this.configCacheService = new IotModbusTcpConfigCacheService(deviceApi); | ||
| 88 | + | ||
| 89 | + // 初始化 Handler | ||
| 90 | + IotModbusDataConverter dataConverter = new IotModbusDataConverter(); | ||
| 91 | + IotModbusTcpClient modbusClient = new IotModbusTcpClient(); | ||
| 92 | + IotDeviceMessageService messageService = SpringUtil.getBean(IotDeviceMessageService.class); | ||
| 93 | + IotModbusTcpUpstreamHandler upstreamHandler = new IotModbusTcpUpstreamHandler(messageService, dataConverter, serverId); | ||
| 94 | + IotModbusTcpDownstreamHandler downstreamHandler = new IotModbusTcpDownstreamHandler(connectionManager, | ||
| 95 | + modbusClient, dataConverter, configCacheService); | ||
| 96 | + | ||
| 97 | + // 初始化轮询调度器 | ||
| 98 | + this.pollScheduler = new IotModbusTcpPollScheduler(vertx, connectionManager, modbusClient, upstreamHandler); | ||
| 99 | + | ||
| 100 | + // 初始化下行消息订阅者 | ||
| 101 | + IotMessageBus messageBus = SpringUtil.getBean(IotMessageBus.class); | ||
| 102 | + this.downstreamSubscriber = new IotModbusTcpDownstreamSubscriber(this, downstreamHandler, messageBus); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + @Override | ||
| 106 | + public String getId() { | ||
| 107 | + return properties.getId(); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + @Override | ||
| 111 | + public IotProtocolTypeEnum getType() { | ||
| 112 | + return IotProtocolTypeEnum.MODBUS_TCP; | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + @Override | ||
| 116 | + public void start() { | ||
| 117 | + if (running) { | ||
| 118 | + log.warn("[start][IoT Modbus TCP 协议 {} 已经在运行中]", getId()); | ||
| 119 | + return; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + try { | ||
| 123 | + // 1.1 首次加载配置 | ||
| 124 | + refreshConfig(); | ||
| 125 | + // 1.2 启动配置刷新定时器 | ||
| 126 | + int refreshInterval = properties.getModbusTcp().getConfigRefreshInterval(); | ||
| 127 | + configRefreshTimerId = vertx.setPeriodic( | ||
| 128 | + TimeUnit.SECONDS.toMillis(refreshInterval), | ||
| 129 | + id -> refreshConfig() | ||
| 130 | + ); | ||
| 131 | + running = true; | ||
| 132 | + log.info("[start][IoT Modbus TCP 协议 {} 启动成功,serverId={}]", getId(), serverId); | ||
| 133 | + | ||
| 134 | + // 2. 启动下行消息订阅者 | ||
| 135 | + this.downstreamSubscriber.start(); | ||
| 136 | + } catch (Exception e) { | ||
| 137 | + log.error("[start][IoT Modbus TCP 协议 {} 启动失败]", getId(), e); | ||
| 138 | + // 启动失败时关闭资源 | ||
| 139 | + if (vertx != null) { | ||
| 140 | + vertx.close(); | ||
| 141 | + } | ||
| 142 | + throw e; | ||
| 143 | + } | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + @Override | ||
| 147 | + public void stop() { | ||
| 148 | + if (!running) { | ||
| 149 | + return; | ||
| 150 | + } | ||
| 151 | + // 1. 停止下行消息订阅者 | ||
| 152 | + try { | ||
| 153 | + downstreamSubscriber.stop(); | ||
| 154 | + log.info("[stop][IoT Modbus TCP 协议 {} 下行消息订阅者已停止]", getId()); | ||
| 155 | + } catch (Exception e) { | ||
| 156 | + log.error("[stop][IoT Modbus TCP 协议 {} 下行消息订阅者停止失败]", getId(), e); | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + // 2.1 取消配置刷新定时器 | ||
| 160 | + if (configRefreshTimerId != null) { | ||
| 161 | + vertx.cancelTimer(configRefreshTimerId); | ||
| 162 | + configRefreshTimerId = null; | ||
| 163 | + } | ||
| 164 | + // 2.2 停止轮询调度器 | ||
| 165 | + pollScheduler.stopAll(); | ||
| 166 | + log.info("[stop][IoT Modbus TCP 协议 {} 轮询调度器已停止]", getId()); | ||
| 167 | + // 2.3 关闭所有连接 | ||
| 168 | + connectionManager.closeAll(); | ||
| 169 | + log.info("[stop][IoT Modbus TCP 协议 {} 连接管理器已关闭]", getId()); | ||
| 170 | + | ||
| 171 | + // 3. 关闭 Vert.x 实例 | ||
| 172 | + if (vertx != null) { | ||
| 173 | + try { | ||
| 174 | + vertx.close().result(); | ||
| 175 | + log.info("[stop][IoT Modbus TCP 协议 {} Vertx 已关闭]", getId()); | ||
| 176 | + } catch (Exception e) { | ||
| 177 | + log.error("[stop][IoT Modbus TCP 协议 {} Vertx 关闭失败]", getId(), e); | ||
| 178 | + } | ||
| 179 | + } | ||
| 180 | + running = false; | ||
| 181 | + log.info("[stop][IoT Modbus TCP 协议 {} 已停止]", getId()); | ||
| 182 | + } | ||
| 183 | + | ||
| 184 | + /** | ||
| 185 | + * 刷新配置 | ||
| 186 | + */ | ||
| 187 | + private synchronized void refreshConfig() { | ||
| 188 | + try { | ||
| 189 | + // 1. 从 biz 拉取最新配置 | ||
| 190 | + List<IotModbusDeviceConfigRespDTO> configs = configCacheService.refreshConfig(); | ||
| 191 | + log.debug("[refreshConfig][获取到 {} 个 Modbus 设备配置]", configs.size()); | ||
| 192 | + | ||
| 193 | + // 2. 更新连接和轮询任务 | ||
| 194 | + for (IotModbusDeviceConfigRespDTO config : configs) { | ||
| 195 | + try { | ||
| 196 | + // 2.1 确保连接存在 | ||
| 197 | + connectionManager.ensureConnection(config); | ||
| 198 | + // 2.2 更新轮询任务 | ||
| 199 | + pollScheduler.updatePolling(config); | ||
| 200 | + } catch (Exception e) { | ||
| 201 | + log.error("[refreshConfig][处理设备配置失败, deviceId={}]", config.getDeviceId(), e); | ||
| 202 | + } | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + // 3. 清理已删除设备的资源 | ||
| 206 | + configCacheService.cleanupRemovedDevices(configs, deviceId -> { | ||
| 207 | + pollScheduler.stopPolling(deviceId); | ||
| 208 | + connectionManager.removeDevice(deviceId); | ||
| 209 | + }); | ||
| 210 | + } catch (Exception e) { | ||
| 211 | + log.error("[refreshConfig][刷新配置失败]", e); | ||
| 212 | + } | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | +} |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/IotModbusTcpUpstreamProtocol.java deleted
| 1 | -package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO; | ||
| 4 | -import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties; | ||
| 5 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConfigCacheService; | ||
| 6 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConnectionManager; | ||
| 7 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpPollScheduler; | ||
| 8 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.router.IotModbusTcpUpstreamHandler; | ||
| 9 | -import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService; | ||
| 10 | -import io.vertx.core.Vertx; | ||
| 11 | -import jakarta.annotation.PostConstruct; | ||
| 12 | -import jakarta.annotation.PreDestroy; | ||
| 13 | -import lombok.Getter; | ||
| 14 | -import lombok.RequiredArgsConstructor; | ||
| 15 | -import lombok.extern.slf4j.Slf4j; | ||
| 16 | - | ||
| 17 | -import java.util.List; | ||
| 18 | -import java.util.UUID; | ||
| 19 | -import java.util.concurrent.TimeUnit; | ||
| 20 | - | ||
| 21 | -/** | ||
| 22 | - * IoT Modbus TCP 上行协议:定时拉取配置、管理连接、调度轮询任务 | ||
| 23 | - * | ||
| 24 | - * @author 芋道源码 | ||
| 25 | - */ | ||
| 26 | -@RequiredArgsConstructor | ||
| 27 | -@Slf4j | ||
| 28 | -public class IotModbusTcpUpstreamProtocol { | ||
| 29 | - | ||
| 30 | - private final IotGatewayProperties.ModbusTcpProperties modbusTcpProperties; | ||
| 31 | - private final IotDeviceMessageService messageService; | ||
| 32 | - private final IotModbusTcpConnectionManager connectionManager; | ||
| 33 | - private final IotModbusTcpPollScheduler pollScheduler; | ||
| 34 | - private final IotModbusTcpConfigCacheService configCacheService; | ||
| 35 | - private final IotModbusTcpUpstreamHandler upstreamHandler; | ||
| 36 | - private final Vertx vertx; | ||
| 37 | - | ||
| 38 | - /** | ||
| 39 | - * 服务器 ID,用于标识当前网关实例 | ||
| 40 | - */ | ||
| 41 | - @Getter | ||
| 42 | - private final String serverId = UUID.randomUUID().toString(); | ||
| 43 | - | ||
| 44 | - /** | ||
| 45 | - * 配置刷新定时器 ID | ||
| 46 | - */ | ||
| 47 | - private Long configRefreshTimerId; | ||
| 48 | - | ||
| 49 | - @PostConstruct | ||
| 50 | - public void start() { | ||
| 51 | - log.info("[start][Modbus TCP 协议启动, serverId={}]", serverId); | ||
| 52 | - | ||
| 53 | - // 0. 设置 serverId 到上行处理器 | ||
| 54 | - upstreamHandler.setServerId(serverId); | ||
| 55 | - | ||
| 56 | - // 1. 首次加载配置 | ||
| 57 | - refreshConfig(); | ||
| 58 | - | ||
| 59 | - // 2. 启动配置定时刷新 | ||
| 60 | - int refreshInterval = modbusTcpProperties.getConfigRefreshInterval(); | ||
| 61 | - configRefreshTimerId = vertx.setPeriodic( | ||
| 62 | - TimeUnit.SECONDS.toMillis(refreshInterval), | ||
| 63 | - id -> refreshConfig() | ||
| 64 | - ); | ||
| 65 | - log.info("[start][配置刷新定时器已启动, 间隔={}秒]", refreshInterval); | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | - @PreDestroy | ||
| 69 | - public void stop() { | ||
| 70 | - log.info("[stop][Modbus TCP 协议停止]"); | ||
| 71 | - | ||
| 72 | - // 1. 取消配置刷新定时器 | ||
| 73 | - if (configRefreshTimerId != null) { | ||
| 74 | - vertx.cancelTimer(configRefreshTimerId); | ||
| 75 | - } | ||
| 76 | - | ||
| 77 | - // 2. 停止轮询调度器 | ||
| 78 | - pollScheduler.stopAll(); | ||
| 79 | - | ||
| 80 | - // 3. 关闭所有连接 | ||
| 81 | - connectionManager.closeAll(); | ||
| 82 | - } | ||
| 83 | - | ||
| 84 | - /** | ||
| 85 | - * 刷新配置 | ||
| 86 | - */ | ||
| 87 | - private void refreshConfig() { | ||
| 88 | - try { | ||
| 89 | - // 1. 从 biz 拉取最新配置 | ||
| 90 | - List<IotModbusDeviceConfigRespDTO> configs = configCacheService.refreshConfig(); | ||
| 91 | - log.debug("[refreshConfig][获取到 {} 个 Modbus 设备配置]", configs.size()); | ||
| 92 | - | ||
| 93 | - // 2. 更新连接和轮询任务 | ||
| 94 | - for (IotModbusDeviceConfigRespDTO config : configs) { | ||
| 95 | - try { | ||
| 96 | - // 2.1 确保连接存在 | ||
| 97 | - connectionManager.ensureConnection(config); | ||
| 98 | - // 2.2 更新轮询任务 | ||
| 99 | - pollScheduler.updatePolling(config); | ||
| 100 | - } catch (Exception e) { | ||
| 101 | - log.error("[refreshConfig][处理设备配置失败, deviceId={}]", config.getDeviceId(), e); | ||
| 102 | - } | ||
| 103 | - } | ||
| 104 | - | ||
| 105 | - // 3. 清理已删除设备的资源 | ||
| 106 | - configCacheService.cleanupRemovedDevices(configs, deviceId -> { | ||
| 107 | - pollScheduler.stopPolling(deviceId); | ||
| 108 | - connectionManager.removeDevice(deviceId); | ||
| 109 | - }); | ||
| 110 | - } catch (Exception e) { | ||
| 111 | - log.error("[refreshConfig][刷新配置失败]", e); | ||
| 112 | - } | ||
| 113 | - } | ||
| 114 | - | ||
| 115 | -} |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/router/IotModbusTcpDownstreamHandler.java renamed to yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/handler/downstream/IotModbusTcpDownstreamHandler.java
| 1 | -package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.router; | 1 | +package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.handler.downstream; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO; | 4 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO; |
| 5 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusPointRespDTO; | 5 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusPointRespDTO; |
| 6 | +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; | ||
| 6 | import cn.iocoder.yudao.module.iot.core.enums.IotModbusFunctionCodeEnum; | 7 | import cn.iocoder.yudao.module.iot.core.enums.IotModbusFunctionCodeEnum; |
| 7 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | 8 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 8 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.codec.IotModbusDataConverter; | ||
| 9 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.client.IotModbusTcpClient; | 9 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.client.IotModbusTcpClient; |
| 10 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.codec.IotModbusDataConverter; | ||
| 10 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConfigCacheService; | 11 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConfigCacheService; |
| 11 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConnectionManager; | 12 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager.IotModbusTcpConnectionManager; |
| 12 | import lombok.RequiredArgsConstructor; | 13 | import lombok.RequiredArgsConstructor; |
| @@ -16,7 +17,7 @@ import java.util.Map; | @@ -16,7 +17,7 @@ import java.util.Map; | ||
| 16 | 17 | ||
| 17 | /** | 18 | /** |
| 18 | * IoT Modbus TCP 下行消息处理器 | 19 | * IoT Modbus TCP 下行消息处理器 |
| 19 | - * | 20 | + * <p> |
| 20 | * 负责: | 21 | * 负责: |
| 21 | * 1. 处理下行消息(如属性设置 thing.service.property.set) | 22 | * 1. 处理下行消息(如属性设置 thing.service.property.set) |
| 22 | * 2. 执行 Modbus 写入操作 | 23 | * 2. 执行 Modbus 写入操作 |
| @@ -38,8 +39,7 @@ public class IotModbusTcpDownstreamHandler { | @@ -38,8 +39,7 @@ public class IotModbusTcpDownstreamHandler { | ||
| 38 | @SuppressWarnings("unchecked") | 39 | @SuppressWarnings("unchecked") |
| 39 | public void handle(IotDeviceMessage message) { | 40 | public void handle(IotDeviceMessage message) { |
| 40 | // 1.1 检查是否是属性设置消息 | 41 | // 1.1 检查是否是属性设置消息 |
| 41 | - // TODO @AI:要使用枚举 | ||
| 42 | - if (!"thing.service.property.set".equals(message.getMethod())) { | 42 | + if (!IotDeviceMessageMethodEnum.PROPERTY_SET.getMethod().equals(message.getMethod())) { |
| 43 | log.debug("[handle][忽略非属性设置消息: {}]", message.getMethod()); | 43 | log.debug("[handle][忽略非属性设置消息: {}]", message.getMethod()); |
| 44 | return; | 44 | return; |
| 45 | } | 45 | } |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/IotModbusTcpDownstreamSubscriber.java renamed to yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/handler/downstream/IotModbusTcpDownstreamSubscriber.java
| 1 | -package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp; | 1 | +package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.handler.downstream; |
| 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.IotMessageSubscriber; | 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.core.util.IotDeviceMessageUtils; | 6 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; |
| 7 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.router.IotModbusTcpDownstreamHandler; | ||
| 8 | -import jakarta.annotation.PostConstruct; | 7 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.IotModbusTcpProtocol; |
| 9 | import lombok.RequiredArgsConstructor; | 8 | import lombok.RequiredArgsConstructor; |
| 10 | import lombok.extern.slf4j.Slf4j; | 9 | import lombok.extern.slf4j.Slf4j; |
| 11 | 10 | ||
| @@ -18,19 +17,29 @@ import lombok.extern.slf4j.Slf4j; | @@ -18,19 +17,29 @@ import lombok.extern.slf4j.Slf4j; | ||
| 18 | @Slf4j | 17 | @Slf4j |
| 19 | public class IotModbusTcpDownstreamSubscriber implements IotMessageSubscriber<IotDeviceMessage> { | 18 | public class IotModbusTcpDownstreamSubscriber implements IotMessageSubscriber<IotDeviceMessage> { |
| 20 | 19 | ||
| 21 | - private final IotModbusTcpUpstreamProtocol upstreamProtocol; | 20 | + private final IotModbusTcpProtocol protocol; |
| 22 | private final IotModbusTcpDownstreamHandler downstreamHandler; | 21 | private final IotModbusTcpDownstreamHandler downstreamHandler; |
| 23 | private final IotMessageBus messageBus; | 22 | private final IotMessageBus messageBus; |
| 24 | 23 | ||
| 25 | - @PostConstruct | ||
| 26 | - public void subscribe() { | 24 | + /** |
| 25 | + * 启动订阅 | ||
| 26 | + */ | ||
| 27 | + public void start() { | ||
| 27 | messageBus.register(this); | 28 | messageBus.register(this); |
| 28 | - log.info("[subscribe][Modbus TCP 下行消息订阅器已启动, topic={}]", getTopic()); | 29 | + log.info("[start][Modbus TCP 下行消息订阅器已启动, topic={}]", getTopic()); |
| 30 | + } | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 停止订阅 | ||
| 34 | + */ | ||
| 35 | + public void stop() { | ||
| 36 | + messageBus.unregister(this); | ||
| 37 | + log.info("[stop][Modbus TCP 下行消息订阅器已停止]"); | ||
| 29 | } | 38 | } |
| 30 | 39 | ||
| 31 | @Override | 40 | @Override |
| 32 | public String getTopic() { | 41 | public String getTopic() { |
| 33 | - return IotDeviceMessageUtils.buildMessageBusGatewayDeviceMessageTopic(upstreamProtocol.getServerId()); | 42 | + return IotDeviceMessageUtils.buildMessageBusGatewayDeviceMessageTopic(protocol.getServerId()); |
| 34 | } | 43 | } |
| 35 | 44 | ||
| 36 | @Override | 45 | @Override |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/router/IotModbusTcpUpstreamHandler.java renamed to yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/handler/upstream/IotModbusTcpUpstreamHandler.java
| 1 | -package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.router; | 1 | +package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.handler.upstream; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.map.MapUtil; | 3 | import cn.hutool.core.map.MapUtil; |
| 4 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO; | 4 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO; |
| @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; | @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; | ||
| 7 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | 7 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 8 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.codec.IotModbusDataConverter; | 8 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.codec.IotModbusDataConverter; |
| 9 | import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService; | 9 | import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService; |
| 10 | -import lombok.Setter; | ||
| 11 | import lombok.extern.slf4j.Slf4j; | 10 | import lombok.extern.slf4j.Slf4j; |
| 12 | 11 | ||
| 13 | import java.util.Map; | 12 | import java.util.Map; |
| @@ -22,14 +21,14 @@ public class IotModbusTcpUpstreamHandler { | @@ -22,14 +21,14 @@ public class IotModbusTcpUpstreamHandler { | ||
| 22 | 21 | ||
| 23 | private final IotDeviceMessageService messageService; | 22 | private final IotDeviceMessageService messageService; |
| 24 | private final IotModbusDataConverter dataConverter; | 23 | private final IotModbusDataConverter dataConverter; |
| 25 | - | ||
| 26 | - @Setter | ||
| 27 | - private String serverId; | 24 | + private final String serverId; |
| 28 | 25 | ||
| 29 | public IotModbusTcpUpstreamHandler(IotDeviceMessageService messageService, | 26 | public IotModbusTcpUpstreamHandler(IotDeviceMessageService messageService, |
| 30 | - IotModbusDataConverter dataConverter) { | 27 | + IotModbusDataConverter dataConverter, |
| 28 | + String serverId) { | ||
| 31 | this.messageService = messageService; | 29 | this.messageService = messageService; |
| 32 | this.dataConverter = dataConverter; | 30 | this.dataConverter = dataConverter; |
| 31 | + this.serverId = serverId; | ||
| 33 | } | 32 | } |
| 34 | 33 | ||
| 35 | /** | 34 | /** |
| @@ -40,8 +39,8 @@ public class IotModbusTcpUpstreamHandler { | @@ -40,8 +39,8 @@ public class IotModbusTcpUpstreamHandler { | ||
| 40 | * @param rawValue 原始值(int 数组) | 39 | * @param rawValue 原始值(int 数组) |
| 41 | */ | 40 | */ |
| 42 | public void handleReadResult(IotModbusDeviceConfigRespDTO config, | 41 | public void handleReadResult(IotModbusDeviceConfigRespDTO config, |
| 43 | - IotModbusPointRespDTO point, | ||
| 44 | - int[] rawValue) { | 42 | + IotModbusPointRespDTO point, |
| 43 | + int[] rawValue) { | ||
| 45 | try { | 44 | try { |
| 46 | // 1.1 转换原始值为物模型属性值 | 45 | // 1.1 转换原始值为物模型属性值 |
| 47 | Object convertedValue = dataConverter.convertToPropertyValue(rawValue, point); | 46 | Object convertedValue = dataConverter.convertToPropertyValue(rawValue, point); |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbustcp/manager/IotModbusTcpPollScheduler.java
| @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager; | @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.manager; | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO; | 4 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO; |
| 5 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusPointRespDTO; | 5 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusPointRespDTO; |
| 6 | -import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.router.IotModbusTcpUpstreamHandler; | ||
| 7 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.client.IotModbusTcpClient; | 6 | import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.client.IotModbusTcpClient; |
| 7 | +import cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp.handler.upstream.IotModbusTcpUpstreamHandler; | ||
| 8 | import io.vertx.core.Vertx; | 8 | import io.vertx.core.Vertx; |
| 9 | import lombok.AllArgsConstructor; | 9 | import lombok.AllArgsConstructor; |
| 10 | import lombok.Data; | 10 | import lombok.Data; |
yudao-module-iot/yudao-module-iot-gateway/src/main/resources/application.yaml
| @@ -51,8 +51,6 @@ yudao: | @@ -51,8 +51,6 @@ yudao: | ||
| 51 | protocol: http | 51 | protocol: http |
| 52 | port: 8092 | 52 | port: 8092 |
| 53 | enabled: false | 53 | enabled: false |
| 54 | - http: | ||
| 55 | - ssl-enabled: false | ||
| 56 | # ==================================== | 54 | # ==================================== |
| 57 | # 针对引入的 TCP 组件的配置 | 55 | # 针对引入的 TCP 组件的配置 |
| 58 | # ==================================== | 56 | # ==================================== |
| @@ -64,7 +62,6 @@ yudao: | @@ -64,7 +62,6 @@ yudao: | ||
| 64 | tcp: | 62 | tcp: |
| 65 | max-connections: 1000 | 63 | max-connections: 1000 |
| 66 | keep-alive-timeout-ms: 30000 | 64 | keep-alive-timeout-ms: 30000 |
| 67 | - ssl-enabled: false | ||
| 68 | codec: | 65 | codec: |
| 69 | type: delimiter # 拆包类型:length_field / delimiter / fixed_length | 66 | type: delimiter # 拆包类型:length_field / delimiter / fixed_length |
| 70 | delimiter: "\\n" # 分隔符(支持转义:\\n=换行, \\r=回车, \\t=制表符) | 67 | delimiter: "\\n" # 分隔符(支持转义:\\n=换行, \\r=回车, \\t=制表符) |
| @@ -101,7 +98,6 @@ yudao: | @@ -101,7 +98,6 @@ yudao: | ||
| 101 | max-message-size: 65536 # 最大消息大小(字节,默认 64KB) | 98 | max-message-size: 65536 # 最大消息大小(字节,默认 64KB) |
| 102 | max-frame-size: 65536 # 最大帧大小(字节,默认 64KB) | 99 | max-frame-size: 65536 # 最大帧大小(字节,默认 64KB) |
| 103 | idle-timeout-seconds: 60 # 空闲超时时间(秒,默认 60) | 100 | idle-timeout-seconds: 60 # 空闲超时时间(秒,默认 60) |
| 104 | - ssl-enabled: false # 是否启用 SSL(wss://) | ||
| 105 | # ==================================== | 101 | # ==================================== |
| 106 | # 针对引入的 CoAP 组件的配置 | 102 | # 针对引入的 CoAP 组件的配置 |
| 107 | # ==================================== | 103 | # ==================================== |
| @@ -117,14 +113,13 @@ yudao: | @@ -117,14 +113,13 @@ yudao: | ||
| 117 | # 针对引入的 MQTT 组件的配置 | 113 | # 针对引入的 MQTT 组件的配置 |
| 118 | # ==================================== | 114 | # ==================================== |
| 119 | - id: mqtt-json | 115 | - id: mqtt-json |
| 120 | - enabled: true | 116 | + enabled: false |
| 121 | protocol: mqtt | 117 | protocol: mqtt |
| 122 | port: 1883 | 118 | port: 1883 |
| 123 | serialize: json | 119 | serialize: json |
| 124 | mqtt: | 120 | mqtt: |
| 125 | max-message-size: 8192 # 最大消息大小(字节) | 121 | max-message-size: 8192 # 最大消息大小(字节) |
| 126 | connect-timeout-seconds: 60 # 连接超时时间(秒) | 122 | connect-timeout-seconds: 60 # 连接超时时间(秒) |
| 127 | - ssl-enabled: false # 是否启用 SSL | ||
| 128 | # ==================================== | 123 | # ==================================== |
| 129 | # 针对引入的 EMQX 组件的配置 | 124 | # 针对引入的 EMQX 组件的配置 |
| 130 | # ==================================== | 125 | # ==================================== |
| @@ -168,43 +163,15 @@ yudao: | @@ -168,43 +163,15 @@ yudao: | ||
| 168 | key-store-password: "your-keystore-password" # 客户端证书库密码 | 163 | key-store-password: "your-keystore-password" # 客户端证书库密码 |
| 169 | trust-store-path: "classpath:certs/trust.jks" # 信任的 CA 证书库路径 | 164 | trust-store-path: "classpath:certs/trust.jks" # 信任的 CA 证书库路径 |
| 170 | trust-store-password: "your-truststore-password" # 信任的 CA 证书库密码 | 165 | trust-store-password: "your-truststore-password" # 信任的 CA 证书库密码 |
| 171 | - http-port: 8090 # MQTT HTTP 服务端口 | ||
| 172 | - mqtt-host: 127.0.0.1 # MQTT Broker 地址 | ||
| 173 | - mqtt-port: 1883 # MQTT Broker 端口 | ||
| 174 | - mqtt-username: admin # MQTT 用户名 | ||
| 175 | - mqtt-password: public # MQTT 密码 | ||
| 176 | - mqtt-client-id: iot-gateway-mqtt # MQTT 客户端 ID | ||
| 177 | - mqtt-ssl: false # 是否开启 SSL | ||
| 178 | - mqtt-topics: | ||
| 179 | - - "/sys/#" # 系统主题 | ||
| 180 | - clean-session: true # 是否启用 Clean Session (默认: true) | ||
| 181 | - keep-alive-interval-seconds: 60 # 心跳间隔,单位秒 (默认: 60) | ||
| 182 | - max-inflight-queue: 10000 # 最大飞行消息队列,单位:条 | ||
| 183 | - connect-timeout-seconds: 10 # 连接超时,单位:秒 | ||
| 184 | - # 是否信任所有 SSL 证书 (默认: false)。警告:生产环境必须为 false! | ||
| 185 | - # 仅在开发环境或内网测试时,如果使用了自签名证书,可以临时设置为 true | ||
| 186 | - trust-all: true # 在 dev 环境可以设为 true | ||
| 187 | - # 遗嘱消息配置 (用于网关异常下线时通知其他系统) | ||
| 188 | - will: | ||
| 189 | - enabled: true # 生产环境强烈建议开启 | ||
| 190 | - topic: "gateway/status/${yudao.iot.gateway.emqx.mqtt-client-id}" # 遗嘱消息主题 | ||
| 191 | - payload: "offline" # 遗嘱消息负载 | ||
| 192 | - qos: 1 # 遗嘱消息 QoS | ||
| 193 | - retain: true # 遗嘱消息是否保留 | ||
| 194 | - # 高级 SSL/TLS 配置 (当 trust-all: false 且 mqtt-ssl: true 时生效) | ||
| 195 | - ssl-options: | ||
| 196 | - key-store-path: "classpath:certs/client.jks" # 客户端证书库路径 | ||
| 197 | - key-store-password: "your-keystore-password" # 客户端证书库密码 | ||
| 198 | - trust-store-path: "classpath:certs/trust.jks" # 信任的 CA 证书库路径 | ||
| 199 | - trust-store-password: "your-truststore-password" # 信任的 CA 证书库密码 | ||
| 200 | # ==================================== | 166 | # ==================================== |
| 201 | - # 针对引入的 MQTT 组件的配置 | 167 | + # 针对引入的 Modbus TCP 组件的配置 |
| 202 | # ==================================== | 168 | # ==================================== |
| 203 | - # 协议配置(旧版,保持兼容) | ||
| 204 | - protocol: | ||
| 205 | - modbus-tcp: | 169 | + - id: modbus-tcp-1 |
| 206 | enabled: true | 170 | enabled: true |
| 207 | - config-refresh-interval: 30 # 配置刷新间隔(秒) | 171 | + protocol: modbus_tcp |
| 172 | + port: 502 | ||
| 173 | + modbus-tcp: | ||
| 174 | + config-refresh-interval: 30 # 配置刷新间隔(秒) | ||
| 208 | 175 | ||
| 209 | --- #################### 日志相关配置 #################### | 176 | --- #################### 日志相关配置 #################### |
| 210 | 177 | ||
| @@ -226,6 +193,7 @@ logging: | @@ -226,6 +193,7 @@ logging: | ||
| 226 | cn.iocoder.yudao.module.iot.gateway.protocol.mqtt: DEBUG | 193 | cn.iocoder.yudao.module.iot.gateway.protocol.mqtt: DEBUG |
| 227 | cn.iocoder.yudao.module.iot.gateway.protocol.coap: DEBUG | 194 | cn.iocoder.yudao.module.iot.gateway.protocol.coap: DEBUG |
| 228 | cn.iocoder.yudao.module.iot.gateway.protocol.websocket: DEBUG | 195 | cn.iocoder.yudao.module.iot.gateway.protocol.websocket: DEBUG |
| 196 | + cn.iocoder.yudao.module.iot.gateway.protocol.modbustcp: DEBUG | ||
| 229 | # 根日志级别 | 197 | # 根日志级别 |
| 230 | root: INFO | 198 | root: INFO |
| 231 | 199 |