using HslCommunication;
using LLAirtightApi;
using Microsoft.Office.Interop.Excel;
using System;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SLZ_4
{
    public partial class FormMain : AutoResizeForm
    {
        public int devNum = 1;
        public int channelNum = 4;      //通道数量
        //警告
        public WarningInfo wa = new WarningInfo();
        public static FormMain form;
        public bool bExit;                  //程序退出
        public string user;                 //当前用户
        public ConfigINI configIni;         //配置文件

        public string[] strStatus = {"空闲","测试","充气","平衡","检测", "排气"};
        public string[] strResult = { "", "OK", "NG"};
        public string[] strListPressureUnit = { "Pa", "KPa", "MPa", "bar", "Psi", "kg/cm²", "atm" };  //压力单位
        public string[] strListLeakageUnit = { "Pa", "KPa", "mbar", "atm", "SCCM", "CCM/S", "Pa/s" };        //泄漏量单位

        public DEVICE_PARAM[] arrDevParam;    //设备数组
        public DeviceObject[] arrDevObj;      //设备对象数组

        public SCAN_PARAM[] arrScanParam;     //扫码配置参数
        public SCANNER_PARAM[] arrScannerObj; //扫码枪配置参数
        public ScanNetwork[] arrScanNetwork;    //网络扫码枪对象数组
        public int scanType;                    //扫码枪类型

        public PLC_PARAM plcParam;              //PLC参数
        public PlcObject plcObj;                //PLC对象
        public PRINTER_PARAM printParam;                   //打印条码
        public MES_PARAM mesParam;              //MES参数
        public MesObj mesObj;                   //MES对象

        public STATISTICS_INFO statisticInfo;   //统计信息

        public STORAGE_PARAM storageParam;
        public string strOperator;          //操作员

        //设置窗口
        public ConfigDevicePort cfgDevForm;     //仪器窗口
        public LogOn logonForm;             //登录窗口
        public Electricity devParamForm;    //仪器参数窗口
        public ConfigStorage storageForm;   //存储配置窗口
        public ConfigScanner scannerForm;   //扫码枪配置窗口
        public ConfigPLC plcForm;           //PLC配置窗口
        public ConfigPassword passwordForm; //配置密码窗口
        public ConfigMes mesForm;           //MES设置窗口

        public Microsoft.Office.Interop.Excel.Application xapp;
        public Workbook xbook;
        public SqlConnection sqlConnection;
        SynchronizationContext syncContext;

        object lockObject = new object();       //统计加锁
        object lockSN = new object();           //序列号自增加锁
        public FormMain()
        {
            InitializeComponent();

            form = this;
            bExit = false;

            user = "操作员";
            labelUser.Text = user;
            labelOperator.Text = "";
                 
            InStatus1.Text = "";
            OutStatus1.Text = "";
            InStatus2.Text = "";
            OutStatus2.Text = "";

            arrDevParam = new DEVICE_PARAM[devNum];
            arrDevObj = new DeviceObject[devNum];

            arrScanParam = new SCAN_PARAM[2];
            arrScannerObj = new SCANNER_PARAM[2];
            arrScanNetwork = new ScanNetwork[2];

            storageParam = new STORAGE_PARAM();
            plcParam = new PLC_PARAM();
            mesParam = new MES_PARAM();

            statisticInfo = new STATISTICS_INFO();
            statisticInfo.ch = new STATISTICS_CHANNEL[channelNum];


            for (int i = 0; i < devNum; i++)
            {
                arrDevParam[i].iDevType = (int)DEVICE_TYPE.DEVICE_SLZ_4;    //LL-28
                arrDevParam[i].iProtocol = 0;   //网络
                arrDevParam[i].sDevAddr = "";
                arrDevParam[i].iSlaveId = i + 1;

            }
            for (int i = 0; i < channelNum; i++)
            {
                statisticInfo.ch[i] = new STATISTICS_CHANNEL();
            }

            configIni = new ConfigINI("Model", "Config");

            //创建窗口
            cfgDevForm = new ConfigDevicePort();
            logonForm = new LogOn();
            devParamForm = new Electricity();
            storageForm = new ConfigStorage();
            scannerForm = new ConfigScanner();
            plcForm = new ConfigPLC();
            passwordForm = new ConfigPassword();
            mesForm = new ConfigMes();

            //加载配置信息
            Config.loadConfig();                    //加载仪器配置信息
            Config.loadStorage(ref storageParam);   //加载存储信息
            Config.loadScanParam();                 //加载扫码参数
            Config.loadScanner();                   //加载扫码枪配置信息
            Config.loadPLC(ref plcParam);           //加载PLC配置信息
            Config.loadPrint(ref printParam);                     //加载打印机信息
            Config.loadMes(ref mesParam);           //加载MES配置信息
            Config.loadCount(ref statisticInfo);    //加载统计信息

            labelOperator.Text = strOperator;
            scanType = scannerForm.scanType;

            //添加仪器
            for (int i = 0; i < devNum; i++)
            {
                addDevObj(i);
            }
            //添加PLC
            //if (plcParam.sPort != "" && plcParam.iBaudrate != 0)
            //{
            //    plcObj = new PlcObject();
            //}
            //添加扫码枪
            if (scannerForm.scanType == (int)SCANNER_TYPE.INDUSTRY_NETWORK)
            {
                for (int i = 0; i < scannerForm.scanNum; i++)
                {
                    addScanNetwork(i);
                }
            }

            mesObj = new MesObj();
            syncContext = SynchronizationContext.Current;

            //扫码枪 PLC
            Task.Run(() =>
            {
                processScanner();
            });

            //工业扫码枪，发送开始扫码命令
            if (scanType == (int)SCANNER_TYPE.INDUSTRY_COM || scanType == (int)SCANNER_TYPE.INDUSTRY_NETWORK)
            {
                startScanCode(scanType);
            }

            Task.Run(() =>
            {
                refreshUI_CH(0);
            });
        }
        private void MainForm_Load(object sender, EventArgs e)
        {
            //if (arrDevParam[0].sDevAddr == "" || arrDevParam[1].sDevAddr == "")
            //{
            //    cfgDevForm.UDPBroadcast();
            //}         

            this.WindowState = FormWindowState.Maximized;
            timerUpdate.Start();

            uiLabelPassNumber.ForeColor = Color.Green;
            uiLabelFailNumber.ForeColor = Color.Red;

            ShowStatistics();
        }
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            bExit = true;

            Thread.Sleep(500);
        }
        public void clearUI(int i)
        {
            if (i == 0)//通道1
            {
                InStatus1.Text = "";
                OutStatus1.Text = "";
                uiTextCode1.Text = "";
                commStatus1.Text = "未配置";
                commStatus1.BackColor = Color.Red;
                pressure1.Text = "";
                leakage1.Text = "";
                uiProcessBar1.Value = 0;
                result1.Text = "";
                workState1.Text = "";
            }
            else if (i == 1)//通道2
            {
                InStatus2.Text = "";
                OutStatus2.Text = "";
                uiTextCode2.Text = "";
                commStatus2.Text = "未配置";
                commStatus2.BackColor = Color.Red;
                pressure2.Text = "";
                leakage2.Text = "";
                uiProcessBar2.Value = 0;
                result2.Text = "";
                workState2.Text = "";
            }       
        }
        public void processScanner()
        {
            Thread.Sleep(500);
            while (!bExit)
            {
                if (scannerForm.Visible == false)
                {
                    //连接扫码枪
                    if (scanType == (int)SCANNER_TYPE.COMMON || scanType == (int)SCANNER_TYPE.INDUSTRY_COM)
                    {
                        if (arrScannerObj[0].sPort.Length > 0 && arrScannerObj[0].iBaudrate != 0)
                        {
                            openScanner1();
                        }
                        if (arrScannerObj[1].sPort.Length > 0 && arrScannerObj[1].iBaudrate != 0)
                        {
                            openScanner2();
                        }
                    }
                    else if (scannerForm.scanType == (int)SCANNER_TYPE.INDUSTRY_NETWORK)    //网口
                    {
                        for (int i = 0; i < scannerForm.scanNum; i++)
                        {
                            openScannerNetwork(i);
                        }
                    }
                }
                //连接PLC
                //if (plcObj != null && !plcObj.PLC.IsOpen())
                //{
                //    plcObj.openPLC(plcParam);
                //}
                syncContext.Post(new SendOrPostCallback(obj =>
                {
                    //更新PLC状态
                    if (plcObj != null)
                    {
                        updatePLCStatus(plcObj.PLC.IsOpen());
                    }

                    //更新MES状态
                    if (mesObj != null)
                    {
                        updateMESStatus(mesParam.bCheckOut);
                    }
                }), null);

                Thread.Sleep(2000);
            }
        }
        public void refreshUI_CH(int iCH)
        {
            while (!bExit)
            {
                //更新UI
                syncContext.Post(new SendOrPostCallback(obj =>
                {
                    if (arrDevObj[iCH] != null && bExit == false)
                    {
                        refreshUI(iCH, ref arrDevObj[iCH].testInfo, arrDevObj[iCH].bStatus);
                    }
                    else
                    {
                        clearUI(iCH);
                    }
                }), null);

                if (arrDevObj[iCH] != null && bExit == false)
                {
                    for (int i = 0; i < channelNum; i++)
                    {
                        if (arrDevObj[iCH].testInfo.chTest[i].iRecordFlag == 1)
                        {
                            WriteRecord(ref arrDevObj[iCH].testInfo, storageParam.sPath, i);
                            arrDevObj[iCH].testInfo.chTest[i].iRecordFlag = 0;
                        }
                    }
                }

                Thread.Sleep(100);
            }
        }

        public void refreshUI(int iCH, ref TEST_PARAM testInfo, bool bSatus)
        {
            int ichannel = 0;
            //CH1      
            commStatus1.Text = bSatus ? "在线" : "离线";
            commStatus1.BackColor = bSatus ? Color.Green : Color.Red;
            pressure1.Text = testInfo.chTest[ichannel].fTestPressure.ToString("F3") + " " + strListPressureUnit[testInfo.iPressureUnit];
            leakage1.Text = testInfo.chTest[ichannel].fLeakAmount.ToString("F3") + " " + strListLeakageUnit[testInfo.iLeakUnit];
            uiProcessBar1.Value = (int)testInfo.fProgressValue;

            result1.Text = strResult[testInfo.chTest[ichannel].ResultFlag];
            workState1.Text = strStatus[testInfo.iWorkStatus];

            //CH2
            ichannel += 1;
            commStatus2.Text = bSatus ? "在线" : "离线";
            commStatus2.BackColor = bSatus ? Color.Green : Color.Red;
            pressure2.Text = testInfo.chTest[ichannel].fTestPressure.ToString("F3") + " " + strListPressureUnit[testInfo.iPressureUnit];
            leakage2.Text = testInfo.chTest[ichannel].fLeakAmount.ToString("F3") + " " + strListLeakageUnit[testInfo.iLeakUnit];
            uiProcessBar2.Value = (int)testInfo.fProgressValue;

            result2.Text = strResult[testInfo.chTest[ichannel].ResultFlag];
            workState2.Text = strStatus[testInfo.iWorkStatus];

            //CH3
            ichannel += 1;
            pressure3.Text = testInfo.chTest[ichannel].fTestPressure.ToString("F3") + " " + strListPressureUnit[testInfo.iPressureUnit];
            leakage3.Text = testInfo.chTest[ichannel].fLeakAmount.ToString("F3") + " " + strListLeakageUnit[testInfo.iLeakUnit];
            result3.Text = strResult[testInfo.chTest[ichannel].ResultFlag];

            //CH4
            ichannel += 1;
            pressure4.Text = testInfo.chTest[ichannel].fTestPressure.ToString("F3") + " " + strListPressureUnit[testInfo.iPressureUnit];
            leakage4.Text = testInfo.chTest[ichannel].fLeakAmount.ToString("F3") + " " + strListLeakageUnit[testInfo.iLeakUnit];
            result4.Text = strResult[testInfo.chTest[ichannel].ResultFlag];

            for (int i = 0; i < channelNum; i++)
            {
                showResult(testInfo.chTest[i].ResultFlag, i);

                string code1 = "";
                string code2 = "";
                if (testInfo.chTest[i].iRecordFlag == 1)
                {
                    switch (i)
                    {
                        case 0:
                            code1 = uiTextCode1.Text;
                            code2 = uiTextCode11.Text;
                            break;
                        case 1:
                            code1 = uiTextCode2.Text;
                            code2 = uiTextCode22.Text;
                            break;
                        case 2:
                            code1 = uiTextCode3.Text;
                            code2 = uiTextCode33.Text;
                            break;
                        case 3:
                            code1 = uiTextCode4.Text;
                            code2 = uiTextCode44.Text;
                            break;
                        default:
                            break;
                    }

                    ShowRecord(ref testInfo, i, code1);
                    ShowStatistics(testInfo.chTest[i].ResultFlag, i);
                    if (code2 != "")
                    {
                        ShowRecord(ref testInfo, i, code2);
                        ShowStatistics(testInfo.chTest[i].ResultFlag, i);
                    }
                }
            }
        }

        private void showResult(int iResult, int iCH)
        {
            Color color = Color.Transparent;
            switch (iResult)
            {
                case 0:
                    color = Color.Transparent;
                    if (iCH == 0)
                    {
                        OutStatus1.Text = "";
                        OutStatus1.BackColor = color;
                    }
                    else if (iCH == 1)
                    {
                        OutStatus2.Text = "";
                        OutStatus2.BackColor = color;
                    }
                    else if (iCH == 2)
                    {
                        OutStatus3.Text = "";
                        OutStatus3.BackColor = color;
                    }
                    else if (iCH == 3)
                    {
                        OutStatus4.Text = "";
                        OutStatus4.BackColor = color;
                    }
                    break;
                case 1:
                    color = Color.Green;
                    break;
                case 2:
                    color = Color.Red;
                    break;
                default:
                    break;
            }
            if (iCH == 0)
            {
                result1.ForeColor = color;
            }
            else if (iCH == 1)
            {
                result2.ForeColor = color;
            }
            else if (iCH == 2)
            {
                result3.ForeColor = color;
            }
            else if (iCH == 3)
            {
                result4.ForeColor = color;
            }
        }

        private void uiNavBar_MenuItemClick(string itemText, int menuIndex, int pageIndex)
        {
            //以下操作不需要判断用户
            if (itemText == "登录")
            {
                logonForm.setOperator(labelOperator.Text);
                logonForm.StartPosition = FormStartPosition.CenterParent;
                logonForm.ShowDialog();
                if (labelUser.Text != "操作员")
                {
                    timerUser.Start();
                }
                if (labelOperator.Text != "")
                {
                    uiTextMsg.Text = "";
                    uiTextMsg.ForeColor = Color.Black;

                    uiTextCH2.Text = "";
                    uiTextCH2.ForeColor = Color.Black;
                }
            }
            else if (itemText == "注销")
            {
                labelUser.Text = "操作员";
            }
            if (labelUser.Text == "管理员")
            {
                if (itemText == "修改密码")
                {
                    passwordForm.clear();
                    passwordForm.StartPosition = FormStartPosition.CenterParent;
                    passwordForm.ShowDialog();
                }
            }
            //需要用户权限
            if (labelUser.Text == "厂商" || labelUser.Text == "管理员" || labelUser.Text == "工程师")
            {
                if (itemText == "MES设置")
                {
                    mesForm.SetConfig(ref mesParam);
                    mesForm.StartPosition = FormStartPosition.CenterParent;
                    mesForm.ShowDialog();
                }
                else if (itemText == "测试参数")
                {
                    devParamForm.SetConfig();
                    devParamForm.StartPosition = FormStartPosition.CenterParent;
                    devParamForm.ShowDialog();
                    //OpenForm(devParamForm);
                }
                else if (itemText == "存储设置")
                {
                    storageForm.SetConfig(ref storageParam);
                    storageForm.StartPosition = FormStartPosition.CenterParent;
                    storageForm.ShowDialog();
                    //OpenForm(storageForm);
                }
                else if (itemText == "产量清零")
                {
                    if (MessageBox.Show("你确定要清空产量吗?", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        for (int i = 0; i < devNum; i++)
                        {
                            statisticInfo.ch[i].iCount = 0;
                            statisticInfo.ch[i].iPass = 0;
                            statisticInfo.ch[i].iFailed = 0;

                        }
                        statisticInfo.iCount = 0;
                        statisticInfo.iPass = 0;
                        statisticInfo.iFailed = 0;

                        Config.setCount(ref statisticInfo);
                        ShowStatistics();
                    }   
                }
                else if (itemText == "仪器启动")
                {
                    if (arrDevObj[0] != null && arrDevObj[0].bStatus)
                    {
                        arrDevObj[0].Start(true);
                    }
                }
                else if (itemText == "仪器复位")
                {
                    if (arrDevObj[0] != null && arrDevObj[0].bStatus)
                    {
                        arrDevObj[0].Start(false);
                    }
                }
                else if (itemText == "仪器设置")
                {
                    cfgDevForm.showDevInfo();
                    cfgDevForm.StartPosition = FormStartPosition.CenterParent;
                    cfgDevForm.ShowDialog();
                }
                else if (itemText == "扫码枪设置")
                {
                    scannerForm.setConfig();
                    scannerForm.refreshPort();
                    scannerForm.StartPosition = FormStartPosition.CenterParent;
                    scannerForm.ShowDialog();
                    if (scanType != scannerForm.scanType)
                    {
                        scanType = scannerForm.scanType;
                        if (scanType == (int)SCANNER_TYPE.INDUSTRY_COM || scanType == (int)SCANNER_TYPE.INDUSTRY_NETWORK)
                        {
                            startScanCode(scanType);
                        }
                    }
                }
                else if (itemText == "PLC设置")
                {
                    plcForm.setConfig(ref plcParam);
                    plcForm.StartPosition = FormStartPosition.CenterParent;
                    plcForm.ShowDialog();
                }
            }
        }
        private void ShowRecord(ref TEST_PARAM testInfo, int iCH, string code)
        {
            //添加测试记录
            int iCount = 0;
            if (iCH == 0 || iCH == 2)
            {
                if (uiDataGridView1.Rows.Count >= 1000)
                {
                    uiDataGridView1.Rows.Clear();
                }
                iCount = uiDataGridView1.Rows.Count + 1;
                uiDataGridView1.Rows.Insert(0, iCount.ToString(),labelOperator.Text, DateTime.Now.ToString(), code, 
                    testInfo.chTest[iCH].fTestPressure.ToString("F3"), 
                    testInfo.chTest[iCH].fLeakAmount.ToString("F3"), strResult[testInfo.chTest[iCH].ResultFlag]);
                if (testInfo.chTest[iCH].ResultFlag == 2)
                {
                    uiDataGridView1.Rows[0].DefaultCellStyle.ForeColor = Color.Red;
                }
                else
                { 
                    uiDataGridView1.Rows[0].DefaultCellStyle.ForeColor = Color.Green;
                }
            }
            else if (iCH == 1 || iCH == 3)
            {
                if (uiDataGridView2.Rows.Count >= 1000)
                {
                    uiDataGridView2.Rows.Clear();
                }
                iCount = uiDataGridView2.Rows.Count + 1;
                uiDataGridView2.Rows.Insert(0, iCount.ToString(), labelOperator.Text, DateTime.Now.ToString(), code,
                    testInfo.chTest[iCH].fTestPressure.ToString("F3"),
                    testInfo.chTest[iCH].fLeakAmount.ToString("F3"), strResult[testInfo.chTest[iCH].ResultFlag]);
                if (testInfo.chTest[iCH].ResultFlag == 2)
                {
                    uiDataGridView2.Rows[0].DefaultCellStyle.ForeColor = Color.Red;
                }
                else
                {
                    uiDataGridView2.Rows[0].DefaultCellStyle.ForeColor = Color.Green;
                }
            }
        }

        private void ShowStatistics(int result, int iCH)
        {
            lock(lockObject)
            {
                statisticInfo.ch[iCH].iCount += 1;
                statisticInfo.iCount += 1;
                if (result == 1)    //OK
                {
                    statisticInfo.ch[iCH].iPass += 1;
                    statisticInfo.iPass += 1;
                }
                else
                {
                    statisticInfo.ch[iCH].iFailed += 1;
                    statisticInfo.iFailed += 1;
                }
                Config.setCount(ref statisticInfo);

                ShowStatistics();
            }
        }
        private void ShowStatistics()
        {
            uiLabelSumNumber.Text = statisticInfo.iCount.ToString();
            uiLabelPassNumber.Text = statisticInfo.iPass.ToString();
            uiLabelFailNumber.Text = statisticInfo.iFailed.ToString();
            if (statisticInfo.iCount > 0)
            {
                uiProcessPass.Value = 100 * statisticInfo.iPass / statisticInfo.iCount;
            }
            else
            {
                uiProcessPass.Value = 0;
            }
        }
        private void WriteRecord(ref TEST_PARAM testInfo, string strPath, int iCH)
        {
            string code1 = "";
            string code2 = "";
            switch (iCH)
            {
                case 0:
                    code1 = uiTextCode1.Text;
                    code2 = uiTextCode11.Text;
                    break;
                case 1:
                    code1 = uiTextCode2.Text;
                    code2 = uiTextCode22.Text;
                    break;
                case 2:
                    code1 = uiTextCode3.Text;
                    code2 = uiTextCode33.Text;
                    break;
                case 3:
                    code1 = uiTextCode4.Text;
                    code2 = uiTextCode44.Text;
                    break;
                default:
                    break;
            }

            if (storageParam.sPath.Length <= 0) //存储路径为空
            {
                storageParam.sPath = AppDomain.CurrentDomain.BaseDirectory + "\\Storage";
            }
            if (!Directory.Exists(storageParam.sPath))
            {
                Directory.CreateDirectory(storageParam.sPath);
            }

            if (storageParam.bTxt)
            {
                SaveRecord.WriteTXT(ref testInfo, code1, strPath, iCH);
                if (code2 != "")
                {
                    SaveRecord.WriteTXT(ref testInfo, code2, strPath, iCH);
                }
            }
            if (storageParam.bCSV)
            {
                SaveRecord.WriteCSV(ref testInfo, code1, strPath, iCH);
                if (code2 != "")
                {
                    SaveRecord.WriteCSV(ref testInfo, code2, strPath, iCH);
                }
            }
            if (storageParam.bSQL)
            {
                SaveRecord.WriteSQL(ref testInfo, code1, strPath, iCH);
                if (code2 != "")
                {
                    SaveRecord.WriteSQL(ref testInfo, code2, strPath, iCH);
                }
            }
            if (storageParam.bExcel)
            {
                SaveRecord.WriteExcel(testInfo, code1, strPath, iCH);
                if (code2 != "")
                {
                    SaveRecord.WriteExcel(testInfo, code2, strPath, iCH);
                }
            }
            if (mesParam.bCheckOut)
            {
                MesCheckout(ref testInfo, code1, iCH);
                if (code2 != "")
                {
                    MesCheckout(ref testInfo, code2, iCH);
                }
            }

            syncContext.Post(new SendOrPostCallback(obj =>
            {
                switch (iCH)
                {
                    case 0:
                        uiTextCode1.Text = "";
                        uiTextCode11.Text = "";
                        break;
                    case 1:
                        uiTextCode2.Text = "";
                        uiTextCode22.Text = "";
                        break;
                    case 2:
                        uiTextCode3.Text = "";
                        uiTextCode33.Text = "";
                        break;
                    case 3:
                        uiTextCode4.Text = "";
                        uiTextCode44.Text = "";
                        break;
                    default:
                        break;
                }
            }), null);
        }

        public void addDevObj(int i)
        {
            if (arrDevParam[i].sDevAddr != "" && arrDevParam[i].iPort != 0 && arrDevParam[i].iSlaveId != 0)
            {
                if (arrDevObj[i] == null)
                {
                    arrDevObj[i] = new DeviceObject(ref arrDevParam[i]);
                }
            }
        }
        public void deleteDevObj(int i)
        {
            if (arrDevObj[i] != null)
            {
                arrDevObj[i].bExit = true;
                arrDevObj[i] = null;
            }
        }

        public void addScanNetwork(int i)
        {
            if (arrScannerObj[i].sIpaddr != "" && arrScannerObj[i].iPort != 0
                || ConfigScanner.IsValidIp(arrScannerObj[i].sIpaddr))
            {
                if (arrScanNetwork[i] != null)
                {
                    arrScanNetwork[i].Disconnect();
                }
                arrScanNetwork[i] = new ScanNetwork(
                    arrScannerObj[i].sIpaddr,
                    arrScannerObj[i].iPort,
                    arrScanParam[i].iCodeLength,
                    code => { ProcessCode(i, code); },
                    error => { ProcessStatus(i, error); },
                    status => { ProcessStatus(i, status); }
                    );
            }
        }

        /// <summary>
        /// 打开扫码枪 网络连接
        /// </summary>
        /// <param name="i"></param>
        public void openScannerNetwork(int i)
        {
            if (arrScanNetwork[i] != null && arrScanNetwork[i].IsConnected)
            {
                return;
            }
            if (arrScanNetwork[i] != null)
            {
                arrScanNetwork[i].Connect();
            }
        }

        public void closeScannerNetwork(int i)
        {
            if (arrScanNetwork[i] != null && arrScanNetwork[i].IsConnected)
            {
                arrScanNetwork[i].Disconnect();
                arrScanNetwork[i] = null;
            }
        }

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

        private void btnClearCode1_Click(object sender, EventArgs e)
        {
            uiTextMsg.Text = "";
            uiTextCode1.Text = "";
            InStatus1.Text = "";
            OutStatus1.Text = "";
            InStatus1.BackColor = Color.Transparent;
            OutStatus1.BackColor = Color.Transparent;
        }

        private void btnClearCode2_Click(object sender, EventArgs e)
        {
            uiTextCH2.Text = "";
            uiTextCode2.Text = "";
            InStatus2.Text = "";
            OutStatus2.Text = "";
            InStatus2.BackColor = Color.Transparent;
            OutStatus2.BackColor = Color.Transparent;
        }
        public void openScanner1()
        {
            if (serialPortCode1.IsOpen)
            {
                return;
            }
            try
            {
                //设置端口的参数，包括波特率等
                serialPortCode1.BaudRate = arrScannerObj[0].iBaudrate;
                serialPortCode1.PortName = arrScannerObj[0].sPort;
                serialPortCode1.DataBits = 8;
                serialPortCode1.StopBits = System.IO.Ports.StopBits.One;
                serialPortCode1.Parity = System.IO.Ports.Parity.None;
                serialPortCode1.Open();
            }
            catch (Exception ex)
            {
                string str = "打开扫码枪串口1失败:" + ex.Message;
                FileLogger.Log(str, LogLevel.ERROR);

                syncContext.Post(new SendOrPostCallback(obj =>
                {
                    uiTextMsg.Text = str;
                    uiTextMsg.ForeColor = Color.Red;
                }), null);
            }
        }
        public void openScanner2()
        {
            if (serialPortCode2.IsOpen)
            {
                return;
            }
            try
            {
                //设置端口的参数，包括波特率等
                serialPortCode2.BaudRate = arrScannerObj[1].iBaudrate;
                serialPortCode2.PortName = arrScannerObj[1].sPort;
                serialPortCode2.DataBits = 8;
                serialPortCode2.StopBits = System.IO.Ports.StopBits.One;
                serialPortCode2.Parity = System.IO.Ports.Parity.None;
                serialPortCode2.Open();
            }
            catch (Exception ex)
            {
                string str = "打开扫码枪串口2失败:" + ex.Message;
                FileLogger.Log(str, LogLevel.ERROR);
                syncContext.Post(new SendOrPostCallback(obj =>
                {
                    uiTextCH2.Text = str;
                    uiTextCH2.ForeColor = Color.Red;
                }), null);
            }
        }

        private void startScanCode(int iType)
        {
            Task.Run(() =>
            {
                while (!bExit)
                {
                    if (scanType == (int)SCANNER_TYPE.COMMON)
                    {
                        break;
                    }
                    if (scannerForm.Visible == true)
                    {
                        Thread.Sleep(100);
                        continue;
                    }
                    if (workState1.Text == "空闲" && workState2.Text == "空闲")
                    {
                        if (iType == 1)//串口
                        {
                            string data = "73 74 61 72 74"; // "start"
                            byte[] byt = ScanNetwork.StrtoHexbyte(data);
                            if (serialPortCode1.IsOpen)
                            {
                                serialPortCode1.Write(byt, 0, byt.Length);
                            }
                            if (serialPortCode2.IsOpen)
                            {
                                serialPortCode2.Write(byt, 0, byt.Length);
                            }
                        }
                        else if (iType == 2) //网络
                        {
                            for (int i = 0; i < devNum; i++)
                            {
                                if (arrScanNetwork[i] != null)
                                {
                                    arrScanNetwork[i].SendStartCommand();
                                }
                            }
                        }
                    }

                    Thread.Sleep(100);
                }
                Console.WriteLine($"startScanCode Exit : {iType} \n");
            });
        }
        private void serialPortCode1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            try
            {
                System.Threading.Thread.Sleep(50);
                int len = serialPortCode1.BytesToRead;//获取可以读取的字节数
                if (len > 1)
                {
                    byte[] buff = new byte[len];//创建缓存数据数组
                    serialPortCode1.Read(buff, 0, len);//把数据读取到buff数组
                    Invoke((new System.Action(() => //接收计数
                    {
                        string code = Encoding.Default.GetString(buff);
                        code = code.Replace("\r", "");
                        code = code.Replace("\n", "");

                        if (uiTextCode1.Text.Length == 0)
                        {
                            uiTextCode1.Text = code;
                        }
                        else if (scannerForm.scanNum == 1 && uiTextCode2.Text.Length == 0)
                        {
                            uiTextCode2.Text = code;
                        }

                        serialPortCode1.DiscardInBuffer();

                    })));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("扫码枪1:" + ex.Message);
            }
        }

        private void serialPortCode2_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            try
            {
                System.Threading.Thread.Sleep(50);
                int len = serialPortCode2.BytesToRead;//获取可以读取的字节数
                if (len > 1)
                {
                    byte[] buff = new byte[len];//创建缓存数据数组
                    serialPortCode2.Read(buff, 0, len);//把数据读取到buff数组
                    Invoke((new System.Action(() => //接收计数
                    {
                        string code = Encoding.Default.GetString(buff);
                        code = code.Replace("\r", "");
                        code = code.Replace("\n", "");

                        uiTextCode2.Text = code;

                        serialPortCode2.DiscardInBuffer();

                    })));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("扫码枪2:" + ex.Message);
            }
        }

        private void Code1_TextChanged(object sender, EventArgs e)
        {
            checkStart(0, uiTextCode1.Text.Length, uiTextCode1.Text);
        }

        private void Code2_TextChanged(object sender, EventArgs e)
        {
            checkStart(1, uiTextCode2.Text.Length, uiTextCode2.Text);
        }
        /// <summary>
        /// 处理扫码枪接收到网络数据
        /// </summary>
        /// <param name="iCH"></param>
        /// <param name="code"></param>
        private void ProcessCode(int iCH, string code)
        {
            syncContext.Post(new SendOrPostCallback(obj =>
            {
                if (iCH == 0)
                {
                    if (uiTextCode1.Text == "")
                    {
                        uiTextCode1.Text = code;
                    }
                    else if (uiTextCode11.Text == "")
                    {
                        uiTextCode11.Text = code;
                    }
                    else if (uiTextCode2.Text == "")
                    {
                        uiTextCode2.Text = code;
                    }
                    else if (uiTextCode22.Text == "")
                    {
                        uiTextCode22.Text = code;
                    }
                    else if (uiTextCode3.Text == "")
                    {
                        uiTextCode3.Text = code;
                    }
                    else if (uiTextCode33.Text == "")
                    {
                        uiTextCode33.Text = code;
                    }
                    else if (uiTextCode4.Text == "")
                    {
                        uiTextCode4.Text = code;
                    }
                    else if (uiTextCode44.Text == "")
                    {
                        uiTextCode44.Text = code;
                    }
                    //else if (scannerForm.scanNum == 1 && uiTextCode2.Text == "")
                    //{
                    //    uiTextCode2.Text = code;
                    //}
                }
                else
                {
                    if (code != uiTextCode2.Text)
                    {
                        uiTextCode2.Text = code;
                    }
                }
            }), null);
        }

        private void ProcessStatus(int iCH, string code)
        {
            syncContext.Post(new SendOrPostCallback(obj =>
            {
                if (iCH == 0)
                {
                    uiTextMsg.Text = code;
                }
                else
                {
                    uiTextCH2.Text = code;
                }
            }), null);
        }

        /// <summary>
        /// 检查是否收到合法条码
        /// </summary>
        /// <param name="iCH"></param>
        /// <param name="iCodeLen"></param>
        /// <param name="code"></param>
        private void checkStart(int iCH, int iCodeLen, string code)
        {
            //条码检测
            if (arrScanParam[iCH].bCheckLen && iCodeLen != arrScanParam[iCH].iCodeLength)
            {
                return;
            }
            //扫码启动
            if (/*arrScanParam[iCH].bStart && */iCodeLen == arrScanParam[iCH].iCodeLength)
            {
                Task.Run(() => 
                {
                    if (mesParam.bCheckOut)
                    {
                        string str = mesObj.MesCheckIn(code, iCH, mesParam.sUrl);
                        if (str != "")
                        {
                            bool bOK = mesObj.mesReply.code == 200;
                            //更新UI
                            syncContext.Post(new SendOrPostCallback(obj =>
                            {
                                if (iCH == 0)
                                {
                                    uiTextMsg.Text = str;                                    
                                    InStatus1.Text = bOK ? "OK" : "NG";
                                    InStatus1.BackColor = bOK ? Color.Green : Color.Red;
                                    uiTextMsg.ForeColor = bOK ? Color.Green : Color.Red;
                                }
                                else if (iCH == 1)
                                {
                                    uiTextCH2.Text = str;
                                    InStatus2.Text = bOK ? "OK" : "NG";
                                    InStatus2.BackColor = bOK ? Color.Green : Color.Red;
                                    uiTextCH2.ForeColor = bOK ? Color.Green : Color.Red;
                                }
                            }), null);
                            if (!bOK)
                            {
                                return;
                            }
                        }
                    }
                    //PLC发送扫码启动命令
                    if (plcObj != null)
                    {
                        if (!plcObj.ScanFinish(iCH))
                        {
                            FileLogger.Log(iCH + "PLC扫码完成命令发送失败:",LogLevel.ERROR);
                        }
                    }
                });
                //if (arrDevObj[iCH] != null && arrDevObj[iCH].bStatus) 自动启动
                //{
                //    arrDevObj[iCH].Start(true);
                //}
            }
        }

        public void updateStorage(STORAGE_PARAM pStorage)
        {
            storageParam = pStorage; 
        }

        public void updatePLCStatus(bool status)
        {
            picturePLC.BackColor = status ? Color.Green : Color.Red;
        }

        public void updateMESStatus(bool status)
        {
            pictureMES.BackColor = status ? Color.Green : Color.Red;
        }
        /// <summary>
        /// 更新PLC配置
        /// </summary>
        /// <param name="port"></param>
        /// <param name="baudrate"></param>
        public void updatePLC(string port, int baudrate)
        {
            plcParam.sPort = port;
            plcParam.iBaudrate = baudrate;
            if (plcObj == null)
            {
                plcObj = new PlcObject();
            }
            plcObj.closePLC();
            plcObj.openPLC(plcParam);

            Config.savePLC(ref plcParam);
        }
        /// <summary>
        /// 更新仪器配置
        /// </summary>
        /// <param name="port"></param>
        /// <param name="baudrate"></param>
        public void updateDevice(string port, int baudrate)
        {
            arrDevParam[0].sDevAddr = port;
            arrDevParam[0].iPort = baudrate;
        }

        /// <summary>
        /// 设置是否扫码启动
        /// </summary>
        /// <param name="iCH"></param>
        /// <param name="bStart"></param>
        public void updataScanStart(int iCH, bool bStart)
        {
            if (plcObj != null)
            {
                plcObj.SetScan(iCH, bStart);
                if (!plcObj.SetScan(iCH, bStart))
                {
                    FileLogger.Log(iCH.ToString() + ": PLC配置扫码启动失败 " + bStart.ToString(), LogLevel.ERROR);
                    MessageBox.Show(iCH.ToString() + ": PLC配置扫码启动失败 " + bStart.ToString());
                }
            }
        }

        public void UpdateMesConfig(ref MES_PARAM pParam)
        {
            mesParam = pParam;
            Config.saveMes(ref mesParam);
        }
        private void MesCheckout(ref TEST_PARAM testInfo, string code, int iCH)
        {
            string str = mesObj.MesCheckOut(ref testInfo.chTest[iCH], ref arrDevObj[iCH].configParam, code, iCH, mesParam.sUrl);
            syncContext.Post(new SendOrPostCallback(obj =>
            {
                bool bOK = mesObj.mesReply.code == 200;
                if (iCH == 0)
                {
                    uiTextMsg.Text = str;
                    OutStatus1.Text = bOK ? "OK" : "NG";
                    OutStatus1.BackColor = bOK ? Color.Green : Color.Red;
                    uiTextMsg.ForeColor = bOK ? Color.Green : Color.Red;

                    InStatus1.BackColor = Color.Transparent;
                    InStatus1.Text = "";
                }
                else if (iCH == 1)
                {
                    uiTextCH2.Text = str;
                    OutStatus2.Text = bOK ? "OK" : "NG";
                    OutStatus2.BackColor = bOK ? Color.Green : Color.Red;
                    uiTextCH2.ForeColor = bOK ? Color.Green : Color.Red;

                    InStatus2.BackColor = Color.Transparent;
                    InStatus2.Text = "";
                }
            }), null);
        }

        private void timerUser_Tick(object sender, EventArgs e)
        {
            timerUser.Stop();
            labelUser.Text = "操作员";
        }

        private void timerUpdate_Tick(object sender, EventArgs e)
        {
            uiLabelTime.Text = DateTime.Now.ToString("HH:mm:ss");
        }

        public void ShowPrintError(string strTips)
        {
            FormMain.form.Invoke((MethodInvoker)delegate
            {
                MessageBox.Show(strTips);
                uiTextMsg.Text = strTips;
            });
        }

        private bool StartDevice(bool bStart)
        {
            if (arrDevObj[0] != null && arrDevObj[0].bStatus)
            {
                return arrDevObj[0].Start(bStart);
            }
            return false;
        }
        private void uiButtonStart_Click(object sender, EventArgs e)
        {
            if (StartDevice(true))
            {
                uiTextMsg.Text = "启动仪器成功";
            }
            else
            {
                uiTextMsg.Text = "启动仪器失败";
            }
        }

        private void uiButtonStop_Click(object sender, EventArgs e)
        {
            if (StartDevice(false))
            {
                uiTextMsg.Text = "复位仪器成功";
            }
            else
            {
                uiTextMsg.Text = "复位仪器失败";
            }
        }
    }
}
