ShangHaiMesParent/moduleService/plcConnectModule/src/main/java/com/mes/connect/Thread/MachineThread.java
@@ -24,10 +24,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@@ -55,6 +52,24 @@
        this.api = api;
        this.logicConfig = JsonConversion.jsonToObjectByJackson(ReadFile.readJson(machine.getLogicFile()).toString(), LogicConfig.class);
        this.plcParameters = JsonConversion.jsonToObjectByJackson(ReadFile.readJson(machine.getMachineFile()).toString(), PlcParameters.class);
        this.logicConfig.getLogics();
        this.plcParameters.Initialization();
        for (LogicItem logicItem : logicConfig.getLogics()) {
            if (logicItem.getLogicInterval()==0){
                //默认1000毫秒
                logicItem.setLogicInterval(1000);
            }
            for (Logic logic : logicItem.getLogic()) {
                logic.setAddress(this.plcParameters.getMap().get(logic.getCodeId()).getAddress());
                logic.setPlcDataType(this.plcParameters.getMap().get(logic.getCodeId()).getPlcDataType());
            }
            for (ReturnValue returnValue : logicItem.getReturnValue()) {
                returnValue.setAddress(this.plcParameters.getMap().get(returnValue.getCodeId()).getAddress());
                returnValue.setPlcDataType(this.plcParameters.getMap().get(returnValue.getCodeId()).getPlcDataType());
            }
        }
        switch (machine.getProtocolType().getName()) {
            case "ModbusTcp":
                client = new ModbusTcpClient(machine.getIp(), machine.getPort(), 1);
@@ -72,54 +87,23 @@
                log.error("无效的协议类型: {}", protocolType);
                throw new IllegalArgumentException("无效的协议类型: " + protocolType);
        }
        if (client != null) {
            client.connect();
            boolean connected = client.isConnected();
            if (!connected) {
                log.error("连接PLC失败: {}", machine.getIp());
            }
        }
    }
    @Override
    public void run() {
        log.info("MachineThread启动,设备IP: {}", machine.getIp());
        if (client == null || !client.isConnected()) {
            log.error("PLC客户端未连接,线程退出");
            return;
        }
        plcParameters.Initialization();
        try {
            // 初始化读取PLC参数
            readPlcParameter();
        } catch (Exception e) {
            log.error("初始化读取PLC参数失败: {}", e.getMessage(), e);
            return;
        }
        // 为每个逻辑项创建并启动子线程
        //startLogicThread(logicConfig.getLogics().get(0));
        for (LogicItem logicItem : logicConfig.getLogics()) {
            startLogicThread(logicItem);
            //startLogicThread(logicConfig.getLogics().get(0));
        }
        // 主线程持续运行,定期读取PLC参数并监控连接状态
        while (running) {
            try {
                // 读取PLC参数,为逻辑处理提供最新数据
                readPlcParameter();
                // 检查PLC连接状态
                if (!client.isConnected()) {
                    log.warn("PLC连接断开,尝试重新连接");
                    log.info("PLC尝试连接... 设备IP: {}", machine.getIp());
                    tryReconnect();
                }
                // 检查逻辑线程状态,重启已终止的线程
                // 读取PLC参数,为逻辑处理提供最新数据
                this.readPlcParameter();
                plcParameters.Initialization();
                // 检查逻辑线程状态,开启/重启 线程
                checkLogicThreadsStatus();
                // 等待下一个执行周期
                Thread.sleep(mainThreadInterval);
            } catch (InterruptedException e) {
@@ -140,7 +124,6 @@
                }
            }
        }
        // 线程退出前关闭所有资源
        shutdown();
        log.info("MachineThread已退出,设备IP: {}", machine.getIp());
@@ -148,28 +131,22 @@
    // 为指定逻辑项创建并启动子线程
    private void startLogicThread(LogicItem logicItem) {
        String logicId = logicItem.getName(); // 假设每个LogicItem有唯一ID
        String logicId = this.machine.getId()+" - "+this.machine.getName()+" - "+ logicItem.getName(); // 假设每个LogicItem有唯一ID
        if (logicThreads.containsKey(logicId) && logicThreads.get(logicId).isAlive()) {
            log.warn("逻辑项线程已在运行: {}", logicId);
            return;
        }
        // 设置运行标志
        logicRunningFlags.put(logicId, true);
        // 创建并启动线程
        Thread thread = new Thread(() -> {
            log.info("逻辑项线程启动: {}", logicId);
            // 逻辑项子线程持续运行的循环
            while (logicRunningFlags.getOrDefault(logicId, false)) {
                try {
                    // 执行实际业务逻辑
                    basicsLogic(logicItem);
                    // 根据逻辑项的执行频率设置等待时间,默认1000ms
                    int logicInterval = 1000;
                    Thread.sleep(logicInterval);
                    Thread.sleep(logicItem.getLogicInterval());
                } catch (InterruptedException e) {
                    log.info("逻辑项线程被中断,准备退出: {}", logicId);
                    logicRunningFlags.put(logicId, false);
@@ -186,31 +163,23 @@
                    }
                }
            }
            log.info("逻辑项线程已退出: {}", logicId);
        });
        // 设置线程名称
        thread.setName("Logic-" + logicId);
        thread.setName(logicId);
        // 存储线程引用
        logicThreads.put(logicId, thread);
        // 启动线程
        thread.start();
        log.info("已启动逻辑项线程: {}", logicId);
        //log.info("已启动逻辑项线程: {}", logicId);
    }
    // 检查逻辑线程状态,重启已终止的线程
    private void checkLogicThreadsStatus() {
        for (LogicItem logicItem : logicConfig.getLogics()) {
            String logicId = logicItem.getName();
            String logicId = this.machine.getId()+" - "+this.machine.getName()+" - "+ logicItem.getName();
            Thread thread = logicThreads.get(logicId);
            // 如果线程不存在或已终止且运行标志为true,则重启线程
            if ((thread == null || !thread.isAlive()) &&
                    logicRunningFlags.getOrDefault(logicId, false)) {
                log.warn("逻辑项线程已终止,准备重启: {}", logicId);
            if ((thread == null || !thread.isAlive()) &&!logicRunningFlags.getOrDefault(logicId, false)) {
                startLogicThread(logicItem);
            }
        }
@@ -220,9 +189,9 @@
    private void tryReconnect() {
        if (client != null) {
            try {
                log.info("尝试重新连接PLC: {}", machine.getIp());
                client.disconnect();
                Thread.sleep(2000);
                client.connect();
                boolean reconnected = client.isConnected();
                if (reconnected) {
                    log.info("PLC重新连接成功: {}", machine.getIp());
@@ -238,7 +207,6 @@
    // 关闭线程前的清理工作
    public void shutdown() {
        running = false;
        // 停止所有逻辑线程
        for (String logicId : logicRunningFlags.keySet()) {
            logicRunningFlags.put(logicId, false);
@@ -247,7 +215,6 @@
                thread.interrupt();
            }
        }
        // 等待所有逻辑线程结束
        for (String logicId : logicThreads.keySet()) {
            Thread thread = logicThreads.get(logicId);
@@ -292,37 +259,24 @@
                }
            }
            if (isEqual){
                List<String> result=new ArrayList<>();
                log.info("满足条件:{}",logicItem.getName());
                //3.查询此逻辑下需要返回给PLC的数据 result可接收  HTTP接口,视图,存储过程 等  如下
                try{
                    String connectType=logicItem.getConnectType();
                    String connectAddress=logicItem.getConnectAddress();
                    Map map=new HashMap();
                    switch (connectType) {
                        case "Http":
                            map.put("method","POST");
                            map.put("plcParameter",plcParameters);
                            result= api.httpApi(connectAddress,map);
                            log.info("接口返回内容:{}",result);
                            break;
                        case "View": // 视图/表
                            result= api.viewApi(connectAddress,map);
                            break;
                        case "Procedure": // 存储过程
                            //result= api.procedureAPI(connectAddress,plcParameter);
                            break;
                        default:
                            log.warn("不支持的连接类型: {}", connectType);
                            return; // 不支持的方式
                List<String> resultWrite=null;
                if (logicItem.getApiConfigBefore()!=null){
                    ApiConfig apiConfig=logicItem.getApiConfigBefore();
                    resultWrite=api.callApi(apiConfig,plcParameters);
                    log.info("ApiConfigBefore  外置接口[{}:{}]返回的内容:{}",apiConfig.getType(),apiConfig.getAddress(),resultWrite);
                }
                //写入PLC返回值成功时调用接口
                if (basicsResult(resultWrite,logicItem.getReturnValue())){
                    ApiConfig apiConfig=logicItem.getApiConfigAfter();
                    if (logicItem.getApiConfigAfter()!=null){
                        List<String> result=api.callApi(apiConfig,plcParameters);
                        log.info("ApiConfigAfter  外置接口[{}:{}]返回的内容:{}",apiConfig.getType(),apiConfig.getAddress(),result);
                    }
                    }
                }catch (Exception e){
                    log.error("调用接口失败: {}", e.getMessage(), e);
                }
                //4.返回PLC内容
                if (result != null&&!result.isEmpty()) {
                    basicsResult(result,logicItem.getReturnValue());
                }
            }
        }  catch (Exception e) {
            log.error("执行basicsLogic失败: {}", e.getMessage(), e);
@@ -344,20 +298,22 @@
            if (values!=null && !values.equals("")){
                //还需增添  不同类型调用不同方法
                switch (itemReturnValue.getPlcDataType()) {
                    case "int":
                    case "Word":
                        client.writeRegister(itemReturnValue.getAddress(),(int)Double.parseDouble(values));
                        break;
                    case "string":
                    case "String":
                        client.writeString(itemReturnValue.getAddress(),values);
                        break;
                    case "float":
                    case "Float":
                        client.writeFloat(itemReturnValue.getAddress(),Float.valueOf(values));
                        break;
                    case "bit":
                        client.writeBit(itemReturnValue.getAddress(),Boolean.valueOf(values));
                        break;
                    default:
                        log.error("不支持的数据类型: {}", itemReturnValue.getPlcDataType());
                        return false;
                }
            }
        }
        return true;