fix:协议驱动完善+工厂类
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package org.nl.iot.core.driver;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.common.exception.CommonException;
|
||||
import org.nl.iot.core.driver.service.DriverCustomService;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 抽象驱动类
|
||||
* @Author: liyongde
|
||||
* @Date: 2026/3/19 16:06
|
||||
* @Modified By:
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractProtocolDriver<T> implements DriverCustomService {
|
||||
|
||||
protected Map<String, T> connectMap = new ConcurrentHashMap<>();;
|
||||
|
||||
// 注入映射管理器
|
||||
protected final ConnectionProtocolMappingManager mappingManager;
|
||||
|
||||
// 构造方法注入
|
||||
public AbstractProtocolDriver(ConnectionProtocolMappingManager mappingManager) {
|
||||
this.mappingManager = mappingManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建连接(统一方法,自动注册映射)
|
||||
* @param connectionId 连接ID(原key)
|
||||
* @param protocolCode 协议编码
|
||||
* @param connection 连接对象
|
||||
*/
|
||||
public void addConnection(String connectionId, String protocolCode, T connection) {
|
||||
if (connection == null) {
|
||||
throw new CommonException("连接对象不能为空");
|
||||
}
|
||||
connectMap.put(connectionId, connection);
|
||||
// 注册连接ID与协议的映射
|
||||
mappingManager.registerMapping(connectionId, protocolCode);
|
||||
log.info("新增连接:协议={},连接ID={}", protocolCode, connectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写删除方法:删除连接后同步清理映射
|
||||
*/
|
||||
public void removeConnection(String connectionId) {
|
||||
if (connectMap.isEmpty() || !connectMap.containsKey(connectionId)) {
|
||||
log.warn("连接ID={}不存在,无需删除", connectionId);
|
||||
return;
|
||||
}
|
||||
// 1. 删除连接对象
|
||||
T connection = connectMap.remove(connectionId);
|
||||
closeConnection(connection);
|
||||
// 2. 清理映射关系
|
||||
mappingManager.removeMapping(connectionId);
|
||||
log.info("删除连接成功:连接ID={}", connectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽象方法:子类实现具体的连接关闭逻辑(类型安全)
|
||||
* @param connection 要关闭的连接对象
|
||||
*/
|
||||
protected abstract void closeConnection(T connection);
|
||||
|
||||
// 保留event方法的抽象(子类必须实现)
|
||||
// @Override
|
||||
// public abstract void event(MetadataEventDTO metadataEvent);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.nl.iot.core.driver;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.common.exception.CommonException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 全局连接ID-协议编码映射管理器
|
||||
* 核心作用:记录每个连接ID所属的协议编码,解决删除时"只知ID不知协议"的问题
|
||||
* @Author: liyongde
|
||||
* @Date: 2026/3/19 16:30
|
||||
* @Modified By:
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ConnectionProtocolMappingManager {
|
||||
|
||||
/**
|
||||
* 映射表:连接ID → 协议编码(如 "conn_123" → "MODBUS")
|
||||
*/
|
||||
private final Map<String, String> connectionId2ProtocolCode = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 注册连接ID与协议编码的映射(创建连接时调用)
|
||||
*/
|
||||
public void registerMapping(String connectionId, String protocolCode) {
|
||||
if (connectionId == null || connectionId.trim().isEmpty()) {
|
||||
throw new CommonException("连接ID不能为空");
|
||||
}
|
||||
if (protocolCode == null || protocolCode.trim().isEmpty()) {
|
||||
throw new CommonException("协议编码不能为空");
|
||||
}
|
||||
String upperCode = protocolCode.trim().toUpperCase();
|
||||
connectionId2ProtocolCode.put(connectionId.trim(), upperCode);
|
||||
log.debug("注册连接映射:连接ID={} → 协议编码={}", connectionId, upperCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据连接ID获取协议编码(删除连接时调用)
|
||||
*/
|
||||
public String getProtocolCodeByConnectionId(String connectionId) {
|
||||
if (connectionId == null || connectionId.trim().isEmpty()) {
|
||||
throw new CommonException("连接ID不能为空");
|
||||
}
|
||||
String protocolCode = connectionId2ProtocolCode.get(connectionId.trim());
|
||||
if (protocolCode == null) {
|
||||
throw new CommonException("未找到连接ID[" + connectionId + "]对应的协议编码");
|
||||
}
|
||||
return protocolCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除映射关系(连接删除后同步清理)
|
||||
*/
|
||||
public void removeMapping(String connectionId) {
|
||||
if (connectionId == null) {
|
||||
return;
|
||||
}
|
||||
connectionId2ProtocolCode.remove(connectionId.trim());
|
||||
log.debug("移除连接映射:连接ID={}", connectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查连接ID是否已注册
|
||||
*/
|
||||
public boolean containsMapping(String connectionId) {
|
||||
return connectionId != null && connectionId2ProtocolCode.containsKey(connectionId.trim());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.nl.iot.core.driver;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.common.exception.CommonException;
|
||||
import org.nl.iot.core.driver.service.DriverCustomService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* @Author: liyongde
|
||||
* @Date: 2026/3/19 16:49
|
||||
* @Modified By:
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DriverConnectionManager {
|
||||
|
||||
@Resource
|
||||
private DriverCustomFactory driverCustomFactory;
|
||||
@Resource
|
||||
private ConnectionProtocolMappingManager mappingManager;
|
||||
|
||||
/**
|
||||
* 核心方法:仅传入连接ID,自动删除对应协议的连接
|
||||
* (无需知道协议编码,完全适配你的场景)
|
||||
*/
|
||||
public void removeConnectionById(String connectionId) {
|
||||
// 1. 校验参数
|
||||
if (connectionId == null || connectionId.trim().isEmpty()) {
|
||||
throw new CommonException("连接ID不能为空");
|
||||
}
|
||||
// 2. 根据连接ID获取协议编码
|
||||
String protocolCode = mappingManager.getProtocolCodeByConnectionId(connectionId);
|
||||
// 3. 通过工厂类获取对应驱动
|
||||
DriverCustomService driver = driverCustomFactory.getDriver(protocolCode);
|
||||
if (!(driver instanceof AbstractProtocolDriver<?>)) {
|
||||
throw new CommonException("驱动类[" + driver.getClass().getSimpleName() + "]未继承AbstractProtocolDriver");
|
||||
}
|
||||
// 4. 强转并调用删除方法
|
||||
AbstractProtocolDriver<?> abstractDriver = (AbstractProtocolDriver<?>) driver;
|
||||
abstractDriver.removeConnection(connectionId);
|
||||
log.info("删除连接完成:连接ID={},协议编码={}", connectionId, protocolCode);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.nl.iot.core.driver.protocol.modbustcp;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.plc4x.java.DefaultPlcDriverManager;
|
||||
@@ -11,6 +10,8 @@ import org.apache.plc4x.java.api.messages.PlcWriteRequest;
|
||||
import org.apache.plc4x.java.api.messages.PlcWriteResponse;
|
||||
import org.apache.plc4x.java.api.types.PlcResponseCode;
|
||||
import org.apache.plc4x.java.api.value.PlcValue;
|
||||
import org.nl.iot.core.driver.AbstractProtocolDriver;
|
||||
import org.nl.iot.core.driver.ConnectionProtocolMappingManager;
|
||||
import org.nl.iot.core.driver.ProtocolDriver;
|
||||
import org.nl.iot.core.driver.ProtocolType;
|
||||
import org.nl.iot.core.driver.bo.DeviceBO;
|
||||
@@ -19,16 +20,16 @@ import org.nl.iot.core.driver.bo.SiteBO;
|
||||
import org.nl.iot.core.driver.entity.RValue;
|
||||
import org.nl.iot.core.driver.entity.WResponse;
|
||||
import org.nl.iot.core.driver.entity.WValue;
|
||||
import org.nl.iot.core.driver.enums.MetadataOperateTypeEnum;
|
||||
import org.nl.iot.core.driver.util.JavaToPlcValueConvertUtil;
|
||||
import org.nl.iot.core.driver.protocol.modbustcp.util.ModBusTcpUtils;
|
||||
import org.nl.iot.core.driver.util.JavaToPlcValueConvertUtil;
|
||||
import org.nl.iot.core.driver.util.PlcValueConvertUtil;
|
||||
import org.nl.iot.core.driver.service.DriverCustomService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -39,14 +40,14 @@ import java.util.concurrent.TimeUnit;
|
||||
@Slf4j
|
||||
@Service
|
||||
@ProtocolDriver(ProtocolType.MODBUS)
|
||||
public class ModBusProtocolDriverImpl implements DriverCustomService {
|
||||
public class ModBusProtocolDriverImpl extends AbstractProtocolDriver<PlcConnection> {
|
||||
|
||||
private Map<String, PlcConnection> connectMap;
|
||||
public ModBusProtocolDriverImpl(ConnectionProtocolMappingManager mappingManager) {
|
||||
super(mappingManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void initial() {
|
||||
connectMap = new ConcurrentHashMap<>(16);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,13 +57,13 @@ 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());
|
||||
}
|
||||
// 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
|
||||
@@ -85,6 +86,14 @@ public class ModBusProtocolDriverImpl implements DriverCustomService {
|
||||
return batchWriteValue(getConnector(device), wValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeConnection(PlcConnection connection) {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (Exception e) {
|
||||
log.warn("关闭失败:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
@SneakyThrows
|
||||
public static List<WResponse> batchWriteValue(PlcConnection modbusMaster, List<WValue> wValues) {
|
||||
List<WResponse> res = new ArrayList<>();
|
||||
@@ -119,6 +128,7 @@ public class ModBusProtocolDriverImpl implements DriverCustomService {
|
||||
try {
|
||||
if (Objects.isNull(modbusMaster)) {
|
||||
modbusMaster = new DefaultPlcDriverManager().getConnection(ModBusTcpUtils.buildModBusPlcUrl(deviceBO));
|
||||
createModBusConnection(deviceBO.getId(), modbusMaster);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -126,6 +136,12 @@ public class ModBusProtocolDriverImpl implements DriverCustomService {
|
||||
return modbusMaster;
|
||||
}
|
||||
|
||||
// 业务中创建连接时,调用父类的addConnection方法
|
||||
public void createModBusConnection(String connectionId, PlcConnection connection) {
|
||||
// 传入协议编码(MODBUS)和连接ID、连接对象
|
||||
addConnection(connectionId, ProtocolType.MODBUS.getMainCode(), connection);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public String readValue(PlcConnection modbusMaster, SiteBO point) {
|
||||
// 1. 解析配置
|
||||
|
||||
@@ -2,12 +2,13 @@ package org.nl.iot.core.driver.protocol.opcda;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jinterop.dcom.common.JIException;
|
||||
import org.jinterop.dcom.core.JIVariant;
|
||||
import org.nl.common.exception.CommonException;
|
||||
import org.nl.iot.core.driver.AbstractProtocolDriver;
|
||||
import org.nl.iot.core.driver.ConnectionProtocolMappingManager;
|
||||
import org.nl.iot.core.driver.ProtocolDriver;
|
||||
import org.nl.iot.core.driver.ProtocolType;
|
||||
import org.nl.iot.core.driver.bo.DeviceBO;
|
||||
@@ -16,14 +17,12 @@ import org.nl.iot.core.driver.bo.SiteBO;
|
||||
import org.nl.iot.core.driver.entity.RValue;
|
||||
import org.nl.iot.core.driver.entity.WResponse;
|
||||
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.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.NotConnectedException;
|
||||
import org.nl.iot.core.driver.protocol.opcda.org.openscada.opc.lib.da.*;
|
||||
import org.nl.iot.core.driver.protocol.opcda.util.JIVariantToStringUtil;
|
||||
import org.nl.iot.core.driver.service.DriverCustomService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
@@ -31,29 +30,19 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ProtocolDriver(ProtocolType.OPCDA)
|
||||
public class OpcDaProtocolDriverImpl implements DriverCustomService {
|
||||
/**
|
||||
* Opc Da Server Map
|
||||
*/
|
||||
private Map<String, Server> connectMap;
|
||||
public class OpcDaProtocolDriverImpl extends AbstractProtocolDriver<Server> {
|
||||
|
||||
public OpcDaProtocolDriverImpl(ConnectionProtocolMappingManager mappingManager) {
|
||||
super(mappingManager);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void initial() {
|
||||
/*
|
||||
* 驱动初始化逻辑
|
||||
*
|
||||
* 提示: 此处逻辑仅供参考, 请务必结合实际应用场景进行修改。
|
||||
* 驱动启动时会自动执行该方法, 您可以在此处执行特定的初始化操作。
|
||||
*
|
||||
*/
|
||||
connectMap = new ConcurrentHashMap<>(16);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,12 +52,21 @@ 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);
|
||||
// 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());
|
||||
// }
|
||||
}
|
||||
|
||||
// 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
|
||||
protected void closeConnection(Server server) {
|
||||
try {
|
||||
server.disconnect();
|
||||
} catch (Exception e) {
|
||||
log.warn("关闭失败:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,9 +107,9 @@ public class OpcDaProtocolDriverImpl implements DriverCustomService {
|
||||
server = new Server(connectionInformation, Executors.newSingleThreadScheduledExecutor());
|
||||
try {
|
||||
server.connect();
|
||||
connectMap.put(deviceBO.getId(), server);
|
||||
addOpcDaConnection(deviceBO.getId(), server);
|
||||
} catch (AlreadyConnectedException | UnknownHostException | JIException e) {
|
||||
connectMap.entrySet().removeIf(next -> next.getKey().equals(deviceBO.getId()));
|
||||
removeConnection(deviceBO.getId());
|
||||
log.error("Connect opc da server error: {}", e.getMessage(), e);
|
||||
throw new CommonException(e.getMessage());
|
||||
}
|
||||
@@ -119,6 +117,12 @@ public class OpcDaProtocolDriverImpl implements DriverCustomService {
|
||||
return server;
|
||||
}
|
||||
|
||||
// 业务中创建连接时,调用父类的addConnection方法
|
||||
public void addOpcDaConnection(String connectionId, Server connection) {
|
||||
// 传入协议编码(OpcDa)和连接ID、连接对象
|
||||
addConnection(connectionId, ProtocolType.OPCDA.getMainCode(), connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 OPC DA 服务器读取位号值
|
||||
* <p>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package org.nl.iot.core.driver.protocol.opcua;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
|
||||
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
|
||||
import org.eclipse.milo.opcua.stack.core.AttributeId;
|
||||
import org.eclipse.milo.opcua.stack.core.UaException;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
|
||||
@@ -13,8 +11,9 @@ import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
|
||||
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.structured.WriteValue;
|
||||
import org.nl.common.exception.CommonException;
|
||||
import org.nl.iot.core.driver.AbstractProtocolDriver;
|
||||
import org.nl.iot.core.driver.ConnectionProtocolMappingManager;
|
||||
import org.nl.iot.core.driver.ProtocolDriver;
|
||||
import org.nl.iot.core.driver.ProtocolType;
|
||||
import org.nl.iot.core.driver.bo.DeviceBO;
|
||||
@@ -25,49 +24,38 @@ import org.nl.iot.core.driver.entity.WResponse;
|
||||
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.service.DriverCustomService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ProtocolDriver(ProtocolType.OPCUA)
|
||||
public class OpcUaProtocolDriverImpl implements DriverCustomService {
|
||||
private Map<String, OpcUaClient> connectMap;
|
||||
public class OpcUaProtocolDriverImpl extends AbstractProtocolDriver<OpcUaClient> {
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void initial() {
|
||||
/*
|
||||
* 驱动初始化逻辑
|
||||
*
|
||||
* 提示: 此处逻辑仅供参考, 请务必结合实际应用场景进行修改。
|
||||
* 驱动启动时会自动执行该方法, 您可以在此处执行特定的初始化操作。
|
||||
*
|
||||
*/
|
||||
connectMap = new ConcurrentHashMap<>(16);
|
||||
public OpcUaProtocolDriverImpl(ConnectionProtocolMappingManager mappingManager) {
|
||||
super(mappingManager);
|
||||
}
|
||||
|
||||
// @PreDestroy
|
||||
// public void destroy() {
|
||||
// // 应用关闭时清理所有连接
|
||||
// log.info("Cleaning up OPC UA connections...");
|
||||
// connectMap.values().forEach(client -> {
|
||||
// try {
|
||||
// client.disconnect().get(5, TimeUnit.SECONDS);
|
||||
// } catch (Exception e) {
|
||||
// log.warn("Error disconnecting OPC UA client during cleanup: {}", e.getMessage());
|
||||
// }
|
||||
// });
|
||||
// connectMap.clear();
|
||||
// log.info("OPC UA connections cleanup completed");
|
||||
// }
|
||||
@Override
|
||||
public void initial() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeConnection(OpcUaClient client) {
|
||||
try {
|
||||
client.disconnect().get(5, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
log.error("Error disconnecting OPC UA client during cleanup: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void schedule() {
|
||||
@@ -171,10 +159,10 @@ public class OpcUaProtocolDriverImpl implements DriverCustomService {
|
||||
.setSessionTimeout(Unsigned.uint(60000)) // 设置会话超时时间为 60 秒
|
||||
.build()
|
||||
);
|
||||
connectMap.put(device.getId(), opcUaClient);
|
||||
addOPCUAConnection(device.getId(), opcUaClient);
|
||||
log.info("Created new OPC UA client for device: {}", device.getId());
|
||||
} catch (UaException e) {
|
||||
connectMap.entrySet().removeIf(next -> next.getKey().equals(device.getId()));
|
||||
removeConnection(device.getId());
|
||||
log.error("Failed to create OPC UA client: {}", e.getMessage(), e);
|
||||
throw new IllegalArgumentException(e.getMessage());
|
||||
}
|
||||
@@ -182,6 +170,12 @@ public class OpcUaProtocolDriverImpl implements DriverCustomService {
|
||||
return opcUaClient;
|
||||
}
|
||||
|
||||
// 业务中创建连接时,调用父类的addConnection方法
|
||||
public void addOPCUAConnection(String connectionId, OpcUaClient connection) {
|
||||
// 传入协议编码(OPCUA)和连接ID、连接对象
|
||||
addConnection(connectionId, ProtocolType.OPCUA.getMainCode(), connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取 OPC UA 节点的值
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.nl.iot.core.driver.protocol.plcs7;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.plc4x.java.DefaultPlcDriverManager;
|
||||
import org.apache.plc4x.java.api.PlcConnection;
|
||||
@@ -11,6 +10,8 @@ import org.apache.plc4x.java.api.messages.PlcWriteResponse;
|
||||
import org.apache.plc4x.java.api.types.PlcResponseCode;
|
||||
import org.apache.plc4x.java.api.value.PlcValue;
|
||||
import org.nl.common.exception.CommonException;
|
||||
import org.nl.iot.core.driver.AbstractProtocolDriver;
|
||||
import org.nl.iot.core.driver.ConnectionProtocolMappingManager;
|
||||
import org.nl.iot.core.driver.ProtocolDriver;
|
||||
import org.nl.iot.core.driver.ProtocolType;
|
||||
import org.nl.iot.core.driver.bo.DeviceBO;
|
||||
@@ -19,15 +20,17 @@ import org.nl.iot.core.driver.bo.SiteBO;
|
||||
import org.nl.iot.core.driver.entity.RValue;
|
||||
import org.nl.iot.core.driver.entity.WResponse;
|
||||
import org.nl.iot.core.driver.entity.WValue;
|
||||
import org.nl.iot.core.driver.enums.MetadataOperateTypeEnum;
|
||||
import org.nl.iot.core.driver.protocol.plcs7.util.PlcS7Utils;
|
||||
import org.nl.iot.core.driver.util.JavaToPlcValueConvertUtil;
|
||||
import org.nl.iot.core.driver.util.PlcValueConvertUtil;
|
||||
import org.nl.iot.core.driver.protocol.plcs7.util.PlcS7Utils;
|
||||
import org.nl.iot.core.driver.service.DriverCustomService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -37,18 +40,14 @@ import java.util.concurrent.*;
|
||||
@Slf4j
|
||||
@Service
|
||||
@ProtocolDriver(ProtocolType.PLCS7)
|
||||
public class PlcS7ProtocolDriverImpl implements DriverCustomService {
|
||||
public class PlcS7ProtocolDriverImpl extends AbstractProtocolDriver<PlcConnection> {
|
||||
|
||||
/**
|
||||
* Plc Connector Map
|
||||
* 仅供参考
|
||||
*/
|
||||
private Map<String, PlcConnection> connectMap;
|
||||
public PlcS7ProtocolDriverImpl(ConnectionProtocolMappingManager mappingManager) {
|
||||
super(mappingManager);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void initial() {
|
||||
connectMap = new ConcurrentHashMap<>(16);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,12 +57,21 @@ 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);
|
||||
// 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());
|
||||
// }
|
||||
}
|
||||
|
||||
// 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
|
||||
protected void closeConnection(PlcConnection connection) {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (Exception e) {
|
||||
log.warn("关闭失败:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +153,7 @@ public class PlcS7ProtocolDriverImpl implements DriverCustomService {
|
||||
String connectionUrl = PlcS7Utils.getS7ConnectionUrl(deviceBO);
|
||||
log.info("创建S7连接,deviceId: {}, url: {}", deviceId, connectionUrl);
|
||||
connection = new DefaultPlcDriverManager().getConnection(connectionUrl);
|
||||
connectMap.put(deviceId, connection);
|
||||
addPlcS7Connection(deviceBO.getId(), connection);
|
||||
}
|
||||
return connection;
|
||||
} catch (Exception e) {
|
||||
@@ -154,6 +162,12 @@ public class PlcS7ProtocolDriverImpl implements DriverCustomService {
|
||||
}
|
||||
}
|
||||
|
||||
// 业务中创建连接时,调用父类的addConnection方法
|
||||
public void addPlcS7Connection(String connectionId, PlcConnection connection) {
|
||||
// 传入协议编码(PLCS7)和连接ID、连接对象
|
||||
addConnection(connectionId, ProtocolType.PLCS7.getMainCode(), connection);
|
||||
}
|
||||
|
||||
public static PlcReadRequest.Builder doBuildReadRequest(PlcConnection s7Connection, List<SiteBO> points) {
|
||||
try {
|
||||
PlcReadRequest.Builder readBuilder = s7Connection.readRequestBuilder();
|
||||
|
||||
@@ -16,8 +16,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.nl.common.pojo.CommonResult;
|
||||
import org.nl.iot.core.driver.DriverConnectionManager;
|
||||
import org.nl.iot.modular.iot.entity.IotConnect;
|
||||
import org.nl.iot.modular.iot.entity.IotConfig;
|
||||
import org.nl.iot.modular.iot.service.IotConfigService;
|
||||
@@ -43,6 +45,8 @@ public class IotConnectController {
|
||||
|
||||
@Autowired
|
||||
private IotConfigService iotConfigService;
|
||||
@Resource
|
||||
private DriverConnectionManager connectionManager;
|
||||
|
||||
/**
|
||||
* 获取连接列表
|
||||
@@ -92,6 +96,7 @@ public class IotConnectController {
|
||||
@PostMapping("/edit")
|
||||
public CommonResult edit(@RequestBody IotConnect connect) {
|
||||
iotConnectService.updateById(connect);
|
||||
connectionManager.removeConnectionById(connect.getId().toString());
|
||||
return CommonResult.ok();
|
||||
}
|
||||
|
||||
@@ -110,7 +115,7 @@ public class IotConnectController {
|
||||
if (count > 0) {
|
||||
throw new CommonException("连接已被信号配置使用,无法删除");
|
||||
}
|
||||
iotConnectService.removeById(connect.getId());
|
||||
connectionManager.removeConnectionById(connect.getId().toString());
|
||||
return CommonResult.ok();
|
||||
}
|
||||
|
||||
@@ -128,6 +133,9 @@ public class IotConnectController {
|
||||
throw new CommonException("所选连接存在信号配置,无法删除");
|
||||
}
|
||||
}
|
||||
for (Integer id : ids) {
|
||||
connectionManager.removeConnectionById(String.valueOf(id));
|
||||
}
|
||||
iotConnectService.removeBatchByIds(ids);
|
||||
return CommonResult.ok();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user