
//#define SAOMA_PLAN_1    // 一个串口扫码枪
#define SAOMA_PLAN_4      // 四个串口扫码枪

using HslCommunication.Profinet.Melsec;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using EasyModbus;
using DocumentFormat.OpenXml.Bibliography;
using DocumentFormat.OpenXml.EMMA;
using Guna.UI2.WinForms.Suite;
using System.IO.Ports;
using DocumentFormat.OpenXml.Drawing;
using Sunny.UI;
using WindowsFormsApp1;
using Spire.Xls.Core;
using Newtonsoft.Json.Linq;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using C_Windows_1;
using static C_Windows_1.MES;
using System.Reflection.Emit;
using static SLC1_N.DataUp;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Header;
using DocumentFormat.OpenXml.Office2016.Excel;
using Microsoft.VisualBasic.Logging;


namespace SLC1_N
{
    public partial class Form1 : Form
    {
        public static Form1 f1;
        private readonly WindowAutoResizer resizer; // readonly 只能在 声明时初始化或在类的构造函数中赋值，之后不能被修改（不可重新赋值）
        private CancellationTokenSource cts; // 用于协调任务的取消操作

        public string User;    // 记录当前用户

        public ModbusTCP_28 LL28CH1client; // 28客户端线程类
        public ModbusTCP_28 LL28CH2client;
        public ModbusTCP_28 LL28CH3client; // 28客户端线程类
        public ModbusTCP_28 LL28CH4client;

        public SaomaClient saomaClient1;   // 扫码枪客户端
        public SaomaClient saomaClient2;

        public string localipaddress; // 本机IP
        public string ch1ipaddress;   // 记录仪器CH1的IP地址
        public string ch2ipaddress;   // 记录仪器CH2的IP地址
        public string ch3ipaddress;   // 记录仪器CH3的IP地址
        public string ch4ipaddress;   // 记录仪器CH4的IP地址

        ProductionRecord m_production = new ProductionRecord(); // 产能记录

        public bool m_ContinueTest;     // 连续测试
        public int m_ContinueTestCount; // 连续次数

        // 测试次数
        private int CH1testCount = 0;
        private int CH2testCount = 0;
        private int CH3testCount = 0;
        private int CH4testCount = 0;

        public FileSave filesave; // 保存文件设置
        public static bool MESswitch = false; // MES开关

        public delegate void MySignalHandler(int msg, bool mode); // 声明信号
        public event MySignalHandler Signal_SaomaStart;           // 定义信号
        public event MySignalHandler Signal_PLCStatus;            // 定义信号

        // PLC客户端初始化
        // ModbusClient modbusClient = new ModbusClient("192.168.1.88", 502);
        // ModbusClient modbusClient = new ModbusClient("127.0.0.1", 502);
        //ModbusClient modbusClient;

        public ModbusClient HCPLC_client = new ModbusClient();


        // 主界面
        public Form1()
        {
            Control.CheckForIllegalCrossThreadCalls = false; // 禁用跨线程访问控件的异常检查
            InitializeComponent();
            resizer = new WindowAutoResizer(this);
            f1 = this;
            InitializeAfterLoadAsync();
        }

        // 主窗口初始化
        private void Form1_Load(object sender, EventArgs e)
        {
            // 启用线程检查
            //Control.CheckForIllegalCrossThreadCalls = true;

            // 界面初始化
            tb_CH1Code.Text = "";
            tb_CH2Code.Text = "";
            lb_CH1_Result.Text = " ";
            lb_CH2_Result.Text = " ";

            tb_CH3Code.Text = "";
            tb_CH4Code.Text = "";
            lb_CH3_Result.Text = " ";
            lb_CH4_Result.Text = " ";

            // DataGridView 行自动调整高度
            DataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            DataGridView2.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;

            User = "操作员";
            lb_User.Text = "操作员";

            // 清理log文件 保留近30天
            Task.Run(() =>
            {
                mxlLog.Instance.ClearOldLogs(30);
            });

            // 显示时间
            timer_nowTime.Start();

            // 定时清理垃圾
            timer1.Interval = 50000;
            timer1.Start();

            // 用户重置
            UserClear.Interval = 300000;
            UserClear.Start();

            // 发送扫码启动
            timer_SaomaStart.Interval = 500;
            //timer_SaomaStart.Start();

            // 间隔8S清除消息框
            if (lb_User.Text == "操作员")
            {
                tb_CH1codeLeng.Enabled = false;
                tb_CH2codeLeng.Enabled = false;
                tb_CH3codeLeng.Enabled = false;
                tb_CH4codeLeng.Enabled = false;
            }

            // 产能初始化
            Production_Init();

            // 标志位初始化
            Flag_Init();

            // 仪器客户端初始化
            CHXclient_Init();

            // 初始化CancellationTokenSource
            cts = new CancellationTokenSource(); // 创建了取消令牌源 cts 
            Task.Run(() => RunMachine(cts.Token), cts.Token); // 将令牌传递给后台任务 第二个cts.Token 确保任务异常时能自动取消
            Task.Run(() => RunMachine2(cts.Token), cts.Token);
            Task.Run(() => RunMachine3(cts.Token), cts.Token);
            Task.Run(() => RunMachine4(cts.Token), cts.Token);

            // 扫码枪初始化
            var jsconfig = new JsonConfig("config.json");
            string saoma = jsconfig.GetValue<string>("CodeScanner", "SerialPort");
            if(saoma == "SerialPort")
            {
                // 串口扫码枪初始化
                SerialPort_Saoma_Init();
            }
            else if (saoma == "TCP")
            {
                // TCP扫码枪初始化
                TCPSaoma_Init();
            }

            // MES初始化
            MES_Init();

            // PLC客户端初始化
            //PLCclient_Init();

            if (Environment.MachineName.Trim() == "PC-20230419CFZS")  // 计算机名
            {
                lb_User.Text = "厂商";
                User = "厂商";
            }

        }

        private async void InitializeAfterLoadAsync()
        {
            // 等待窗口完全初始化
            await Task.Delay(100);
            InitializeAfterLoad();
        }

        private void InitializeAfterLoad()
        {

        }

        // 显示槽
        private void Slot_MainShow(bool mode)
        {
            this.Show();
            this.Enabled = mode;
            if(!mode)
            {
                this.Close();
            }
        }

        // 产能初始化
        void Production_Init()
        {
            UploadProductionData(m_production.GetTotal(), m_production.GetOK(), m_production.GetNG(), m_production.GetOKRate()); // 更新产能 
        }

        // MES数据
        public string mes_partno; // 料号
        public string mes_station; // 工站名称
        public string mes_workorder; // 工单
        public string mes_equipmentno; // 设备编号
        public string mes_fixturecode; // 夹具编号
        public string mes_plan; // 工厂

        // MES初始化
        private void MES_Init()
        {
            var jsconfig = new JsonConfig("config.json");

            m_LINE = jsconfig.GetValue<string>("LINE", "1");
            m_ActionName = jsconfig.GetValue<string>("ActionName", " ");
            m_Tools = jsconfig.GetValue<string>("Tools", " ");

            // MES开关
            MESswitch = jsconfig.GetValue<bool>("MESswitch", false);
            if (MESswitch && HQMES_Init())
            {
                lb_MESswitch.Text = "MES在线";
                pb_MESswitch.BackColor = Color.Green;
            }
            else
            {
                MESswitch = false;
                lb_MESswitch.Text = "MES离线";
                pb_MESswitch.BackColor = Color.Red;
            }
        }

        // 标志位初始化
        private void Flag_Init()
        {
            var jsconfig = new JsonConfig("config.json");
            //Console.WriteLine($"实际加载的JSON内容: {jsconfig.ShowAllValues()}");

            // 条码长度
            tb_CH1codeLeng.Text = jsconfig.GetValue<string>("CodeLength1", "9");
            tb_CH2codeLeng.Text = jsconfig.GetValue<string>("CodeLength2", "9");
            tb_CH3codeLeng.Text = jsconfig.GetValue<string>("CodeLength3", "9");
            tb_CH4codeLeng.Text = jsconfig.GetValue<string>("CodeLength4", "9");

            // 日志使能
            mxlLog.Instance.IsDebugEnabled = jsconfig.GetValue<bool>("IsDebugEnabled", false);
            mxlLog.Instance.IsErrorEnabled = jsconfig.GetValue<bool>("IsErrorEnabled", false);
            mxlLog.Instance.IsInfoEnabled = jsconfig.GetValue<bool>("IsInfoEnabled", false);
            mxlLog.Instance.IsWarningEnabled = jsconfig.GetValue<bool>("IsWarningEnabled", false);
            mxlLog.Instance.IsXXXEnabled = jsconfig.GetValue<bool>("IsXXXEnabled", false);

            // 连续测试/次数
            m_ContinueTest = jsconfig.GetValue<bool>("chk_ContinueTest", true);
            m_ContinueTestCount = jsconfig.GetValue<int>("tb_ContinueTestCount", 1);

            // 仪器ip
            if (string.IsNullOrEmpty(ch1ipaddress))
            {
                ch1ipaddress = jsconfig.GetValue<string>("ch1ipaddress", "192.168.1.131");
            }
            if (string.IsNullOrEmpty(ch2ipaddress))
            {
                ch2ipaddress = jsconfig.GetValue<string>("ch2ipaddress", "192.168.1.130");
            }
            if (string.IsNullOrEmpty(ch3ipaddress))
            {
                ch3ipaddress = jsconfig.GetValue<string>("ch3ipaddress", "192.168.1.129");
            }
            if (string.IsNullOrEmpty(ch4ipaddress))
            {
                ch4ipaddress = jsconfig.GetValue<string>("ch4ipaddress", "192.168.1.128");
            }
            ch1AutoConnect = jsconfig.GetValue<bool>("ch1AutoConnect", true);
            ch2AutoConnect = jsconfig.GetValue<bool>("ch2AutoConnect", true);
            ch3AutoConnect = jsconfig.GetValue<bool>("ch3AutoConnect", true);
            ch4AutoConnect = jsconfig.GetValue<bool>("ch4AutoConnect", true);

            // 写入文件 标志位
            filesave = new FileSave();
            filesave.TXT = jsconfig.GetValue<bool>("TXT", false);
            filesave.Excel = jsconfig.GetValue<bool>("Excel", false);
            filesave.CSV = jsconfig.GetValue<bool>("CSV", false); 
            filesave.Path = jsconfig.GetValue<string>("FilePath", ""); 
        }

        // 仪器客户端初始化
        private void CHXclient_Init()
        {
            // 线程客户端初始化
            // 通道1
            if (LL28CH1client == null)
            {
                LL28CH1client = new ModbusTCP_28(1);
                LL28CH1client.Connect(ch1ipaddress);
                LL28CH1client.Start();
            }

            // 通道2
            if (LL28CH2client == null)
            {
                LL28CH2client = new ModbusTCP_28(2);
                LL28CH2client.Connect(ch2ipaddress);
                LL28CH2client.Start();
            }

            // 通道3
            if (LL28CH3client == null)
            {
                LL28CH3client = new ModbusTCP_28(3);
                LL28CH3client.Connect(ch3ipaddress);
                LL28CH3client.Start();
            }

            // 通道4
            if (LL28CH4client == null)
            {
                LL28CH4client = new ModbusTCP_28(4);
                LL28CH4client.Connect(ch4ipaddress);
                LL28CH4client.Start();
            }

            timer_yiqiRun.Interval = 500;
            timer_yiqiRun.Start(); // 定时器 监控仪器通讯状态
        }


        public readonly object plcLock = new object();

        // PLC客户端初始化
        private void PLCclient_Init()
        {
            var jsconfig = new JsonConfig("config.json");

            // PLC地址
            //string plcip = jsconfig.GetValue<string>("PLC_IP", "192.168.1.88");
            //int plcport = jsconfig.GetValue<int>("PLC_Port", 502);

            string PortName = jsconfig.GetValue<string>("PLC_PortName", "COM3");
            int BaudRate = jsconfig.GetValue<int>("PLC_BaudRate", 9600);

            HCPLC_client = new ModbusClient();

            if (HCPLC_client.Connected)
            {
                HCPLC_client.Disconnect();
            }

            try
            {
                HCPLC_client.SerialPort = PortName;
                HCPLC_client.Baudrate = BaudRate;          // 波特率
                HCPLC_client.Parity = System.IO.Ports.Parity.None;  // 无校验
                //HCPLC_client.DataBits = 7;             // 数据位
                HCPLC_client.StopBits = System.IO.Ports.StopBits.Two; // 停止位
                //HCPLC_client.UnitIdentifier = 1;       // 站号
                //HCPLC_client.ConnectionTimeout = 1000; // 连接超时
                

                HCPLC_client.Connect(); // 会异常
            }
            catch
            {

            }

            // 绑定PLC状态信号
            //Signal_SaomaStart += Slot_SaomaStart;
            Signal_PLCStatus += Slot_PLCStatus;

            // PLC读取扫码枪启动io监控
            Task.Run(() =>
            {
                while (true)
                {
                    Thread.Sleep(100);
                    try
                    {
                        if (!HCPLC_client.Connected)
                        {
                            Signal_PLCStatus?.Invoke(0, false); // 更新PLC连接状态UI
                            HCPLC_client.Connect();
                        }
                        else
                        {
                            lock (plcLock)  // 加锁
                            {
                                HCPLC_client.ReadHoldingRegisters(0, 1); // 如果失败，会抛异常
                            }
                            
                            Thread.Sleep(10);
                            //bool[] coil501 = HCPLC_client.ReadCoils(501, 4); //  读到=true 启动扫码枪扫码 =false 无操作
                            ////bool[] coil504 = modbusClient.ReadCoils(504, 1);

                            //if (coil501[0]) // 通道1
                            //{
                            //    Signal_SaomaStart?.Invoke(1, true);  // 扫码启动信号
                            //}
                            //if (coil501[3]) // 通道2
                            //{
                            //    Signal_SaomaStart?.Invoke(2, true);
                            //}

                            Signal_PLCStatus?.Invoke(0, true); // 更新PLC连接状态UI

                            //Console.WriteLine($"通道1是否启动扫码枪: {coil501[0]}");
                            //Console.WriteLine($"通道2是否启动扫码枪: {coil501[3]}");
                        }
                    }
                    catch (Exception ex)
                    {
                        Signal_PLCStatus?.Invoke(0, false); // 更新PLC连接状态UI
                        Console.WriteLine($"❌ PLC连接异常: {ex.Message}");
                    }
                    Thread.Sleep(3000);
                }
            });
        }

        // 串口扫码使能
        public bool serialport_saoma_Enabled = false; 

        // 串口扫码枪初始化
        private void SerialPort_Saoma_Init()
        {
            try
            {
                serialport_saoma_Enabled = true;
                var jsconfig = new JsonConfig("config.json");

                int SerialPort_CH1BaudRate = jsconfig.GetValue<int>("SerialPort_CH1BaudRate", 9600);
                string SerialPort_CH1PortName = jsconfig.GetValue<string>("SerialPort_CH1PortName", "COM21");
                int SerialPort_CH2BaudRate = jsconfig.GetValue<int>("SerialPort_CH2BaudRate", 9600);
                string SerialPort_CH2PortName = jsconfig.GetValue<string>("SerialPort_CH2PortName", "COM11");

                int SerialPort_CH3BaudRate = jsconfig.GetValue<int>("SerialPort_CH3BaudRate", 9600);
                string SerialPort_CH3PortName = jsconfig.GetValue<string>("SerialPort_CH3PortName", "COM11");
                int SerialPort_CH4BaudRate = jsconfig.GetValue<int>("SerialPort_CH4BaudRate", 9600);
                string SerialPort_CH4PortName = jsconfig.GetValue<string>("SerialPort_CH4PortName", "COM11");

                //设置端口的参数，包括波特率等
                // 扫码枪1
                SerialPort_CH1Saoma.BaudRate = SerialPort_CH1BaudRate;
                SerialPort_CH1Saoma.PortName = SerialPort_CH1PortName;
                SerialPort_CH1Saoma.DataBits = 8;
                SerialPort_CH1Saoma.StopBits = System.IO.Ports.StopBits.One;
                SerialPort_CH1Saoma.Parity = System.IO.Ports.Parity.None;
                SerialPort_CH1Saoma.Open();
                if (SerialPort_CH1Saoma.IsOpen)
                {
                    Console.WriteLine($"SerialPort_CH1Saoma: T");
                }
                else
                {
                    Console.WriteLine($"SerialPort_CH1Saoma: F");
                    SetUITextBox(tb_CH1MainMessage, $"CH1串口扫码枪打开失败");
                }

                // 扫码枪2
                SerialPort_CH2Saoma.BaudRate = SerialPort_CH2BaudRate;
                SerialPort_CH2Saoma.PortName = SerialPort_CH2PortName;
                SerialPort_CH2Saoma.DataBits = 8;
                SerialPort_CH2Saoma.StopBits = System.IO.Ports.StopBits.One;
                SerialPort_CH2Saoma.Parity = System.IO.Ports.Parity.None;
                SerialPort_CH2Saoma.Open();
                if (SerialPort_CH2Saoma.IsOpen)
                {
                    Console.WriteLine($"SerialPort_CH2Saoma: T");
                }
                else
                {
                    Console.WriteLine($"SerialPort_CH2Saoma: F");
                    SetUITextBox(tb_CH2MainMessage, $"CH2串口扫码枪打开失败");
                }

                // 扫码枪3
                SerialPort_CH3Saoma.BaudRate = SerialPort_CH3BaudRate;
                SerialPort_CH3Saoma.PortName = SerialPort_CH3PortName;
                SerialPort_CH3Saoma.DataBits = 8;
                SerialPort_CH3Saoma.StopBits = System.IO.Ports.StopBits.One;
                SerialPort_CH3Saoma.Parity = System.IO.Ports.Parity.None;
                SerialPort_CH3Saoma.Open();
                if (SerialPort_CH3Saoma.IsOpen)
                {
                    Console.WriteLine($"SerialPort_CH3Saoma: T");
                }
                else
                {
                    Console.WriteLine($"SerialPort_CH3Saoma: F");
                    SetUITextBox(tb_CH1MainMessage, $"CH3串口扫码枪打开失败");
                }

                // 扫码枪4
                SerialPort_CH4Saoma.BaudRate = SerialPort_CH4BaudRate;
                SerialPort_CH4Saoma.PortName = SerialPort_CH4PortName;
                SerialPort_CH4Saoma.DataBits = 8;
                SerialPort_CH4Saoma.StopBits = System.IO.Ports.StopBits.One;
                SerialPort_CH4Saoma.Parity = System.IO.Ports.Parity.None;
                SerialPort_CH4Saoma.Open();
                if (SerialPort_CH4Saoma.IsOpen)
                {
                    Console.WriteLine($"SerialPort_CH4Saoma: T");
                }
                else
                {
                    Console.WriteLine($"SerialPort_CH4Saoma: F");
                    SetUITextBox(tb_CH2MainMessage, $"CH4串口扫码枪打开失败");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"串口扫码枪初始化 异常,行号{ex.StackTrace},{ex.Message}");
                mxlLog.Instance.Error($"串口扫码枪初始化 异常 ,行号{ex.StackTrace} ", ex);
            }
        }

        // 网口扫码使能
        public bool tcpSaoma_Enabled = false;
        // TCP扫码枪初始化
        private void TCPSaoma_Init()
        {
            tcpSaoma_Enabled = true;
            var jsconfig = new JsonConfig("config.json");

            // 扫码枪客户端初始化
            string smip1 = jsconfig.GetValue<string>("Saoma_IP1", "127.0.0.1");
            int smport1 = jsconfig.GetValue<int>("Saoma_Port1", 51111);
            string smip2 = jsconfig.GetValue<string>("Saoma_IP2", "127.0.0.1");
            int smport2 = jsconfig.GetValue<int>("Saoma_Port2", 52222);

            saomaClient1 = new SaomaClient(
                smip1,    // IP地址
                smport1,  // 端口号
                Convert.ToInt32(tb_CH1codeLeng.Text),  // 条码长度
                code => {
                    TCPCode_DataReceived(1, code);
                },
                error => {
                    mxlLog.Instance.Error($"CH1 {error} ");
                },
                status => {
                    SetUITextBox(tb_CH1MainMessage, $"CH1 {status} ");
                });

            saomaClient2 = new SaomaClient(
                smip2,    // IP地址
                smport2,  // 端口号
                Convert.ToInt32(tb_CH2codeLeng.Text),  // 条码长度
                code => {
                    TCPCode_DataReceived(2, code);
                },
                error => {
                    mxlLog.Instance.Error($"CH2 {error} ");
                },
                status => {
                    SetUITextBox(tb_CH2MainMessage, $"CH2 {status} ");
                });

            Task.Run(() =>
            {
                saomaClient1.Connect();
                saomaClient2.Connect();
            });
        }

        // PLC连接状态
        private void Slot_PLCStatus(int msg, bool mode)
        {
            //Console.WriteLine($"PLC连接状态: {mode}");
            if (mode)
                pb_PLC_CommunicationStatus.BackColor = Color.Green;
            else
                pb_PLC_CommunicationStatus.BackColor = Color.Red;
        }

        // PLC写入线圈槽函数
        private async void Slot_PLC_WriteCoil(int msg, bool mode)
        {
            try
            {
                if (HCPLC_client?.Connected != true)
                    return;

                // 使用Task超时控制, 防止10s太久死锁
                var writeTask = Task.Run(() =>
                {
                    lock (plcLock)
                    {
                        HCPLC_client.WriteMultipleCoils(msg, new bool[] { mode }); // 写超时10s不可配置
                    }
                });

                // 设置2秒超时
                if (await Task.WhenAny(writeTask, Task.Delay(2000)) == writeTask)
                {
                    await writeTask; // 确保任务完成
                }
                else
                {
                    mxlLog.Instance.Warning($"PLC写入超时，地址: {msg}, 模式: {mode}");
                }
            }
            catch (Exception ex)
            {
                mxlLog.Instance.Error($"PLC写入槽函数异常, 地址: {msg}, 错误: {ex.Message}");
            }
        }

        // 扫码启动槽
        private void Slot_SaomaStart(int msg, bool mode = false)
        {
            //Console.WriteLine($"扫码启动槽: {msg}");
            string data = "73 74 61 72 74"; // "start"
            byte[] byt = StrtoHexbyte(data);
            switch (msg)
            {
                case 1:   // 扫码枪1启动              
                    if (serialport_saoma_Enabled && SerialPort_CH1Saoma != null && SerialPort_CH1Saoma.IsOpen)
                    {
                        SerialPort_CH1Saoma.Write(byt, 0, byt.Length);
                    }

                    if(tcpSaoma_Enabled)
                        saomaClient1?.SendStartCommand();
                    break;

                case 2:   // 扫码枪2启动             
                    if (serialport_saoma_Enabled && SerialPort_CH2Saoma != null && SerialPort_CH2Saoma.IsOpen)
                    {
                        SerialPort_CH2Saoma.Write(byt, 0, byt.Length);
                    }

                    if (tcpSaoma_Enabled)
                        saomaClient2?.SendStartCommand();
                    break;

                case 3:   // 扫码枪3启动              
                    if (serialport_saoma_Enabled && SerialPort_CH3Saoma != null && SerialPort_CH3Saoma.IsOpen)
                    {
                        SerialPort_CH3Saoma.Write(byt, 0, byt.Length);
                    }

                    //if (tcpSaoma_Enabled)
                    //    saomaClient3?.SendStartCommand();
                    break;

                case 4:   // 扫码枪4启动              
                    if (serialport_saoma_Enabled && SerialPort_CH4Saoma != null && SerialPort_CH4Saoma.IsOpen)
                    {
                        SerialPort_CH4Saoma.Write(byt, 0, byt.Length);
                    }

                    //if (tcpSaoma_Enabled)
                    //    saomaClient4?.SendStartCommand();
                    break;
            }
        }


        string ch1_oldcode = "";
        string ch2_oldcode = "";

        // TCP收到条码
        private void TCPCode_DataReceived(int CH, string code)
        {
            try
            {
                if (CH == 1)
                {
                    string CODE = code.Replace("\r\n", "");

                    //Console.WriteLine("扫码枪1收到:" + code);
                    if (!CODE.IsNullOrEmpty() && CODE.Length.ToString() == tb_CH1codeLeng.Text)
                    {
                        //SetUITextBox(tb_CH1MainMessage, "CH1 TCP扫码完成");
                        
                        if(CODE == ch1_oldcode)
                        {
                            return;
                        }
                        ch1_oldcode = CODE;
                        tb_CH1Code.Text = CODE;

                        if (MESswitch)
                        {
                            SetLabelText(lb_CH1MES_OUTstatus, "");

                            var rdata = ruzhan(CODE, m_ActionName, m_Tools);
                            if (rdata.result)
                            {
                                SetLabelText(lb_CH1MES_INstatus, "PASS", Color.Green);
                            }
                            else
                            {
                                SetLabelText(lb_CH1MES_INstatus, "NG", Color.Red);
                                SetUITextBox(tb_CH1MainMessage, $"CH1 入站NG:{rdata.msg}");
                            }
                            SetLabelText(lb_CH1MES_OUTstatus, "");
                        }
                    }
                    else
                    {
                        SetUITextBox(tb_CH1MainMessage, "CH1 当前条形码长度为" + CODE.Length + "所设置的条码长度为" + tb_CH1codeLeng.Text);
                    }
                }
                if (CH == 2)
                {
                    string CODE = code.Replace("\r\n", "");

                    //Console.WriteLine("扫码枪2收到:" + code);
                    if (!CODE.IsNullOrEmpty() && CODE.Length.ToString() == tb_CH2codeLeng.Text)
                    {
                        //SetUITextBox(tb_CH2MainMessage, "CH2 TCP扫码完成");

                        if (CODE == ch2_oldcode)
                        {
                            return;
                        }
                        ch2_oldcode = CODE;
                        tb_CH2Code.Text = CODE;

                        if (MESswitch)
                        {
                            SetLabelText(lb_CH2MES_OUTstatus, "");

                            var rdata = ruzhan(CODE, m_ActionName, m_Tools);
                            if (rdata.result)
                            {
                                SetLabelText(lb_CH2MES_INstatus, "PASS", Color.Green);
                            }
                            else
                            {
                                SetLabelText(lb_CH2MES_INstatus, "NG", Color.Red);
                                SetUITextBox(tb_CH2MainMessage, $"CH2 入站NG:{rdata.msg}");
                            }
                            SetLabelText(lb_CH2MES_OUTstatus, "");
                        }
                    }
                    else
                    {
                        SetUITextBox(tb_CH2MainMessage, "CH2 当前条形码长度为" + CODE.Length + "所设置的条码长度为" + tb_CH2codeLeng.Text);
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理MES上传异常
            }
        }


        public struct RtValue
        {
            public bool result { get; set; }
            public string data { get; set; }

            public RtValue(bool Result, string Data)
            {
                result = Result;
                data =Data;
            }
        }

        public struct TestTime
        {
            public string startTime { get; set; }
            public string stopTime { get; set; }

            public TestTime(string startTime, string stopTime)
            {
                this.startTime = startTime;
                this.stopTime = stopTime;
            }
        }


        /*
        // MES 入站
        private RtValue ruzhan(int CH, string code, string mode = null)
        {
            RtValue ruzhan_result = new RtValue(false, "##");
            switch (CH)
            { 
                case 1:
                    {
                        MES mes = new MES(urlip, urlport);
                        var request = new MES_IN_Data
                        {
                            time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            code = code,
                            fulltime =  (LL28CH1client.ArrRegister[6] / 10.0).ToString(),        // 充气时间
                            balantime = (LL28CH1client.ArrRegister[7] / 10.0).ToString(),        // 平衡时间
                            testtime =  (LL28CH1client.ArrRegister[8] / 10.0).ToString(),        // 检测时间
                            exhausttime = (LL28CH1client.ArrRegister[9] / 10.0).ToString()       // 排气时间
                        };
                        string response = mes.UploadData(request);

                        if (response.Contains("OK") || response.Contains("ok")
                            || response.Contains("TRUE") || response.Contains("true")
                            || response.Contains("PASS") || response.Contains("pass")
                            || response.Contains("Success") || response.Contains("success"))
                        {
                            ruzhan_result.result = true;
                            ruzhan_result.data = response;
                        }
                        else
                        {
                            ruzhan_result.result = false;
                            ruzhan_result.data = response;
                        }
                    }
                    break;
                case 2:
                    {
                        MES mes = new MES(urlip, urlport);
                        var request = new MES_IN_Data
                        {
                            time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            code = code,
                            fulltime = (LL28CH2client.ArrRegister[6] / 10.0).ToString(),        // 充气时间
                            balantime = (LL28CH2client.ArrRegister[7] / 10.0).ToString(),       // 平衡时间
                            testtime = (LL28CH2client.ArrRegister[8] / 10.0).ToString(),        // 检测时间
                            exhausttime = (LL28CH2client.ArrRegister[9] / 10.0).ToString()      // 排气时间
                        };
                        string response = mes.UploadData(request);

                        if (response.Contains("OK") || response.Contains("ok")
                            || response.Contains("TRUE") || response.Contains("true")
                            || response.Contains("PASS") || response.Contains("pass")
                            || response.Contains("Success") || response.Contains("success"))
                        {
                            ruzhan_result.result = true;
                            ruzhan_result.data = response;
                        }
                        else
                        {
                            ruzhan_result.result = false;
                            ruzhan_result.data = response;
                        }
                    }
                    break;
                case 3:
                    {
                        MES mes = new MES(urlip, urlport);
                        var request = new MES_IN_Data
                        {
                            time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            code = code,
                            fulltime = (LL28CH3client.ArrRegister[6] / 10.0).ToString(),        // 充气时间
                            balantime = (LL28CH3client.ArrRegister[7] / 10.0).ToString(),       // 平衡时间
                            testtime = (LL28CH3client.ArrRegister[8] / 10.0).ToString(),        // 检测时间
                            exhausttime = (LL28CH3client.ArrRegister[9] / 10.0).ToString()      // 排气时间
                        };
                        string response = mes.UploadData(request);

                        if (response.Contains("OK") || response.Contains("ok")
                            || response.Contains("TRUE") || response.Contains("true")
                            || response.Contains("PASS") || response.Contains("pass")
                            || response.Contains("Success") || response.Contains("success"))
                        {
                            ruzhan_result.result = true;
                            ruzhan_result.data = response;
                        }
                        else
                        {
                            ruzhan_result.result = false;
                            ruzhan_result.data = response;
                        }
                    }
                    break;
                case 4:
                    {
                        MES mes = new MES(urlip, urlport);
                        var request = new MES_IN_Data
                        {
                            time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            code = code,
                            fulltime = (LL28CH4client.ArrRegister[6] / 10.0).ToString(),        // 充气时间
                            balantime = (LL28CH4client.ArrRegister[7] / 10.0).ToString(),       // 平衡时间
                            testtime = (LL28CH4client.ArrRegister[8] / 10.0).ToString(),        // 检测时间
                            exhausttime = (LL28CH4client.ArrRegister[9] / 10.0).ToString()      // 排气时间
                        };
                        string response = mes.UploadData(request);

                        if (response.Contains("OK") || response.Contains("ok")
                            || response.Contains("TRUE") || response.Contains("true")
                            || response.Contains("PASS") || response.Contains("pass")
                            || response.Contains("Success") || response.Contains("success"))
                        {
                            ruzhan_result.result = true;
                            ruzhan_result.data = response;
                        }
                        else
                        {
                            ruzhan_result.result = false;
                            ruzhan_result.data = response;
                        }
                    }
                    break;
            }

            return ruzhan_result;
        }

        private RtValue chuzhan(int CH, string code, bool result, string mode = null)
        {
            RtValue ruzhan_result = new RtValue(false, "##");
            switch (CH)
            {
                case 1:
                    {
                        MES mes = new MES(urlip, urlport);
                        var request = new MES_OUT_Data
                        {
                            time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            code = code,
                            result = result ? "OK" : "NG",
                            TestPressure = LL28CH1client.readFloatF2(57).ToString(),  // 测试压力
                            LeakValue = LL28CH1client.readFloatF2(38).ToString(),     // 泄漏量
                        };
                        string response = mes.UploadData(request);

                        if (response.Contains("OK") || response.Contains("ok")
                            || response.Contains("TRUE") || response.Contains("true")
                            || response.Contains("PASS") || response.Contains("pass")
                            || response.Contains("Success") || response.Contains("success"))
                        {
                            ruzhan_result.result = true;
                            ruzhan_result.data = response;
                        }
                        else
                        {
                            ruzhan_result.result = false;
                            ruzhan_result.data = response;
                        }
                    }
                    break;
                case 2:
                    {
                        MES mes = new MES(urlip, urlport);
                        var request = new MES_OUT_Data
                        {
                            time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            code = code,
                            result = result ? "OK":"NG",
                            TestPressure = LL28CH2client.readFloatF2(57).ToString(),  // 测试压力
                            LeakValue = LL28CH2client.readFloatF2(38).ToString(),     // 泄漏量
                        };
                        string response = mes.UploadData(request);

                        if (response.Contains("OK") || response.Contains("ok")
                            || response.Contains("TRUE") || response.Contains("true")
                            || response.Contains("PASS") || response.Contains("pass")
                            || response.Contains("Success") || response.Contains("success"))
                        {
                            ruzhan_result.result = true;
                            ruzhan_result.data = response;
                        }
                        else
                        {
                            ruzhan_result.result = false;
                            ruzhan_result.data = response;
                        }
                    }
                    break;
                case 3:
                    {
                        MES mes = new MES(urlip, urlport);
                        var request = new MES_OUT_Data
                        {
                            time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            code = code,
                            result = result ? "OK" : "NG",
                            TestPressure = LL28CH3client.readFloatF2(57).ToString(),  // 测试压力
                            LeakValue = LL28CH3client.readFloatF2(38).ToString(),     // 泄漏量
                        };
                        string response = mes.UploadData(request);

                        if (response.Contains("OK") || response.Contains("ok")
                            || response.Contains("TRUE") || response.Contains("true")
                            || response.Contains("PASS") || response.Contains("pass")
                            || response.Contains("Success") || response.Contains("success"))
                        {
                            ruzhan_result.result = true;
                            ruzhan_result.data = response;
                        }
                        else
                        {
                            ruzhan_result.result = false;
                            ruzhan_result.data = response;
                        }
                    }
                    break;
                case 4:
                    {
                        MES mes = new MES(urlip, urlport);
                        var request = new MES_OUT_Data
                        {
                            time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            code = code,
                            result = result ? "OK" : "NG",
                            TestPressure = LL28CH4client.readFloatF2(57).ToString(),  // 测试压力
                            LeakValue = LL28CH4client.readFloatF2(38).ToString(),     // 泄漏量
                        };
                        string response = mes.UploadData(request);

                        if (response.Contains("OK") || response.Contains("ok")
                            || response.Contains("TRUE") || response.Contains("true")
                            || response.Contains("PASS") || response.Contains("pass")
                            || response.Contains("Success") || response.Contains("success"))
                        {
                            ruzhan_result.result = true;
                            ruzhan_result.data = response;
                        }
                        else
                        {
                            ruzhan_result.result = false;
                            ruzhan_result.data = response;
                        }
                    }
                    break;
            }

            return ruzhan_result;
        }

        */

        // 将令牌传递给后台任务 第二个cts.Token 确保任务异常时能自动取消
        private void RunMachine(CancellationToken token)
        {
            ch1workstation = (int)yiqi.standby;
            while (!token.IsCancellationRequested)
            {
                try
                {
                    Thread.Sleep(500); // 使用Thread.Sleep而不是Task.Delay，因为这是后台线程

                    if (!token.IsCancellationRequested)
                    {
                        CH1machine();
                    }
                }
                catch (OperationCanceledException)
                {
                    break;// 任务被取消，正常退出
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"CH1状态机更新错误: {ex.Message} ,行号{ex.StackTrace}"); // 记录错误但继续运行
                    mxlLog.Instance.Error($"CH1状态机更新错误 ,行号{ex.StackTrace} ", ex);
                }
            }
        }

        private void RunMachine2(CancellationToken token)
        {
            ch2workstation = (int)yiqi.standby;
            while (!token.IsCancellationRequested)
            {
                try
                {
                    Thread.Sleep(500); // 使用Thread.Sleep而不是Task.Delay，因为这是后台线程

                    if (!token.IsCancellationRequested)
                    {
                        CH2machine();
                    }
                }
                catch (OperationCanceledException)
                {
                    break;// 任务被取消，正常退出
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"CH2状态机更新错误: {ex.Message} ,行号{ex.StackTrace}"); // 记录错误但继续运行
                    mxlLog.Instance.Error($"CH2状态机更新错误 ,行号{ex.StackTrace} ", ex);
                }
            }
        }

        private void RunMachine3(CancellationToken token)
        {
            ch3workstation = (int)yiqi.standby;
            while (!token.IsCancellationRequested)
            {
                try
                {
                    Thread.Sleep(500); // 使用Thread.Sleep而不是Task.Delay，因为这是后台线程

                    if (!token.IsCancellationRequested)
                    {
                        CH3machine();
                    }
                }
                catch (OperationCanceledException)
                {
                    break;// 任务被取消，正常退出
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"CH3状态机更新错误: {ex.Message} ,行号{ex.StackTrace}"); // 记录错误但继续运行
                    mxlLog.Instance.Error($"CH3状态机更新错误 ,行号{ex.StackTrace} ", ex);
                }
            }
        }

        private void RunMachine4(CancellationToken token)
        {
            ch4workstation = (int)yiqi.standby;
            while (!token.IsCancellationRequested)
            {
                try
                {
                    Thread.Sleep(500); // 使用Thread.Sleep而不是Task.Delay，因为这是后台线程

                    if (!token.IsCancellationRequested)
                    {
                        CH4machine();
                    }
                }
                catch (OperationCanceledException)
                {
                    break;// 任务被取消，正常退出
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"CH4状态机更新错误: {ex.Message} ,行号{ex.StackTrace}"); // 记录错误但继续运行
                    mxlLog.Instance.Error($"CH4状态机更新错误 ,行号{ex.StackTrace} ", ex);
                }
            }
        }

        int ch1workstation; // 状态
        public enum yiqi
        {
            start,  //启动
            rst,    //复位
            prepare,//准备
            test,   //测试
            finish, //完成（导出数据）
            writedate,//写入数据
            standby,//待机
        };

        TestTime CH1TestTime = new TestTime(); 
        TestTime CH2TestTime = new TestTime(); 
        TestTime CH3TestTime = new TestTime(); 
        TestTime CH4TestTime = new TestTime();

        private Dictionary<int, DateTime> prepareOutTime_Dictionary = new Dictionary<int, DateTime>();


        // 通道1状态机
        public void CH1machine()
        {
            switch (ch1workstation)
            {
                case (int)yiqi.start:
                    {
                        SetLabelText(lb_CH1_Status, "启动");
                        LL28CH1client.writeCoil("0", true);
                        ch1workstation = (int)yiqi.prepare;
                    }
                    break;

                case (int)yiqi.rst:
                    {
                        SetProgressBar(pb_CH1progressBar, 0); // 复位进度条置为0
                        SetLabelText(lb_CH1_Status, "复位");
                        CH1testCount = 0; // 重置测试次数
                        LL28CH1client.writeCoil("1", true);
                        ch1workstation = (int)yiqi.standby;
                    }
                    break;

                case (int)yiqi.prepare://读取检测时间，充气，平衡检测
                    {
                        // 准备超时处理
                        if (!prepareOutTime_Dictionary.ContainsKey(1))
                        {
                            prepareOutTime_Dictionary[1] = DateTime.Now.AddSeconds(5); // 5s后还在准备就去启动
                        }
                        else if (DateTime.Now > prepareOutTime_Dictionary[1])
                        {
                            prepareOutTime_Dictionary.Remove(1); // 清除超时记录
                            ch1workstation = (int)yiqi.start;
                            break;
                        }

                        CH1TestTime.startTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        SetLabelText(lb_CH1_Result, "");
                        SetLabelText(lb_CH1_Status, "准备");

                        int CH1progressbar = Convert.ToInt32(LL28CH1client.ArrRegister[6] / 10.0) // 充气时间
                                         + Convert.ToInt32(LL28CH1client.ArrRegister[7] / 10.0)   // 平衡时间
                                         + Convert.ToInt32(LL28CH1client.ArrRegister[8] / 10.0)   // 检测时间
                                         + Convert.ToInt32(LL28CH1client.ArrRegister[9] / 10.0);  // 排气时间

                        // 配置进度条
                        SetProgressBar(pb_CH1progressBar, 0);
                        SetProgressBarMax(pb_CH1progressBar, (CH1progressbar + 1) * 10); // 补偿1秒

                        // 设备运行状态
                        //Console.WriteLine($"prepare-设备运行状态: {LL28CH1client.ArrCoil[2]}");
                        if (LL28CH1client.ArrCoil[2])
                        {
                            prepareOutTime_Dictionary.Remove(1);
                            ch1workstation = (int)yiqi.test;
                        }
                    }
                    break;

                case (int)yiqi.standby://读取仪器是否启动
                    {
                        SetLabelText(lb_CH1_Status, "待机");

                        // 设备运行状态
                        //Console.WriteLine($"standby-设备运行状态: {LL28CH1client.ArrCoil[2]}");
                        if (LL28CH1client.ArrCoil[2])
                        {
                            ch1workstation = (int)yiqi.prepare;
                        }
                    }
                    break;

                case (int)yiqi.test:
                    {
                        int yiqirunning = Convert.ToInt32(LL28CH1client.ArrRegister[34]);
                        switch(yiqirunning)
                        {
                            case 1:
                                SetLabelText(lb_CH1_Status, "准备");
                                break;
                            case 2:
                                SetLabelText(lb_CH1_Status, "充气");
                                break;
                            case 3:
                                SetLabelText(lb_CH1_Status, "平衡");
                                break;
                            case 4:
                                SetLabelText(lb_CH1_Status, "检测");
                                break;
                            case 5:
                                SetLabelText(lb_CH1_Status, "排气");
                                break;
                        }

                        // 压力单位
                        int punit = Convert.ToInt32(LL28CH1client.ArrRegister[27]);
                        SetPUnit(1, punit);

                        // 泄漏量单位
                        int lunit = Convert.ToInt32(LL28CH1client.ArrRegister[28]);
                        SetLUnit(1, lunit);

                        // 当前压力
                        string fNowpressure = LL28CH1client.readFloatF2(48);
                        SetLabelText(lb_CH1nowPressure, fNowpressure);

                        // 充气压力（测试压力）
                        string fTestpressure = LL28CH1client.readFloatF2(57);
                        SetLabelText(lb_CH1_TestPressure, fTestpressure);

                        // 大漏（平衡压差）
                        string fBigLeak = LL28CH1client.readFloatF2(35);
                        SetLabelText(lb_CH1BigLeak, fBigLeak);

                        // 微漏（泄漏量）
                        string fSmallLeak = LL28CH1client.readFloatF2(38);

                        // 处理大于2000, 先显示2000，后续再处理
                        if (fSmallLeak.ToDouble() > 2000)
                        {
                            fSmallLeak = "2000";
                        }
                        SetLabelText(lb_CH1_SmallLeak, fSmallLeak);

                        // 进度条
                        int pb_value = pb_CH1progressBar.Value + 5;
                        SetProgressBar(pb_CH1progressBar, pb_value);

                        if (pb_value >= pb_CH1progressBar.Maximum)
                        {
                            pb_value = pb_CH1progressBar.Maximum;
                            SetProgressBar(pb_CH1progressBar, pb_value);
                        }

                        // 设备运行状态
                        //Console.WriteLine($"test-设备运行状态: {LL28CH1client.ArrCoil[2]}");
                        if (!LL28CH1client.ArrCoil[2])
                        {
                            int testresult = Convert.ToInt32(LL28CH1client.ArrRegister[41]);
                            string Overresult = "";
                            if (testresult == 1)
                            {
                                Overresult = "OK";
                                SetLabelText(lb_CH1_Result, "OK", Color.Green);
                            }
                            else if (testresult == 2)
                            {
                                Overresult = "NG";
                                SetLabelText(lb_CH1_Result, "NG", Color.Red);
                            }
                            else
                            {
                                Overresult = "";
                                SetLabelText(lb_CH1_Result, "");
                            }

                            if (Overresult != "")  // 有ok/ng结果
                            {
                                ch1workstation = (int)yiqi.finish;
                            }
                            else
                            {
                                SetProgressBar(pb_CH1progressBar, 0);
                                ch1workstation = (int)yiqi.standby;
                            }
                        }
                    }
                    break;

                case (int)yiqi.finish:
                    {
                        CH1TestTime.stopTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        SetLabelText(lb_CH1_Status, "完成");

                        // 当前压力
                        string fNowpressure = LL28CH1client.readFloatF2(48);
                        SetLabelText(lb_CH1nowPressure, fNowpressure);

                        // 充气压力
                        string fTestpressure = LL28CH1client.readFloatF2(57);
                        SetLabelText(lb_CH1_TestPressure, fTestpressure);

                        //大漏
                        string fBigLeak = LL28CH1client.readFloatF2(35);
                        SetLabelText(lb_CH1BigLeak, fBigLeak);

                        //微漏
                        string fSmallLeak = LL28CH1client.readFloatF2(38);

                        // 处理大于2000, 先显示2000，后续再处理
                        if (fSmallLeak.ToDouble() > 2000)
                        {
                            fSmallLeak = "2000";
                        }
                        SetLabelText(lb_CH1_SmallLeak, fSmallLeak);

                        // 结果
                        int testresult = Convert.ToInt32(LL28CH1client.ArrRegister[41]);
                        bool result = false;
                        if (testresult == 1)
                        {
                            SetLabelText(lb_CH1_Result, "OK", Color.Green);
                            result = true;
                        }
                        else if (testresult == 2)
                        {
                            SetLabelText(lb_CH1_Result, "NG", Color.Red);
                            result = false;
                        }
                        else
                        {
                            SetLabelText(lb_CH1_Result, "");
                        }

                        // 设备运行状态-停止
                        if (LL28CH1client.ArrCoil[2] == false)
                        {
                            SetProgressBar(pb_CH1progressBar, pb_CH1progressBar.Maximum);

                            // 表格
                            DataGridView1.Invoke(new System.Action<int, bool, string>(Display),
                                1, result, tb_CH1Code.Text);

                            bool testfinish = false; // 测试结束标志位

                            // 连续测试
                            if (result == false) // NG直接视为本次测试结束
                            {
                                testfinish = true;
                            }
                            else if (m_ContinueTest) // 开了连续
                            {
                                CH1testCount++;
                                if (CH1testCount >= m_ContinueTestCount) // 测试次数满足
                                {
                                    testfinish = true;
                                }
                                else
                                {
                                    Thread.Sleep(150);
                                    ch1workstation = (int)yiqi.start;
                                }
                            }
                            else if (m_ContinueTest == false) // 没开连续测试直接视为本次测试结束
                            {
                                testfinish = true;
                            }

                            if(testfinish) // 该产品测试完成
                            {
                                if(result)
                                {
                                    m_production.AddOK();
                                }
                                else
                                {
                                    m_production.AddNG();
                                }
                                UploadProductionData(m_production.GetTotal(), m_production.GetOK(), m_production.GetNG(), m_production.GetOKRate()); // 更新产能 

                                // 文件
                                CreateFile(1, result, tb_CH1Code.Text);

                                // MES
                                if (MESswitch)
                                {
                                    var rdata = chuzhan(1, tb_CH1Code.Text, m_ActionName, m_Tools, G_CHECKFLOWID, result);
                                    if (rdata.result)
                                    {
                                        SetLabelText(lb_CH1MES_OUTstatus, "PASS", Color.Green);
                                    }
                                    else
                                    {
                                        SetLabelText(lb_CH1MES_OUTstatus, "NG", Color.Red);
                                        SetUITextBox(tb_CH1MainMessage, $"CH1 出站NG:{rdata.msg}");
                                    }
                                }

                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(10, 0);
                                            mxlLog.Instance.Info($"CH1清除PLC信号");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH1清除PLC信号异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }

                                CH1testCount = 0; // 重置测试次数
                                tb_CH1Code.Text = "";
                                ch1workstation = (int)yiqi.standby;
                            }
                        }
                    }
                    break;

                default: break;
            }
        }

        // ----------- 通道2 

        int ch2workstation; // 状态

        // 通道2状态机
        public void CH2machine()
        {
            switch (ch2workstation)
            {
                case (int)yiqi.start:
                    {
                        SetLabelText(lb_CH2_Status, "启动");
                        LL28CH2client.writeCoil("0", true);
                        ch2workstation = (int)yiqi.prepare;
                    }
                    break;

                case (int)yiqi.rst:
                    {
                        SetProgressBar(pb_CH2progressBar, 0); // 复位进度条置为0
                        SetLabelText(lb_CH2_Status, "复位");
                        CH2testCount = 0; // 重置测试次数
                        LL28CH2client.writeCoil("1", true);
                        ch2workstation = (int)yiqi.standby;
                    }
                    break;

                case (int)yiqi.prepare://读取检测时间，充气，平衡检测
                    {
                        // 准备超时处理
                        if (!prepareOutTime_Dictionary.ContainsKey(2))
                        {
                            prepareOutTime_Dictionary[2] = DateTime.Now.AddSeconds(5); // 5s后还在准备就去启动
                        }
                        else if (DateTime.Now > prepareOutTime_Dictionary[2])
                        {
                            prepareOutTime_Dictionary.Remove(2); // 清除超时记录
                            ch2workstation = (int)yiqi.start;
                            break;
                        }

                        CH2TestTime.startTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        SetLabelText(lb_CH2_Result, "");
                        SetLabelText(lb_CH2_Status, "准备");

                        int CH2progressbar = Convert.ToInt32(LL28CH2client.ArrRegister[6] / 10.0) // 充气时间
                                         + Convert.ToInt32(LL28CH2client.ArrRegister[7] / 10.0)   // 平衡时间
                                         + Convert.ToInt32(LL28CH2client.ArrRegister[8] / 10.0)   // 检测时间
                                         + Convert.ToInt32(LL28CH2client.ArrRegister[9] / 10.0);  // 排气时间

                        // 配置进度条
                        SetProgressBar(pb_CH2progressBar, 0);
                        SetProgressBarMax(pb_CH2progressBar, (CH2progressbar + 1) * 10); // 补偿1秒

                        // 设备运行状态
                        //Console.WriteLine($"prepare-设备运行状态: {LL28CH2client.ArrCoil[2]}");
                        if (LL28CH2client.ArrCoil[2])
                        {
                            prepareOutTime_Dictionary.Remove(2);
                            ch2workstation = (int)yiqi.test;
                        }
                    }
                    break;

                case (int)yiqi.standby://读取仪器是否启动
                    {
                        SetLabelText(lb_CH2_Status, "待机");

                        // 设备运行状态
                        //Console.WriteLine($"standby-设备运行状态: {LL28CH2client.ArrCoil[2]}");
                        if (LL28CH2client.ArrCoil[2])
                        {
                            ch2workstation = (int)yiqi.prepare;
                        }
                    }
                    break;

                case (int)yiqi.test:
                    {
                        int yiqirunning = Convert.ToInt32(LL28CH2client.ArrRegister[34]);
                        switch (yiqirunning)
                        {
                            case 1:
                                SetLabelText(lb_CH2_Status, "准备");
                                break;
                            case 2:
                                SetLabelText(lb_CH2_Status, "充气");
                                break;
                            case 3:
                                SetLabelText(lb_CH2_Status, "平衡");
                                break;
                            case 4:
                                SetLabelText(lb_CH2_Status, "检测");
                                break;
                            case 5:
                                SetLabelText(lb_CH2_Status, "排气");
                                break;
                        }

                        // 压力单位
                        int punit = Convert.ToInt32(LL28CH2client.ArrRegister[27]);
                        SetPUnit(2, punit);

                        // 泄漏量单位
                        int lunit = Convert.ToInt32(LL28CH2client.ArrRegister[28]);
                        SetLUnit(2, lunit);

                        // 当前压力
                        string fNowpressure = LL28CH2client.readFloatF2(48);
                        SetLabelText(lb_CH2nowPressure, fNowpressure);

                        // 充气压力（测试压力）
                        string fTestpressure = LL28CH2client.readFloatF2(57);
                        SetLabelText(lb_CH2_TestPressure, fTestpressure);

                        // 大漏（平衡压差）
                        string fBigLeak = LL28CH2client.readFloatF2(35);
                        SetLabelText(lb_CH2BigLeak, fBigLeak);

                        // 微漏（泄漏量）
                        string fSmallLeak = LL28CH2client.readFloatF2(38);

                        // 处理大于2000, 先显示2000，后续再处理
                        if (fSmallLeak.ToDouble() > 2000)
                        {
                            fSmallLeak = "2000";
                        }
                        SetLabelText(lb_CH2_SmallLeak, fSmallLeak);

                        // 进度条
                        int pb_value = pb_CH2progressBar.Value + 5;
                        SetProgressBar(pb_CH2progressBar, pb_value);

                        if (pb_value >= pb_CH2progressBar.Maximum)
                        {
                            pb_value = pb_CH2progressBar.Maximum;
                            SetProgressBar(pb_CH2progressBar, pb_value);
                        }

                        // 设备运行状态
                        //Console.WriteLine($"test-设备运行状态: {LL28CH2client.ArrCoil[2]}");
                        if (!LL28CH2client.ArrCoil[2])
                        {
                            int testresult = Convert.ToInt32(LL28CH2client.ArrRegister[41]);
                            string Overresult = "";
                            if (testresult == 1)
                            {
                                Overresult = "OK";
                                SetLabelText(lb_CH2_Result, "OK", Color.Green);
                            }
                            else if (testresult == 2)
                            {
                                Overresult = "NG";
                                SetLabelText(lb_CH2_Result, "NG", Color.Red);
                            }
                            else
                            {
                                Overresult = "";
                                SetLabelText(lb_CH2_Result, "");
                            }

                            if (Overresult != "")  // 有ok/ng结果
                            {
                                ch2workstation = (int)yiqi.finish;
                            }
                            else
                            {
                                SetProgressBar(pb_CH2progressBar, 0);
                                ch2workstation = (int)yiqi.standby;
                            }
                        }
                    }
                    break;

                case (int)yiqi.finish:
                    {
                        SetLabelText(lb_CH2_Status, "完成");
                        CH2TestTime.stopTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                        // 当前压力
                        string fNowpressure = LL28CH2client.readFloatF2(48);
                        SetLabelText(lb_CH2nowPressure, fNowpressure);

                        // 充气压力
                        string fTestpressure = LL28CH2client.readFloatF2(57);
                        SetLabelText(lb_CH2_TestPressure, fTestpressure);

                        //大漏
                        string fBigLeak = LL28CH2client.readFloatF2(35);
                        SetLabelText(lb_CH2BigLeak, fBigLeak);

                        //微漏
                        string fSmallLeak = LL28CH2client.readFloatF2(38);

                        // 处理大于2000, 先显示2000，后续再处理
                        if (fSmallLeak.ToDouble() > 2000)
                        {
                            fSmallLeak = "2000";
                        }
                        SetLabelText(lb_CH2_SmallLeak, fSmallLeak);

                        // 结果
                        int testresult = Convert.ToInt32(LL28CH2client.ArrRegister[41]);
                        bool result = false;
                        if (testresult == 1)
                        {
                            SetLabelText(lb_CH2_Result, "OK", Color.Green);
                            result = true;
                        }
                        else if (testresult == 2)
                        {
                            SetLabelText(lb_CH2_Result, "NG", Color.Red);
                            result = false;
                        }
                        else
                        {
                            SetLabelText(lb_CH2_Result, "");
                        }
                        //Console.WriteLine($"finish-结果: {testresult}");

                        // 设备运行状态-停止
                        //Console.WriteLine($"finish-设备运行状态: {LL28CH2client.ArrCoil[2]}");
                        if (LL28CH2client.ArrCoil[2] == false)
                        {
                            SetProgressBar(pb_CH2progressBar, pb_CH2progressBar.Maximum);

                            // 表格
                            DataGridView2.Invoke(new System.Action<int, bool, string>(Display),
                                2, result, tb_CH2Code.Text);

                            bool testfinish = false; // 测试结束标志位

                            // 连续测试
                            if (result == false) // NG直接视为本次测试结束
                            {
                                testfinish = true;
                            }
                            else if (m_ContinueTest) // 开了连续
                            {
                                CH2testCount++;
                                if (CH2testCount >= m_ContinueTestCount) // 测试次数满足
                                {
                                    testfinish = true;
                                }
                                else
                                {
                                    Thread.Sleep(150);
                                    ch2workstation = (int)yiqi.start;
                                }
                            }
                            else if (m_ContinueTest == false) // 没开连续测试直接视为本次测试结束
                            {
                                testfinish = true;
                            }

                            if(testfinish)
                            {
                                if(result)
                                {
                                    m_production.AddOK();
                                }
                                else
                                {
                                    m_production.AddNG();
                                }
                                UploadProductionData(m_production.GetTotal(), m_production.GetOK(), m_production.GetNG(), m_production.GetOKRate()); // 更新产能 

                                // 文件
                                CreateFile(2, result, tb_CH2Code.Text);

                                // MES
                                if (MESswitch)
                                {
                                    var rdata = chuzhan(2, tb_CH2Code.Text, m_ActionName, m_Tools, G_CHECKFLOWID, result);
                                    if (rdata.result)
                                    {
                                        SetLabelText(lb_CH2MES_OUTstatus, "PASS", Color.Green);
                                    }
                                    else
                                    {
                                        SetLabelText(lb_CH2MES_OUTstatus, "NG", Color.Red);
                                        SetUITextBox(tb_CH2MainMessage, $"CH2 出站NG:{rdata.msg}");
                                    }
                                }

                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(11, 0);
                                            mxlLog.Instance.Info($"CH2清除PLC信号");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH2清除PLC信号异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }

                                CH2testCount = 0; // 重置测试次数
                                tb_CH2Code.Text = "";
                                ch2workstation = (int)yiqi.standby;
                            }
                        }
                    }
                    break;

                default: break;
            }
        }

        // ----------- 通道3 

        int ch3workstation; // 状态

        // 通道3状态机
        public void CH3machine()
        {
            switch (ch3workstation)
            {
                case (int)yiqi.start:
                    {
                        SetLabelText(lb_CH3_Status, "启动");
                        LL28CH3client.writeCoil("0", true);
                        ch3workstation = (int)yiqi.prepare;
                    }
                    break;

                case (int)yiqi.rst:
                    {
                        SetProgressBar(pb_CH3progressBar, 0); // 复位进度条置为0
                        SetLabelText(lb_CH3_Status, "复位");
                        CH3testCount = 0; // 重置测试次数
                        LL28CH3client.writeCoil("1", true);
                        ch3workstation = (int)yiqi.standby;
                    }
                    break;

                case (int)yiqi.prepare://读取检测时间，充气，平衡检测
                    {
                        // 准备超时处理
                        if (!prepareOutTime_Dictionary.ContainsKey(3))
                        {
                            prepareOutTime_Dictionary[3] = DateTime.Now.AddSeconds(5); // 5s后还在准备就去启动
                        }
                        else if (DateTime.Now > prepareOutTime_Dictionary[3])
                        {
                            prepareOutTime_Dictionary.Remove(3); // 清除超时记录
                            ch3workstation = (int)yiqi.start;
                            break;
                        }

                        CH3TestTime.startTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        SetLabelText(lb_CH3_Result, "");
                        SetLabelText(lb_CH3_Status, "准备");

                        int CH3progressbar = Convert.ToInt32(LL28CH3client.ArrRegister[6] / 10.0) // 充气时间
                                         + Convert.ToInt32(LL28CH3client.ArrRegister[7] / 10.0)   // 平衡时间
                                         + Convert.ToInt32(LL28CH3client.ArrRegister[8] / 10.0)   // 检测时间
                                         + Convert.ToInt32(LL28CH3client.ArrRegister[9] / 10.0);  // 排气时间

                        // 配置进度条
                        SetProgressBar(pb_CH3progressBar, 0);
                        SetProgressBarMax(pb_CH3progressBar, (CH3progressbar + 1) * 10); // 补偿1秒

                        // 设备运行状态
                        //Console.WriteLine($"prepare-设备运行状态: {LL28CH3client.ArrCoil[2]}");
                        if (LL28CH3client.ArrCoil[2])
                        {
                            prepareOutTime_Dictionary.Remove(3);
                            ch3workstation = (int)yiqi.test;
                        }
                    }
                    break;

                case (int)yiqi.standby://读取仪器是否启动
                    {
                        SetLabelText(lb_CH3_Status, "待机");

                        // 设备运行状态
                        //Console.WriteLine($"standby-设备运行状态: {LL28CH3client.ArrCoil[2]}");
                        if (LL28CH3client.ArrCoil[2])
                        {
                            ch3workstation = (int)yiqi.prepare;
                        }
                    }
                    break;

                case (int)yiqi.test:
                    {
                        int yiqirunning = Convert.ToInt32(LL28CH3client.ArrRegister[34]);
                        switch (yiqirunning)
                        {
                            case 1:
                                SetLabelText(lb_CH3_Status, "准备");
                                break;
                            case 2:
                                SetLabelText(lb_CH3_Status, "充气");
                                break;
                            case 3:
                                SetLabelText(lb_CH3_Status, "平衡");
                                break;
                            case 4:
                                SetLabelText(lb_CH3_Status, "检测");
                                break;
                            case 5:
                                SetLabelText(lb_CH3_Status, "排气");
                                break;
                        }

                        // 压力单位
                        int punit = Convert.ToInt32(LL28CH3client.ArrRegister[27]);
                        SetPUnit(3,punit);

                        // 泄漏量单位
                        int lunit = Convert.ToInt32(LL28CH3client.ArrRegister[28]);
                        SetLUnit(3, lunit);

                        // 当前压力
                        string fNowpressure = LL28CH3client.readFloatF2(48);
                        SetLabelText(lb_CH3nowPressure, fNowpressure);

                        // 充气压力（测试压力）
                        string fTestpressure = LL28CH3client.readFloatF2(57);
                        SetLabelText(lb_CH3_TestPressure, fTestpressure);

                        // 大漏（平衡压差）
                        string fBigLeak = LL28CH3client.readFloatF2(35);
                        SetLabelText(lb_CH3BigLeak, fBigLeak);

                        // 微漏（泄漏量）
                        string fSmallLeak = LL28CH3client.readFloatF2(38);

                        // 处理大于2000, 先显示2000，后续再处理
                        if (fSmallLeak.ToDouble() > 2000)
                        {
                            fSmallLeak = "2000";
                        }
                        SetLabelText(lb_CH3_SmallLeak, fSmallLeak);

                        // 进度条
                        int pb_value = pb_CH3progressBar.Value + 5;
                        SetProgressBar(pb_CH3progressBar, pb_value);

                        if (pb_value >= pb_CH3progressBar.Maximum)
                        {
                            pb_value = pb_CH3progressBar.Maximum;
                            SetProgressBar(pb_CH3progressBar, pb_value);
                        }

                        // 设备运行状态
                        //Console.WriteLine($"test-设备运行状态: {LL28CH3client.ArrCoil[2]}");
                        if (!LL28CH3client.ArrCoil[2])
                        {
                            int testresult = Convert.ToInt32(LL28CH3client.ArrRegister[41]);
                            string Overresult = "";
                            if (testresult == 1)
                            {
                                Overresult = "OK";
                                SetLabelText(lb_CH3_Result, "OK", Color.Green);
                            }
                            else if (testresult == 2)
                            {
                                Overresult = "NG";
                                SetLabelText(lb_CH3_Result, "NG", Color.Red);
                            }
                            else
                            {
                                Overresult = "";
                                SetLabelText(lb_CH3_Result, "");
                            }

                            if (Overresult != "")  // 有ok/ng结果
                            {
                                ch3workstation = (int)yiqi.finish;
                            }
                            else
                            {
                                SetProgressBar(pb_CH3progressBar, 0);
                                ch3workstation = (int)yiqi.standby;
                            }
                        }
                    }
                    break;

                case (int)yiqi.finish:
                    {
                        SetLabelText(lb_CH3_Status, "完成");
                        CH3TestTime.stopTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                        // 当前压力
                        string fNowpressure = LL28CH3client.readFloatF2(48);
                        SetLabelText(lb_CH3nowPressure, fNowpressure);

                        // 充气压力
                        string fTestpressure = LL28CH3client.readFloatF2(57);
                        SetLabelText(lb_CH3_TestPressure, fTestpressure);

                        //大漏
                        string fBigLeak = LL28CH3client.readFloatF2(35);
                        SetLabelText(lb_CH3BigLeak, fBigLeak);

                        //微漏
                        string fSmallLeak = LL28CH3client.readFloatF2(38);

                        // 处理大于2000, 先显示2000，后续再处理
                        if (fSmallLeak.ToDouble() > 2000)
                        {
                            fSmallLeak = "2000";
                        }
                        SetLabelText(lb_CH3_SmallLeak, fSmallLeak);

                        // 结果
                        int testresult = Convert.ToInt32(LL28CH3client.ArrRegister[41]);
                        bool result = false;
                        if (testresult == 1)
                        {
                            SetLabelText(lb_CH3_Result, "OK", Color.Green);
                            result = true;
                        }
                        else if (testresult == 2)
                        {
                            SetLabelText(lb_CH3_Result, "NG", Color.Red);
                            result = false;
                        }
                        else
                        {
                            SetLabelText(lb_CH3_Result, "");
                        }

                        // 设备运行状态-停止
                        //Console.WriteLine($"finish-设备运行状态: {LL28CH3client.ArrCoil[2]}");
                        if (LL28CH3client.ArrCoil[2] == false)
                        {
                            SetProgressBar(pb_CH3progressBar, pb_CH3progressBar.Maximum);

                            // 表格
                            DataGridView1.Invoke(new System.Action<int, bool, string>(Display),
                                3, result, tb_CH3Code.Text);

                            bool testfinish = false; // 测试结束标志位

                            // 连续测试
                            if (result == false) // NG直接视为本次测试结束
                            {
                                testfinish = true;
                            }
                            else if (m_ContinueTest) // 开了连续
                            {
                                CH3testCount++;
                                if (CH3testCount >= m_ContinueTestCount) // 测试次数满足
                                {
                                    testfinish = true;
                                }
                                else
                                {
                                    Thread.Sleep(150);
                                    ch3workstation = (int)yiqi.start;
                                }
                            }
                            else if (m_ContinueTest == false) // 没开连续测试直接视为本次测试结束
                            {
                                testfinish = true;
                            }

                            if(testfinish)
                            {
                                if(result)
                                {
                                    m_production.AddOK();
                                }
                                else
                                {
                                    m_production.AddNG();
                                }
                                UploadProductionData(m_production.GetTotal(), m_production.GetOK(), m_production.GetNG(), m_production.GetOKRate()); // 更新产能 

                                // 文件
                                CreateFile(3, result, tb_CH3Code.Text);

                                // MES
                                if (MESswitch)
                                {
                                    var rdata = chuzhan(3, tb_CH3Code.Text, m_ActionName, m_Tools, G_CHECKFLOWID, result);
                                    if (rdata.result)
                                    {
                                        SetLabelText(lb_CH3MES_OUTstatus, "PASS", Color.Green);
                                    }
                                    else
                                    {
                                        SetLabelText(lb_CH3MES_OUTstatus, "NG", Color.Red);
                                        SetUITextBox(tb_CH1MainMessage, $"CH3 出站NG:{rdata.msg}");
                                    }
                                }

                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(12, 0);
                                            mxlLog.Instance.Info($"CH3清除PLC信号");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH3清除PLC信号异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }

                                CH3testCount = 0; // 重置测试次数
                                tb_CH3Code.Text = "";
                                ch3workstation = (int)yiqi.standby;
                            }
                        }
                    }
                    break;

                default: break;
            }
        }

        // ----------- 通道4 

        int ch4workstation; // 状态

        // 通道4状态机
        public void CH4machine()
        {
            switch (ch4workstation)
            {
                case (int)yiqi.start:
                    {
                        SetLabelText(lb_CH4_Status, "启动");
                        LL28CH4client.writeCoil("0", true);
                        ch4workstation = (int)yiqi.prepare;
                    }
                    break;

                case (int)yiqi.rst:
                    {
                        SetProgressBar(pb_CH4progressBar, 0); // 复位进度条置为0
                        SetLabelText(lb_CH4_Status, "复位");
                        CH4testCount = 0; // 重置测试次数
                        LL28CH4client.writeCoil("1", true);
                        ch4workstation = (int)yiqi.standby;
                    }
                    break;

                case (int)yiqi.prepare://读取检测时间，充气，平衡检测
                    {
                        // 准备超时处理
                        if (!prepareOutTime_Dictionary.ContainsKey(4))
                        {
                            prepareOutTime_Dictionary[4] = DateTime.Now.AddSeconds(5); // 5s后还在准备就去启动
                        }
                        else if (DateTime.Now > prepareOutTime_Dictionary[4])
                        {
                            prepareOutTime_Dictionary.Remove(4); // 清除超时记录
                            ch4workstation = (int)yiqi.start;
                            break;
                        }

                        CH4TestTime.startTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        SetLabelText(lb_CH4_Result, "");
                        SetLabelText(lb_CH4_Status, "准备");

                        int CH4progressbar = Convert.ToInt32(LL28CH4client.ArrRegister[6] / 10.0) // 充气时间
                                         + Convert.ToInt32(LL28CH4client.ArrRegister[7] / 10.0)   // 平衡时间
                                         + Convert.ToInt32(LL28CH4client.ArrRegister[8] / 10.0)   // 检测时间
                                         + Convert.ToInt32(LL28CH4client.ArrRegister[9] / 10.0);  // 排气时间

                        // 配置进度条
                        SetProgressBar(pb_CH4progressBar, 0);
                        SetProgressBarMax(pb_CH4progressBar, (CH4progressbar + 1) * 10); // 补偿1秒

                        // 设备运行状态
                        //Console.WriteLine($"prepare-设备运行状态: {LL28CH4client.ArrCoil[2]}");
                        if (LL28CH4client.ArrCoil[2])
                        {
                            prepareOutTime_Dictionary.Remove(4);
                            ch4workstation = (int)yiqi.test;
                        }
                    }
                    break;

                case (int)yiqi.standby: // 读取仪器是否启动
                    {
                        SetLabelText(lb_CH4_Status, "待机");

                        // 设备运行状态
                        //Console.WriteLine($"standby-设备运行状态: {LL28CH4client.ArrCoil[2]}");
                        if (LL28CH4client.ArrCoil[2])
                        {
                            ch4workstation = (int)yiqi.prepare;
                        }
                    }
                    break;

                case (int)yiqi.test:
                    {
                        int yiqirunning = Convert.ToInt32(LL28CH4client.ArrRegister[34]);
                        switch (yiqirunning)
                        {
                            case 1:
                                SetLabelText(lb_CH4_Status, "准备");
                                break;
                            case 2:
                                SetLabelText(lb_CH4_Status, "充气");
                                break;
                            case 3:
                                SetLabelText(lb_CH4_Status, "平衡");
                                break;
                            case 4:
                                SetLabelText(lb_CH4_Status, "检测");
                                break;
                            case 5:
                                SetLabelText(lb_CH4_Status, "排气");
                                break;
                        }

                        // 压力单位
                        int punit = Convert.ToInt32(LL28CH4client.ArrRegister[27]);
                        SetPUnit(4, punit);

                        // 泄漏量单位
                        int lunit = Convert.ToInt32(LL28CH4client.ArrRegister[28]);
                        SetLUnit(4, lunit);

                        // 当前压力
                        string fNowpressure = LL28CH4client.readFloatF2(48);
                        SetLabelText(lb_CH4nowPressure, fNowpressure);

                        // 充气压力（测试压力）
                        string fTestpressure = LL28CH4client.readFloatF2(57);
                        SetLabelText(lb_CH4_TestPressure, fTestpressure);

                        // 大漏（平衡压差）
                        string fBigLeak = LL28CH4client.readFloatF2(35);
                        SetLabelText(lb_CH4BigLeak, fBigLeak);

                        // 微漏（泄漏量）
                        string fSmallLeak = LL28CH4client.readFloatF2(38);

                        // 处理大于2000, 先显示2000，后续再处理
                        if (fSmallLeak.ToDouble() > 2000)
                        {
                            fSmallLeak = "2000";
                        }
                        SetLabelText(lb_CH4_SmallLeak, fSmallLeak);

                        // 进度条
                        int pb_value = pb_CH4progressBar.Value + 5;
                        SetProgressBar(pb_CH4progressBar, pb_value);

                        if (pb_value >= pb_CH4progressBar.Maximum)
                        {
                            pb_value = pb_CH4progressBar.Maximum;
                            SetProgressBar(pb_CH4progressBar, pb_value);

                        }

                        // 设备运行状态
                        //Console.WriteLine($"test-设备运行状态: {LL28CH4client.ArrCoil[2]}");
                        if (!LL28CH4client.ArrCoil[2])
                        {
                            int testresult = Convert.ToInt32(LL28CH4client.ArrRegister[41]);
                            string Overresult = "";
                            if (testresult == 1)
                            {
                                Overresult = "OK";
                                SetLabelText(lb_CH4_Result, "OK", Color.Green);
                            }
                            else if (testresult == 2)
                            {
                                Overresult = "NG";
                                SetLabelText(lb_CH4_Result, "NG", Color.Red);
                            }
                            else
                            {
                                Overresult = "";
                                SetLabelText(lb_CH4_Result, "");
                            }

                            if (Overresult != "")  // 有ok/ng结果
                            {
                                ch4workstation = (int)yiqi.finish;
                            }
                            else
                            {
                                SetProgressBar(pb_CH4progressBar, 0);
                                ch4workstation = (int)yiqi.standby;
                            }
                        }
                    }
                    break;

                case (int)yiqi.finish:
                    {
                        SetLabelText(lb_CH4_Status, "完成");
                        CH4TestTime.stopTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                        // 当前压力
                        string fNowpressure = LL28CH4client.readFloatF2(48);
                        SetLabelText(lb_CH4nowPressure, fNowpressure);

                        // 充气压力
                        string fTestpressure = LL28CH4client.readFloatF2(57);
                        SetLabelText(lb_CH4_TestPressure, fTestpressure);

                        //大漏
                        string fBigLeak = LL28CH4client.readFloatF2(35);
                        SetLabelText(lb_CH4BigLeak, fBigLeak);

                        //微漏
                        string fSmallLeak = LL28CH4client.readFloatF2(38);

                        // 处理大于2000, 先显示2000，后续再处理
                        if (fSmallLeak.ToDouble() > 2000)
                        {
                            fSmallLeak = "2000";
                        }
                        SetLabelText(lb_CH4_SmallLeak, fSmallLeak);

                        // 结果
                        int testresult = Convert.ToInt32(LL28CH4client.ArrRegister[41]);
                        bool result = false;
                        if (testresult == 1)
                        {
                            SetLabelText(lb_CH4_Result, "OK", Color.Green);
                            result = true;
                        }
                        else if (testresult == 2)
                        {
                            SetLabelText(lb_CH4_Result, "NG", Color.Red);
                            result = false;
                        }
                        else
                        {
                            SetLabelText(lb_CH4_Result, "");
                        }
                        //Console.WriteLine($"finish-结果: {testresult}");

                        // 设备运行状态-停止
                        //Console.WriteLine($"finish-设备运行状态: {LL28CH4client.ArrCoil[2]}");
                        if (LL28CH4client.ArrCoil[2] == false)
                        {
                            SetProgressBar(pb_CH4progressBar, pb_CH4progressBar.Maximum);

                            // 表格
                            DataGridView2.Invoke(new System.Action<int, bool, string>(Display),
                                4, result, tb_CH4Code.Text);

                            bool testfinish = false; // 测试结束标志位

                            // 连续测试
                            if (result == false) // NG直接视为本次测试结束
                            {
                                testfinish = true;
                            }
                            else if (m_ContinueTest) // 开了连续
                            {
                                CH4testCount++;
                                if (CH4testCount >= m_ContinueTestCount) // 测试次数满足
                                {
                                    testfinish = true;
                                }
                                else
                                {
                                    Thread.Sleep(150);
                                    ch4workstation = (int)yiqi.start;
                                }
                            }
                            else if (m_ContinueTest == false) // 没开连续测试直接视为本次测试结束
                            {
                                testfinish = true;
                            }

                            if(testfinish)
                            {
                                if(result)
                                {
                                    m_production.AddOK();
                                }
                                else
                                {
                                    m_production.AddNG();
                                }
                                UploadProductionData(m_production.GetTotal(), m_production.GetOK(), m_production.GetNG(), m_production.GetOKRate()); // 更新产能 

                                // 文件
                                CreateFile(4, result, tb_CH4Code.Text);

                                // MES
                                if (MESswitch)
                                {
                                    var rdata = chuzhan(4, tb_CH4Code.Text, m_ActionName, m_Tools, G_CHECKFLOWID, result);
                                    if (rdata.result)
                                    {
                                        SetLabelText(lb_CH4MES_OUTstatus, "PASS", Color.Green);
                                    }
                                    else
                                    {
                                        SetLabelText(lb_CH4MES_OUTstatus, "NG", Color.Red);
                                        SetUITextBox(tb_CH2MainMessage, $"CH4 出站NG:{rdata.msg}");
                                    }
                                }

                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(13, 0);
                                            mxlLog.Instance.Info($"CH4清除PLC信号");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH4清除PLC信号异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }

                                CH4testCount = 0; // 重置测试次数
                                tb_CH4Code.Text = "";
                                ch4workstation = (int)yiqi.standby;
                            }
                        }
                    }
                    break;

                default: break;
            }
        }

        // 更新产能数据
        void UploadProductionData(int total, int ok, int ng, double okRate)
        {
            SetLabelText(lb_Total, $"{total}");
            SetLabelText(lb_OKnumber, $"{ok}");
            SetLabelText(lb_NGnumber, $"{ng}");
            SetLabelText(lb_OKRate, $"{okRate}%");
        }

        //写入文件
        private void CreateFile(int CH, bool result, string code)
        {
            try
            {
                //Invoke((new System.Action(() =>
                //Task.Run(() =>
                //{
                    if (filesave.Excel)
                    {
                        Task.Run(() => // 这个会卡顿一下，放到线程 应该是使用和打开了Excel的app
                        {
                            AddExcel(CH, result, code);
                        });
                    }
                    if (filesave.TXT)
                    {
                        AddTxT(CH, result, code);
                    }
                    if (filesave.CSV)
                    {
                        AddCSV(CH, result);
                    }
                //});
            }
            catch (Exception ex)
            {
                MessageBox.Show("CreateFile:" + ex.Message);
                mxlLog.Instance.Error($"CreateFile写入错误 ,行号{ex.StackTrace} ", ex);
                //throw;
            }

        }

        // 设置压力单位
        private void SetPUnit(int ch, int unit)
        {
            string PUnit = "Pa";
            switch (unit)
            {
                case 0: PUnit = "Pa"; break;
                case 1: PUnit = "KPa"; break;
                case 2: PUnit = "MPa"; break;
                case 3: PUnit = "bar"; break;
                case 4: PUnit = "Psi"; break;
                case 5: PUnit = "kg/cm^2"; break;
                case 6: PUnit = "atm"; break;
                case 7: PUnit = "mmHg"; break;
            }

            switch (ch)
            {
                case 1:
                    lb_CH1_PressureUnit.Invoke((MethodInvoker)delegate
                    {
                        lb_CH1BigLeakUnit.Text = PUnit;
                        lb_CH1_nowPressureUnit.Text = PUnit;
                        lb_CH1_PressureUnit.Text = PUnit;
                    });
                    break;
                case 2:
                    lb_CH2_PressureUnit.Invoke((MethodInvoker)delegate
                    {
                        lb_CH2BigLeakUnit.Text = PUnit;
                        lb_CH2_nowPressureUnit.Text = PUnit;
                        lb_CH2_PressureUnit.Text = PUnit;
                    });
                    break;
                case 3:
                    lb_CH3_PressureUnit.Invoke((MethodInvoker)delegate
                    {
                        lb_CH3BigLeakUnit.Text = PUnit;
                        lb_CH3_nowPressureUnit.Text = PUnit;
                        lb_CH3_PressureUnit.Text = PUnit;
                    });
                    break;
                case 4:
                    lb_CH4_PressureUnit.Invoke((MethodInvoker)delegate
                    {
                        lb_CH4BigLeakUnit.Text = PUnit;
                        lb_CH4_nowPressureUnit.Text = PUnit;
                        lb_CH4_PressureUnit.Text = PUnit;
                    });
                    break;
            }
        }

        // 设置泄露量单位
        private void SetLUnit(int ch, int unit)
        {
            string LUnit = "Pa";
            switch (unit)
            {
                case 0: LUnit = "Pa"; break;
                case 1: LUnit = "KPa"; break;
                case 2: LUnit = "mbar"; break;
                case 3: LUnit = "atm"; break;
                case 4: LUnit = "sccm"; break;
                case 5: LUnit = "ccm3/s"; break;
                case 6: LUnit = "Pa/s"; break;
            }
            
            switch (ch)
            {
                case 1:
                    lb_CH1_SmallLeakUnit.Invoke((MethodInvoker)delegate
                    {
                        //lb_CH1_BigLeakUnit.Text = LUnit;
                        lb_CH1_SmallLeakUnit.Text = LUnit;
                    });
                    break;
                case 2:
                    lb_CH2_SmallLeakUnit.Invoke((MethodInvoker)delegate
                    {
                        //lb_CH2_BigLeakUnit.Text = LUnit;
                        lb_CH2_SmallLeakUnit.Text = LUnit;
                    });
                    break;
                case 3:
                    lb_CH3_SmallLeakUnit.Invoke((MethodInvoker)delegate
                    {
                        //lb_CH3_BigLeakUnit.Text = LUnit;
                        lb_CH3_SmallLeakUnit.Text = LUnit;
                    });
                    break;
                case 4:
                    lb_CH4_SmallLeakUnit.Invoke((MethodInvoker)delegate
                    {
                        //lb_CH4_BigLeakUnit.Text = LUnit;
                        lb_CH4_SmallLeakUnit.Text = LUnit;
                    });
                    break;
            }
        }


        //将数据写入Txt
        public void AddTxT(int CH, bool result, string code)
        {
            try
            {
                string datatime = DateTime.Now.ToString("yyyyMMdd");
                if (String.IsNullOrEmpty(filesave.Path)) // 若路径处不输入则获取桌面路径
                {
                    filesave.Path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                    filesave.Path = AppDomain.CurrentDomain.BaseDirectory + "Storage";
                }

                string filepath = filesave.Path + "\\";

                if (!Directory.Exists(filepath))
                {
                    Directory.CreateDirectory(filepath);
                }

                string updata = "";
                if (CH == 1)
                {
                    string ngret = "";
                    string fSmallLeak = LL28CH1client.readFloatF2(38);
                    if (fSmallLeak.ToDouble() > 2000)
                    {
                        ngret = LeakNG_ARP(fSmallLeak);
                    }
                    else
                    {
                        ngret = lb_CH1_SmallLeak.Text + lb_CH1_SmallLeakUnit.Text;
                    }

                    updata = "CH1 " + "时间 " + DateTime.Now + " 条形码 " + code +
                        " 结果" + (result ? "OK" : "NG") +
                        " 充气时间" + (LL28CH1client.ArrRegister[6] / 10.0).ToString() + "s" +
                        " 平衡时间" + (LL28CH1client.ArrRegister[7] / 10.0).ToString() + "s" +
                        " 测试时间" + (LL28CH1client.ArrRegister[8] / 10.0).ToString() + "s" +
                        " 排气时间" + (LL28CH1client.ArrRegister[9] / 10.0).ToString() + "s" +
                        " 测试压力" + lb_CH1_TestPressure.Text + lb_CH1_PressureUnit.Text +
                        " 泄漏量" + ngret + " \n";
                }
                if (CH == 2)
                {
                    string ngret = "";
                    string fSmallLeak = LL28CH2client.readFloatF2(38);
                    if (fSmallLeak.ToDouble() > 2000)
                    {
                        ngret = LeakNG_ARP(fSmallLeak);
                    }
                    else
                    {
                        ngret = lb_CH2_SmallLeak.Text + lb_CH2_SmallLeakUnit.Text;
                    }
                    updata = "CH2 " + "时间 " + DateTime.Now + " 条形码 " + code +
                        " 结果" + (result ? "OK" : "NG") +
                        " 充气时间" + (LL28CH2client.ArrRegister[6] / 10.0).ToString() + "s" +
                        " 平衡时间" + (LL28CH2client.ArrRegister[7] / 10.0).ToString() + "s" +
                        " 测试时间" + (LL28CH2client.ArrRegister[8] / 10.0).ToString() + "s" +
                        " 排气时间" + (LL28CH2client.ArrRegister[9] / 10.0).ToString() + "s" +
                        " 测试压力" + lb_CH2_TestPressure.Text + lb_CH2_PressureUnit.Text +
                        " 泄漏量" + ngret + " \n";
                }

                if (CH == 3)
                {
                    string ngret = "";
                    string fSmallLeak = LL28CH3client.readFloatF2(38);
                    if (fSmallLeak.ToDouble() > 2000)
                    {
                        ngret = LeakNG_ARP(fSmallLeak);
                    }
                    else
                    {
                        ngret = lb_CH3_SmallLeak.Text + lb_CH3_SmallLeakUnit.Text;
                    }
                    updata = "CH3 " + "时间 " + DateTime.Now + " 条形码 " + code +
                        " 结果" + (result ? "OK" : "NG") +
                        " 充气时间" + (LL28CH3client.ArrRegister[6] / 10.0).ToString() + "s" +
                        " 平衡时间" + (LL28CH3client.ArrRegister[7] / 10.0).ToString() + "s" +
                        " 测试时间" + (LL28CH3client.ArrRegister[8] / 10.0).ToString() + "s" +
                        " 排气时间" + (LL28CH3client.ArrRegister[9] / 10.0).ToString() + "s" +
                        " 测试压力" + lb_CH3_TestPressure.Text + lb_CH3_PressureUnit.Text +
                        " 泄漏量" + ngret + " \n";
                }

                if (CH == 4)
                {
                    string ngret = "";
                    string fSmallLeak = LL28CH4client.readFloatF2(38);
                    if (fSmallLeak.ToDouble() > 2000)
                    {
                        ngret = LeakNG_ARP(fSmallLeak);
                    }
                    else
                    {
                        ngret = lb_CH4_SmallLeak.Text + lb_CH4_SmallLeakUnit.Text;
                    }
                    updata = "CH4 " + "时间 " + DateTime.Now + " 条形码 " + code +
                        " 结果" + (result ? "OK" : "NG") +
                        " 充气时间" + (LL28CH4client.ArrRegister[6] / 10.0).ToString() + "s" +
                        " 平衡时间" + (LL28CH4client.ArrRegister[7] / 10.0).ToString() + "s" +
                        " 测试时间" + (LL28CH4client.ArrRegister[8] / 10.0).ToString() + "s" +
                        " 排气时间" + (LL28CH4client.ArrRegister[9] / 10.0).ToString() + "s" +
                        " 测试压力" + lb_CH4_TestPressure.Text + lb_CH4_PressureUnit.Text +
                        " 泄漏量" + ngret + " \n";
                }

                // 文件不存在则创建
                string strfile = filepath + DateTime.Today.ToString("yyyy-MM-dd") + "_" + CH + ".txt";
                if (!System.IO.File.Exists(strfile))
                {
                    FileStream fs1 = new FileStream(strfile, FileMode.Create, FileAccess.Write);
                    StreamWriter sw = new StreamWriter(fs1);
                    sw.WriteLine(updata); //开始写入值
                    sw.Close();
                    fs1.Close();
                }
                else
                {
                    FileStream fs = new FileStream(strfile, FileMode.Append, FileAccess.Write);
                    StreamWriter sr = new StreamWriter(fs);
                    sr.WriteLine(updata); //开始写入值
                    sr.Close();
                    fs.Close();
                }
            }
            catch (Exception ex)
            {
                mxlLog.Instance.Error($"AddTxT写入错误 CH{CH}: {ex.Message}", ex);
            }
        }

        //将数据写入Excel表格  通道 结果 条码
        private void AddExcel(int CH, bool result, string code)
        {
            Console.WriteLine($"AddExcel code: {code}");
            try
            {
                string datatime = DateTime.Now.ToString("yyyyMMdd");
                if (String.IsNullOrEmpty(filesave.Path)) // 若路径处不输入则获取桌面路径
                {
                    filesave.Path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                }

                string filepath = filesave.Path + "\\";

                if (CH == 1)
                {
                    filepath += "CH1\\";
                }
                else if(CH == 2)
                {
                    filepath += "CH2\\";
                }
                else if (CH == 3)
                {
                    filepath += "CH3\\";
                }
                else if (CH == 4)
                {
                    filepath += "CH4\\";
                }

                if (!Directory.Exists(filepath)) // 没有则创建
                {
                    Directory.CreateDirectory(filepath);
                }
                string name = CH.ToString() + "_" + datatime + ".xls";
                filepath += name;

                Excel.Application xapp = new Excel.Application();
                Excel.Workbook xbook = null;

                if (File.Exists(filepath) == false) // 文件没有则创建
                {
                    // 若不存在该文件，则创建新文件
                    xbook = xapp.Workbooks.Add();

                    Excel.Worksheet hxsheet = (Excel.Worksheet)xbook.Sheets[1];

                    string[] fieldArr = { "时间", 
                                    "条形码", 
                                    "充气时间", 
                                    "平衡时间", 
                                    "检测时间",
                                    "排气时间", 
                                    "充气压力上限", 
                                    "充气压力下限", 
                                    "平衡压差上限",
                                    "平衡压差下限", 
                                    "泄漏量上限", 
                                    "泄漏量下限", 
                                    "测试结果",
                                    "测试压力", 
                                    "微漏泄漏量" 
                    };

                    //写入表头
                    for (int i = 0; i < fieldArr.Length; i++)
                    {
                        hxsheet.Cells[1, i + 1] = fieldArr[i];
                    }

                    xbook.SaveAs(filepath);
                    xbook.Close();
                }

                // 打开文件
                xbook = xapp.Workbooks.Open(filepath);
                Excel.Worksheet xsheet = (Excel.Worksheet)xbook.Sheets[1];

                // 获取最后一行
                int lastRow = xsheet.Cells.Find("*", System.Reflection.Missing.Value,
                                       System.Reflection.Missing.Value,
                                       System.Reflection.Missing.Value,
                                       Excel.XlSearchOrder.xlByRows,
                                       Excel.XlSearchDirection.xlPrevious,
                                       false, System.Reflection.Missing.Value,
                                       System.Reflection.Missing.Value).Row;

                // 准备数据
                string[] dataArr = null;
                if (CH == 1)
                {
                    string ngret = "";
                    string fSmallLeak = LL28CH1client.readFloatF2(38);
                    if (fSmallLeak.ToDouble() > 2000)
                    {
                        ngret = LeakNG_ARP(fSmallLeak);
                    }
                    else
                    {
                        ngret = lb_CH1_SmallLeak.Text + lb_CH1_SmallLeakUnit.Text;
                    }
                    dataArr = new string[] {
                        DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"),
                        code,
                        (LL28CH1client.ArrRegister[6] / 10.0).ToString() + "s",
                        (LL28CH1client.ArrRegister[7] / 10.0).ToString() + "s",
                        (LL28CH1client.ArrRegister[8] / 10.0).ToString() + "s",
                        (LL28CH1client.ArrRegister[9] / 10.0).ToString() + "s",
                        LL28CH1client.readFloatF2(13) + lb_CH1_PressureUnit.Text,
                        LL28CH1client.readFloatF2(15) + lb_CH1_PressureUnit.Text,
                        LL28CH1client.readFloatF2(17) + lb_CH1_PressureUnit.Text,
                        LL28CH1client.readFloatF2(19) + lb_CH1_PressureUnit.Text,
                        LL28CH1client.readFloatF2(21) + lb_CH1_SmallLeakUnit.Text,
                        LL28CH1client.readFloatF2(23) + lb_CH1_SmallLeakUnit.Text,
                        result ? "OK":"NG",
                        lb_CH1_TestPressure.Text + lb_CH1_PressureUnit.Text,
                        ngret
                    };
                }
                else if (CH == 2)
                {
                    string ngret = "";
                    string fSmallLeak = LL28CH2client.readFloatF2(38);
                    if (fSmallLeak.ToDouble() > 2000)
                    {
                        ngret = LeakNG_ARP(fSmallLeak);
                    }
                    else
                    {
                        ngret = lb_CH2_SmallLeak.Text + lb_CH2_SmallLeakUnit.Text;
                    }
                    dataArr = new string[] {
                        DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"),
                        code,
                        (LL28CH2client.ArrRegister[6] / 10.0).ToString() + "s",
                        (LL28CH2client.ArrRegister[7] / 10.0).ToString() + "s",
                        (LL28CH2client.ArrRegister[8] / 10.0).ToString() + "s",
                        (LL28CH2client.ArrRegister[9] / 10.0).ToString() + "s",
                        LL28CH2client.readFloatF2(13) + lb_CH2_PressureUnit.Text,
                        LL28CH2client.readFloatF2(15) + lb_CH2_PressureUnit.Text,
                        LL28CH2client.readFloatF2(17) + lb_CH2_PressureUnit.Text,
                        LL28CH2client.readFloatF2(19) + lb_CH2_PressureUnit.Text,
                        LL28CH2client.readFloatF2(21) + lb_CH2_SmallLeakUnit.Text,
                        LL28CH2client.readFloatF2(23) + lb_CH2_SmallLeakUnit.Text,
                        result ? "OK":"NG",
                        lb_CH2_TestPressure.Text + lb_CH2_PressureUnit.Text,
                        ngret
                    };
                }
                else if (CH == 3)
                {
                    string ngret = "";
                    string fSmallLeak = LL28CH3client.readFloatF2(38);
                    if (fSmallLeak.ToDouble() > 2000)
                    {
                        ngret = LeakNG_ARP(fSmallLeak);
                    }
                    else
                    {
                        ngret = lb_CH3_SmallLeak.Text + lb_CH3_SmallLeakUnit.Text;
                    }
                    dataArr = new string[] {
                        DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"),
                        code,
                        (LL28CH3client.ArrRegister[6] / 10.0).ToString() + "s",
                        (LL28CH3client.ArrRegister[7] / 10.0).ToString() + "s",
                        (LL28CH3client.ArrRegister[8] / 10.0).ToString() + "s",
                        (LL28CH3client.ArrRegister[9] / 10.0).ToString() + "s",
                        LL28CH3client.readFloatF2(13) + lb_CH3_PressureUnit.Text,
                        LL28CH3client.readFloatF2(15) + lb_CH3_PressureUnit.Text,
                        LL28CH3client.readFloatF2(17) + lb_CH3_PressureUnit.Text,
                        LL28CH3client.readFloatF2(19) + lb_CH3_PressureUnit.Text,
                        LL28CH3client.readFloatF2(21) + lb_CH3_SmallLeakUnit.Text,
                        LL28CH3client.readFloatF2(23) + lb_CH3_SmallLeakUnit.Text,
                        result ? "OK":"NG",
                        lb_CH3_TestPressure.Text + lb_CH3_PressureUnit.Text,
                        ngret
                    };
                }
                else if (CH == 4)
                {
                    string ngret = "";
                    string fSmallLeak = LL28CH4client.readFloatF2(38);
                    if (fSmallLeak.ToDouble() > 2000)
                    {
                        ngret = LeakNG_ARP(fSmallLeak);
                    }
                    else
                    {
                        ngret = lb_CH4_SmallLeak.Text + lb_CH4_SmallLeakUnit.Text;
                    }
                    dataArr = new string[] {
                        DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"),
                        code,
                        (LL28CH4client.ArrRegister[6] / 10.0).ToString() + "s",
                        (LL28CH4client.ArrRegister[7] / 10.0).ToString() + "s",
                        (LL28CH4client.ArrRegister[8] / 10.0).ToString() + "s",
                        (LL28CH4client.ArrRegister[9] / 10.0).ToString() + "s",
                        LL28CH4client.readFloatF2(13) + lb_CH4_PressureUnit.Text,
                        LL28CH4client.readFloatF2(15) + lb_CH4_PressureUnit.Text,
                        LL28CH4client.readFloatF2(17) + lb_CH4_PressureUnit.Text,
                        LL28CH4client.readFloatF2(19) + lb_CH4_PressureUnit.Text,
                        LL28CH4client.readFloatF2(21) + lb_CH4_SmallLeakUnit.Text,
                        LL28CH4client.readFloatF2(23) + lb_CH4_SmallLeakUnit.Text,
                        result ? "OK":"NG",
                        lb_CH4_TestPressure.Text + lb_CH4_PressureUnit.Text,
                        ngret
                    };
                }

                // 写入数据
                for (int i = 0; i < dataArr.Length; i++)
                {
                    xsheet.Cells[lastRow + 1, i + 1] = dataArr[i];
                }

                // 保存并关闭
                xbook.Save();
                xbook.Close();
                xapp.Quit();

                // 释放COM对象
                Marshal.ReleaseComObject(xsheet);
                Marshal.ReleaseComObject(xbook);
                Marshal.ReleaseComObject(xapp);

                //// 在保存完成后，生成图表
                //System.Threading.ThreadPool.QueueUserWorkItem(state =>
                //{
                //    // 生成趋势图（每20个产品生成一次）
                //    Chart.Create_TrendChart(CH, filepath, 20);

                //    // 生成统计图（每天生成一次）
                //    Chart.Create_PieChart(CH, filepath);
                //});
            }
            catch (Exception ex)
            {
                MessageBox.Show("Excel写入错误:" + ex.Message);
                mxlLog.Instance.Error($"Excel写入错误 ,行号{ex.StackTrace} ", ex);
            }
            finally
            {
                // 确保Excel进程被关闭
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }

        //离线版CSV文件
        private void AddCSVLiXianNg(int CH, bool IsSpot, string code)
        {
            try
            {
                string fileName;
                string file = DateTime.Now.ToString("yyyyMMdd");
                if (String.IsNullOrEmpty(filesave.Path))
                {
                    fileName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\";
                }
                else
                {
                    fileName = filesave.Path + "\\";
                }
                if (IsSpot)
                {
                    if (CH == 1)
                    {
                        fileName += "离线OK\\";
                        file = "1_" + file;
                    }
                    else if (CH == 2)

                    {
                        fileName += "离线OK\\";
                        file = "2_" + file;
                    }
                    else if (CH == 3)

                    {
                        //fileName += "Left\\";
                        fileName += "离线OK\\";
                        file = "3_" + file;
                    }
                }
                else
                {
                    if (CH == 1)
                    {
                        //fileName += "Left\\";
                        fileName += "离线NG\\";
                        file = "1_" + file;
                    }
                    else if (CH == 2)
                    {
                        //fileName += "Right\\";
                        fileName += "离线NG\\";
                        file = "2_" + file;
                    }
                    else
                    {
                        //fileName += "Right\\";
                        fileName += "离线NG\\";
                        file = "3_" + file;
                    }
                }

                if (!Directory.Exists(fileName))
                {
                    Directory.CreateDirectory(fileName);
                }
                string name = file + ".csv";
                fileName += name;
                if (File.Exists(fileName) == false)
                {
                    StreamWriter fileWriter1 = new StreamWriter(fileName, true, Encoding.UTF8);
                    fileWriter1.Write("时间,条形码,充气时间,平衡时间,测试时间,排气时间,测试压力,泄漏量,测试结果" + "\r\n");
                    fileWriter1.Flush();
                    fileWriter1.Close();
                }
                StreamWriter fileWriter = new StreamWriter(fileName, true, Encoding.UTF8);

                string nowdate = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");

                if (CH == 1)
                {
                    //fileWriter.Write(nowdate + ",\t" + MesCh1Code + ",");
                    //fileWriter.Write(ch1params.FullTime + "s" + ",");
                    //fileWriter.Write(ch1params.BalanTime + "s" + ",");
                    //fileWriter.Write(ch1params.TestTime1 + "s" + ",");
                    //fileWriter.Write(ch1params.ExhaustTime + "s" + ",");
                    //fileWriter.Write(ch1params.FPtoplimit + ch1params.PUnit + ",");
                    //fileWriter.Write(ch1params.FPlowlimit + ch1params.PUnit + ",");
                    //fileWriter.Write(ch1params.BalanPreMax + "Pa" + ",");
                    //fileWriter.Write(ch1params.BalanPreMin + "Pa" + ",");
                    //fileWriter.Write(ch1params.Leaktoplimit + ch1params.LUnit + ",");
                    //fileWriter.Write(ch1params.Leaklowlimit + ch1params.LUnit + ",");
                    //fileWriter.Write(CH1Tlight.Text + ",");
                    //fileWriter.Write(lb_CH1_TestPressure.Text + ch1params.PUnit + ",");
                    //fileWriter.Write(CH1BigLeak.Text + ",");
                    //fileWriter.Write(lb_CH1_SmallLeak.Text + ch1params.LUnit + ",");

                    fileWriter.Write(lb_CH1_Result.Text + "\n");
                }
                if (CH == 2)
                {
                    //fileWriter.Write(nowdate + ",\t" + MesCh2Code + ",");
                    //fileWriter.Write(ch2params.FullTime + "s" + ",");
                    //fileWriter.Write(ch2params.BalanTime + "s" + ",");
                    //fileWriter.Write(ch2params.TestTime1 + "s" + ",");
                    //fileWriter.Write(ch2params.ExhaustTime + "s" + ",");
                    //fileWriter.Write(ch2params.FPtoplimit + ch2params.PUnit + ",");
                    //fileWriter.Write(ch2params.FPlowlimit + ch2params.PUnit + ",");
                    //fileWriter.Write(ch2params.BalanPreMax + "Pa" + ",");
                    //fileWriter.Write(ch2params.BalanPreMin + "Pa" + ",");
                    //fileWriter.Write(ch2params.Leaktoplimit + ch2params.LUnit + ",");
                    //fileWriter.Write(ch2params.Leaklowlimit + ch2params.LUnit + ",");
                    //fileWriter.Write(CH2Tlight.Text + ",");
                    //fileWriter.Write(CH2LeakPress.Text + ch2params.PUnit + ",");
                    //fileWriter.Write(CH2BigLeak.Text + ",");
                    //fileWriter.Write(CH2SmallLeak.Text + ch2params.LUnit + ",");
                    //fileWriter.Write(CH2Tlight.Text + "\n");
                }

                fileWriter.Flush();
                fileWriter.Close();
            }
            catch (Exception ex)
            {
                //MessageBox.Show("CSV:" + ex.Message);
                //wa.InsertWarningData(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), "-", "CSV:" + ex.Message);
            }
        }

        //将数据写入CSV文件中
        private void AddCSV(int CH, bool IsSpot)
        {
            try
            {
                string fileName;
                string file = DateTime.Now.ToString("yyyyMMdd");
                if (String.IsNullOrEmpty(filesave.Path))
                {
                    fileName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\";
                }
                else
                {
                    fileName = filesave.Path + "\\";
                }
                if (IsSpot)
                {
                    if (CH == 1)
                    {
                        fileName += "在线OK\\";
                        file = "1_" + file;
                    }
                    else if (CH == 2)
                    {
                        fileName += "在线OK\\";
                        file = "2_" + file;
                    }
                    else
                    {
                        fileName += "在线OK\\";
                        file = "3_" + file;
                    }
                }
                else
                {
                    if (CH == 1)
                    {
                        //fileName += "Left\\";
                        fileName += "在线NG\\";
                        file = "1_" + file;
                    }
                    else if (CH == 2)
                    {
                        //fileName += "Right\\";
                        fileName += "在线NG\\";
                        file = "2_" + file;
                    }
                    else
                    {
                        fileName += "在线NG\\";
                        file = "3_" + file;
                    }
                }

                if (!Directory.Exists(fileName))
                {
                    Directory.CreateDirectory(fileName);
                }
                string name = file + ".csv";
                fileName += name;


                if (File.Exists(fileName) == false)
                {
                    StreamWriter fileWriter1 = new StreamWriter(fileName, true, Encoding.UTF8);
                    fileWriter1.Write("时间,条形码,充气时间,平衡时间,测试时间,排气时间,测试压力,泄漏量,测试结果" + "\r\n");
                    fileWriter1.Flush();
                    fileWriter1.Close();
                }
                StreamWriter fileWriter = new StreamWriter(fileName, true, Encoding.UTF8);

                string nowdate = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");

                if (CH == 1)
                {
                    //fileWriter.Write(nowdate + ",\t" + MesCh1Code + ",");
                    //fileWriter.Write(ch1params.FullTime + "s" + ",");
                    //fileWriter.Write(ch1params.BalanTime + "s" + ",");
                    //fileWriter.Write(ch1params.TestTime1 + "s" + ",");
                    //fileWriter.Write(ch1params.ExhaustTime + "s" + ",");
                    //fileWriter.Write(ch1params.FPtoplimit + ch1params.PUnit + ",");
                    //fileWriter.Write(ch1params.FPlowlimit + ch1params.PUnit + ",");
                    //fileWriter.Write(ch1params.BalanPreMax + "Pa" + ",");
                    //fileWriter.Write(ch1params.BalanPreMin + "Pa" + ",");
                    //fileWriter.Write(ch1params.Leaktoplimit + ch1params.LUnit + ",");
                    //fileWriter.Write(ch1params.Leaklowlimit + ch1params.LUnit + ",");

                    //fileWriter.Write(lb_CH1_TestPressure.Text + ch1params.PUnit + ",");
                    //fileWriter.Write(CH1BigLeak.Text + ",");
                    //fileWriter.Write(lb_CH1_SmallLeak.Text + ch1params.LUnit + ",");
                    fileWriter.Write(lb_CH1_Result.Text + "\n");
                    //fileWriter.Write(CH1Tlight.Text + "\n");
                }
                if (CH == 2)
                {
                    //fileWriter.Write(nowdate + ",\t" + MesCh2Code + ",");
                    //fileWriter.Write(ch2params.FullTime + "s" + ",");
                    //fileWriter.Write(ch2params.BalanTime + "s" + ",");
                    //fileWriter.Write(ch2params.TestTime1 + "s" + ",");
                    //fileWriter.Write(ch2params.ExhaustTime + "s" + ",");
                    //fileWriter.Write(ch2params.FPtoplimit + ch2params.PUnit + ",");
                    //fileWriter.Write(ch2params.FPlowlimit + ch2params.PUnit + ",");
                    //fileWriter.Write(ch2params.BalanPreMax + "Pa" + ",");
                    //fileWriter.Write(ch2params.BalanPreMin + "Pa" + ",");
                    //fileWriter.Write(ch2params.Leaktoplimit + ch2params.LUnit + ",");
                    //fileWriter.Write(ch2params.Leaklowlimit + ch2params.LUnit + ",");
                    fileWriter.Write(lb_CH2_Result.Text + ",");
                    //fileWriter.Write(CH2LeakPress.Text + ch2params.PUnit + ",");
                    fileWriter.Write(lb_CH2BigLeak.Text + ",");
                    //fileWriter.Write(CH2SmallLeak.Text + ch2params.LUnit + ",");
                    fileWriter.Write(lb_CH2_Result.Text + "\n");
                }

                fileWriter.Flush();
                fileWriter.Close();
            }
            catch (Exception ex)
            {
                //MessageBox.Show("CSV:" + ex.Message);
                //wa.InsertWarningData(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), "-", "CSV:" + ex.Message);
            }
        }


        //在界面显示数据
        private void Display(int CH, bool result, string code)
        {
            string nowdate = DateTime.Now.ToString("HH:mm:ss");
            if (CH == 1)
            {
                string ngret = "";
                string fSmallLeak = LL28CH1client.readFloatF2(38);
                if (fSmallLeak.ToDouble() > 2000)
                {
                    ngret = LeakNG_ARP(fSmallLeak);
                }
                else
                {
                    ngret = lb_CH1_SmallLeak.Text + lb_CH1_SmallLeakUnit.Text;
                }
                string[] dataArr = { $"[CH{CH}] {nowdate}", code, lb_CH1_TestPressure.Text + lb_CH1_PressureUnit.Text, ngret, result ? "OK":"NG"};
                DataGridView1.Rows.Insert(0, dataArr[0], dataArr[1], dataArr[2], dataArr[3], dataArr[4]);
            }
            if (CH == 3)
            {
                string ngret = "";
                string fSmallLeak = LL28CH3client.readFloatF2(38);
                if (fSmallLeak.ToDouble() > 2000)
                {
                    ngret = LeakNG_ARP(fSmallLeak);
                }
                else
                {
                    ngret = lb_CH3_SmallLeak.Text + lb_CH3_SmallLeakUnit.Text;
                }
                string[] dataArr = { $"[CH{CH}] {nowdate}", code, lb_CH3_TestPressure.Text + lb_CH3_PressureUnit.Text, ngret, result ? "OK" : "NG" };
                DataGridView1.Rows.Insert(0, dataArr[0], dataArr[1], dataArr[2], dataArr[3], dataArr[4]);
            }

            if (CH == 2)
            {
                string ngret = "";
                string fSmallLeak = LL28CH2client.readFloatF2(38);
                if (fSmallLeak.ToDouble() > 2000)
                {
                    ngret = LeakNG_ARP(fSmallLeak);
                }
                else
                {
                    ngret = lb_CH2_SmallLeak.Text + lb_CH2_SmallLeakUnit.Text;
                }
                string[] dataArr = { $"[CH{CH}] {nowdate}", code, lb_CH2_TestPressure.Text + lb_CH2_PressureUnit.Text, ngret, result ? "OK" : "NG"};
                DataGridView2.Rows.Insert(0, dataArr[0], dataArr[1], dataArr[2], dataArr[3], dataArr[4]);
            }
            if (CH == 4)
            {
                string ngret = "";
                string fSmallLeak = LL28CH4client.readFloatF2(38);
                if (fSmallLeak.ToDouble() > 2000)
                {
                    ngret = LeakNG_ARP(fSmallLeak);
                }
                else
                {
                    ngret = lb_CH4_SmallLeak.Text + lb_CH4_SmallLeakUnit.Text;
                }
                string[] dataArr = { $"[CH{CH}] {nowdate}", code, lb_CH4_TestPressure.Text + lb_CH4_PressureUnit.Text, ngret, result ? "OK" : "NG" };
                DataGridView2.Rows.Insert(0, dataArr[0], dataArr[1], dataArr[2], dataArr[3], dataArr[4]);
            }
        }

        // 解析NG项
        private string LeakNG_ARP(string leakdata)
        {
            //int sw = leakdata.ToInt();
            if (leakdata.Split(".")[0] == "5000")
            {
                return "超出充气上限";
            }
            if (leakdata.Split(".")[0] == "5001")
            {
                return "超出充气下限";
            }
            if (leakdata.Split(".")[0] == "5002")
            {
                return "超出平衡压差上限";
            }
            if (leakdata.Split(".")[0] == "5003")
            {
                return "超出平衡压差下限";
            }
            if (leakdata.Split(".")[0] == "5004")
            {
                return "平衡超出充气压力上限";
            }
            if (leakdata.Split(".")[0] == "5005")
            {
                return "平衡超出充气压力下限";
            }
            return "--";
        }

        // 解析NG项
        private string LeakNG_ARP_Text(string leakdata)
        {
            if (leakdata.Split(".")[0] == "5000")
                return "50"; // "超出充气上限"

            if (leakdata.Split(".")[0] == "5001")
                return "51"; // "超出充气下限"

            if (leakdata.Split(".")[0] == "5002")
                return "52"; //"超出平衡压差上限"

            if (leakdata.Split(".")[0] == "5003")
                return "53"; //"超出平衡压差下限"

            if (leakdata.Split(".")[0] == "5004")
                return "54"; //"平衡超出充气压力上限"

            if (leakdata.Split(".")[0] == "5005")
                return "55"; //"平衡超出充气压力下限"

            return "49";
        }

        // 关闭窗口
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("将要关闭窗体，是否继续？", "询问", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                if (cts != null && !cts.IsCancellationRequested)
                {
                    cts.Cancel(); // 取消任务
                    cts.Dispose(); // 释放资源
                }

                LL28CH1client?.Stop(); // 停止线程
                LL28CH1client?.Disconnect(); // 断开连接
                LL28CH1client?.Dispose(); // 释放资源
                LL28CH1client = null;

                LL28CH2client?.Stop(); // 停止线程
                LL28CH2client?.Disconnect(); // 断开连接
                LL28CH2client?.Dispose(); // 释放资源
                LL28CH2client = null;

                LL28CH3client?.Stop(); // 停止线程
                LL28CH3client?.Disconnect(); // 断开连接
                LL28CH3client?.Dispose(); // 释放资源
                LL28CH3client = null;

                LL28CH4client?.Stop(); // 停止线程
                LL28CH4client?.Disconnect(); // 断开连接
                LL28CH4client?.Dispose(); // 释放资源
                LL28CH4client = null;

                e.Cancel = false;
                Application.Exit();
            }
            else
            {
                e.Cancel = true;
            }
        }

        // 更新UI标签文本
        private void SetLabelText(System.Windows.Forms.Label label, string text, Color? color = null)
        {
            try
            {
                if (label.IsDisposed || cts?.IsCancellationRequested == true)
                    return;

                if (label.InvokeRequired)
                {
                    label.BeginInvoke((MethodInvoker)delegate
                    {
                        if (!label.IsDisposed)
                        {
                            label.Text = text;
                            if (color.HasValue)
                                label.ForeColor = color.Value;
                        } 
                    });
                }
                else
                {
                    if (!label.IsDisposed)
                    {
                        label.Text = text;
                        if (color.HasValue)
                            label.ForeColor = color.Value;
                    }
                }
            }
            catch (ObjectDisposedException)
            {
                
            }
        }

        // 更新UI文本框文本
        private void SetUITextBox(UITextBox textbox, string text, Color? color = null)
        {
            try
            {
                if (textbox.IsDisposed || cts?.IsCancellationRequested == true)
                    return;

                if (textbox.InvokeRequired)
                {
                    textbox.BeginInvoke((MethodInvoker)delegate
                    {
                        if (!textbox.IsDisposed)
                        {
                            textbox.Text = text;
                            if (color.HasValue)
                                textbox.ForeColor = color.Value;
                        }
                    });
                }
                else
                {
                    if (!textbox.IsDisposed)
                    {
                        textbox.Text = text;
                        if (color.HasValue)
                            textbox.ForeColor = color.Value;
                    }
                }
            }
            catch (ObjectDisposedException)
            {

            }
        }

        // 更新进度条值
        private void SetProgressBar(Sunny.UI.UIProcessBar progressBar, int value)
        {
            try
            {
                if (progressBar.IsDisposed || cts?.IsCancellationRequested == true)
                    return;

                if (progressBar.InvokeRequired)
                {
                    progressBar.BeginInvoke((MethodInvoker)delegate
                    {
                        if (!progressBar.IsDisposed)
                        {
                            progressBar.Value = Math.Min(value, progressBar.Maximum);
                        }
                    });
                }
                else
                {
                    if (!progressBar.IsDisposed)
                    {
                        progressBar.Value = Math.Min(value, progressBar.Maximum);
                    }
                }
            }
            catch (ObjectDisposedException)
            {
                // 
            }
        }

        // 设置进度条最大值
        private void SetProgressBarMax(Sunny.UI.UIProcessBar progressBar, int maximum)
        {
            try
            {
                if (progressBar.IsDisposed || cts?.IsCancellationRequested == true)
                    return;

                if (progressBar.InvokeRequired)
                {
                    progressBar.BeginInvoke((MethodInvoker)delegate
                    {
                        if (!progressBar.IsDisposed)
                        {
                            progressBar.Maximum = maximum;
                            // 确保当前值不超过新的最大值
                            if (progressBar.Value > maximum)
                                progressBar.Value = maximum;
                        }
                    });
                }
                else
                {
                    if (!progressBar.IsDisposed)
                    {
                        progressBar.Maximum = maximum;
                        if (progressBar.Value > maximum)
                            progressBar.Value = maximum;
                    }
                }
            }
            catch (ObjectDisposedException)
            {
                // 
            }
        }


        // 串口1接收函数（扫码枪1）
        //private void CodePort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        //{
        //    try
        //    {
        //        System.Threading.Thread.Sleep(50);
        //        int len = CodePort1.BytesToRead; //获取可以读取的字节数
        //        if (len > 1)
        //        {
        //            byte[] buff = new byte[len]; //创建缓存数据数组
        //            CodePort1.Read(buff, 0, len); //把数据读取到buff数组
        //            Invoke((new System.Action(() =>  //接收计数
        //            {
        //                string time = DateTime.Now.ToString();
        //                string code = Encoding.Default.GetString(buff);
        //                string CODE = code.Replace("\r\n", "");
        //                //log.MES_Logmsg(time + "   " + CODE);
        //                //ClcCode = CODE;

        //                string codecd = CODE.Length.ToString();
        //                //  PlcCode = code.Substring(0,int.Parse(CH1codeLeng.Text));

        //                Console.WriteLine("扫码枪1串口收到:" + code);
        //                if (CODE.Length == int.Parse(CH1codeLeng.Text))
        //                {
        //                    CH1Code.Text = CODE;
        //                    Slot_PLC_WriteCoil(502, true);
        //                    ChkINMsg.Text = "CH1扫码完成";
        //                }
        //                else
        //                {
        //                    ChkINMsg.Text = "当前条形码长度为" + CODE.Length + "     " + "所设置的条码长度为" + CH1codeLeng.Text;
        //                }
        //                //PlcReadCode.Interval = 500;
        //                //PlcReadCode.Start();
        //                //   CodeLength(code);
        //                CodePort1.DiscardInBuffer();
        //                //c#如何把a跟b数据绑定在一起并判断 a是string b是bool
        //            })));

        //            //入站接口
        //            //   AddGhMES_CheckPass();
        //        }
        //        else
        //        {
        //            return;
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        ShowMessage("Code1:" + ex.Message, 2);
        //        log.PLC_Logmsg(DateTime.Now.ToString() + "   " + ex.Message);
        //    }
        //}

        // 主界面菜单栏
        private void uiNavBar1_MenuItemClick(string itemText, int menuIndex, int pageIndex)
        {
            if (!String.IsNullOrEmpty(User) && (User != "操作员"))
            {
                if (itemText == "PLC通讯配置")
                {
                    Form_PLCconnect elec = new Form_PLCconnect();
                    OpenForm(elec);
                }

                //if (itemText == "基本设置")
                //{
                //    Config c1 = new Config();
                //    OpenForm(c1);
                //}
                if (itemText == "测试参数")
                {
                    Electricity elec = new Electricity();
                    elec.Signal_PLC_WriteCoil += Slot_PLC_WriteCoil;
                    OpenForm(elec);
                }
                if (itemText == "产能清零")
                {
                    DialogResult result = MessageBox.Show(
                        "确定要清零吗？",
                        "确认",
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Question
                    );

                    if (result == DialogResult.Yes)
                    {
                        m_production.Clear();
                        UploadProductionData(m_production.GetTotal(), m_production.GetOK(), m_production.GetNG(), m_production.GetOKRate()); // 更新产能 
                    }
                }
                //if (itemText == "LIN设置")
                //{
                //    LinConfig lin = new LinConfig();
                //    OpenForm(lin);
                //}
                if (itemText == "存储设置")
                {
                    Form_Save save = new Form_Save();
                    OpenForm(save);
                }
                if (itemText == "仪器网络设置")
                {
                    Form_NetworkSet tcp = new Form_NetworkSet();
                    OpenForm(tcp);
                }
                if (itemText == "MES在线/离线")
                {
                    MES_Switch();
                    //Form_Save tcp = new Form_Save();
                    //OpenForm(tcp);
                }
                if (itemText == "查看UPH")
                {
                    //UPH upph = new UPH();
                    //OpenForm(upph);
                }
                if (itemText == "扫码器设置")
                {
                    Form_SaomaSet port = new Form_SaomaSet("SerialPort"); // SerialPort/TCP
                    OpenForm(port);
                }
                if (itemText == "复测数据")
                {
                    //DateNG port = new DateNG();
                    //OpenForm(port);
                }

                if (itemText == "权限设置")
                {
                    UserManagement user = new UserManagement();
                    OpenForm(user);
                }
                if (itemText == "报警记录")
                {
                    Warning warn = new Warning();
                    OpenForm(warn);
                }

                if (itemText == "清理日志")
                {
                    mxlLog.Instance.ClearOldLogs();
                }

                //if (itemText=="SPC设置")
                //{
                //    SpcApi spc = new SpcApi();
                //    OpenForm(spc);
                //}
                //if (itemText == "智能手表设置")
                //{
                //    Watch spc = new Watch();
                //    OpenForm(spc);
                //}

                //if (itemText == "打开文件")
                //{
                //    OpenMachineINI.CheckFileExists = true;
                //    OpenMachineINI.Multiselect = false;
                //    OpenMachineINI.CheckPathExists = true;
                //    OpenMachineINI.DefaultExt = ".ini";
                //    OpenMachineINI.Filter = "配置文件(*.ini)|*.ini";
                //    OpenMachineINI.ShowDialog();
                //    string machine_path = OpenMachineINI.FileName;
                //    if (!String.IsNullOrEmpty(machinepath) && (machine_path != "openFileDialog1"))
                //    {
                //        machine = OpenMachineINI.SafeFileName;
                //        machinepath = OpenMachineINI.FileName;
                //        //ReadOrder();
                //        //ReadSetting();
                //    }
                //}
                //if (itemText == "左工位1通道自检")
                //{
                //    ReadParameters(4, 1);
                //}
                //if (itemText == "左工位2通道自检")
                //{
                //    ReadParameters(4, 2);
                //}
                //if (itemText == "右工位1通道自检")
                //{
                //    ReadParameters(4, 3);
                //}
                //if (itemText == "右工位2通道自检")
                //{
                //    ReadParameters(4, 4);
                //}
            }
            if (itemText == "PLC重连")
            {

            }
            if (itemText == "段别查询")
            {
                //DuanBie db = new DuanBie();
                //OpenForm(db);
            }
            if (itemText == "MES设置")
            {
                Form_HQMESconfig mes = new Form_HQMESconfig();
                OpenForm(mes);
                //GhMes mes = new GhMes();
                //OpenForm(mes);
            }
            //if (itemText == "启动")
            //{
            //    plc.MachineStart();
            //}
            //if (itemText == "复位")
            //{
            //    plc.MachineReset();
            //}
            if (itemText == "登录")
            {
                Form_LogOn log = new Form_LogOn();
                OpenForm(log);
            }
            if (itemText == "注销")
            {
                User = "操作员";
                lb_User.Text = "操作员";
                tb_CH1codeLeng.Enabled = false;
                tb_CH2codeLeng.Enabled = false;
                tb_CH3codeLeng.Enabled = false;
                tb_CH4codeLeng.Enabled = false;

            }
            if (itemText == "MES日志")
            {
                //MESMsg.mesmsg.Show();
                //if (filesave.ChkMES)
                //{
                //    //mesmsg.Show();
                //    string path = System.Environment.CurrentDirectory + "\\MES_Log" + "/" + DateTime.Today.ToString("yyyy-MM-dd") + ".txt";
                //    if (File.Exists(path))
                //    {
                //        Process.Start(path);
                //        //File.Open(path, FileMode.Open);
                //        //pro
                //    }
                //    else
                //    {
                //        //MessageBox.Show("无今日mes日志！");
                //    }
                //}
                //else
                //{
                //    //MessageBox.Show("没有勾选mes!");
                //}
            }
            if (User == "厂商" || User == "工程师")
            {
                if (itemText == "CH1仪器启动")
                {
                    //LL28CH1client.writeCoil("0", true);
                    ch1workstation = (int)yiqi.start;
                    return;
                }
                if (itemText == "CH2仪器启动")
                {
                    //LL28CH2client.writeCoil("0", true);
                    ch2workstation = (int)yiqi.start;
                    return;
                }
                if (itemText == "CH3仪器启动")
                {
                    //LL28CH3client.writeCoil("0", true);
                    ch3workstation = (int)yiqi.start;
                    return;
                }
                if (itemText == "CH4仪器启动")
                {
                    //LL28CH4client.writeCoil("0", true);
                    ch4workstation = (int)yiqi.start;
                    return;
                }

                if (itemText == "CH1仪器复位")
                {
                    LL28CH1client.writeCoil("1", true);
                    ch1workstation = (int)yiqi.rst;
                    return;
                }
                if (itemText == "CH2仪器复位")
                {
                    LL28CH2client.writeCoil("1", true);
                    ch2workstation = (int)yiqi.rst;
                    return;
                }
                if (itemText == "CH3仪器复位")
                {
                    LL28CH3client.writeCoil("1", true);
                    ch3workstation = (int)yiqi.rst;
                    return;
                }
                if (itemText == "CH4仪器复位")
                {
                    LL28CH4client.writeCoil("1", true);
                    ch4workstation = (int)yiqi.rst;
                    return;
                }

                if (itemText == "厂商配置")
                {
                    Form_RootSet root = new Form_RootSet();
                    OpenForm(root);
                }
            }
            if (User == "厂商")
            {
                if (itemText == "高级功能设置")
                {
                    LeakCompensate comp = new LeakCompensate();
                    OpenForm(comp);
                }
            }
        }

        // MES开关
        private void MES_Switch()
        {
            var jsconfig = new JsonConfig("config.json");

            if (MESswitch)
            {
                MESswitch = false;
                lb_MESswitch.Text = "MES离线";
                pb_MESswitch.BackColor = Color.Red;
                jsconfig.SetValue("MESswitch", false);
            }
            else
            {
                // mes初始化
                if (HQMES_Init())
                {
                    MESswitch = true;
                    lb_MESswitch.Text = "MES在线";
                    pb_MESswitch.BackColor = Color.Green;
                    jsconfig.SetValue("MESswitch", true);
                }
                else
                {
                    MESswitch = false;
                    lb_MESswitch.Text = "MES离线";
                    pb_MESswitch.BackColor = Color.Red;
                    jsconfig.SetValue("MESswitch", false);
                }
            }
        }

        // 表格1根据结果变色
        //#region 表格根据结果变色
        private void DataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
        {
            for (int i = 0; i < this.DataGridView1.Rows.Count - 1; i++)
            {
                if (this.DataGridView1.Rows[i].Cells["Column7"].Value.ToString() == "OK")
                {
                    this.DataGridView1.Rows[i].DefaultCellStyle.ForeColor = Color.Green;
                }
                if (this.DataGridView1.Rows[i].Cells["Column7"].Value.ToString() == "NG")
                {
                    this.DataGridView1.Rows[i].DefaultCellStyle.ForeColor = Color.Red;
                }
                if ((this.DataGridView1.Rows[i].Cells["Column7"].Value.ToString() != "NG") && (this.DataGridView1.Rows[i].Cells["Column7"].Value.ToString() != "OK"))
                {
                    this.DataGridView1.Rows[i].DefaultCellStyle.ForeColor = Color.Blue;
                }
            }
        }

        // 表格2根据结果变色
        private void DataGridView2_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
        {
            for (int i = 0; i < this.DataGridView2.Rows.Count - 1; i++)
            {
                if (this.DataGridView2.Rows[i].Cells["dataGridViewTextBoxColumn7"].Value.ToString() == "OK")
                {
                    this.DataGridView2.Rows[i].DefaultCellStyle.ForeColor = Color.Green;
                }
                if (this.DataGridView2.Rows[i].Cells["dataGridViewTextBoxColumn7"].Value.ToString() == "NG")
                {
                    this.DataGridView2.Rows[i].DefaultCellStyle.ForeColor = Color.Red;
                }
                if ((this.DataGridView2.Rows[i].Cells["dataGridViewTextBoxColumn7"].Value.ToString() != "NG") && (this.DataGridView2.Rows[i].Cells["dataGridViewTextBoxColumn7"].Value.ToString() != "OK"))
                {
                    this.DataGridView2.Rows[i].DefaultCellStyle.ForeColor = Color.Blue;
                }
            }
        }

        // 界面退出按钮
        private void uiHeaderButton1_Click(object sender, EventArgs e)
        {
            System.Environment.Exit(0);
        }

        // 字节转字符串
        public string ByteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            try
            {
                if (bytes != null)
                {
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        returnStr += bytes[i].ToString("X2");//每个字节转换成两位十六进制
                                                             //     returnStr += " ";//两个16进制用空格隔开,方便看数据
                    }
                }
                return returnStr;
            }
            catch (Exception)
            {
                return returnStr;
            }
        }

        //将发送数据转为十六进制数据
        private static byte[] StrtoHexbyte(String hexstring)
        {
            hexstring = hexstring.Replace(" ", "");
            byte[] returnBytes = new byte[(hexstring.Length) / 2];
            try
            {
                for (int i = 0; i < returnBytes.Length; i++)
                {
                    returnBytes[i] = Convert.ToByte(hexstring.Substring(i * 2, 2), 16);
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
                return null;
            }
            return returnBytes;
        }

        //定时清理垃圾
        [DllImport("kernel32.dll")]
        private static extern bool SetProcessWorkingSetSize(IntPtr process, int minsuze, int maxSize);

        //定时清理垃圾
        private void timer1_Tick(object sender, EventArgs e)
        {
            FlushMemory();
            if (lb_MESswitch.Text == "MES离线")
            {
                lb_CH1MES_INstatus.Text = "";
                lb_CH2MES_INstatus.Text = "";
                lb_CH3MES_INstatus.Text = "";
                lb_CH4MES_INstatus.Text = "";

                lb_CH1MES_OUTstatus.Text = "";
                lb_CH2MES_OUTstatus.Text = "";
                lb_CH3MES_OUTstatus.Text = "";
                lb_CH4MES_OUTstatus.Text = "";
            }
        }

        //强制释放内存
        public static void FlushMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
            }
        }

        // 定时函数 定时退出用户
        private void UserClear_Tick(object sender, EventArgs e)
        {
            if (Form1.f1.lb_User.Text == "厂商")
            {
                lb_User.Text = "操作员";
                User = "操作员";
            }
        }

        // 用户变化
        private void Admin_TextChanged(object sender, EventArgs e)
        {
            if (lb_User.Text == "厂商" && lb_User.Text == "管理员")
            {
                tb_CH1codeLeng.Enabled = true;
                tb_CH2codeLeng.Enabled = true;
                tb_CH3codeLeng.Enabled = true;
                tb_CH4codeLeng.Enabled = true;
            }
            else
            {
                tb_CH1codeLeng.Enabled = false;
                tb_CH2codeLeng.Enabled = false;
                tb_CH3codeLeng.Enabled = false;
                tb_CH4codeLeng.Enabled = false;
            }
        }

        // 用户属性变化
        private void Admin_TabIndexChanged(object sender, EventArgs e)
        {
            if (lb_User.Text == "厂商")
            {
                // 用户重置
                UserClear.Interval = 600000; 
                UserClear.Start();
            }
        }

        // 清除条码1
        private void button2_Click(object sender, EventArgs e)
        {
            tb_CH1Code.Text = "";
            ch1_oldcode = "";
            lb_CH1MES_INstatus.Text = "##";
        }

        // 清除条码2
        private void button3_Click(object sender, EventArgs e)
        {
            tb_CH2Code.Text = "";
            ch1_oldcode = "";
            lb_CH2MES_INstatus.Text = "##";
        }
        // 清除条码3
        private void bt_code3clear_Click(object sender, EventArgs e)
        {
            tb_CH3Code.Text = "";
            ch1_oldcode = "";
            lb_CH3MES_INstatus.Text = "##";
        }
        // 清除条码4
        private void bt_code4clear_Click(object sender, EventArgs e)
        {
            tb_CH4Code.Text = "";
            ch1_oldcode = "";
            lb_CH4MES_INstatus.Text = "##";
        }

        //防止打开多个相同的窗口
        public void OpenForm(System.Windows.Forms.Form frm, bool isStatic = false)
        {
            if (frm == null) return;
            foreach (System.Windows.Forms.Form f in System.Windows.Forms.Application.OpenForms)
            {
                if (f.Name == frm.Name)
                {
                    f.Activate();
                    //if(isStatic)
                    //    f.ShowDialog();
                    //else
                        f.Show();
                    frm.Dispose();
                    System.GC.Collect();
                    System.GC.WaitForPendingFinalizers();
                    return;
                }
            }
            frm.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            //if (isStatic)
            //    frm.ShowDialog();
            //else
                frm.Show();
            System.GC.Collect();
            System.GC.WaitForPendingFinalizers();
        }

        public bool ch1AutoConnect = true; // 仪器自动重连
        public bool ch2AutoConnect = true;
        public bool ch3AutoConnect = true; 
        public bool ch4AutoConnect = true;

        private int ch1ReconnectCount = 0; // 仪器自动重连次数
        private int ch2ReconnectCount = 0;
        private int ch3ReconnectCount = 0; 
        private int ch4ReconnectCount = 0;

        // 定时器 监控仪器通讯状态
        private void timer_yiqiRun_Tick(object sender, EventArgs e)
        {
            try 
            { 
                // 通道1
                if (LL28CH1client != null && LL28CH1client.isRunning)
                {
                    lb_CH1Communication_status.Text = "OK";
                    lb_CH1Communication_status.ForeColor = Color.Green;

                    ch1ReconnectCount = 0;
                }
                else
                {
                    lb_CH1Communication_status.Text = "NG";
                    lb_CH1Communication_status.ForeColor = Color.Red;

                    if(ch1AutoConnect) // 重连
                    {
                        ch1ReconnectCount++;
                        if (ch1ReconnectCount % 6 == 0) 
                        {
                            LL28CH1client?.Stop(); // 先停止线程（如果正在运行）
                            LL28CH1client?.Disconnect(); // 断开旧连接
                            LL28CH1client?.Connect(ch1ipaddress); // 连接新 IP
                            LL28CH1client?.Start(); // 重新启动线程
                        }
                    }
                }

                // 通道2
                if (LL28CH2client != null && LL28CH2client.isRunning)
                {
                    lb_CH2Communication_status.Text = "OK";
                    lb_CH2Communication_status.ForeColor = Color.Green;

                    ch2ReconnectCount = 0;
                }
                else
                {
                    lb_CH2Communication_status.Text = "NG";
                    lb_CH2Communication_status.ForeColor = Color.Red;

                    if(ch2AutoConnect) // 重连
                    {
                        ch2ReconnectCount++;
                        if (ch2ReconnectCount % 6 == 0)
                        {
                            LL28CH2client?.Stop(); // 先停止线程（如果正在运行）
                            LL28CH2client?.Disconnect(); // 断开旧连接
                            LL28CH2client?.Connect(ch2ipaddress); // 连接新 IP
                            LL28CH2client?.Start(); // 重新启动线程
                        }
                    }
                }

                // 通道3
                if (LL28CH3client != null && LL28CH3client.isRunning)
                {
                    lb_CH3Communication_status.Text = "OK";
                    lb_CH3Communication_status.ForeColor = Color.Green;

                    ch3ReconnectCount = 0;
                }
                else
                {
                    lb_CH3Communication_status.Text = "NG";
                    lb_CH3Communication_status.ForeColor = Color.Red;

                    if (ch3AutoConnect) // 重连
                    {
                        ch3ReconnectCount++;
                        if (ch3ReconnectCount % 6 == 0)
                        {
                            LL28CH3client?.Stop(); // 先停止线程（如果正在运行）
                            LL28CH3client?.Disconnect(); // 断开旧连接
                            LL28CH3client?.Connect(ch3ipaddress); // 连接新 IP
                            LL28CH3client?.Start(); // 重新启动线程
                        }
                    }
                }

                // 通道4
                if (LL28CH4client != null && LL28CH4client.isRunning)
                {
                    lb_CH4Communication_status.Text = "OK";
                    lb_CH4Communication_status.ForeColor = Color.Green;

                    ch4ReconnectCount = 0;
                }
                else
                {
                    lb_CH4Communication_status.Text = "NG";
                    lb_CH4Communication_status.ForeColor = Color.Red;

                    if (ch4AutoConnect) // 重连
                    {
                        ch4ReconnectCount++;
                        if (ch4ReconnectCount % 6 == 0)
                        {
                            LL28CH4client?.Stop(); // 先停止线程（如果正在运行）
                            LL28CH4client?.Disconnect(); // 断开旧连接
                            LL28CH4client?.Connect(ch4ipaddress); // 连接新 IP
                            LL28CH4client?.Start(); // 重新启动线程
                        }
                    }
                }
            }
            catch (OverflowException)
            {
                ch1ReconnectCount = 0; // 溢出时重置
                ch2ReconnectCount = 0;
                ch3ReconnectCount = 0; 
                ch4ReconnectCount = 0;
            }
        }

        // 更新条码框
        private void UpdateCodeBox(string CODE)
        {
            // 1-4顺序放
            if (string.IsNullOrEmpty(tb_CH1Code.Text))
            {
                tb_CH1Code.Text = CODE;
                lastUseCodebox = 1;
            }
            else if (string.IsNullOrEmpty(tb_CH2Code.Text))
            {
                tb_CH2Code.Text = CODE;
                lastUseCodebox = 2;
            }
            else if (string.IsNullOrEmpty(tb_CH3Code.Text))
            {
                tb_CH3Code.Text = CODE;
                lastUseCodebox = 3;
            }
            else if (string.IsNullOrEmpty(tb_CH4Code.Text))
            {
                tb_CH4Code.Text = CODE;
                lastUseCodebox = 4;
            }
            else  // suoy 所有框都有条码时
            {
                lastUseCodebox = lastUseCodebox % 4 + 1;

                switch (lastUseCodebox)
                {
                    case 1: tb_CH1Code.Text = CODE; break;
                    case 2: tb_CH2Code.Text = CODE; break;
                    case 3: tb_CH3Code.Text = CODE; break;
                    case 4: tb_CH4Code.Text = CODE; break;
                }
            }
        }


        string lastCode = "";   // 保存上一次条码
        int lastUseCodebox = 0; // 保存上一次填充的条码框

        // 扫码枪串口接收函数
        private void SerialPort_CH1Saoma_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                #if SAOMA_PLAN_1
                {
                    System.Threading.Thread.Sleep(50);
                    int len = SerialPort_CH1Saoma.BytesToRead; // 获取可以读取的字节数
                    if (len > 1)
                    {
                        byte[] buff = new byte[len]; // 创建缓存数据数组
                        SerialPort_CH1Saoma.Read(buff, 0, len); // 把数据读取到buff数组
                        Invoke((new System.Action(() =>
                        {
                            string time = DateTime.Now.ToString();
                            string code = Encoding.Default.GetString(buff).Replace(" ", "").Replace("\r", "").Replace("\n", "");
                            string codelen = code.Length.ToString();

                            Console.WriteLine("扫码枪1串口收到:" + code);



                            //code = code.Split(';')[0];
                            //Console.WriteLine("扫码枪1串口去掉分隔符:" + code);

                            if (code == lastCode) // || code.Length > Convert.ToInt32(tb_CH1codeLeng.Text)
                                return;
                            lastCode = code; // 保存

                            if (tb_CH1Code.Text == code || tb_CH2Code.Text == code || tb_CH3Code.Text == code || tb_CH4Code.Text == code)
                            {
                                //MessageBox.Show($"条码 {CODE} 已存在", "重复提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                return;
                            }

                            // 更新条码框
                            UpdateCodeBox(code);

                            /*
                            if (codelen == tb_CH1codeLeng.Text.Trim())
                            {
                                if (code != lb_CH1Code.Text)
                                {
                                    lb_CH1Code.Text = code;
                                    SetUITextBox(tb_CH1MainMessage, "CH1扫码完成");
                                }
                                else
                                {
                                    //tb_CH1MainMessage.Text = "CH1条形码输入重复";
                                }
                            }
                            else
                            {
                                SetUITextBox(tb_CH1MainMessage, "CH1当前条形码长度为" + code.Length + " 所设置的条码长度为" + tb_CH1codeLeng.Text);
                            }
                            */

                            SerialPort_CH1Saoma.DiscardInBuffer();
                        })));
                    }
                    else
                    {
                        return;
                    }
                }
                #elif SAOMA_PLAN_4
                {
                    System.Threading.Thread.Sleep(50);
                    int len = SerialPort_CH1Saoma.BytesToRead; // 获取可以读取的字节数
                    if (len > 1)
                    {
                        byte[] buff = new byte[len]; // 创建缓存数据数组
                        SerialPort_CH1Saoma.Read(buff, 0, len); // 把数据读取到buff数组
                        Invoke((new System.Action(() =>
                        {
                            string time = DateTime.Now.ToString();
                            string code = Encoding.Default.GetString(buff).Replace("\r\n", "");
                            string codelen = code.Length.ToString();

                            Console.WriteLine("扫码枪1串口收到:" + code);



                            if (codelen == tb_CH1codeLeng.Text.Trim())
                            {
                                if (code != tb_CH1Code.Text)
                                {
                                    tb_CH1Code.Text = code;
                                    //SetUITextBox(tb_CH1MainMessage, "CH1扫码完成");
                                }
                                else
                                {
                                    SetUITextBox(tb_CH1MainMessage, "CH1条形码输入重复");
                                }
                            }
                            else
                            {
                                SetUITextBox(tb_CH1MainMessage, "CH1当前条形码长度为" + code.Length + " 所设置的条码长度为" + tb_CH1codeLeng.Text);
                            }

                            SerialPort_CH1Saoma.DiscardInBuffer();
                        })));
                    }
                    else
                    {
                        return;
                    }
                }
                #endif
            }
            catch (Exception ex)
            {
                mxlLog.Instance.Error($"串口扫码枪1接收函数 异常 ,行号{ex.StackTrace} ", ex);
            }
        }


        private void SerialPort_CH2Saoma_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                #if SAOMA_PLAN_4
                {
                    System.Threading.Thread.Sleep(50);
                    int len = SerialPort_CH2Saoma.BytesToRead; // 获取可以读取的字节数
                    if (len > 1)
                    {
                        byte[] buff = new byte[len]; // 创建缓存数据数组
                        SerialPort_CH2Saoma.Read(buff, 0, len); // 把数据读取到buff数组
                        Invoke((new System.Action(() =>
                        {
                            string time = DateTime.Now.ToString();
                            string code = Encoding.Default.GetString(buff).Replace("\r\n", "");
                            string codelen = code.Length.ToString();

                            Console.WriteLine("扫码枪2串口收到:" + code);



                            if (codelen == tb_CH2codeLeng.Text.Trim())
                            {
                                if (code != tb_CH2Code.Text)
                                {
                                    tb_CH2Code.Text = code;
                                    //SetUITextBox(tb_CH2MainMessage, "CH2扫码完成");
                                }
                                else
                                {
                                    SetUITextBox(tb_CH2MainMessage, "CH2条形码输入重复");
                                }
                            }
                            else
                            {
                                SetUITextBox(tb_CH2MainMessage, "CH2当前条形码长度为" + code.Length + " 所设置的条码长度为" + tb_CH2codeLeng.Text);
                            }

                            SerialPort_CH2Saoma.DiscardInBuffer();
                        })));
                    }
                    else
                    {
                        return;
                    }
                }
                #endif
            }
            catch (Exception ex)
            {
                mxlLog.Instance.Error($"CH2串口扫码枪接收函数 异常 ,行号{ex.StackTrace} ", ex);
            }
        }

        // 扫码枪3串口接收函数
        private void SerialPort_CH3Saoma_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                #if SAOMA_PLAN_4
                {
                    System.Threading.Thread.Sleep(50);
                    int len = SerialPort_CH3Saoma.BytesToRead; // 获取可以读取的字节数
                    if (len > 1)
                    {
                        byte[] buff = new byte[len]; // 创建缓存数据数组
                        SerialPort_CH3Saoma.Read(buff, 0, len); // 把数据读取到buff数组
                        Invoke((new System.Action(() =>
                        {
                            string time = DateTime.Now.ToString();
                            string code = Encoding.Default.GetString(buff).Replace(" ", "").Replace("\r", "").Replace("\n", "");

                            Console.WriteLine("扫码枪3串口收到:" + code);
                            //code = code.Split(';')[0];
                            //Console.WriteLine("扫码枪3串口去掉分隔符:" + code);

                            if (tb_CH1Code.Text == code || tb_CH2Code.Text == code || tb_CH3Code.Text == code || tb_CH4Code.Text == code)
                            {
                                //MessageBox.Show($"条码 {CODE} 已存在", "重复提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                SerialPort_CH3Saoma.DiscardInBuffer();
                                return;
                            }

                            if (code.Length.ToString() == tb_CH3codeLeng.Text.Trim())
                            {
                                tb_CH3Code.Text = code;
                            }
                            else
                            {
                                //SetUITextBox(tb_CH3MainMessage, "CH3当前条形码长度为" + code.Length + " 所设置的条码长度为" + tb_CH3codeLeng.Text);
                            }

                            SerialPort_CH3Saoma.DiscardInBuffer();
                        })));
                    }
                    else
                    {
                        return;
                    }
                }
                #endif
            }
            catch (Exception ex)
            {
                mxlLog.Instance.Error($"串口扫码枪3接收函数 异常 ,行号{ex.StackTrace} ", ex);
            }
        }

        // 扫码枪4串口接收函数
        private void SerialPort_CH4Saoma_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                #if SAOMA_PLAN_4
                {
                    System.Threading.Thread.Sleep(50);
                    int len = SerialPort_CH4Saoma.BytesToRead; // 获取可以读取的字节数
                    if (len > 1)
                    {
                        byte[] buff = new byte[len]; // 创建缓存数据数组
                        SerialPort_CH4Saoma.Read(buff, 0, len); // 把数据读取到buff数组
                        Invoke((new System.Action(() =>
                        {
                            string time = DateTime.Now.ToString();
                            string code = Encoding.Default.GetString(buff).Replace(" ", "").Replace("\r", "").Replace("\n", "");

                            Console.WriteLine("扫码枪4串口收到:" + code);
                            //code = code.Split(';')[0];
                            //Console.WriteLine("扫码枪4串口去掉分隔符:" + code);

                            if (tb_CH1Code.Text == code || tb_CH2Code.Text == code || tb_CH3Code.Text == code || tb_CH4Code.Text == code)
                            {
                                //MessageBox.Show($"条码 {CODE} 已存在", "重复提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                SerialPort_CH4Saoma.DiscardInBuffer();
                                return;
                            }

                            if (code.Length.ToString() == tb_CH4codeLeng.Text.Trim())
                            {
                                tb_CH4Code.Text = code;
                            }
                            else
                            {
                                //SetUITextBox(tb_CH4MainMessage, "CH4当前条形码长度为" + code.Length + " 所设置的条码长度为" + tb_CH4codeLeng.Text);
                            }

                            SerialPort_CH4Saoma.DiscardInBuffer();
                        })));
                    }
                    else
                    {
                        return;
                    }
                }
                #endif
            }
            catch (Exception ex)
            {
                mxlLog.Instance.Error($"串口扫码枪1接收函数 异常 ,行号{ex.StackTrace} ", ex);
            }
        }

        // 条码变化函数
        private void CH1Code_TextChanged(object sender, EventArgs e)
        {
            if (!tb_CH1Code.Text.IsNullOrEmpty())
            {
                bool len_bool = tb_CH1Code.Text.Length.ToString() == tb_CH1codeLeng.Text.Trim(); // 长度
                bool rep_bool = (tb_CH1Code.Text != tb_CH2Code.Text && 
                                 tb_CH1Code.Text != tb_CH3Code.Text && 
                                 tb_CH1Code.Text != tb_CH4Code.Text); // 重复
                if (len_bool && rep_bool)
                {
                    Console.WriteLine("CH1Code_TextChanged()");

                    // 治具下压-仪器启动
                    if (MESswitch)
                    {
                        Task.Run(() =>
                        {
                            // MES入站
                            var ret = ruzhan(tb_CH1Code.Text, m_ActionName, m_Tools);
                            if (ret.result)
                            {
                                SetLabelText(lb_CH1MES_INstatus, "PASS", Color.Green);
                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(10, 10);
                                            mxlLog.Instance.Info($"CH1入站 PLC写入10");
                                        }
                                        catch(Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH1入站 PLC写入10异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }  
                                }
                            }
                            else
                            {
                                SetLabelText(lb_CH1MES_INstatus, "NG", Color.Red);
                                SetUITextBox(tb_CH1MainMessage, $"CH1 入站NG:{ret.msg}");
                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(10, 0);
                                            mxlLog.Instance.Info($"CH1入站 PLC写入0");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH1入站 PLC写入0异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }
                            }
                            SetLabelText(lb_CH1MES_OUTstatus, "");
                        });
                    }
                    else
                    {
                        if (HCPLC_client.Connected)
                        {
                            lock (plcLock)  // 加锁
                            {
                                try
                                {
                                    HCPLC_client.WriteSingleRegister(10, 10);
                                    mxlLog.Instance.Info($"CH1入站 PLC写入10");
                                }
                                catch (Exception ex)
                                {
                                    mxlLog.Instance.Error($"CH1入站 PLC写入10异常 ,行号{ex.StackTrace} ", ex);
                                }
                            }
                        }
                    }
                }
                else
                {
                    if(!len_bool)
                        SetUITextBox(tb_CH1MainMessage, $"[CH1]当前条码长度{tb_CH1Code.Text.Length},限定{tb_CH1codeLeng.Text}");
                    else if(!rep_bool)
                        SetUITextBox(tb_CH1MainMessage, "[CH1]当前条码重复"); // 看起来条码接收函数处理了，这里不会触发
                    tb_CH1Code.Text = "";
                }
            }
        }

        private void CH2Code_TextChanged(object sender, EventArgs e)
        {
            if (!tb_CH2Code.Text.IsNullOrEmpty())
            {
                bool len_bool = tb_CH2Code.Text.Length.ToString() == tb_CH2codeLeng.Text.Trim();
                bool rep_bool = (tb_CH2Code.Text != tb_CH1Code.Text && 
                                 tb_CH2Code.Text != tb_CH3Code.Text && 
                                 tb_CH2Code.Text != tb_CH4Code.Text);
                if (len_bool && rep_bool)
                {
                    Console.WriteLine("CH2Code_TextChanged()");

                    // 治具下压-仪器启动

                    if (MESswitch)
                    {
                        Task.Run(() =>
                        {
                            // MES入站
                            var ret = ruzhan(tb_CH2Code.Text, m_ActionName, m_Tools);
                            if (ret.result)
                            {
                                SetLabelText(lb_CH2MES_INstatus, "PASS", Color.Green);
                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(11, 10);
                                            mxlLog.Instance.Info($"CH2入站 PLC写入10");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH2入站 PLC写入10异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                SetLabelText(lb_CH2MES_INstatus, "NG", Color.Red);
                                SetUITextBox(tb_CH2MainMessage, $"CH2 入站NG:{ret.msg}");
                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(11, 0);
                                            mxlLog.Instance.Info($"CH2入站 PLC写入0");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH2入站 PLC写入0异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }
                            }
                            SetLabelText(lb_CH2MES_OUTstatus, "");
                        });
                    }
                    else
                    {
                        if (HCPLC_client.Connected)
                        {
                            lock (plcLock)  // 加锁
                            {
                                try
                                {
                                    HCPLC_client.WriteSingleRegister(11, 10);
                                    mxlLog.Instance.Info($"CH2入站 PLC写入10");
                                }
                                catch (Exception ex)
                                {
                                    mxlLog.Instance.Error($"CH2入站 PLC写入10异常 ,行号{ex.StackTrace} ", ex);
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (!len_bool)
                        SetUITextBox(tb_CH2MainMessage, $"[CH2]当前条码长度{tb_CH2Code.Text.Length},限定{tb_CH2codeLeng.Text}");
                    else if (!rep_bool)
                        SetUITextBox(tb_CH2MainMessage, "[CH2]当前条码重复");
                    tb_CH2Code.Text = "";
                }
            }
        }


        private void lb_CH3Code_TextChanged(object sender, EventArgs e)
        {
            if (!tb_CH3Code.Text.IsNullOrEmpty())
            {
                bool len_bool = tb_CH3Code.Text.Length.ToString() == tb_CH3codeLeng.Text.Trim();
                bool rep_bool = (tb_CH3Code.Text != tb_CH1Code.Text && 
                                 tb_CH3Code.Text != tb_CH2Code.Text && 
                                 tb_CH3Code.Text != tb_CH4Code.Text);
                if (len_bool && rep_bool)
                {
                    Console.WriteLine("CH3Code_TextChanged()");

                    // 治具下压-仪器启动

                    if (MESswitch)
                    {
                        Task.Run(() =>
                        {
                            // MES入站
                            var ret = ruzhan(tb_CH3Code.Text, m_ActionName, m_Tools);
                            if (ret.result)
                            {
                                SetLabelText(lb_CH3MES_INstatus, "PASS", Color.Green);
                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(12, 10);
                                            mxlLog.Instance.Info($"CH3入站 PLC写入10");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH3入站 PLC写入10异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                SetLabelText(lb_CH3MES_INstatus, "NG", Color.Red);
                                SetUITextBox(tb_CH1MainMessage, $"CH3 入站NG:{ret.msg}");
                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(12, 0);
                                            mxlLog.Instance.Info($"CH3入站 PLC写入0");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH3入站 PLC写入0异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }
                            }
                            SetLabelText(lb_CH3MES_OUTstatus, "");
                        });
                    }
                    else
                    {
                        if (HCPLC_client.Connected)
                        {
                            lock (plcLock)  // 加锁
                            {
                                try
                                {
                                    HCPLC_client.WriteSingleRegister(12, 10);
                                    mxlLog.Instance.Info($"CH3入站 PLC写入10");
                                }
                                catch (Exception ex)
                                {
                                    mxlLog.Instance.Error($"CH3入站 PLC写入10异常 ,行号{ex.StackTrace} ", ex);
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (!len_bool)
                        SetUITextBox(tb_CH1MainMessage, $"[CH3]当前条码长度{tb_CH3Code.Text.Length},限定{tb_CH3codeLeng.Text}");
                    else if (!rep_bool)
                        SetUITextBox(tb_CH1MainMessage, "[CH3]当前条码重复");
                    tb_CH3Code.Text = "";
                }
            }
        }

        private void lb_CH4Code_TextChanged(object sender, EventArgs e)
        {
            if (!tb_CH4Code.Text.IsNullOrEmpty())
            {
                bool len_bool = tb_CH4Code.Text.Length.ToString() == tb_CH4codeLeng.Text.Trim();
                bool rep_bool = (tb_CH4Code.Text != tb_CH1Code.Text && 
                                 tb_CH4Code.Text != tb_CH2Code.Text && 
                                 tb_CH4Code.Text != tb_CH3Code.Text);
                if (len_bool && rep_bool)
                {
                    Console.WriteLine("CH4Code_TextChanged()");

                    // 治具下压-仪器启动

                    if (MESswitch)
                    {
                        Task.Run(() =>
                        {
                            // MES入站
                            var ret = ruzhan(tb_CH4Code.Text, m_ActionName, m_Tools);
                            if (ret.result)
                            {
                                SetLabelText(lb_CH4MES_INstatus, "PASS", Color.Green);
                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(13, 10);
                                            mxlLog.Instance.Info($"CH4入站 PLC写入10");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH4入站 PLC写入10异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                SetLabelText(lb_CH4MES_INstatus, "NG", Color.Red);
                                SetUITextBox(tb_CH2MainMessage, $"CH4 入站NG:{ret.msg}");
                                if (HCPLC_client.Connected)
                                {
                                    lock (plcLock)  // 加锁
                                    {
                                        try
                                        {
                                            HCPLC_client.WriteSingleRegister(13, 0);
                                            mxlLog.Instance.Info($"CH4入站 PLC写入0");
                                        }
                                        catch (Exception ex)
                                        {
                                            mxlLog.Instance.Error($"CH4入站 PLC写入0异常 ,行号{ex.StackTrace} ", ex);
                                        }
                                    }
                                }
                            }
                            SetLabelText(lb_CH4MES_OUTstatus, "");
                        });
                    }
                    else
                    {
                        if (HCPLC_client.Connected)
                        {
                            lock (plcLock)  // 加锁
                            {
                                try
                                {
                                    HCPLC_client.WriteSingleRegister(13, 10);
                                    mxlLog.Instance.Info($"CH4入站 PLC写入10");
                                }
                                catch (Exception ex)
                                {
                                    mxlLog.Instance.Error($"CH4入站 PLC写入10异常 ,行号{ex.StackTrace} ", ex);
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (!len_bool)
                        SetUITextBox(tb_CH2MainMessage, $"[CH4]当前条码长度{tb_CH4Code.Text.Length},限定{tb_CH4codeLeng.Text}");
                    else if (!rep_bool)
                        SetUITextBox(tb_CH2MainMessage, "[CH4]当前条码重复");
                    tb_CH4Code.Text = "";
                }
            }
        }



        private void tb_CH1MainMessage_TextChanged(object sender, EventArgs e)
        {
            timer_ClearMainMessage.Stop();
            timer_ClearMainMessage.Start(); // 重新计时
        }
        private void tb_CH2MainMessage_TextChanged(object sender, EventArgs e)
        {
            timer_ClearMainMessage.Stop();
            timer_ClearMainMessage.Start();
        }
        // 定时清空主界面信息框
        private void timer_ClearMainMessage_Tick(object sender, EventArgs e)
        {
            timer_ClearMainMessage.Stop();
            tb_CH1MainMessage.Clear();
            tb_CH2MainMessage.Clear();
        }

        static int aaaaa = 0;
        private void bt_test_Click(object sender, EventArgs e)
        {
            aaaaa++;
            if(aaaaa % 10 == 1)
            {
                m_production.AddNG();
            }
            else
            {
                m_production.AddOK();
            }
            UploadProductionData(m_production.GetTotal(), m_production.GetOK(), m_production.GetNG(), m_production.GetOKRate()); // 更新产能 

            //// 测试文件冲突
            //CreateFile(1, true, "123456789");
            //CreateFile(2, true, "123456789");
            //CreateFile(3, true, "123456789");
            //CreateFile(4, true, "123456789");

            // 写入激活状态
            //ActivationManager.WriteActivationStatus(false);
            //this.Enabled = false;

            //Form_Activate elec = new Form_Activate();
            //elec.Signal_LoginResult += Slot_MainShow;
            //OpenForm(elec, true);

            //this.Enabled = false;
            //mxlLog.Instance.ClearOldLogs();
            // MES
            //if (MESswitch)
            //{
            //    RtValue rdata = chuzhan(2, lb_CH2Code.Text, false);
            //    if (rdata.result)
            //    {
            //        SetLabelText(lb_CH2MES_OUTstatus, "PASS", Color.Green);
            //    }
            //    else
            //    {
            //        SetLabelText(lb_CH2MES_OUTstatus, "NG", Color.Red);
            //    }
            //}

            //AddTxT(1,true,"123456789");
            //tb_CH1MainMessage.Text = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20";
            //mxlLog.Instance.Debug($"debug2");
            //mxlLog.Instance.Error($"error2");
            //LL28CH2client.writeRegisters(1076, new int[] {1});
        }

        // 条码长度变化
        private void tb_CH1codeLeng_TextChanged(object sender, EventArgs e)
        {
            if(tcpSaoma_Enabled && saomaClient1 != null && !tb_CH1codeLeng.Text.IsNullOrEmpty())
            {
                saomaClient1.codeLength = Convert.ToInt32(tb_CH1codeLeng.Text);
            }
        }
        private void tb_CH2codeLeng_TextChanged(object sender, EventArgs e)
        {
            if(tcpSaoma_Enabled && saomaClient2 != null && !tb_CH2codeLeng.Text.IsNullOrEmpty())
            {
                saomaClient2.codeLength = Convert.ToInt32(tb_CH2codeLeng.Text);
            }
        }

        // 发送扫码启动
        private void timer_SaomaStart_Tick(object sender, EventArgs e)
        {
            Slot_SaomaStart(1);
            Slot_SaomaStart(2);
            Slot_SaomaStart(3);
            Slot_SaomaStart(4);
        }

        // 显示时间
        private void timer_nowTime_Tick(object sender, EventArgs e)
        {
            string time = System.DateTime.Now.ToString("HH:mm:ss");
            lb_NowTime.Text = time;
        }
        private string GetLocalIPv4()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return ip.ToString();
                }
            }
            throw new Exception("No IPv4 address found.");
        }

        #region USB扫码
        private StringBuilder codeBuff = new StringBuilder();
        private DateTime lastKeyTime = DateTime.Now;
        private readonly int timeoutMs = 300;
        private bool monitorAllInput = false;

        private void tb_CHxCode_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (monitorAllInput || sender is Sunny.UI.UITextBox)
            {
                ProcessKeyPress(e.KeyChar);
                e.Handled = true; // 阻止字符显示
            }
        }

        // 条码字符处理
        private void ProcessKeyPress(char keyChar)
        {
            TimeSpan elapsed = DateTime.Now - lastKeyTime;
            if (elapsed.TotalMilliseconds > timeoutMs)
            {
                codeBuff.Clear();
            }

            lastKeyTime = DateTime.Now;

            if (keyChar == '\r' || keyChar == '\n')
            {
                string barcode = codeBuff.ToString().Trim();
                if (!string.IsNullOrEmpty(barcode))
                {
                    UpdateCodeBox(barcode);
                }
                codeBuff.Clear();
            }
            else
            {
                codeBuff.Append(keyChar);
            }
        }

        // 主窗口的KeyPreview设置为true，重写函数捕获所有键盘输入（勿删！没有引用，但是运行会调用）
        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            if (monitorAllInput)
            {
                ProcessKeyPress(e.KeyChar);
                e.Handled = true; // 阻止进一步处理
            }
            base.OnKeyPress(e); // 调用基类实现，确保其他功能正常
        }

        // 专注扫码复选框
        private void chk_SaomaFocus_CheckedChanged(object sender, EventArgs e)
        {
            monitorAllInput = chk_SaomaFocus.Checked;

            if (monitorAllInput)
            {
                // 监控所有输入时，让文本框获取焦点以便接收键盘事件
                this.Focus();
            }
        }
        #endregion

        #region 华勤MES
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate int MESBackFunc(StringBuilder data);

        /// <summary>
        /// mes函数执行成功
        /// </summary>
        public const int MesBackOK = 0;

        /// <summary>
        /// MES的句柄
        /// </summary>
        public static int hMes = 0;
        private const string DLLPATH = "HQMES.dll";
        [DllImport(DLLPATH)]
        public static extern int MesInit(MESBackFunc func, ref int hMes, StringBuilder sInfo, ref int InfoLen);
        [DllImport(DLLPATH)]
        public static extern int MesStart(int hMes, string SN, string ActionName, string Tools, StringBuilder sInfo, ref int InfoLen);
        [DllImport(DLLPATH)]
        public static extern int MesStart2(int hMes, string SN, string SNType, string ActionName, string Tools, StringBuilder sInfo, ref int InfoLen);
        [DllImport(DLLPATH)]
        public static extern int MesEnd(int hMes, string SN, string ActionName, string Tools, string ErrorCode, StringBuilder sInfo, ref int InfoLen);
        [DllImport(DLLPATH)]
        public static extern int MesEnd2(int hMes, string SN, string SNType, string ActionName, string Tools, string ErrorCode, string AllData, StringBuilder sInfo, ref int InfoLen);
        [DllImport(DLLPATH)]
        private static extern int MesSaveAndGetExtraInfo(int hMes, string G_TYPE, string G_POSITION, string G_KEY, string G_VALUE, string G_EXTINFO, StringBuilder sInfo, ref int InfoLen);
        [DllImport(DLLPATH)]
        public static extern int MesUnInit(int hMes);
        [DllImport(DLLPATH)]
        public static extern int MesStart3(int hMes, string SN, string SNType, string ActionName, string Tools, string Extinfo, StringBuilder sInfo, ref int InfoLen);


        private static MESBackFunc tempFunc;// 必须要加一个变量，这样不会被回收
        public static int WriteLogFile(StringBuilder data)
        {
            return 0;
        }

        // 华勤mes参数
        public static string m_ActionName;
        public static string m_Tools;
        public static string m_LINE;
        public static string G_CHECKFLOWID;

        static int hmes = 0;

        // 华勤MES初始化
        public static bool HQMES_Init()
        {
            int len = 102400;
            StringBuilder strdata = new StringBuilder(len);
            if (hMes == 0)
            {
                tempFunc = WriteLogFile;  // 必须要加一个变量，这样不会被回收 这个回调函数赋值只能放在这个位置，防止当多次点击init之后可能会出现回调函数被回收的现象
                if (0 == MesInit(tempFunc, ref hMes, strdata, ref len))
                {
                    JObject mesObj = (JObject)JsonConvert.DeserializeObject(strdata.ToString());
                    string version = "";
                    version = mesObj.GetValue("H_MSG") == null ? "" : mesObj.GetValue("H_MSG").ToString(); // 获取meshelepr的版本
                    MessageBox.Show("初始化链接MES 成功 ！MEShelper版本：" + version); // strdata会返回一个meshelper的版本号表示初始化成功
                    return true;
                }
                else
                {
                    hMes = 0;
                    MessageBox.Show("初始化链接MES 失败！");
                    return false;
                }
            }
            else
            {
                //MessageBox.Show("请勿重复初始化MES链接！");

                return true;
            }
        }

        // 华勤MES入站
        public static (bool result, string msg) ruzhan(string SN, string ActionName, string toolName)
        {
            string time1 = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            int InfoLen = 102400;
            StringBuilder sInfo = new StringBuilder(InfoLen);

            if (hMes != 0)
            {
                string DATA = "";
                string H_MSG = "";
                string G_RET_DATA = "";
                string NeedLoad = "";

                mxlLog.Instance.MESDebug($"入站前 SN:{SN} - ActionName:{ActionName} - toolName:{toolName} - sInfo:{sInfo} - InfoLen:{InfoLen}");
                if (0 == MesStart(hMes, SN, ActionName, toolName, sInfo, ref InfoLen))
                {
                    mxlLog.Instance.MESDebug($"入站 OK:{SN} - sInfo:{sInfo.ToString()}");

                    JObject retObj = (JObject)JsonConvert.DeserializeObject(sInfo.ToString());
                    DATA = retObj.GetValue("DATA") == null ? "" : retObj.GetValue("DATA").ToString(); // data是一个json字符串，其中包含mes返回的主要字段，按照这个参考继续解析出来 例如获取CSN

                    // 解析返回信息
                    JObject dataObj = (JObject)JsonConvert.DeserializeObject(DATA);
                    string CSN = dataObj.GetValue("CSN") == null ? "" : dataObj.GetValue("CSN").ToString();
                    G_CHECKFLOWID = dataObj.GetValue("G_CHECKFLOWID") == null ? "" : dataObj.GetValue("G_CHECKFLOWID").ToString();

                    H_MSG = retObj.GetValue("H_MSG") == null ? "" : retObj.GetValue("H_MSG").ToString();
                    G_RET_DATA = retObj.GetValue("G_RET_DATA") == null ? "" : retObj.GetValue("G_RET_DATA").ToString(); // 标记工具需要回传给MES的字段，是json格式，将其解析出来可以得到字段，工具必须将该字段赋值并回传给MES，在endmes函数回传
                    NeedLoad = retObj.GetValue("NeedLoad") == null ? "" : retObj.GetValue("NeedLoad").ToString(); // 标记工具是否需要重启

                    if (!String.IsNullOrEmpty(H_MSG) && H_MSG == "MES response:")
                    {
                        return (true, H_MSG);
                    }
                    else
                    {
                        return (false, H_MSG);
                    }
                }
                else
                {
                    mxlLog.Instance.MESDebug($"入站 NG:{SN} - sInfo:{sInfo.ToString()}");

                    JObject retObj = (JObject)JsonConvert.DeserializeObject(sInfo.ToString());
                    H_MSG = retObj.GetValue("H_MSG") == null ? "" : retObj.GetValue("H_MSG").ToString(); // mes返回的错误信息最好将其在工具界面展示出来给操作人员查看

                    return (false, sInfo.ToString());
                }
            }
            else
            {
                MessageBox.Show("请初始化MES链接！");
                return (false, sInfo.ToString());
            }
        }

        public static (bool result, string msg) chuzhan(int CH, string SN, string ActionName, string Tools, string checkFlowId, bool result)
        {
            int InfoLen = 102400;
            Log log = new Log();
            StringBuilder sInfo = new StringBuilder(InfoLen);

            if (hMes != 0)
            {
                string ErrorCode = "0";

                Dictionary<String, Object> map = new Dictionary<string, object>();

                // 确认错误码和错误项
                if (result)
                {
                    ErrorCode = "0";
                }
                else
                {
                    ErrorCode = "NG";
                    sInfo.Append($"泄漏量超出设定范围"); // 错误详细描述
                }

                switch (CH)
                {
                    case 1:
                        map["Xlvall"] = Form1.f1.lb_CH1_TestPressure.Text + Form1.f1.lb_CH1_PressureUnit.Text; // 测试压力
                        map["Csvall"] = Form1.f1.LL28CH1client.readFloatF2(38); // 泄漏量
                        break;
                    case 2:
                        map["Xlvall"] = Form1.f1.lb_CH2_TestPressure.Text + Form1.f1.lb_CH2_PressureUnit.Text; // 测试压力
                        map["Csvall"] = Form1.f1.LL28CH2client.readFloatF2(38); // 泄漏量
                        break;
                    case 3:
                        map["Xlvall"] = Form1.f1.lb_CH3_TestPressure.Text + Form1.f1.lb_CH3_PressureUnit.Text; // 测试压力
                        map["Csvall"] = Form1.f1.LL28CH3client.readFloatF2(38); // 泄漏量
                        break;
                    case 4:
                        map["Xlvall"] = Form1.f1.lb_CH4_TestPressure.Text + Form1.f1.lb_CH4_PressureUnit.Text; // 测试压力
                        map["Csvall"] = Form1.f1.LL28CH4client.readFloatF2(38); // 泄漏量
                        break;
                }

                //压力转换
                map["G_OP_LINE"] = m_LINE;
                map["DateTime"] = DateTime.Now.ToString();
                map["G_CHECKFLOWID"] = checkFlowId;

                string AllData = JsonConvert.SerializeObject(map);
                string SNType = "1";

                mxlLog.Instance.MESDebug($"出站-通道{CH} MesEnd2：" + $"hMes:{hMes}-SN:{SN}-SNType:{SNType}-ActionName:{ActionName}-toolName:{Tools}-ErrorCode:{ErrorCode}-AllData:{AllData}-strdata:{sInfo}-len:{InfoLen}");
                if (0 == MesEnd2(hMes, SN, SNType, ActionName, Tools, ErrorCode, AllData, sInfo, ref InfoLen))
                {
                    mxlLog.Instance.MESDebug($"出站-通道{CH} OK:{SN} - sInfo:{sInfo.ToString()}");

                    JObject retObj = (JObject)JsonConvert.DeserializeObject(sInfo.ToString());
                    string msg = retObj.GetValue("G_NEXTWS") == null ? "" : retObj.GetValue("G_NEXTWS").ToString();

                    if (!String.IsNullOrEmpty(msg) && (msg.Contains("过站成功") || msg.Contains("测试PASS"))) // 还需优化，文档未标注已过站字段
                    {
                        return (true, msg);
                    }
                    else
                    {
                        return (false, msg);
                    }
                }
                else
                {
                    mxlLog.Instance.MESDebug($"出站-通道{CH} NG:{SN} - sInfo:{sInfo.ToString()}");
                    return (false, sInfo.ToString());
                }
            }
            else
            {
                MessageBox.Show("请初始化MES链接！");
                return (false, sInfo.ToString());
            }
        }
        #endregion

    }
}
