package com.mes.plc.factory; import com.mes.device.entity.DeviceConfig; import com.mes.plc.client.PlcClient; import com.mes.plc.client.impl.ModbusPlcClient; import com.mes.plc.client.impl.S7PlcClient; import com.mes.service.PlcDynamicDataService; import com.mes.s7.enhanced.EnhancedS7Serializer; import com.mes.s7.provider.S7SerializerProvider; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * PLC客户端工厂 *

* 根据设备配置创建不同类型的PLC客户端实例 *

* * @author huang * @date 2025/12/19 */ @Slf4j @Component public class PlcClientFactory { // S7序列化器提供者 @Autowired private S7SerializerProvider s7SerializerProvider; // PLC动态数据服务 @Autowired private PlcDynamicDataService plcDynamicDataService; // 客户端缓存,提高性能 private final ConcurrentMap clientCache = new ConcurrentHashMap<>(); /** * 根据设备配置创建或获取PLC客户端 * * @param device 设备配置 * @return PLC客户端实例 */ public PlcClient getClient(DeviceConfig device) { if (device == null) { log.error("设备配置为空,无法创建PLC客户端"); return null; } // 生成缓存键 String cacheKey = generateCacheKey(device); // 尝试从缓存中获取客户端 PlcClient client = clientCache.get(cacheKey); if (client != null && client.isConnected()) { return client; } // 缓存中没有或连接已断开,创建新客户端 try { client = createClient(device); if (client != null) { // 连接PLC if (client.connect()) { // 将客户端放入缓存 clientCache.put(cacheKey, client); log.info("PLC客户端创建成功: cacheKey={}, plcType={}", cacheKey, client.getPlcType()); } else { log.error("PLC客户端连接失败: cacheKey={}, plcType={}", cacheKey, client.getPlcType()); // 连接失败,不放入缓存 client = null; } } } catch (Exception e) { log.error("创建PLC客户端失败: cacheKey={}", cacheKey, e); client = null; } return client; } /** * 生成缓存键 * * @param device 设备配置 * @return 缓存键 */ private String generateCacheKey(DeviceConfig device) { StringBuilder sb = new StringBuilder(); sb.append("device:") .append(device.getId()) .append(":") .append(device.getPlcType()) .append(":") .append(device.getPlcIp()) .append(":") .append(device.getPlcPort()); return sb.toString(); } /** * 根据设备类型创建不同的PLC客户端 * * @param device 设备配置 * @return PLC客户端实例 */ private PlcClient createClient(DeviceConfig device) { if (device == null) { return null; } String plcType = device.getPlcType(); if (plcType == null || plcType.isEmpty()) { log.error("PLC类型为空,无法创建客户端: deviceId={}", device.getId()); return null; } // 根据PLC类型创建不同的客户端 // 支持 S7_1200, S7_1500 等格式,也支持 S1200, S1500 等格式 String normalizedPlcType = plcType.toUpperCase(); if (normalizedPlcType.startsWith("S7") || normalizedPlcType.startsWith("S1200") || normalizedPlcType.startsWith("S1500") || normalizedPlcType.startsWith("S200") || normalizedPlcType.startsWith("S300") || normalizedPlcType.startsWith("S400")) { // S7协议客户端 return createS7Client(device); } else if (normalizedPlcType.equals("MODBUS")) { // Modbus协议客户端 return createModbusClient(device); } else { log.error("不支持的PLC类型: deviceId={}, plcType={}", device.getId(), plcType); return null; } } /** * 创建S7协议客户端 * * @param device 设备配置 * @return S7客户端实例 */ private PlcClient createS7Client(DeviceConfig device) { try { // 获取S7序列化器 EnhancedS7Serializer s7Serializer = s7SerializerProvider.getSerializer(device); if (s7Serializer == null) { log.error("获取S7Serializer失败: deviceId={}", device.getId()); return null; } // 创建S7客户端 S7PlcClient client = new S7PlcClient(device, s7Serializer); // 设置PLC动态数据服务 client.setPlcDynamicDataService(this.plcDynamicDataService); return client; } catch (Exception e) { log.error("创建S7客户端失败: deviceId={}", device.getId(), e); return null; } } /** * 创建Modbus协议客户端 * * @param device 设备配置 * @return Modbus客户端实例 */ private PlcClient createModbusClient(DeviceConfig device) { try { // 创建Modbus客户端 return new ModbusPlcClient(device); } catch (Exception e) { log.error("创建Modbus客户端失败: deviceId={}", device.getId(), e); return null; } } /** * 关闭并移除指定设备的PLC客户端 * * @param device 设备配置 */ public void removeClient(DeviceConfig device) { if (device == null) { return; } String cacheKey = generateCacheKey(device); PlcClient client = clientCache.remove(cacheKey); if (client != null) { client.disconnect(); log.info("PLC客户端已移除: cacheKey={}", cacheKey); } } /** * 关闭并清除所有PLC客户端 */ public void clearAllClients() { log.info("开始清除所有PLC客户端,当前缓存大小: {}", clientCache.size()); for (PlcClient client : clientCache.values()) { try { client.disconnect(); } catch (Exception e) { log.error("关闭PLC客户端失败", e); } } clientCache.clear(); log.info("所有PLC客户端已清除"); } /** * 获取客户端缓存大小 * * @return 缓存大小 */ public int getCacheSize() { return clientCache.size(); } }