using System;

using System.Threading;
using System.IO.Ports;
using System.Windows.Forms;

using LFP_Manager.DataStructure;
using LFP_Manager.Function;
using LFP_Manager.Utils;
using DevExpress.XtraGauges.Core.Model;

namespace LFP_Manager.Threads
{
    class CsUartThread124050
    {
        #region VARIABLES

        private readonly CommConfig Config;
        private DeviceSystemData SystemData;
        private Thread serialComm = null;
        private SerialPort sPort = null;
        private bool SerialPortThreadEnd = true;

        public int SystemId = 0;
        private bool UartPolling = false;
        private bool AutoUartTx = true;

        private int addr_ch = 0;
        private ushort RequestRegAddr = 0x0000;                 //Byul Init 0x0000
        private ushort RequestRegLen = 50;
        private bool rFlag = false;
        private int rFlag2 = 0;
        private int wFlag = 0;

        private ushort ReadRegAddr = 0x0000;                   //Byul Init 0x0000
        private ushort ReadRegLen = 0x0000;                   //Byul Init 0x0000

        private ushort WriteRegAddr = 0x0000;                   //Byul Init 0x0000
        private short WriteCoilRegData = 0;
        private byte[] WriteRegData;

        private TUartTxBuff uartTxBuff = null;

        public event UartDataUpdate OnUpdate = null;
        public event UartDataRecv OnDataRecv = null;
        public event UartDataPrint OnPrint = null;

        #endregion

        #region CONSTRUCTORS

        public CsUartThread124050(int sId, CommConfig aConfig, ref DeviceSystemData aSystemData)
        {
            SystemId = sId;
            Config = aConfig;
            SystemData = aSystemData;

            uartTxBuff = new TUartTxBuff();

            serialComm = new Thread(uartCommThread);
        }

        public void disposeThread()
        {
            if (sPort != null)
            {
                if (sPort.IsOpen)
                {
                    sPort.Close();
                }
                sPort = null;
            }
            SerialPortThreadEnd = true;
            if (serialComm != null)
            {
                if (serialComm.IsAlive)
                {
                    serialComm.Abort();
                }
                serialComm = null;
            }
        }

        public bool Start(ref CommConfig aConfig, int sId, bool aPolling)
        {
            bool result = false;

            SystemId = sId;
            UartPolling = aPolling;

            if (Open(aConfig.UartPort, 115200))          //Byul Init 9600
            {
                SerialPortThreadEnd = false;
                serialComm.Start();
                result = true;
            }
            return result;
        }

        public void Stop()
        {
            SerialPortThreadEnd = true;
            Close();
        }

        #endregion

        #region COMMPORT CONTROLS

        private void sDataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            byte[] sRead = new byte[1024];
            int rLen = 0;

            try
            {
                rLen = ((SerialPort)sender).Read(sRead, 0, 1024);

                for (int i = 0; i < rLen; i++)
                {
                    PutBuff(sRead[i]);
                }
            }
            catch (Exception)
            {

            }
        }

        private void sErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e)
        {
            //
            //csMakeDataFunction.SetData()
        }

        private void sPinChanged(object sender, System.IO.Ports.SerialPinChangedEventArgs e)
        {
            //
        }

        private bool Open(string cPort, int cBaudrate)
        {
            sPort = new SerialPort();
            sPort.PortName = cPort;
            sPort.BaudRate = cBaudrate;
            sPort.DataReceived += sDataReceived;
            sPort.ErrorReceived += sErrorReceived;
            sPort.PinChanged += sPinChanged;

            try
            {
                sPort.Open();
            }
            catch (Exception ex)
            {
                throw new Exception("Error Open - " + ex.Message);
            }

            return sPort.IsOpen;
        }

        private void Close()
        {
            if (sPort != null)
            {
                if (sPort.IsOpen)
                {
                    sPort.Close();
                }
                sPort = null;
            }
        }

        #endregion

        #region PUBLIC FUNCTION

        public void SetPolling(bool flag, int sId, ref DeviceSystemData aSystemData)
        {
            SystemId = sId;
            UartPolling = flag;
            SystemData = aSystemData;
            SystemData.mNo = SystemId;
        }

        public void SetAutoTx(bool autoTx)
        {
            AutoUartTx = autoTx;
        }

        public void SetWriteCoilReg(ushort WriteAddr, short WriteData)
        {
            wFlag = 2;
            WriteRegAddr = WriteAddr;
            WriteCoilRegData = WriteData;

            for (int i = 0; i < 500; i += 10)
            {
                Thread.Sleep(10);
                Application.DoEvents();
            }
        }

        public void SetWriteReg(ushort WriteAddr, byte[] WriteData, bool ReplyFlag, int type)
        {
            WriteRegAddr = WriteAddr;

            TUartTRxData uartTRxData = new TUartTRxData();
            uartTRxData.type = type;
            //uartTRxData.data = csSerialCommFunction.MakeWriteRegisterData((ushort)SystemId, WriteRegAddr, WriteData);
            uartTRxData.data = WriteData;
            uartTRxData.length = uartTRxData.data.Length;

            uartTxBuff?.PutBuff(uartTRxData);
        }
        public void SetReadReg(ushort ReadAddr, ushort ReadLen, bool ReplyFlag)
        {
            wFlag = 4;
            ReadRegAddr = ReadAddr;
            ReadRegLen = ReadLen;
        }

        public void SetParam(ushort WriteAddr, short[] WriteData)
        {
            wFlag = 1;

            WriteRegAddr = WriteAddr;

            TUartTRxData uartTRxData = new TUartTRxData();
            uartTRxData.type = wFlag;
            uartTRxData.data = csSerialCommFunction.MakeWriteRegisterData((ushort)SystemId, WriteRegAddr, WriteData);
            uartTRxData.length = uartTRxData.data.Length;

            uartTxBuff?.PutBuff(uartTRxData);
        }

        public void SendProcessFromApp(int sId, int mode, int index, int flag, ref DeviceParamData aParam, ref DeviceCalibration aCalib)
        {
            short[] data = null;

            switch (mode)
            {
                case csConstData.UART_PARAM_LIST.CELL_UNDER_VOLTAGE:         // Cell Under Volatge Parameter
                    data = new short[1];
                    data[0] = aParam.CellUnderVoltageWarning; SetParam((ushort)(mode + 0), data);
                    data[0] = aParam.CellUnderVoltageTrip; SetParam((ushort)(mode + 1), data);
                    data[0] = aParam.CellUnderVoltageRelease; SetParam((ushort)(mode + 2), data);
                    break;
                case csConstData.UART_PARAM_LIST.CELL_OVER_VOLTAGE:         // Cell Over Volatge Parameter
                    data = new short[1];
                    data[0] = aParam.CellOverVoltageWarning; SetParam((ushort)(mode + 0), data);
                    data[0] = aParam.CellOverVoltageTrip; SetParam((ushort)(mode + 1), data);
                    data[0] = aParam.CellOverVoltageRelease; SetParam((ushort)(mode + 2), data);
                    break;
                case csConstData.UART_PARAM_LIST.PACK_UNDER_VOLTAGE:        // Pack Under Volatge Parameter
                    data = new short[1];
                    data[0] = (short)(aParam.SysUnderVoltageWarning * 10); SetParam((ushort)(mode + 0), data);
                    data[0] = (short)(aParam.SysUnderVoltageTrip * 10); SetParam((ushort)(mode + 1), data);
                    data[0] = (short)(aParam.SysUnderVoltageRelease * 10); SetParam((ushort)(mode + 2), data);
                    break;
                case csConstData.UART_PARAM_LIST.PACK_OVER_VOLTAGE:         // Pack Over Volatge Parameter
                    data = new short[1];
                    data[0] = (short)(aParam.SysOverVoltageWarning * 10); SetParam((ushort)(mode + 0), data);
                    data[0] = (short)(aParam.SysOverVoltageTrip * 10); SetParam((ushort)(mode + 1), data);
                    data[0] = (short)(aParam.SysOverVoltageRelease * 10); SetParam((ushort)(mode + 2), data);
                    break;
                case csConstData.UART_PARAM_LIST.CHG_LOW_TEMPERATURE:       // Charge Low Temperature Parameter
                    data = new short[1];
                    data[0] = (short)(aParam.ChaLowTempWarning + 50); SetParam((ushort)(mode + 0), data);
                    data[0] = (short)(aParam.ChaLowTempTrip + 50); SetParam((ushort)(mode + 1), data);
                    data[0] = (short)(aParam.ChaLowTempRelease + 50); SetParam((ushort)(mode + 2), data);
                    break;
                case csConstData.UART_PARAM_LIST.CHG_HIGH_TEMPERATURE:      // Pack High Temperature Parameter
                    data = new short[1];
                    data[0] = (short)(aParam.ChaHighTempWarning + 50); SetParam((ushort)(mode + 0), data);
                    data[0] = (short)(aParam.ChaHighTempTrip + 50); SetParam((ushort)(mode + 1), data);
                    data[0] = (short)(aParam.ChaHighTempRelease + 50); SetParam((ushort)(mode + 2), data);
                    break;
                case csConstData.UART_PARAM_LIST.DCH_LOW_TEMPERATURE:       // Charge Low Temperature Parameter
                    data = new short[1];
                    data[0] = (short)(aParam.DchLowTempWarning + 50); SetParam((ushort)(mode + 0), data);
                    data[0] = (short)(aParam.DchLowTempTrip + 50); SetParam((ushort)(mode + 1), data);
                    data[0] = (short)(aParam.DchLowTempRelease + 50); SetParam((ushort)(mode + 2), data);
                    break;
                case csConstData.UART_PARAM_LIST.DCH_HIGH_TEMPERATURE:      // Pack High Temperature Parameter
                    data = new short[1];
                    data[0] = (short)(aParam.DchHighTempWarning + 50); SetParam((ushort)(mode + 0), data);
                    data[0] = (short)(aParam.DchHighTempTrip + 50); SetParam((ushort)(mode + 1), data);
                    data[0] = (short)(aParam.DchHighTempRelease + 50); SetParam((ushort)(mode + 2), data);
                    break;
                case csConstData.UART_PARAM_LIST.CHG_OVER_CURRENT:          // Charge Over Current Parameter
                    data = new short[1];
                    data[0] = (short)(aParam.ChaOverCurrentReleaseTime * 1); SetParam((ushort)(mode + 0), data);
                    data[0] = (short)(aParam.ChaOverCurrentTrip1 * 10); SetParam((ushort)(mode + 2), data);
                    data[0] = (short)(aParam.ChaOverCurrentTrip2 * 10); SetParam((ushort)(mode + 5), data);
                    break;
                case csConstData.UART_PARAM_LIST.DCH_OVER_CURRENT:          // Discharge Over Current Parameter
                    data = new short[1];
                    data[0] = (short)(aParam.DchOverCurrentReleaseTime * 1); SetParam((ushort)(mode + 0), data);
                    data[0] = (short)(aParam.DchOverCurrentTrip1 * 10); SetParam((ushort)(mode + 2), data);
                    data[0] = (short)(aParam.DchOverCurrentTrip2 * 10); SetParam((ushort)(mode + 5), data);
                    break;
                case csConstData.UART_PARAM_LIST.LOW_CAPACITY:
                    data = new short[1];
                    data[0] = aParam.LowSocWarning; SetParam((ushort)(mode + 0), data);
                    break;
                case csConstData.UART_PARAM_LIST.DEFAULT_PARAM:             // Default Parameter
                    int i = 0;

                    Forms.fmxWait WaitForm = new Forms.fmxWait();
                    WaitForm.StartPosition = FormStartPosition.CenterScreen;

                    try
                    {
                        data = new short[1];

                        i = csConstData.UART_PARAM_LIST.CELL_UNDER_VOLTAGE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                        i = csConstData.UART_PARAM_LIST.PACK_UNDER_VOLTAGE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                        i = csConstData.UART_PARAM_LIST.CELL_OVER_VOLTAGE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                        i = csConstData.UART_PARAM_LIST.PACK_OVER_VOLTAGE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);

                        i = csConstData.UART_PARAM_LIST.CHG_OVER_CURRENT;
                        data[0] = 0; SetParam((ushort)(i - 2), data);
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                        data[0] = 0; SetParam((ushort)(i + 5), data);
                        data[0] = 0; SetParam((ushort)(i + 8), data);
                        data[0] = 0; SetParam((ushort)(i + 9), data);

                        i = csConstData.UART_PARAM_LIST.DCH_OVER_CURRENT;
                        data[0] = 0; SetParam((ushort)(i - 2), data);
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                        data[0] = 0; SetParam((ushort)(i + 5), data);
                        data[0] = 0; SetParam((ushort)(i + 8), data);
                        data[0] = 0; SetParam((ushort)(i + 9), data);

                        i = csConstData.UART_PARAM_LIST.CHG_LOW_TEMPERATURE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                        i = csConstData.UART_PARAM_LIST.CHG_HIGH_TEMPERATURE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                        i = csConstData.UART_PARAM_LIST.DCH_LOW_TEMPERATURE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                        i = csConstData.UART_PARAM_LIST.DCH_HIGH_TEMPERATURE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);

                        i = csConstData.UART_PARAM_LIST.LOW_CAPACITY;
                        data[0] = 0; SetParam((ushort)(i + 0), data);

                        i = csConstData.UART_PARAM_LIST.ENV_LOW_TEMPERATURE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                        i = csConstData.UART_PARAM_LIST.ENV_HIGH_TEMPERATURE;
                        data[0] = 0; SetParam((ushort)(i + 0), data);
                        data[0] = 0; SetParam((ushort)(i + 1), data);
                        data[0] = 0; SetParam((ushort)(i + 2), data);
                    }
                    catch (Exception)
                    {

                    }
                    break;
                case 15:         // Capcity change
                    data = new short[1];
                    i = csConstData.UART_PARAM_LIST.DESIGN_CAPACITY;
                    data[0] = (short)aCalib.CapCalib.DesignCapacity; SetParam((ushort)(i + 0), data);
                    i = csConstData.UART_PARAM_LIST.SOC_VALUE;
                    data[0] = (short)aCalib.CapCalib.SocValue; SetParam((ushort)(i + 0), data);
                    break;
                case 16:         // Charge Mode
                    data = new short[1];
                    i = csConstData.UART_CALIB_ADDR_LIST.CHAGE_MODE;
                    data[0] = (short)aCalib.ChaMode.Mode; SetParam((ushort)(i + 0), data);
                    data[0] = (short)aCalib.ChaMode.Value; SetParam((ushort)(i + 1), data);
                    break;
                case 17:         // BMS DateTime Set
                    data = new short[2];
                    i = csConstData.UART_CALIB_ADDR_LIST.BMS_DATETIME;
                    data[0] = (short)aCalib.BmsDateTime.sValue[0];
                    data[1] = (short)aCalib.BmsDateTime.sValue[1]; SetParam((ushort)(i + 0), data);
                    break;
                case 18:
                    data = new short[1];
                    i = csConstData.UART_CALIB_ADDR_LIST.ANTI_THEFT_GYRO;
                    data[0] = (short)aCalib.AntiTheft.GyroScope; SetParam((ushort)(i + 0), data);
                    break;
                case 19:    // Clear Protect
                    data = new short[1];
                    i = csConstData.UART_CALIB_ADDR_LIST.ANTI_THEFT_GYRO;
                    data[0] = (short)0; SetParam((ushort)(i + 0), data);
                    data[0] = (short)aCalib.AntiTheft.GyroScope; SetParam((ushort)(i + 0), data);
                    break;
                case 20:
                    data = new short[1];
                    i = csConstData.UART_CALIB_ADDR_LIST.ANTI_THEFT_COMM;
                    data[0] = (short)aCalib.AntiTheft.Comm; SetParam((ushort)(i + 0), data);
                    break;
                case 21:        // Cell Balancing Voltage
                    data = new short[1];
                    i = csConstData.UART_CALIB_ADDR_LIST.BAL_VOLT;
                    data[0] = (short)aCalib.BalCalib.Volt; SetParam((ushort)(i + 0), data);
                    break;
                case 22:        // Cell Balancing Diff
                    data = new short[1];
                    i = csConstData.UART_CALIB_ADDR_LIST.BAL_DIFF;
                    data[0] = (short)aCalib.BalCalib.Diff; SetParam((ushort)(i + 0), data);
                    break;
                default:
                    break;
            }
        }

        #endregion

        #region RX BUFFERING

        private const int BUFFER_SIZE = 512;

        private readonly byte[] rBuffer = new byte[BUFFER_SIZE];
        private int rBufStart = 0;
        private int rBufEnd = 0;

        private void PutBuff(byte c)
        {
            rBuffer[rBufStart++] = c;
            rBufStart %= BUFFER_SIZE;

            if (rBufStart == rBufEnd)
            {
                rBufEnd++;
                rBufEnd %= BUFFER_SIZE;
            }
        }

        private int GetBuff()
        {
            int result = 0;

            if (rBufStart != rBufEnd)
            {
                result = 0x0100 + rBuffer[rBufEnd++];
                rBufEnd %= BUFFER_SIZE;
            }
            return result;
        }

        private void FlushBuff()
        {
            rBufStart = rBufEnd = 0;
        }

        #endregion

        #region TX BUFFERING

        private byte[] MakeWriteRegData(ushort DevID, ushort WriteAddr, ushort WriteLen, ref ushort[] WriteData)
        {
            byte[] wData = null;

            if (WriteLen > 0)
            {

            }

            return wData;
        }

        private string MakeCheckSum(byte[] sData, int len)
        {
            string result = "";
            int checksum = 0;

            for (int i = 0; i < len; i++)
            {
                checksum += sData[i + 1];
            }

            checksum = ~checksum + 1;

            result = String.Format("{0:X2}{1:X2}", (byte)(checksum >> 8), (byte)checksum);

            return result;
        }

        private byte[] MakeTxDataVision(ref bool wData)
        {
            byte[] sData = null;

            rFlag2 = 0;

            if ((uartTxBuff != null) && (uartTxBuff.CheckBuff()))
            {
                TUartTRxData sBuff = uartTxBuff.GetBuff();
                if (sBuff != null)
                {
                    sData = sBuff.data;
                    wData = true;
                    rFlag = true;
                    rFlag2 = sBuff.type;
                }
            }
            else if (wFlag == 2)
            {
                sData = csSerialCommFunction.MakeWriteCoilData((ushort)SystemId, WriteRegAddr, WriteCoilRegData);
                if (wFlag != 0) wFlag = 0;
                rFlag = true;
            }
            else if (wFlag == 3)
            {
                sData = WriteRegData;
                if (wFlag != 0) wFlag = 0;
                rFlag = true;
            }
            else if (wFlag == 4)
            {
                sData = csSerialCommFunction.MakeReadRegisterData((ushort)SystemId, csSerialCommFunction.READ_HOLDING_REG, ReadRegAddr, ReadRegLen);
                if (wFlag != 0) wFlag = 0;
                rFlag = true;
            }
            else
            {
                if (UartPolling && AutoUartTx)
                {
                    ushort sCmd;
                    switch (addr_ch)
                    {
                        case 0:
                            addr_ch = 1;
                            RequestRegAddr = 0x0000;        //Byul Init 0x0000
                            RequestRegLen = 0x0040;
                            sCmd = csSerialCommFunction.READ_HOLDING_REG;
                            rFlag = true;
                            break;
                        case 1:
                            addr_ch = 2;
                            RequestRegAddr = 0x0040;
                            RequestRegLen = 0x0040;
                            sCmd = csSerialCommFunction.READ_HOLDING_REG;
                            rFlag = true;
                            break;
                        case 2:
                            addr_ch = 3;
                            RequestRegAddr = 0x0080;
                            RequestRegLen = 0x0040;
                            sCmd = csSerialCommFunction.READ_HOLDING_REG;
                            rFlag = true;
                            break;
                        case 3:
                            if (Config.ModuleQty > 1)
                            {
                                SystemId++;
                                if (SystemId > Config.ModuleQty)
                                {
                                    SystemId = 1;
                                }
                            }
                            addr_ch = 0;
                            sCmd = csSerialCommFunction.NO_CMD;
                            rFlag = false;
                            break;
                        default:
                            addr_ch = 0;
                            RequestRegAddr = 0x0000;        //Byul Init 0x0000
                            RequestRegLen = 100;
                            sCmd = csSerialCommFunction.READ_HOLDING_REG;
                            break;
                    }
                    if (sCmd == csSerialCommFunction.NO_CMD)
                    {
                        sData = null;
                    }
                    else
                    {
                        sData = csSerialCommFunction.MakeReadRegisterData((ushort)SystemId, sCmd, RequestRegAddr, RequestRegLen);
                    }
                }
            }
            return sData;
        }

        #endregion

        #region COMM THREAD

        private readonly byte[] ReadBuf = new byte[BUFFER_SIZE];
        ushort rPosition = 0;
        bool BuffStart = false;

        private void RecvPacketInit()
        {
            BuffStart = false;
            rPosition = 0;
        }

        private void uartCommThread()
        {
            int RecvTimeout = Config.RecvWaitTime;
            int getData = 0;
            byte cData = 0;
            int TimeOutCount = 0;

        StartSend:
            while (SerialPortThreadEnd == false)
            {
                if ((sPort == null) || (sPort.IsOpen == false)) continue;

                bool wMode = false;
                byte[] txData = MakeTxDataVision(ref wMode);
                if (txData != null)
                {
                    FlushBuff();
                    sPort.Write(txData, 0, txData.Length);
                    OnPrint?.Invoke(this, csLog.trx_data_print(txData, txData.Length, 0));
                }

                if (rFlag == true)
                {
                    RecvPacketInit();
                    DateTime rDateTime = DateTime.Now;

                    while (true)
                    {
                        DateTime nDateTime = rDateTime.AddMilliseconds(RecvTimeout);
                        if (nDateTime < DateTime.Now) break;

                        if (((getData = GetBuff()) & 0x0100) != 0x0000)
                        {
                            rDateTime = DateTime.Now;
                            cData = (byte)(getData & 0x00FF);
                            if (rPosition >= BUFFER_SIZE) RecvPacketInit();

                            if (BuffStart == false)
                            {
                                if ((cData == (byte)SystemId) || (cData == (byte)0x7F))
                                {
                                    rPosition = 0;
                                    ReadBuf[rPosition++] = cData;
                                    BuffStart = true;
                                }
                            }
                            else
                            {
                                ReadBuf[rPosition++] = cData;

                                switch (csSerialCommFunction.ModbusPacketFromSlaveCheck(ReadBuf, rPosition))
                                {
                                    case 0:         // Need more data
                                        break;
                                    case 1:         // Packet OK, no error
                                        OnPrint?.Invoke(this, csLog.trx_data_print(ReadBuf, rPosition, 1));

                                        TimeOutCount = 0;

                                        int mID = ReadBuf[0];
                                        if (mID > 0) mID--;

                                        SystemData.CommFail = false;
                                        SystemData.ShelfCommFail = false;

                                        if (rFlag2 == 0)
                                        {
                                            short[] result_code = csSerialCommFunction124050.SerialRxProcess(ReadBuf, RequestRegAddr, rPosition, ref SystemData);

                                            OnUpdate?.Invoke(this, ref SystemData);
                                        }
                                        else
                                        {
                                            rFlag2 = 0;
                                            wMode = false;
                                            WriteRegAddr = 0;
                                            if (OnDataRecv != null)
                                            {
                                                byte[] adata = new byte[rPosition + 1];
                                                for (int j = 0; j < adata.Length; j++) { adata[j] = ReadBuf[j]; }
                                                OnDataRecv(adata);
                                            }
                                        }
                                        rFlag = false;
                                        Thread.Sleep(100);
                                        goto StartSend;
                                    case 2:         // Fw Update Packet OK
                                        OnPrint?.Invoke(this, csLog.trx_data_print(ReadBuf, rPosition, 1));

                                        TimeOutCount = 0;
                                        rFlag = false;
                                        if (OnDataRecv != null)
                                        {
                                            byte[] adata = new byte[rPosition + 1];
                                            for (int j = 0; j < adata.Length; j++)
                                            {
                                                adata[j] = ReadBuf[j];
                                            }
                                            OnDataRecv(adata);
                                        }
                                        goto StartSend;
                                    case -1:        // Packet error
                                        RecvPacketInit();
                                        Thread.Sleep(100);
                                        goto StartSend;
                                    default:
                                        break;
                                }
                            }
                        }
                        else
                        {
                            Thread.Sleep(1);
                        }
                    }

                    if (rPosition > 0)
                    {
                        Thread.Sleep(1);
                    }
                    else
                    {
                        WriteRegAddr = 0;
                        TimeOutCount++;
                        if (TimeOutCount >= 5)
                        {
                            TimeOutCount = 5;
                            //SystemData[0].CommFail = true;
                            if (SystemData.ShelfCommFail == false)
                            {
                                csUtils.DataInit(Config, ref SystemData);
                                SystemData.ShelfCommFail = true;
                            }
                        }
                        Thread.Sleep(100);
                    }
                    OnUpdate?.Invoke(this, ref SystemData);
                    Thread.Sleep(1);
                }
                else
                {
                    Thread.Sleep(100);
                }   /* if (rFlag == true) */
                rPosition = 0;
            }
        }

        #endregion
    }
}
