package com.mes.service; import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType; import com.github.xingshuangs.iot.protocol.s7.service.S7PLC; import com.mes.entity.PlcBaseData; import com.mes.entity.PlcAddress; import com.mes.s7.enhanced.EnhancedS7Serializer; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * PLC测试写入服务 * 模拟PLC行为,向PLC写入测试数据,用于测试MES程序 * * @author huang * @date 2025/10/29 */ @Slf4j @Service public class PlcTestWriteService { @Resource private PlcAddressService plcAddressService; private static final int ON = 1; private static final int OFF = 0; // 当前使用的项目标识 private String currentProjectId = "vertical"; // 缓存不同项目的S7Serializer实例 private final ConcurrentMap serializerCache = new ConcurrentHashMap<>(); /** * 模拟PLC发送请求字(触发MES任务下发) */ public boolean simulatePlcRequest() { return simulatePlcRequest(currentProjectId); } /** * 模拟PLC发送请求字(触发MES任务下发)- 支持指定项目 */ public boolean simulatePlcRequest(String projectId) { try { // 获取项目配置(数据库实体) PlcAddress config = plcAddressService.getProjectConfigWithMapping(projectId); // 获取对应的S7Serializer EnhancedS7Serializer s7Serializer = getSerializerForProject(projectId, config); // 读取当前PLC状态 PlcBaseData currentData = s7Serializer.read(PlcBaseData.class, config.getDbArea(), config.getBeginIndex()); if (currentData.getOnlineState() == OFF) { log.info("当前PLC联机模式为0,停止联机"); return false; }else if (currentData.getPlcReport() == ON){ log.info("当前上片PLC汇报字为1,重置为0"); currentData.setPlcReport(OFF); } // 设置PLC请求字为1(触发MES任务处理) currentData.setPlcRequest(ON); s7Serializer.write(currentData, config.getDbArea(), config.getBeginIndex()); log.info("模拟PLC发送请求字成功:plcRequest=1, projectId={}, dbArea={}, beginIndex={}", projectId, config.getDbArea(), config.getBeginIndex()); return true; } catch (Exception e) { log.error("模拟PLC请求字失败", e); return false; } } /** * 模拟PLC任务完成汇报 */ public boolean simulatePlcReport() { return simulatePlcReport(currentProjectId); } /** * 模拟PLC任务完成汇报 - 支持指定项目 */ public boolean simulatePlcReport(String projectId) { try { // 获取项目配置(数据库实体) PlcAddress config = plcAddressService.getProjectConfigWithMapping(projectId); // 获取对应的S7Serializer EnhancedS7Serializer s7Serializer = getSerializerForProject(projectId, config); PlcBaseData currentData = s7Serializer.read(PlcBaseData.class, config.getDbArea(), config.getBeginIndex()); // 设置PLC汇报字为1(任务完成) currentData.setPlcReport(ON); // 请求字清0 currentData.setPlcRequest(OFF); // 设置完成数量等数据 currentData.setMesGlassCount(10); s7Serializer.write(currentData, config.getDbArea(), config.getBeginIndex()); log.info("模拟PLC任务完成汇报:plcReport=1, mesGlassCount=10, projectId={}, dbArea={}, beginIndex={}", projectId, config.getDbArea(), config.getBeginIndex()); return true; } catch (Exception e) { log.error("模拟PLC任务完成汇报失败", e); return false; } } /** * 模拟PLC发送联机状态 */ public boolean simulateOnlineStatus(int onlineState) { return simulateOnlineStatus(onlineState, currentProjectId); } /** * 模拟PLC发送联机状态 - 支持指定项目 */ public boolean simulateOnlineStatus(int onlineState, String projectId) { try { // 获取项目配置(数据库实体) PlcAddress config = plcAddressService.getProjectConfigWithMapping(projectId); // 获取对应的S7Serializer EnhancedS7Serializer s7Serializer = getSerializerForProject(projectId, config); PlcBaseData currentData = s7Serializer.read(PlcBaseData.class, config.getDbArea(), config.getBeginIndex()); // 1:联机 0:脱机 currentData.setOnlineState(onlineState); s7Serializer.write(currentData, config.getDbArea(), config.getBeginIndex()); log.info("模拟PLC联机状态:onlineState={}, projectId={}, dbArea={}, beginIndex={}", onlineState, projectId, config.getDbArea(), config.getBeginIndex()); return true; } catch (Exception e) { log.error("模拟PLC联机状态失败", e); return false; } } /** * 重置PLC所有状态 */ public boolean resetPlc() { return resetPlc(currentProjectId); } /** * 重置PLC所有状态 - 支持指定项目 */ public boolean resetPlc(String projectId) { try { // 获取项目配置(数据库实体) PlcAddress config = plcAddressService.getProjectConfigWithMapping(projectId); // 获取对应的S7Serializer EnhancedS7Serializer s7Serializer = getSerializerForProject(projectId, config); PlcBaseData resetData = new PlcBaseData(); // 重置所有关键字段 resetData.setPlcRequest(OFF); resetData.setPlcReport(OFF); resetData.setMesSend(OFF); resetData.setMesConfirm(OFF); // 默认联机 resetData.setOnlineState(ON); resetData.setMesGlassCount(0); // 清除报警 resetData.setAlarmInfo(OFF); s7Serializer.write(resetData, config.getDbArea(), config.getBeginIndex()); log.info("PLC状态已重置, projectId={}, dbArea={}, beginIndex={}", projectId, config.getDbArea(), config.getBeginIndex()); return true; } catch (Exception e) { log.error("重置PLC状态失败", e); return false; } } /** * 读取PLC当前状态 */ public PlcBaseData readPlcStatus() { return readPlcStatus(currentProjectId); } /** * 读取PLC当前状态 - 支持指定项目 */ public PlcBaseData readPlcStatus(String projectId) { try { // 获取项目配置(数据库实体) PlcAddress config = plcAddressService.getProjectConfigWithMapping(projectId); // 获取对应的S7Serializer EnhancedS7Serializer s7Serializer = getSerializerForProject(projectId, config); return s7Serializer.read(PlcBaseData.class, config.getDbArea(), config.getBeginIndex()); } catch (Exception e) { log.error("读取PLC状态失败", e); return null; } } /** * 设置当前项目标识 */ public void setCurrentProjectId(String projectId) { this.currentProjectId = projectId; } /** * 获取当前项目标识 */ public String getCurrentProjectId() { return this.currentProjectId; } /** * 获取项目对应的S7Serializer实例 * 如果不存在,则创建一个新的实例并缓存 * * @param projectId 项目标识 * @param config 项目配置 * @return S7Serializer实例 */ private EnhancedS7Serializer getSerializerForProject(String projectId, PlcAddress config) { return serializerCache.computeIfAbsent(projectId, id -> { // 解析PLC类型 EPlcType plcType = EPlcType.S1200; // 默认值 if (config != null && config.getPlcType() != null) { try { plcType = EPlcType.valueOf(config.getPlcType()); } catch (IllegalArgumentException e) { log.warn("未知的PLC类型: {}, 使用默认类型 S1200", config.getPlcType()); } } // 创建S7PLC实例 String plcIp = (config != null && config.getPlcIp() != null) ? config.getPlcIp() : "192.168.10.21"; S7PLC s7Plc = new S7PLC(plcType, plcIp); // 创建并返回EnhancedS7Serializer实例 return EnhancedS7Serializer.newInstance(s7Plc); }); } /** * 清除指定项目的S7Serializer缓存 * * @param projectId 项目标识 */ public void clearSerializerCache(String projectId) { serializerCache.remove(projectId); log.info("已清除项目 {} 的S7Serializer缓存", projectId); } /** * 清除所有S7Serializer缓存 */ public void clearAllSerializerCache() { serializerCache.clear(); log.info("已清除所有S7Serializer缓存"); } }