feat(iot):Modbus 支持 Master/Slave 双模式,配置表单和详情按协议类型区分展示

This commit is contained in:
YunaiV
2026-02-13 15:36:17 +08:00
parent 9031c06811
commit fe8044c8a1
34 changed files with 270 additions and 260 deletions

View File

@@ -29,12 +29,6 @@ public class IotDeviceModbusPointDO extends TenantBaseDO {
*/
@TableId
private Long id;
/**
* 产品编号
*
* 关联 {@link cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO#getId()}
*/
private Long productId;
/**
* 设备编号
*

View File

@@ -75,14 +75,14 @@ public class IotDeviceModbusConfigServiceImpl implements IotDeviceModbusConfigSe
if (protocolTypeEnum == null) {
return;
}
if (protocolTypeEnum == IotProtocolTypeEnum.MODBUS_TCP_MASTER) {
Assert.isTrue(StrUtil.isNotEmpty(saveReqVO.getIp()), "Master 模式下IP 地址不能为空");
Assert.notNull(saveReqVO.getPort(), "Master 模式下,端口不能为空");
Assert.notNull(saveReqVO.getTimeout(), "Master 模式下,连接超时时间不能为空");
Assert.notNull(saveReqVO.getRetryInterval(), "Master 模式下,重试间隔不能为空");
} else if (protocolTypeEnum == IotProtocolTypeEnum.MODBUS_TCP_SLAVE) {
Assert.notNull(saveReqVO.getMode(), "Slave 模式下,工作模式不能为空");
Assert.notNull(saveReqVO.getFrameFormat(), "Slave 模式下,数据帧格式不能为空");
if (protocolTypeEnum == IotProtocolTypeEnum.MODBUS_TCP_CLIENT) {
Assert.isTrue(StrUtil.isNotEmpty(saveReqVO.getIp()), "Client 模式下IP 地址不能为空");
Assert.notNull(saveReqVO.getPort(), "Client 模式下,端口不能为空");
Assert.notNull(saveReqVO.getTimeout(), "Client 模式下,连接超时时间不能为空");
Assert.notNull(saveReqVO.getRetryInterval(), "Client 模式下,重试间隔不能为空");
} else if (protocolTypeEnum == IotProtocolTypeEnum.MODBUS_TCP_SERVER) {
Assert.notNull(saveReqVO.getMode(), "Server 模式下,工作模式不能为空");
Assert.notNull(saveReqVO.getFrameFormat(), "Server 模式下,数据帧格式不能为空");
}
}

View File

@@ -25,8 +25,8 @@ public enum IotProtocolTypeEnum implements ArrayValuable<String> {
MQTT("mqtt"),
EMQX("emqx"),
COAP("coap"),
MODBUS_TCP_MASTER("modbus_tcp_master"),
MODBUS_TCP_SLAVE("modbus_tcp_slave");
MODBUS_TCP_CLIENT("modbus_tcp_client"),
MODBUS_TCP_SERVER("modbus_tcp_server");
public static final String[] ARRAYS = Arrays.stream(values()).map(IotProtocolTypeEnum::getType).toArray(String[]::new);

View File

@@ -4,8 +4,8 @@ import cn.iocoder.yudao.module.iot.core.enums.IotProtocolTypeEnum;
import cn.iocoder.yudao.module.iot.gateway.protocol.coap.IotCoapConfig;
import cn.iocoder.yudao.module.iot.gateway.protocol.emqx.IotEmqxConfig;
import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpConfig;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.IotModbusTcpMasterConfig;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.IotModbusTcpSlaveConfig;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.IotModbusTcpClientConfig;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.IotModbusTcpServerConfig;
import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttConfig;
import cn.iocoder.yudao.module.iot.gateway.protocol.tcp.IotTcpConfig;
import cn.iocoder.yudao.module.iot.gateway.protocol.udp.IotUdpConfig;
@@ -169,16 +169,16 @@ public class IotGatewayProperties {
private IotEmqxConfig emqx;
/**
* Modbus TCP Master 协议配置
* Modbus TCP Client 协议配置
*/
@Valid
private IotModbusTcpMasterConfig modbusTcpMaster;
private IotModbusTcpClientConfig modbusTcpClient;
/**
* Modbus TCP Slave 协议配置
* Modbus TCP Server 协议配置
*/
@Valid
private IotModbusTcpSlaveConfig modbusTcpSlave;
private IotModbusTcpServerConfig modbusTcpServer;
}

View File

@@ -7,8 +7,8 @@ import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties;
import cn.iocoder.yudao.module.iot.gateway.protocol.coap.IotCoapProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.emqx.IotEmqxProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.http.IotHttpProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.IotModbusTcpMasterProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.IotModbusTcpSlaveProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.IotModbusTcpClientProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.IotModbusTcpServerProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.tcp.IotTcpProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.udp.IotUdpProtocol;
@@ -114,10 +114,10 @@ public class IotProtocolManager implements SmartLifecycle {
return createMqttProtocol(config);
case EMQX:
return createEmqxProtocol(config);
case MODBUS_TCP_MASTER:
return createModbusTcpMasterProtocol(config);
case MODBUS_TCP_SLAVE:
return createModbusTcpSlaveProtocol(config);
case MODBUS_TCP_CLIENT:
return createModbusTcpClientProtocol(config);
case MODBUS_TCP_SERVER:
return createModbusTcpServerProtocol(config);
default:
throw new IllegalArgumentException(String.format(
"[createProtocol][协议实例 %s 的协议类型 %s 暂不支持]", config.getId(), protocolType));
@@ -195,23 +195,23 @@ public class IotProtocolManager implements SmartLifecycle {
}
/**
* 创建 Modbus TCP Master 协议实例
* 创建 Modbus TCP Client 协议实例
*
* @param config 协议实例配置
* @return Modbus TCP Master 协议实例
* @return Modbus TCP Client 协议实例
*/
private IotModbusTcpMasterProtocol createModbusTcpMasterProtocol(IotGatewayProperties.ProtocolProperties config) {
return new IotModbusTcpMasterProtocol(config);
private IotModbusTcpClientProtocol createModbusTcpClientProtocol(IotGatewayProperties.ProtocolProperties config) {
return new IotModbusTcpClientProtocol(config);
}
/**
* 创建 Modbus TCP Slave 协议实例
* 创建 Modbus TCP Server 协议实例
*
* @param config 协议实例配置
* @return Modbus TCP Slave 协议实例
* @return Modbus TCP Server 协议实例
*/
private IotModbusTcpSlaveProtocol createModbusTcpSlaveProtocol(IotGatewayProperties.ProtocolProperties config) {
return new IotModbusTcpSlaveProtocol(config);
private IotModbusTcpServerProtocol createModbusTcpServerProtocol(IotGatewayProperties.ProtocolProperties config) {
return new IotModbusTcpServerProtocol(config);
}
}

View File

@@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO;
import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusPointRespDTO;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusByteOrderEnum;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusRawDataTypeEnum;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrame;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrame;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

View File

@@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils;
import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusPointRespDTO;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.manager.IotModbusTcpMasterConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.manager.IotModbusTcpClientConnectionManager;
import com.ghgande.j2mod.modbus.io.ModbusTCPTransaction;
import com.ghgande.j2mod.modbus.msg.*;
import com.ghgande.j2mod.modbus.procimg.InputRegister;
@@ -19,14 +19,14 @@ import static cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.I
* <p>
* 封装基于 j2mod Modbus TCP 读写操作
* 1. 根据功能码创建对应的 Modbus /写请求
* 2. 通过 {@link IotModbusTcpMasterConnectionManager.ModbusConnection} 执行事务
* 2. 通过 {@link IotModbusTcpClientConnectionManager.ModbusConnection} 执行事务
* 3. 从响应中提取原始值
*
* @author 芋道源码
*/
@UtilityClass
@Slf4j
public class IotModbusTcpMasterUtils {
public class IotModbusTcpClientUtils {
/**
* 读取 Modbus 数据
@@ -36,7 +36,7 @@ public class IotModbusTcpMasterUtils {
* @param point 点位配置
* @return 原始值int 数组
*/
public static Future<int[]> read(IotModbusTcpMasterConnectionManager.ModbusConnection connection,
public static Future<int[]> read(IotModbusTcpClientConnectionManager.ModbusConnection connection,
Integer slaveId,
IotModbusPointRespDTO point) {
return connection.executeBlocking(tcpConnection -> {
@@ -70,7 +70,7 @@ public class IotModbusTcpMasterUtils {
* @param values 要写入的值
* @return 是否成功
*/
public static Future<Boolean> write(IotModbusTcpMasterConnectionManager.ModbusConnection connection,
public static Future<Boolean> write(IotModbusTcpClientConnectionManager.ModbusConnection connection,
Integer slaveId,
IotModbusPointRespDTO point,
int[] values) {

View File

@@ -1,16 +1,16 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* IoT Modbus TCP Master 协议配置
* IoT Modbus TCP Client 协议配置
*
* @author 芋道源码
*/
@Data
public class IotModbusTcpMasterConfig {
public class IotModbusTcpClientConfig {
/**
* 配置刷新间隔

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient;
import cn.hutool.core.lang.Assert;
import cn.hutool.extra.spring.SpringUtil;
@@ -9,12 +9,12 @@ import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties.ProtocolProperties;
import cn.iocoder.yudao.module.iot.gateway.protocol.IotProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.handler.downstream.IotModbusTcpMasterDownstreamHandler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.handler.downstream.IotModbusTcpMasterDownstreamSubscriber;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.handler.upstream.IotModbusTcpMasterUpstreamHandler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.manager.IotModbusTcpMasterConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.manager.IotModbusTcpMasterConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.manager.IotModbusTcpMasterPollScheduler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.handler.downstream.IotModbusTcpClientDownstreamHandler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.handler.downstream.IotModbusTcpClientDownstreamSubscriber;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.handler.upstream.IotModbusTcpClientUpstreamHandler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.manager.IotModbusTcpClientConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.manager.IotModbusTcpClientConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.manager.IotModbusTcpClientPollScheduler;
import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService;
import io.vertx.core.Vertx;
import lombok.Getter;
@@ -26,12 +26,12 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* IoT 网关 Modbus TCP Master 协议主动轮询 Modbus 从站设备数据
* IoT 网关 Modbus TCP Client 协议主动轮询 Modbus 从站设备数据
*
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpMasterProtocol implements IotProtocol {
public class IotModbusTcpClientProtocol implements IotProtocol {
/**
* 协议配置
@@ -61,18 +61,18 @@ public class IotModbusTcpMasterProtocol implements IotProtocol {
/**
* 连接管理器
*/
private final IotModbusTcpMasterConnectionManager connectionManager;
private final IotModbusTcpClientConnectionManager connectionManager;
/**
* 下行消息订阅者
*/
private IotModbusTcpMasterDownstreamSubscriber downstreamSubscriber;
private IotModbusTcpClientDownstreamSubscriber downstreamSubscriber;
private final IotModbusTcpMasterConfigCacheService configCacheService;
private final IotModbusTcpMasterPollScheduler pollScheduler;
private final IotModbusTcpClientConfigCacheService configCacheService;
private final IotModbusTcpClientPollScheduler pollScheduler;
public IotModbusTcpMasterProtocol(ProtocolProperties properties) {
IotModbusTcpMasterConfig modbusTcpMasterConfig = properties.getModbusTcpMaster();
Assert.notNull(modbusTcpMasterConfig, "Modbus TCP Master 协议配置modbusTcpMaster)不能为空");
public IotModbusTcpClientProtocol(ProtocolProperties properties) {
IotModbusTcpClientConfig modbusTcpClientConfig = properties.getModbusTcpClient();
Assert.notNull(modbusTcpClientConfig, "Modbus TCP Client 协议配置modbusTcpClient)不能为空");
this.properties = properties;
this.serverId = IotDeviceMessageUtils.generateServerId(properties.getPort());
@@ -83,15 +83,15 @@ public class IotModbusTcpMasterProtocol implements IotProtocol {
RedissonClient redissonClient = SpringUtil.getBean(RedissonClient.class);
IotDeviceCommonApi deviceApi = SpringUtil.getBean(IotDeviceCommonApi.class);
IotDeviceMessageService messageService = SpringUtil.getBean(IotDeviceMessageService.class);
this.configCacheService = new IotModbusTcpMasterConfigCacheService(deviceApi);
this.connectionManager = new IotModbusTcpMasterConnectionManager(redissonClient, vertx,
this.configCacheService = new IotModbusTcpClientConfigCacheService(deviceApi);
this.connectionManager = new IotModbusTcpClientConnectionManager(redissonClient, vertx,
messageService, configCacheService, serverId);
// 初始化 Handler
IotModbusTcpMasterUpstreamHandler upstreamHandler = new IotModbusTcpMasterUpstreamHandler(messageService, serverId);
IotModbusTcpClientUpstreamHandler upstreamHandler = new IotModbusTcpClientUpstreamHandler(messageService, serverId);
// 初始化轮询调度器
this.pollScheduler = new IotModbusTcpMasterPollScheduler(vertx, connectionManager, upstreamHandler, configCacheService);
this.pollScheduler = new IotModbusTcpClientPollScheduler(vertx, connectionManager, upstreamHandler, configCacheService);
}
@Override
@@ -101,13 +101,13 @@ public class IotModbusTcpMasterProtocol implements IotProtocol {
@Override
public IotProtocolTypeEnum getType() {
return IotProtocolTypeEnum.MODBUS_TCP_MASTER;
return IotProtocolTypeEnum.MODBUS_TCP_CLIENT;
}
@Override
public void start() {
if (running) {
log.warn("[start][IoT Modbus TCP Master 协议 {} 已经在运行中]", getId());
log.warn("[start][IoT Modbus TCP Client 协议 {} 已经在运行中]", getId());
return;
}
@@ -115,22 +115,22 @@ public class IotModbusTcpMasterProtocol implements IotProtocol {
// 1.1 首次加载配置
refreshConfig();
// 1.2 启动配置刷新定时器
int refreshInterval = properties.getModbusTcpMaster().getConfigRefreshInterval();
int refreshInterval = properties.getModbusTcpClient().getConfigRefreshInterval();
configRefreshTimerId = vertx.setPeriodic(
TimeUnit.SECONDS.toMillis(refreshInterval),
id -> refreshConfig()
);
running = true;
log.info("[start][IoT Modbus TCP Master 协议 {} 启动成功serverId={}]", getId(), serverId);
log.info("[start][IoT Modbus TCP Client 协议 {} 启动成功serverId={}]", getId(), serverId);
// 2. 启动下行消息订阅者
IotMessageBus messageBus = SpringUtil.getBean(IotMessageBus.class);
IotModbusTcpMasterDownstreamHandler downstreamHandler = new IotModbusTcpMasterDownstreamHandler(connectionManager,
IotModbusTcpClientDownstreamHandler downstreamHandler = new IotModbusTcpClientDownstreamHandler(connectionManager,
configCacheService);
this.downstreamSubscriber = new IotModbusTcpMasterDownstreamSubscriber(this, downstreamHandler, messageBus);
this.downstreamSubscriber = new IotModbusTcpClientDownstreamSubscriber(this, downstreamHandler, messageBus);
this.downstreamSubscriber.start();
} catch (Exception e) {
log.error("[start][IoT Modbus TCP Master 协议 {} 启动失败]", getId(), e);
log.error("[start][IoT Modbus TCP Client 协议 {} 启动失败]", getId(), e);
stop0();
throw e;
}
@@ -149,9 +149,9 @@ public class IotModbusTcpMasterProtocol implements IotProtocol {
if (downstreamSubscriber != null) {
try {
downstreamSubscriber.stop();
log.info("[stop][IoT Modbus TCP Master 协议 {} 下行消息订阅者已停止]", getId());
log.info("[stop][IoT Modbus TCP Client 协议 {} 下行消息订阅者已停止]", getId());
} catch (Exception e) {
log.error("[stop][IoT Modbus TCP Master 协议 {} 下行消息订阅者停止失败]", getId(), e);
log.error("[stop][IoT Modbus TCP Client 协议 {} 下行消息订阅者停止失败]", getId(), e);
}
downstreamSubscriber = null;
}
@@ -170,13 +170,13 @@ public class IotModbusTcpMasterProtocol implements IotProtocol {
if (vertx != null) {
try {
vertx.close().result();
log.info("[stop][IoT Modbus TCP Master 协议 {} Vertx 已关闭]", getId());
log.info("[stop][IoT Modbus TCP Client 协议 {} Vertx 已关闭]", getId());
} catch (Exception e) {
log.error("[stop][IoT Modbus TCP Master 协议 {} Vertx 关闭失败]", getId(), e);
log.error("[stop][IoT Modbus TCP Client 协议 {} Vertx 关闭失败]", getId(), e);
}
}
running = false;
log.info("[stop][IoT Modbus TCP Master 协议 {} 已停止]", getId());
log.info("[stop][IoT Modbus TCP Client 协议 {} 已停止]", getId());
}
/**

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.handler.downstream;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.handler.downstream;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO;
@@ -6,16 +6,16 @@ import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusPointRespDTO;
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusTcpMasterUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.manager.IotModbusTcpMasterConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.manager.IotModbusTcpMasterConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusTcpClientUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.manager.IotModbusTcpClientConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.manager.IotModbusTcpClientConnectionManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
/**
* IoT Modbus TCP Master 下行消息处理器
* IoT Modbus TCP Client 下行消息处理器
* <p>
* 负责
* 1. 处理下行消息如属性设置 thing.service.property.set
@@ -25,10 +25,10 @@ import java.util.Map;
*/
@RequiredArgsConstructor
@Slf4j
public class IotModbusTcpMasterDownstreamHandler {
public class IotModbusTcpClientDownstreamHandler {
private final IotModbusTcpMasterConnectionManager connectionManager;
private final IotModbusTcpMasterConfigCacheService configCacheService;
private final IotModbusTcpClientConnectionManager connectionManager;
private final IotModbusTcpClientConfigCacheService configCacheService;
/**
* 处理下行消息
@@ -36,8 +36,11 @@ public class IotModbusTcpMasterDownstreamHandler {
@SuppressWarnings({"unchecked", "DuplicatedCode"})
public void handle(IotDeviceMessage message) {
// 1.1 检查是否是属性设置消息
if (ObjUtil.equals(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(), message.getMethod())) {
return;
}
if (ObjUtil.notEqual(IotDeviceMessageMethodEnum.PROPERTY_SET.getMethod(), message.getMethod())) {
log.debug("[handle][忽略非属性设置消息: {}]", message.getMethod());
log.warn("[handle][忽略非属性设置消息: {}]", message.getMethod());
return;
}
// 1.2 获取设备配置
@@ -79,7 +82,7 @@ public class IotModbusTcpMasterDownstreamHandler {
*/
private void writeProperty(IotModbusDeviceConfigRespDTO config, IotModbusPointRespDTO point, Object value) {
// 1.1 获取连接
IotModbusTcpMasterConnectionManager.ModbusConnection connection = connectionManager.getConnection(config.getDeviceId());
IotModbusTcpClientConnectionManager.ModbusConnection connection = connectionManager.getConnection(config.getDeviceId());
if (connection == null) {
log.warn("[writeProperty][设备 {} 没有连接]", config.getDeviceId());
return;
@@ -94,7 +97,7 @@ public class IotModbusTcpMasterDownstreamHandler {
// 2.1 转换属性值为原始值
int[] rawValues = IotModbusCommonUtils.convertToRawValues(value, point);
// 2.2 执行 Modbus 写入
IotModbusTcpMasterUtils.write(connection, slaveId, point, rawValues)
IotModbusTcpClientUtils.write(connection, slaveId, point, rawValues)
.onSuccess(success -> log.info("[writeProperty][写入成功, deviceId={}, identifier={}, value={}]",
config.getDeviceId(), point.getIdentifier(), value))
.onFailure(e -> log.error("[writeProperty][写入失败, deviceId={}, identifier={}]",

View File

@@ -1,9 +1,9 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.handler.downstream;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.handler.downstream;
import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.gateway.protocol.AbstractIotProtocolDownstreamSubscriber;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.IotModbusTcpMasterProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.IotModbusTcpClientProtocol;
import lombok.extern.slf4j.Slf4j;
/**
@@ -12,12 +12,12 @@ import lombok.extern.slf4j.Slf4j;
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpMasterDownstreamSubscriber extends AbstractIotProtocolDownstreamSubscriber {
public class IotModbusTcpClientDownstreamSubscriber extends AbstractIotProtocolDownstreamSubscriber {
private final IotModbusTcpMasterDownstreamHandler downstreamHandler;
private final IotModbusTcpClientDownstreamHandler downstreamHandler;
public IotModbusTcpMasterDownstreamSubscriber(IotModbusTcpMasterProtocol protocol,
IotModbusTcpMasterDownstreamHandler downstreamHandler,
public IotModbusTcpClientDownstreamSubscriber(IotModbusTcpClientProtocol protocol,
IotModbusTcpClientDownstreamHandler downstreamHandler,
IotMessageBus messageBus) {
super(protocol, messageBus);
this.downstreamHandler = downstreamHandler;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.handler.upstream;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.handler.upstream;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO;
@@ -17,13 +17,13 @@ import java.util.Map;
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpMasterUpstreamHandler {
public class IotModbusTcpClientUpstreamHandler {
private final IotDeviceMessageService messageService;
private final String serverId;
public IotModbusTcpMasterUpstreamHandler(IotDeviceMessageService messageService,
public IotModbusTcpClientUpstreamHandler(IotDeviceMessageService messageService,
String serverId) {
this.messageService = messageService;
this.serverId = serverId;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.manager;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.manager;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@@ -19,13 +19,13 @@ import java.util.concurrent.ConcurrentHashMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
/**
* IoT Modbus TCP Master 配置缓存服务
* IoT Modbus TCP Client 配置缓存服务
*
* @author 芋道源码
*/
@RequiredArgsConstructor
@Slf4j
public class IotModbusTcpMasterConfigCacheService {
public class IotModbusTcpClientConfigCacheService {
private final IotDeviceCommonApi deviceApi;
@@ -51,7 +51,7 @@ public class IotModbusTcpMasterConfigCacheService {
// 1. 从远程获取配置
CommonResult<List<IotModbusDeviceConfigRespDTO>> result = deviceApi.getModbusDeviceConfigList(
new IotModbusDeviceConfigListReqDTO().setStatus(CommonStatusEnum.ENABLE.getStatus())
.setMode(IotModbusModeEnum.POLLING.getMode()).setProtocolType(IotProtocolTypeEnum.MODBUS_TCP_MASTER.getType()));
.setMode(IotModbusModeEnum.POLLING.getMode()).setProtocolType(IotProtocolTypeEnum.MODBUS_TCP_CLIENT.getType()));
result.checkError();
List<IotModbusDeviceConfigRespDTO> configs = result.getData();

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.manager;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.manager;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO;
@@ -30,14 +30,14 @@ import java.util.concurrent.ConcurrentHashMap;
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpMasterConnectionManager {
public class IotModbusTcpClientConnectionManager {
private static final String LOCK_KEY_PREFIX = "iot:modbus-tcp:connection:";
private final RedissonClient redissonClient;
private final Vertx vertx;
private final IotDeviceMessageService messageService;
private final IotModbusTcpMasterConfigCacheService configCacheService;
private final IotModbusTcpClientConfigCacheService configCacheService;
private final String serverId;
/**
@@ -50,9 +50,9 @@ public class IotModbusTcpMasterConnectionManager {
*/
private final Map<Long, String> deviceConnectionMap = new ConcurrentHashMap<>();
public IotModbusTcpMasterConnectionManager(RedissonClient redissonClient, Vertx vertx,
public IotModbusTcpClientConnectionManager(RedissonClient redissonClient, Vertx vertx,
IotDeviceMessageService messageService,
IotModbusTcpMasterConfigCacheService configCacheService,
IotModbusTcpClientConfigCacheService configCacheService,
String serverId) {
this.redissonClient = redissonClient;
this.vertx = vertx;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.manager;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.manager;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
@@ -6,27 +6,27 @@ import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusDeviceConfigRespDTO;
import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusPointRespDTO;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.manager.AbstractIotModbusPollScheduler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusTcpMasterUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster.handler.upstream.IotModbusTcpMasterUpstreamHandler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusTcpClientUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient.handler.upstream.IotModbusTcpClientUpstreamHandler;
import io.vertx.core.Vertx;
import lombok.extern.slf4j.Slf4j;
/**
* IoT Modbus TCP Master 轮询调度器管理点位的轮询定时器调度读取任务并上报结果
* IoT Modbus TCP Client 轮询调度器管理点位的轮询定时器调度读取任务并上报结果
*
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpMasterPollScheduler extends AbstractIotModbusPollScheduler {
public class IotModbusTcpClientPollScheduler extends AbstractIotModbusPollScheduler {
private final IotModbusTcpMasterConnectionManager connectionManager;
private final IotModbusTcpMasterUpstreamHandler upstreamHandler;
private final IotModbusTcpMasterConfigCacheService configCacheService;
private final IotModbusTcpClientConnectionManager connectionManager;
private final IotModbusTcpClientUpstreamHandler upstreamHandler;
private final IotModbusTcpClientConfigCacheService configCacheService;
public IotModbusTcpMasterPollScheduler(Vertx vertx,
IotModbusTcpMasterConnectionManager connectionManager,
IotModbusTcpMasterUpstreamHandler upstreamHandler,
IotModbusTcpMasterConfigCacheService configCacheService) {
public IotModbusTcpClientPollScheduler(Vertx vertx,
IotModbusTcpClientConnectionManager connectionManager,
IotModbusTcpClientUpstreamHandler upstreamHandler,
IotModbusTcpClientConfigCacheService configCacheService) {
super(vertx);
this.connectionManager = connectionManager;
this.upstreamHandler = upstreamHandler;
@@ -54,7 +54,7 @@ public class IotModbusTcpMasterPollScheduler extends AbstractIotModbusPollSchedu
}
// 2.1 获取连接
IotModbusTcpMasterConnectionManager.ModbusConnection connection = connectionManager.getConnection(deviceId);
IotModbusTcpClientConnectionManager.ModbusConnection connection = connectionManager.getConnection(deviceId);
if (connection == null) {
log.warn("[pollPoint][设备 {} 没有连接]", deviceId);
return;
@@ -64,7 +64,7 @@ public class IotModbusTcpMasterPollScheduler extends AbstractIotModbusPollSchedu
Assert.notNull(slaveId, "设备 {} 没有配置 slaveId", deviceId);
// 3. 执行 Modbus 读取
IotModbusTcpMasterUtils.read(connection, slaveId, point)
IotModbusTcpClientUtils.read(connection, slaveId, point)
.onSuccess(rawValue -> upstreamHandler.handleReadResult(config, point, rawValue))
.onFailure(e -> log.error("[pollPoint][读取点位失败, deviceId={}, identifier={}]",
deviceId, point.getIdentifier(), e));

View File

@@ -1,6 +1,6 @@
/**
* Modbus TCP Master主站协议网关主动连接并轮询 Modbus 从站设备
* Modbus TCP Client主站协议网关主动连接并轮询 Modbus 从站设备
* <p>
* 基于 j2mod 实现支持 FC01-04 FC05/06/15/16 定时轮询 + 下发属性设置
*/
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
@@ -6,12 +6,12 @@ import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* IoT Modbus TCP Slave 协议配置
* IoT Modbus TCP Server 协议配置
*
* @author 芋道源码
*/
@Data
public class IotModbusTcpSlaveConfig {
public class IotModbusTcpServerConfig {
/**
* 配置刷新间隔

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
@@ -11,16 +11,16 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties.ProtocolProperties;
import cn.iocoder.yudao.module.iot.gateway.protocol.IotProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrameDecoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.handler.downstream.IotModbusTcpSlaveDownstreamHandler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.handler.downstream.IotModbusTcpSlaveDownstreamSubscriber;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.handler.upstream.IotModbusTcpSlaveUpstreamHandler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConnectionManager.ConnectionInfo;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlavePendingRequestManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlavePollScheduler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrameDecoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.handler.downstream.IotModbusTcpServerDownstreamHandler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.handler.downstream.IotModbusTcpServerDownstreamSubscriber;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.handler.upstream.IotModbusTcpServerUpstreamHandler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConnectionManager.ConnectionInfo;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerPendingRequestManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerPollScheduler;
import cn.iocoder.yudao.module.iot.gateway.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService;
import io.vertx.core.Vertx;
@@ -37,7 +37,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* IoT 网关 Modbus TCP Slave 协议
* IoT 网关 Modbus TCP Server 协议
* <p>
* 作为 TCP Server 接收设备主动连接
* 1. 设备通过自定义功能码FC 65发送认证请求
@@ -46,7 +46,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpSlaveProtocol implements IotProtocol {
public class IotModbusTcpServerProtocol implements IotProtocol {
/**
* 协议配置
@@ -84,25 +84,25 @@ public class IotModbusTcpSlaveProtocol implements IotProtocol {
/**
* 连接管理器
*/
private final IotModbusTcpSlaveConnectionManager connectionManager;
private final IotModbusTcpServerConnectionManager connectionManager;
/**
* 下行消息订阅者
*/
private IotModbusTcpSlaveDownstreamSubscriber downstreamSubscriber;
private IotModbusTcpServerDownstreamSubscriber downstreamSubscriber;
private final IotModbusFrameDecoder frameDecoder;
@SuppressWarnings("FieldCanBeLocal")
private final IotModbusFrameEncoder frameEncoder;
private final IotModbusTcpSlaveConfigCacheService configCacheService;
private final IotModbusTcpSlavePendingRequestManager pendingRequestManager;
private final IotModbusTcpSlaveUpstreamHandler upstreamHandler;
private final IotModbusTcpSlavePollScheduler pollScheduler;
private final IotModbusTcpServerConfigCacheService configCacheService;
private final IotModbusTcpServerPendingRequestManager pendingRequestManager;
private final IotModbusTcpServerUpstreamHandler upstreamHandler;
private final IotModbusTcpServerPollScheduler pollScheduler;
private final IotDeviceMessageService messageService;
public IotModbusTcpSlaveProtocol(ProtocolProperties properties) {
IotModbusTcpSlaveConfig slaveConfig = properties.getModbusTcpSlave();
Assert.notNull(slaveConfig, "Modbus TCP Slave 协议配置modbusTcpSlave不能为空");
public IotModbusTcpServerProtocol(ProtocolProperties properties) {
IotModbusTcpServerConfig slaveConfig = properties.getModbusTcpServer();
Assert.notNull(slaveConfig, "Modbus TCP Server 协议配置modbusTcpServer)不能为空");
this.properties = properties;
this.serverId = IotDeviceMessageUtils.generateServerId(properties.getPort());
@@ -111,9 +111,9 @@ public class IotModbusTcpSlaveProtocol implements IotProtocol {
// 初始化 Manager
IotDeviceCommonApi deviceApi = SpringUtil.getBean(IotDeviceCommonApi.class);
this.connectionManager = new IotModbusTcpSlaveConnectionManager();
this.configCacheService = new IotModbusTcpSlaveConfigCacheService(deviceApi);
this.pendingRequestManager = new IotModbusTcpSlavePendingRequestManager();
this.connectionManager = new IotModbusTcpServerConnectionManager();
this.configCacheService = new IotModbusTcpServerConfigCacheService(deviceApi);
this.pendingRequestManager = new IotModbusTcpServerPendingRequestManager();
// 初始化帧编解码器
this.frameDecoder = new IotModbusFrameDecoder(slaveConfig.getCustomFunctionCode());
@@ -122,14 +122,14 @@ public class IotModbusTcpSlaveProtocol implements IotProtocol {
// 初始化共享事务 ID 自增器PollScheduler DownstreamHandler 共用避免 transactionId 冲突
AtomicInteger transactionIdCounter = new AtomicInteger(0);
// 初始化轮询调度器
this.pollScheduler = new IotModbusTcpSlavePollScheduler(
this.pollScheduler = new IotModbusTcpServerPollScheduler(
vertx, connectionManager, frameEncoder, pendingRequestManager,
slaveConfig.getRequestTimeout(), transactionIdCounter, configCacheService);
// 初始化 Handler
this.messageService = SpringUtil.getBean(IotDeviceMessageService.class);
IotDeviceService deviceService = SpringUtil.getBean(IotDeviceService.class);
this.upstreamHandler = new IotModbusTcpSlaveUpstreamHandler(
this.upstreamHandler = new IotModbusTcpServerUpstreamHandler(
deviceApi, this.messageService, frameEncoder,
connectionManager, configCacheService, pendingRequestManager,
pollScheduler, deviceService, serverId);
@@ -142,19 +142,19 @@ public class IotModbusTcpSlaveProtocol implements IotProtocol {
@Override
public IotProtocolTypeEnum getType() {
return IotProtocolTypeEnum.MODBUS_TCP_SLAVE;
return IotProtocolTypeEnum.MODBUS_TCP_SERVER;
}
@Override
public void start() {
if (running) {
log.warn("[start][IoT Modbus TCP Slave 协议 {} 已经在运行中]", getId());
log.warn("[start][IoT Modbus TCP Server 协议 {} 已经在运行中]", getId());
return;
}
try {
// 1. 启动配置刷新定时器
IotModbusTcpSlaveConfig slaveConfig = properties.getModbusTcpSlave();
IotModbusTcpServerConfig slaveConfig = properties.getModbusTcpServer();
configRefreshTimerId = vertx.setPeriodic(
TimeUnit.SECONDS.toMillis(slaveConfig.getConfigRefreshInterval()),
id -> refreshConfig());
@@ -167,18 +167,18 @@ public class IotModbusTcpSlaveProtocol implements IotProtocol {
slaveConfig.getRequestCleanupInterval(),
id -> pendingRequestManager.cleanupExpired());
running = true;
log.info("[start][IoT Modbus TCP Slave 协议 {} 启动成功, serverId={}, port={}]",
log.info("[start][IoT Modbus TCP Server 协议 {} 启动成功, serverId={}, port={}]",
getId(), serverId, properties.getPort());
// 3. 启动下行消息订阅
IotMessageBus messageBus = SpringUtil.getBean(IotMessageBus.class);
IotModbusTcpSlaveDownstreamHandler downstreamHandler = new IotModbusTcpSlaveDownstreamHandler(
IotModbusTcpServerDownstreamHandler downstreamHandler = new IotModbusTcpServerDownstreamHandler(
connectionManager, configCacheService, frameEncoder, this.pollScheduler.getTransactionIdCounter());
this.downstreamSubscriber = new IotModbusTcpSlaveDownstreamSubscriber(
this.downstreamSubscriber = new IotModbusTcpServerDownstreamSubscriber(
this, downstreamHandler, messageBus);
downstreamSubscriber.start();
} catch (Exception e) {
log.error("[start][IoT Modbus TCP Slave 协议 {} 启动失败]", getId(), e);
log.error("[start][IoT Modbus TCP Server 协议 {} 启动失败]", getId(), e);
stop0();
throw e;
}
@@ -238,7 +238,7 @@ public class IotModbusTcpSlaveProtocol implements IotProtocol {
}
}
running = false;
log.info("[stop][IoT Modbus TCP Slave 协议 {} 已停止]", getId());
log.info("[stop][IoT Modbus TCP Server 协议 {} 已停止]", getId());
}
/**

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusFrameFormatEnum;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusFrameFormatEnum;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusFrameFormatEnum;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.handler.downstream;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.handler.downstream;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
@@ -8,17 +8,17 @@ import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusFrameFormatEnum;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConnectionManager.ConnectionInfo;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConnectionManager.ConnectionInfo;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
* IoT Modbus TCP Slave 下行消息处理器
* IoT Modbus TCP Server 下行消息处理器
* <p>
* 负责
* 1. 处理下行消息如属性设置 thing.service.property.set
@@ -27,10 +27,10 @@ import java.util.concurrent.atomic.AtomicInteger;
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpSlaveDownstreamHandler {
public class IotModbusTcpServerDownstreamHandler {
private final IotModbusTcpSlaveConnectionManager connectionManager;
private final IotModbusTcpSlaveConfigCacheService configCacheService;
private final IotModbusTcpServerConnectionManager connectionManager;
private final IotModbusTcpServerConfigCacheService configCacheService;
private final IotModbusFrameEncoder frameEncoder;
/**
@@ -38,8 +38,8 @@ public class IotModbusTcpSlaveDownstreamHandler {
*/
private final AtomicInteger transactionIdCounter;
public IotModbusTcpSlaveDownstreamHandler(IotModbusTcpSlaveConnectionManager connectionManager,
IotModbusTcpSlaveConfigCacheService configCacheService,
public IotModbusTcpServerDownstreamHandler(IotModbusTcpServerConnectionManager connectionManager,
IotModbusTcpServerConfigCacheService configCacheService,
IotModbusFrameEncoder frameEncoder,
AtomicInteger transactionIdCounter) {
this.connectionManager = connectionManager;
@@ -54,6 +54,9 @@ public class IotModbusTcpSlaveDownstreamHandler {
@SuppressWarnings({"unchecked", "DuplicatedCode"})
public void handle(IotDeviceMessage message) {
// 1.1 检查是否是属性设置消息
if (ObjUtil.equals(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(), message.getMethod())) {
return;
}
if (ObjUtil.notEqual(IotDeviceMessageMethodEnum.PROPERTY_SET.getMethod(), message.getMethod())) {
log.debug("[handle][忽略非属性设置消息: {}]", message.getMethod());
return;

View File

@@ -1,23 +1,23 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.handler.downstream;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.handler.downstream;
import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.gateway.protocol.AbstractIotProtocolDownstreamSubscriber;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.IotModbusTcpSlaveProtocol;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.IotModbusTcpServerProtocol;
import lombok.extern.slf4j.Slf4j;
/**
* IoT Modbus TCP Slave 下行消息订阅器订阅消息总线的下行消息并转发给处理器
* IoT Modbus TCP Server 下行消息订阅器订阅消息总线的下行消息并转发给处理器
*
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpSlaveDownstreamSubscriber extends AbstractIotProtocolDownstreamSubscriber {
public class IotModbusTcpServerDownstreamSubscriber extends AbstractIotProtocolDownstreamSubscriber {
private final IotModbusTcpSlaveDownstreamHandler downstreamHandler;
private final IotModbusTcpServerDownstreamHandler downstreamHandler;
public IotModbusTcpSlaveDownstreamSubscriber(IotModbusTcpSlaveProtocol protocol,
IotModbusTcpSlaveDownstreamHandler downstreamHandler,
public IotModbusTcpServerDownstreamSubscriber(IotModbusTcpServerProtocol protocol,
IotModbusTcpServerDownstreamHandler downstreamHandler,
IotMessageBus messageBus) {
super(protocol, messageBus);
this.downstreamHandler = downstreamHandler;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.handler.upstream;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.handler.upstream;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
@@ -20,14 +20,14 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.core.topic.IotDeviceIdentity;
import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrame;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConnectionManager.ConnectionInfo;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlavePendingRequestManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlavePendingRequestManager.PendingRequest;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlavePollScheduler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrame;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConfigCacheService;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConnectionManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConnectionManager.ConnectionInfo;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerPendingRequestManager;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerPendingRequestManager.PendingRequest;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerPollScheduler;
import cn.iocoder.yudao.module.iot.gateway.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService;
import io.vertx.core.net.NetSocket;
@@ -40,7 +40,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
/**
* IoT Modbus TCP Slave 上行数据处理器
* IoT Modbus TCP Server 上行数据处理器
* <p>
* 处理
* 1. 自定义 FC 认证
@@ -49,28 +49,28 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpSlaveUpstreamHandler {
public class IotModbusTcpServerUpstreamHandler {
private static final String METHOD_AUTH = "auth";
private final IotDeviceCommonApi deviceApi;
private final IotDeviceMessageService messageService;
private final IotModbusFrameEncoder frameEncoder;
private final IotModbusTcpSlaveConnectionManager connectionManager;
private final IotModbusTcpSlaveConfigCacheService configCacheService;
private final IotModbusTcpSlavePendingRequestManager pendingRequestManager;
private final IotModbusTcpSlavePollScheduler pollScheduler;
private final IotModbusTcpServerConnectionManager connectionManager;
private final IotModbusTcpServerConfigCacheService configCacheService;
private final IotModbusTcpServerPendingRequestManager pendingRequestManager;
private final IotModbusTcpServerPollScheduler pollScheduler;
private final IotDeviceService deviceService;
private final String serverId;
public IotModbusTcpSlaveUpstreamHandler(IotDeviceCommonApi deviceApi,
public IotModbusTcpServerUpstreamHandler(IotDeviceCommonApi deviceApi,
IotDeviceMessageService messageService,
IotModbusFrameEncoder frameEncoder,
IotModbusTcpSlaveConnectionManager connectionManager,
IotModbusTcpSlaveConfigCacheService configCacheService,
IotModbusTcpSlavePendingRequestManager pendingRequestManager,
IotModbusTcpSlavePollScheduler pollScheduler,
IotModbusTcpServerConnectionManager connectionManager,
IotModbusTcpServerConfigCacheService configCacheService,
IotModbusTcpServerPendingRequestManager pendingRequestManager,
IotModbusTcpServerPollScheduler pollScheduler,
IotDeviceService deviceService,
String serverId) {
this.deviceApi = deviceApi;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
@@ -18,13 +18,13 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* IoT Modbus TCP Slave 配置缓存认证时按需加载断连时清理定时刷新已连接设备
* IoT Modbus TCP Server 配置缓存认证时按需加载断连时清理定时刷新已连接设备
*
* @author 芋道源码
*/
@RequiredArgsConstructor
@Slf4j
public class IotModbusTcpSlaveConfigCacheService {
public class IotModbusTcpServerConfigCacheService {
private final IotDeviceCommonApi deviceApi;
@@ -45,7 +45,7 @@ public class IotModbusTcpSlaveConfigCacheService {
IotModbusDeviceConfigListReqDTO reqDTO = new IotModbusDeviceConfigListReqDTO()
.setStatus(CommonStatusEnum.ENABLE.getStatus())
.setMode(IotModbusModeEnum.POLLING.getMode())
.setProtocolType(IotProtocolTypeEnum.MODBUS_TCP_SLAVE.getType())
.setProtocolType(IotProtocolTypeEnum.MODBUS_TCP_SERVER.getType())
.setDeviceIds(Collections.singleton(deviceId));
CommonResult<List<IotModbusDeviceConfigRespDTO>> result = deviceApi.getModbusDeviceConfigList(reqDTO);
result.checkError();
@@ -81,7 +81,7 @@ public class IotModbusTcpSlaveConfigCacheService {
CommonResult<List<IotModbusDeviceConfigRespDTO>> result = deviceApi.getModbusDeviceConfigList(
new IotModbusDeviceConfigListReqDTO().setStatus(CommonStatusEnum.ENABLE.getStatus())
.setMode(IotModbusModeEnum.POLLING.getMode())
.setProtocolType(IotProtocolTypeEnum.MODBUS_TCP_SLAVE.getType())
.setProtocolType(IotProtocolTypeEnum.MODBUS_TCP_SERVER.getType())
.setDeviceIds(connectedDeviceIds));
List<IotModbusDeviceConfigRespDTO> modbusConfigs = result.getCheckedData();

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusFrameFormatEnum;
import io.vertx.core.Future;
@@ -15,14 +15,14 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* IoT Modbus TCP Slave 连接管理器
* IoT Modbus TCP Server 连接管理器
* <p>
* 管理设备 TCP 连接socket 设备双向映射
*
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpSlaveConnectionManager {
public class IotModbusTcpServerConnectionManager {
/**
* socket 连接信息

View File

@@ -1,9 +1,9 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusFrameFormatEnum;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrame;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrame;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -15,7 +15,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
/**
* IoT Modbus TCP Slave 待响应请求管理器
* IoT Modbus TCP Server 待响应请求管理器
* <p>
* 管理轮询下发的请求用于匹配设备响应
* - TCP 模式 transactionId 精确匹配
@@ -24,7 +24,7 @@ import java.util.concurrent.ConcurrentLinkedDeque;
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpSlavePendingRequestManager {
public class IotModbusTcpServerPendingRequestManager {
/**
* deviceId 有序队列

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
@@ -7,9 +7,9 @@ import cn.iocoder.yudao.module.iot.core.biz.dto.IotModbusPointRespDTO;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusFrameFormatEnum;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.manager.AbstractIotModbusPollScheduler;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlaveConnectionManager.ConnectionInfo;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.manager.IotModbusTcpSlavePendingRequestManager.PendingRequest;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerConnectionManager.ConnectionInfo;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.manager.IotModbusTcpServerPendingRequestManager.PendingRequest;
import io.vertx.core.Vertx;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@@ -17,17 +17,17 @@ import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.atomic.AtomicInteger;
/**
* IoT Modbus TCP Slave 轮询调度器编码读请求帧通过 TCP 连接发送到设备注册 PendingRequest 等待响应
* IoT Modbus TCP Server 轮询调度器编码读请求帧通过 TCP 连接发送到设备注册 PendingRequest 等待响应
*
* @author 芋道源码
*/
@Slf4j
public class IotModbusTcpSlavePollScheduler extends AbstractIotModbusPollScheduler {
public class IotModbusTcpServerPollScheduler extends AbstractIotModbusPollScheduler {
private final IotModbusTcpSlaveConnectionManager connectionManager;
private final IotModbusTcpServerConnectionManager connectionManager;
private final IotModbusFrameEncoder frameEncoder;
private final IotModbusTcpSlavePendingRequestManager pendingRequestManager;
private final IotModbusTcpSlaveConfigCacheService configCacheService;
private final IotModbusTcpServerPendingRequestManager pendingRequestManager;
private final IotModbusTcpServerConfigCacheService configCacheService;
private final int requestTimeout;
/**
* TCP 事务 ID 自增器 DownstreamHandler 共享
@@ -35,13 +35,13 @@ public class IotModbusTcpSlavePollScheduler extends AbstractIotModbusPollSchedul
@Getter
private final AtomicInteger transactionIdCounter;
public IotModbusTcpSlavePollScheduler(Vertx vertx,
IotModbusTcpSlaveConnectionManager connectionManager,
public IotModbusTcpServerPollScheduler(Vertx vertx,
IotModbusTcpServerConnectionManager connectionManager,
IotModbusFrameEncoder frameEncoder,
IotModbusTcpSlavePendingRequestManager pendingRequestManager,
IotModbusTcpServerPendingRequestManager pendingRequestManager,
int requestTimeout,
AtomicInteger transactionIdCounter,
IotModbusTcpSlaveConfigCacheService configCacheService) {
IotModbusTcpServerConfigCacheService configCacheService) {
super(vertx);
this.connectionManager = connectionManager;
this.frameEncoder = frameEncoder;

View File

@@ -1,6 +1,6 @@
/**
* Modbus TCP Slave从站协议设备主动连接网关自定义 FC65 认证后由网关云端轮询
* Modbus TCP Server从站协议设备主动连接网关自定义 FC65 认证后由网关云端轮询
* <p>
* TCP Server 模式支持 MODBUS_TCP / MODBUS_RTU 帧格式自动检测
*/
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver;

View File

@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.tcp.handler.downstream;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.gateway.protocol.tcp.codec.IotTcpFrameCodec;
import cn.iocoder.yudao.module.iot.gateway.protocol.tcp.manager.IotTcpConnectionManager;
@@ -33,9 +35,17 @@ public class IotTcpDownstreamHandler {
*/
public void handle(IotDeviceMessage message) {
try {
// 1.1 检查是否是属性设置消息
if (ObjUtil.equals(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(), message.getMethod())) {
return;
}
if (ObjUtil.notEqual(IotDeviceMessageMethodEnum.PROPERTY_SET.getMethod(), message.getMethod())) {
log.warn("[handle][忽略非属性设置消息: {}]", message.getMethod());
return;
}
log.info("[handle][处理下行消息,设备 ID: {},方法: {},消息 ID: {}]",
message.getDeviceId(), message.getMethod(), message.getId());
// 1. 检查设备连接
// 1.2 检查设备连接
IotTcpConnectionManager.ConnectionInfo connectionInfo = connectionManager.getConnectionInfoByDeviceId(
message.getDeviceId());
if (connectionInfo == null) {

View File

@@ -164,22 +164,22 @@ yudao:
trust-store-path: "classpath:certs/trust.jks" # 信任的 CA 证书库路径
trust-store-password: "your-truststore-password" # 信任的 CA 证书库密码
# ====================================
# 针对引入的 Modbus TCP Master 组件的配置
# 针对引入的 Modbus TCP Client 组件的配置
# ====================================
- id: modbus-tcp-master-1
- id: modbus-tcp-client-1
enabled: false
protocol: modbus_tcp_master
protocol: modbus_tcp_client
port: 502
modbus-tcp-master:
modbus-tcp-client:
config-refresh-interval: 30 # 配置刷新间隔(秒)
# ====================================
# 针对引入的 Modbus TCP Slave 组件的配置
# 针对引入的 Modbus TCP Server 组件的配置
# ====================================
- id: modbus-tcp-slave-1
- id: modbus-tcp-server-1
enabled: false
protocol: modbus_tcp_slave
protocol: modbus_tcp_server
port: 503
modbus-tcp-slave:
modbus-tcp-server:
config-refresh-interval: 30 # 配置刷新间隔(秒)
custom-function-code: 65 # 自定义功能码(用于认证等扩展交互)
request-timeout: 5000 # Pending Request 超时时间(毫秒)

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpmaster;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpclient;
import com.ghgande.j2mod.modbus.procimg.*;
import com.ghgande.j2mod.modbus.slave.ModbusSlave;
@@ -10,13 +10,13 @@ import org.junit.jupiter.api.Test;
/**
* Modbus TCP 从站模拟器手动测试
*
* <p>测试场景模拟一个标准 Modbus TCP 从站设备 Modbus TCP Master 网关连接和读写数据
* <p>测试场景模拟一个标准 Modbus TCP 从站设备 Modbus TCP Client 网关连接和读写数据
*
* <p>使用步骤
* <ol>
* <li>运行 {@link #testStartSlaveSimulator()} 启动模拟从站默认端口 5020从站地址 1</li>
* <li>启动 yudao-module-iot-gateway 服务需开启 modbus-tcp-master 协议</li>
* <li>确保数据库有对应的 Modbus Master 设备配置ip=127.0.0.1, port=5020, slaveId=1</li>
* <li>启动 yudao-module-iot-gateway 服务需开启 modbus-tcp-client 协议</li>
* <li>确保数据库有对应的 Modbus Client 设备配置ip=127.0.0.1, port=5020, slaveId=1</li>
* <li>网关会自动连接模拟从站并开始轮询读取寄存器数据</li>
* <li>模拟器每 5 秒自动更新输入寄存器和保持寄存器的值模拟传感器数据变化</li>
* </ol>
@@ -33,7 +33,7 @@ import org.junit.jupiter.api.Test;
*/
@Slf4j
@Disabled
public class IoTModbusTcpMasterIntegrationTest {
public class IoTModbusTcpClientIntegrationTest {
private static final int PORT = 5020;
private static final int SLAVE_ID = 1;

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver;
import cn.hutool.core.util.HexUtil;
import cn.hutool.json.JSONObject;
@@ -7,9 +7,9 @@ import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusFrameFormatEnum;
import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.common.utils.IotModbusCommonUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrame;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrameDecoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrame;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrameDecoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrameEncoder;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
@@ -28,13 +28,13 @@ import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* IoT Modbus TCP Slave 协议集成测试 MODBUS_RTU 帧格式手动测试
* IoT Modbus TCP Server 协议集成测试 MODBUS_RTU 帧格式手动测试
*
* <p>测试场景设备TCP Client连接到网关TCP Server使用 MODBUS_RTUCRC16帧格式通信
*
* <p>使用步骤
* <ol>
* <li>启动 yudao-module-iot-gateway 服务需开启 modbus-tcp-slave 协议默认端口 503</li>
* <li>启动 yudao-module-iot-gateway 服务需开启 modbus-tcp-server 协议默认端口 503</li>
* <li>确保数据库有对应的 Modbus 设备配置mode=1, frameFormat=modbus_rtu</li>
* <li>运行以下测试方法
* <ul>
@@ -49,7 +49,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
*/
@Slf4j
@Disabled
public class IotModbusTcpSlaveRtuIntegrationTest {
public class IotModbusTcpServerRtuIntegrationTest {
private static final String SERVER_HOST = "127.0.0.1";
private static final int SERVER_PORT = 503;
@@ -68,8 +68,8 @@ public class IotModbusTcpSlaveRtuIntegrationTest {
// ===================== 设备信息根据实际情况修改 iot_device 表查询 =====================
private static final String PRODUCT_KEY = "modbus_tcp_slave_product_demo";
private static final String DEVICE_NAME = "modbus_tcp_slave_device_demo_rtu";
private static final String PRODUCT_KEY = "modbus_tcp_server_product_demo";
private static final String DEVICE_NAME = "modbus_tcp_server_device_demo_rtu";
private static final String DEVICE_SECRET = "af01c55eb8e3424bb23fc6c783936b2e";
@BeforeAll

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave;
package cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver;
import cn.hutool.core.util.HexUtil;
import cn.hutool.json.JSONObject;
@@ -6,9 +6,9 @@ import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO;
import cn.iocoder.yudao.module.iot.core.enums.modbus.IotModbusFrameFormatEnum;
import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrame;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrameDecoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpslave.codec.IotModbusFrameEncoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrame;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrameDecoder;
import cn.iocoder.yudao.module.iot.gateway.protocol.modbus.tcpserver.codec.IotModbusFrameEncoder;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
@@ -29,13 +29,13 @@ import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* IoT Modbus TCP Slave 协议集成测试 MODBUS_TCP 帧格式手动测试
* IoT Modbus TCP Server 协议集成测试 MODBUS_TCP 帧格式手动测试
*
* <p>测试场景设备TCP Client连接到网关TCP Server使用 MODBUS_TCPMBAP 帧格式通信
*
* <p>使用步骤
* <ol>
* <li>启动 yudao-module-iot-gateway 服务需开启 modbus-tcp-slave 协议默认端口 503</li>
* <li>启动 yudao-module-iot-gateway 服务需开启 modbus-tcp-server 协议默认端口 503</li>
* <li>确保数据库有对应的 Modbus 设备配置mode=1, frameFormat=modbus_tcp</li>
* <li>运行以下测试方法
* <ul>
@@ -50,7 +50,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
*/
@Slf4j
@Disabled
public class IotModbusTcpSlaveTcpIntegrationTest {
public class IotModbusTcpServerTcpIntegrationTest {
private static final String SERVER_HOST = "127.0.0.1";
private static final int SERVER_PORT = 503;
@@ -69,8 +69,8 @@ public class IotModbusTcpSlaveTcpIntegrationTest {
// ===================== 设备信息根据实际情况修改 iot_device 表查询 =====================
private static final String PRODUCT_KEY = "modbus_tcp_slave_product_demo";
private static final String DEVICE_NAME = "modbus_tcp_slave_device_demo_tcp";
private static final String PRODUCT_KEY = "modbus_tcp_server_product_demo";
private static final String DEVICE_NAME = "modbus_tcp_server_device_demo_tcp";
private static final String DEVICE_SECRET = "8e4adeb3d25342ab88643421d3fba3f6";
@BeforeAll