fix: s7地址解析

This commit is contained in:
2026-03-11 15:05:04 +08:00
parent ffb0947e32
commit 07e3abdf73
9 changed files with 286 additions and 10 deletions

View File

@@ -0,0 +1,122 @@
package org.nl.iot.core.driver;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.exception.CommonException;
import org.nl.iot.core.driver.protocol.modbustcp.ModBusProtocolDriverImpl;
import org.nl.iot.core.driver.protocol.opcda.OpcDaProtocolDriverImpl;
import org.nl.iot.core.driver.protocol.opcua.OpcUaProtocolDriverImpl;
import org.nl.iot.core.driver.protocol.plcs7.PlcS7ProtocolDriverImpl;
import org.nl.iot.core.driver.service.DriverCustomService;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 自定义通信协议驱动工厂
* 通过协议编码获取对应的协议驱动单例对象
*
* <p>重要说明:
* <ul>
* <li>工厂返回的驱动实例是 Spring 容器中的 Bean 对象(单例)</li>
* <li>所有驱动类都标注了 @Service 注解,由 Spring 管理生命周期</li>
* <li>工厂通过构造函数注入获取这些 Bean并直接返回引用</li>
* <li>多次调用 getDriver() 返回的是同一个 Spring Bean 实例</li>
* </ul>
*
* @author: lyd
* @date: 2026/3/2
*/
@Slf4j
@Component
public class DriverCustomFactory {
private final ModBusProtocolDriverImpl modBusProtocolDriver;
private final OpcUaProtocolDriverImpl opcUaProtocolDriver;
private final PlcS7ProtocolDriverImpl plcS7ProtocolDriver;
private final OpcDaProtocolDriverImpl opcDaProtocolDriver;
/**
* 协议驱动缓存Map
* key: 协议编码MODBUS、OPCUA、PLCS7、OPCDA
* value: 对应的协议驱动实例
*/
private final Map<String, DriverCustomService> driverMap = new ConcurrentHashMap<>();
/**
* 构造函数注入所有协议驱动实例
*/
public DriverCustomFactory(ModBusProtocolDriverImpl modBusProtocolDriver,
OpcUaProtocolDriverImpl opcUaProtocolDriver,
PlcS7ProtocolDriverImpl plcS7ProtocolDriver,
OpcDaProtocolDriverImpl opcDaProtocolDriver) {
this.modBusProtocolDriver = modBusProtocolDriver;
this.opcUaProtocolDriver = opcUaProtocolDriver;
this.plcS7ProtocolDriver = plcS7ProtocolDriver;
this.opcDaProtocolDriver = opcDaProtocolDriver;
// 初始化协议驱动映射
initDriverMap();
}
/**
* 初始化协议驱动映射关系
*/
private void initDriverMap() {
driverMap.put("MODBUS", modBusProtocolDriver);
driverMap.put("MODBUS-TCP", modBusProtocolDriver);
driverMap.put("OPCUA", opcUaProtocolDriver);
driverMap.put("OPC-UA", opcUaProtocolDriver);
driverMap.put("PLCS7", plcS7ProtocolDriver);
driverMap.put("PLC-S7", plcS7ProtocolDriver);
driverMap.put("OPCDA", opcDaProtocolDriver);
driverMap.put("OPC-DA", opcDaProtocolDriver);
log.info("协议驱动工厂初始化完成,支持的协议: {}", driverMap.keySet());
}
/**
* 根据协议编码获取对应的协议驱动单例对象
*
* <p>返回的驱动实例是 Spring 容器中的 Bean 对象(单例):
* <ul>
* <li>工厂不会创建新对象,只是返回已注入的 Spring Bean 引用</li>
* <li>多次调用返回的是同一个对象(使用 == 比较为 true</li>
* <li>与直接 @Autowired 注入的驱动 Bean 是同一个实例</li>
* </ul>
*
* @param protocolCode 协议编码MODBUS、OPCUA、PLCS7、OPCDA不区分大小写
* @return 对应的协议驱动实例Spring Bean 单例对象)
* @throws CommonException 如果协议编码不支持,抛出异常
*/
public DriverCustomService getDriver(String protocolCode) {
if (protocolCode == null || protocolCode.trim().isEmpty()) {
throw new CommonException("协议编码不能为空");
}
// 转换为大写进行匹配
String upperProtocolCode = protocolCode.trim().toUpperCase();
DriverCustomService driver = driverMap.get(upperProtocolCode);
if (driver == null) {
log.error("不支持的协议编码: {}", protocolCode);
throw new CommonException("不支持的协议编码: " + protocolCode + ",支持的协议: " + driverMap.keySet());
}
log.debug("获取协议驱动: {} -> {}", protocolCode, driver.getClass().getSimpleName());
return driver;
}
/**
* 检查是否支持指定的协议编码
*
* @param protocolCode 协议编码
* @return 如果支持返回true否则返回false
*/
public boolean isSupported(String protocolCode) {
if (protocolCode == null || protocolCode.trim().isEmpty()) {
return false;
}
return driverMap.containsKey(protocolCode.trim().toUpperCase());
}
}

View File

@@ -0,0 +1,30 @@
package org.nl.iot.core.driver.bo;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.nl.iot.core.driver.enums.MetadataOperateTypeEnum;
import java.io.Serial;
import java.io.Serializable;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class MetadataEventDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 连接id
*/
private String connectId;
/**
* 元数据操作类型, 新增, 删除, 修改
*/
private MetadataOperateTypeEnum operateType;
}

View File

@@ -0,0 +1,80 @@
package org.nl.iot.core.driver.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Optional;
@Getter
@AllArgsConstructor
public enum MetadataOperateTypeEnum {
/**
* 新增
*/
ADD((byte) 0, "add", "新增"),
/**
* 删除
*/
DELETE((byte) 1, "delete", "删除"),
/**
* 更新
*/
UPDATE((byte) 2, "update", "更新"),
;
/**
* 索引
*/
@EnumValue
private final Byte index;
/**
* 编码
*/
private final String code;
/**
* 内容
*/
private final String remark;
/**
* 根据枚举索引获取枚举
*
* @param index 索引
* @return {@link MetadataOperateTypeEnum}
*/
public static MetadataOperateTypeEnum ofIndex(Byte index) {
Optional<MetadataOperateTypeEnum> any = Arrays.stream(MetadataOperateTypeEnum.values()).filter(type -> type.getIndex().equals(index)).findFirst();
return any.orElse(null);
}
/**
* 根据枚举编码获取枚举
*
* @param code 编码
* @return {@link MetadataOperateTypeEnum}
*/
public static MetadataOperateTypeEnum ofCode(String code) {
Optional<MetadataOperateTypeEnum> any = Arrays.stream(MetadataOperateTypeEnum.values()).filter(type -> type.getCode().equals(code)).findFirst();
return any.orElse(null);
}
/**
* 根据枚举内容获取枚举
*
* @param name 枚举内容
* @return {@link MetadataOperateTypeEnum}
*/
public static MetadataOperateTypeEnum ofName(String name) {
try {
return valueOf(name);
} catch (IllegalArgumentException e) {
return null;
}
}
}

View File

@@ -5,8 +5,10 @@ import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.nl.common.exception.CommonException; import org.nl.common.exception.CommonException;
import org.nl.iot.core.driver.bo.AttributeBO; import org.nl.iot.core.driver.bo.AttributeBO;
import org.nl.iot.core.driver.bo.MetadataEventDTO;
import org.nl.iot.core.driver.entity.RValue; import org.nl.iot.core.driver.entity.RValue;
import org.nl.iot.core.driver.entity.WValue; import org.nl.iot.core.driver.entity.WValue;
import org.nl.iot.core.driver.enums.MetadataOperateTypeEnum;
import org.nl.iot.core.driver.protocol.modbustcp.com.serotonin.modbus4j.ModbusFactory; import org.nl.iot.core.driver.protocol.modbustcp.com.serotonin.modbus4j.ModbusFactory;
import org.nl.iot.core.driver.protocol.modbustcp.com.serotonin.modbus4j.ModbusMaster; import org.nl.iot.core.driver.protocol.modbustcp.com.serotonin.modbus4j.ModbusMaster;
import org.nl.iot.core.driver.protocol.modbustcp.com.serotonin.modbus4j.exception.ModbusInitException; import org.nl.iot.core.driver.protocol.modbustcp.com.serotonin.modbus4j.exception.ModbusInitException;
@@ -42,7 +44,7 @@ public class ModBusProtocolDriverImpl implements DriverCustomService {
@Override @Override
@PostConstruct @PostConstruct
public void initial() { public void initial() {
connectMap = new ConcurrentHashMap<>(256); connectMap = new ConcurrentHashMap<>(16);
} }
@Override @Override
@@ -50,6 +52,17 @@ public class ModBusProtocolDriverImpl implements DriverCustomService {
} }
@Override
public void event(MetadataEventDTO metadataEvent) {
MetadataOperateTypeEnum operateType = metadataEvent.getOperateType();
log.info("Device metadata event: connectId: {}, operate: {}", metadataEvent.getConnectId(), operateType);
// When the device is updated or deleted, remove the corresponding connection handle
if (MetadataOperateTypeEnum.DELETE.equals(operateType) || MetadataOperateTypeEnum.UPDATE.equals(operateType)) {
connectMap.remove(metadataEvent.getConnectId());
}
}
@Override @Override
public RValue read(IotConnect connect, IotConfig config) { public RValue read(IotConnect connect, IotConfig config) {
return new RValue(config, connect, readValue(getConnector(connect), connect, config)); return new RValue(config, connect, readValue(getConnector(connect), connect, config));

View File

@@ -8,8 +8,10 @@ import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.core.JIVariant; import org.jinterop.dcom.core.JIVariant;
import org.nl.common.exception.CommonException; import org.nl.common.exception.CommonException;
import org.nl.iot.core.driver.bo.AttributeBO; import org.nl.iot.core.driver.bo.AttributeBO;
import org.nl.iot.core.driver.bo.MetadataEventDTO;
import org.nl.iot.core.driver.entity.RValue; import org.nl.iot.core.driver.entity.RValue;
import org.nl.iot.core.driver.entity.WValue; import org.nl.iot.core.driver.entity.WValue;
import org.nl.iot.core.driver.enums.MetadataOperateTypeEnum;
import org.nl.iot.core.driver.enums.PointTypeFlagEnum; import org.nl.iot.core.driver.enums.PointTypeFlagEnum;
import org.nl.iot.core.driver.protocol.opcda.org.openscada.opc.lib.common.AlreadyConnectedException; import org.nl.iot.core.driver.protocol.opcda.org.openscada.opc.lib.common.AlreadyConnectedException;
import org.nl.iot.core.driver.protocol.opcda.org.openscada.opc.lib.common.ConnectionInformation; import org.nl.iot.core.driver.protocol.opcda.org.openscada.opc.lib.common.ConnectionInformation;
@@ -52,6 +54,17 @@ public class OpcDaProtocolDriverImpl implements DriverCustomService {
} }
@Override
public void event(MetadataEventDTO metadataEvent) {
MetadataOperateTypeEnum operateType = metadataEvent.getOperateType();
log.info("Device metadata event: connectId: {}, operate: {}", metadataEvent.getConnectId(), operateType);
// When the device is updated or deleted, remove the corresponding connection handle
if (MetadataOperateTypeEnum.DELETE.equals(operateType) || MetadataOperateTypeEnum.UPDATE.equals(operateType)) {
connectMap.remove(metadataEvent.getConnectId());
}
}
@Override @Override
public RValue read(IotConnect connect, IotConfig config) { public RValue read(IotConnect connect, IotConfig config) {
return new RValue(config, connect, readValue(getConnector(connect), connect, config)); return new RValue(config, connect, readValue(getConnector(connect), connect, config));

View File

@@ -14,8 +14,10 @@ import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn; import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.nl.common.exception.CommonException; import org.nl.common.exception.CommonException;
import org.nl.iot.core.driver.bo.AttributeBO; import org.nl.iot.core.driver.bo.AttributeBO;
import org.nl.iot.core.driver.bo.MetadataEventDTO;
import org.nl.iot.core.driver.entity.RValue; import org.nl.iot.core.driver.entity.RValue;
import org.nl.iot.core.driver.entity.WValue; import org.nl.iot.core.driver.entity.WValue;
import org.nl.iot.core.driver.enums.MetadataOperateTypeEnum;
import org.nl.iot.core.driver.enums.PointTypeFlagEnum; import org.nl.iot.core.driver.enums.PointTypeFlagEnum;
import org.nl.iot.core.driver.service.DriverCustomService; import org.nl.iot.core.driver.service.DriverCustomService;
import org.nl.iot.modular.iot.entity.IotConfig; import org.nl.iot.modular.iot.entity.IotConfig;
@@ -49,7 +51,16 @@ public class OpcUaProtocolDriverImpl implements DriverCustomService {
} }
@Override
public void event(MetadataEventDTO metadataEvent) {
MetadataOperateTypeEnum operateType = metadataEvent.getOperateType();
log.info("Device metadata event: connectId: {}, operate: {}", metadataEvent.getConnectId(), operateType);
// When the device is updated or deleted, remove the corresponding connection handle
if (MetadataOperateTypeEnum.DELETE.equals(operateType) || MetadataOperateTypeEnum.UPDATE.equals(operateType)) {
connectMap.remove(metadataEvent.getConnectId());
}
}
@Override @Override
public RValue read(IotConnect connect, IotConfig config) { public RValue read(IotConnect connect, IotConfig config) {

View File

@@ -9,9 +9,11 @@ import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.nl.common.exception.CommonException; import org.nl.common.exception.CommonException;
import org.nl.iot.core.driver.bo.AttributeBO; import org.nl.iot.core.driver.bo.AttributeBO;
import org.nl.iot.core.driver.bo.MetadataEventDTO;
import org.nl.iot.core.driver.entity.RValue; import org.nl.iot.core.driver.entity.RValue;
import org.nl.iot.core.driver.entity.WValue; import org.nl.iot.core.driver.entity.WValue;
import org.nl.iot.core.driver.enums.AttributeTypeFlagEnum; import org.nl.iot.core.driver.enums.AttributeTypeFlagEnum;
import org.nl.iot.core.driver.enums.MetadataOperateTypeEnum;
import org.nl.iot.core.driver.protocol.plcs7.com.github.s7.PlcS7PointVariable; import org.nl.iot.core.driver.protocol.plcs7.com.github.s7.PlcS7PointVariable;
import org.nl.iot.core.driver.protocol.plcs7.com.github.s7.api.S7Connector; import org.nl.iot.core.driver.protocol.plcs7.com.github.s7.api.S7Connector;
import org.nl.iot.core.driver.protocol.plcs7.com.github.s7.api.S7Serializer; import org.nl.iot.core.driver.protocol.plcs7.com.github.s7.api.S7Serializer;
@@ -53,6 +55,17 @@ public class PlcS7ProtocolDriverImpl implements DriverCustomService {
} }
@Override
public void event(MetadataEventDTO metadataEvent) {
MetadataOperateTypeEnum operateType = metadataEvent.getOperateType();
log.info("Device metadata event: connectId: {}, operate: {}", metadataEvent.getConnectId(), operateType);
// When the device is updated or deleted, remove the corresponding connection handle
if (MetadataOperateTypeEnum.DELETE.equals(operateType) || MetadataOperateTypeEnum.UPDATE.equals(operateType)) {
connectMap.remove(metadataEvent.getConnectId());
}
}
@Override @Override
public RValue read(IotConnect connect, IotConfig config) { public RValue read(IotConnect connect, IotConfig config) {
/* /*

View File

@@ -1,9 +0,0 @@
package org.nl.iot.core.driver.service;
/**
* 自定义通信协议驱动工厂
* @author: lyd
* @date: 2026/3/2
*/
public class DriverCustomFactory {
}

View File

@@ -1,6 +1,7 @@
package org.nl.iot.core.driver.service; package org.nl.iot.core.driver.service;
import org.nl.iot.core.driver.bo.AttributeBO; import org.nl.iot.core.driver.bo.AttributeBO;
import org.nl.iot.core.driver.bo.MetadataEventDTO;
import org.nl.iot.core.driver.entity.RValue; import org.nl.iot.core.driver.entity.RValue;
import org.nl.iot.core.driver.entity.WValue; import org.nl.iot.core.driver.entity.WValue;
import org.nl.iot.modular.iot.entity.IotConfig; import org.nl.iot.modular.iot.entity.IotConfig;
@@ -28,6 +29,8 @@ public interface DriverCustomService {
*/ */
void schedule(); void schedule();
void event(MetadataEventDTO metadataEvent);
// todo驱动事件暂时不需要 // todo驱动事件暂时不需要
/** /**