using System;
using System.Threading.Tasks;
using System.Collections;
using System.Text.RegularExpressions;
using Aitex.Core.Common.DeviceData;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.RT.Tolerance;
using Aitex.Core.Util;
using Aitex.Core.RT.Device;
using MECF.Framework.Common.Communications;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.Device.Bases;
using MECF.Framework.Common.Equipment;
using Venus_Core;
using System.Collections.Generic;
using System.Diagnostics;

namespace Venus_RT.Devices
{
    #region RFG

    static class AdTecRfMessage
    {
        public static string ANALOG = "";
        public const string EOF = "\r";
        public const char DELIMITER = ' ';
        public const string MANUAL = "MANUAL";
        public const string RS232 = "***";
        public const string SET_POWER = " W";
        public const string RF_ON = "G";
        public const string RF_OFF = "S";
        public const string ERR_RES = "N";
        public const string QUERY = "Q";
        public const string RESET = "RESET";
        public const string CHK_COMM = "HS";
    }

    class AdTecGenerator : RfPowerBase
    {
        // ----------------------------Fields--------------------------
        //
        private int QUERY_INTERVAL = 5000;
        private const string INFO_PATTERN = @"(\d{7})\s(\d{5})\s(\d{5})\s(\d{5})\s(\d{5})";
        private double _total;
        private double _fromLast;
        private bool _bRFPowerOn = false;
        private readonly AsyncSerialPort _serial;
        private readonly DeviceTimer _timerQueryStatus = new DeviceTimer();
        private readonly DeviceTimer _timerTotal = new DeviceTimer();
        private readonly DeviceTimer _timerFromLast = new DeviceTimer();
        private readonly DeviceTimer _timerRFTurnOn = new DeviceTimer();
        private DateTime _powerOnStartTime;
        private TimeSpan _powerOnElapsedTime;
        private readonly RD_TRIG _rfOnTrigger = new RD_TRIG();
        private readonly R_TRIG _ErrTrigger = new R_TRIG();
        private readonly R_TRIG _trigPMNeeded = new R_TRIG();
        private readonly RD_TRIG _trigOnOff = new RD_TRIG();
        private ToleranceChecker _checkerPower;
        private ToleranceChecker _checkerReflectPower;
        private readonly double _scPowerAlarmTime;
        private readonly double _scPowerAlarmRange;
        private readonly double _scPowerWarningTime;
        private readonly double _scPowerWarningRange;
        private readonly double _scReflectPowerAlarmTime;
        private readonly double _scReflectPowerAlarmRange;
        private readonly double _scPowerRange;
        private readonly DIAccessor _diIntlk;
        private StatsDataItemRFAndPump _statRFOnTime;
        private readonly VenusDevice _device;

        private Stopwatch monitorStopwatch = new Stopwatch();

        private JetPMBase _chamber;

        private bool _intrtlockFlag = false;
        public bool ConnectedStatus { get; set; }
        public override float ScalePower => (float)_scPowerRange;

        public GeneratorStatus Status { get; set; }

        public string LastPMTime
        {
            get
            {
                return _statRFOnTime != null ? _statRFOnTime.LastPMTime.ToString() : "";
            }
        }

        public double DaysFromLastPM
        {
            get
            {
                return _statRFOnTime == null ? 0 : _statRFOnTime.fromLastPM;
            }
            set
            {
                if (_statRFOnTime != null)
                    _statRFOnTime.fromLastPM = value;
            }
        }

        public double TotalDays
        {
            get
            {
                return _statRFOnTime != null ? _statRFOnTime.Total : 0;
            }
            set
            {
                if (_statRFOnTime != null)
                    _statRFOnTime.Total = value;
            }
        }

        public double PMIntervalDays
        {
            get
            {
                return _statRFOnTime != null ? _statRFOnTime.PMInterval : 0;
            }
        }

        public bool IsPMNeeded
        {
            get
            {
                return DaysFromLastPM > PMIntervalDays;
            }
        }

        public bool EnableAlarm
        {
            get
            {
                return _statRFOnTime == null || _statRFOnTime.AlarmEnable;
            }
        }

        public override bool IsPowerOn
        {
            get => Status == GeneratorStatus.ON;
            set { }
        }

        public override bool IsError
        {
            get => Status == GeneratorStatus.ERROR;
            set { }
        }

        [Subscription("PowerOnTime")]
        public string PowerOnTime
        {
            get
            {
                if (_bRFPowerOn)
                    _powerOnElapsedTime = DateTime.Now - _powerOnStartTime;

                return $"{(int)_powerOnElapsedTime.TotalHours:00}:{_powerOnElapsedTime.Minutes:00}:{(_powerOnElapsedTime.Seconds > 0 ? (_powerOnElapsedTime.Seconds + 1) : 0):00}";
            }
        }

        public bool RFInterlock => _diIntlk == null || _diIntlk.Value;

        private float _forwardPower;
        public override float ForwardPower
        {
            get
            {
                return _forwardPower;
            }
            set
            {
                _forwardPower = CalibrationData(value, false);
            }
        }

        public new AITRfData DeviceData =>
            new AITRfData
            {
                Module = Module,
                DeviceName = Name,
                ScalePower = ScalePower,
                ForwardPower = ForwardPower,
                ReflectPower = ReflectPower,
                IsRfOn = IsPowerOn,
                PowerSetPoint = PowerSetPoint,
                PowerOnElapsedTime = PowerOnTime,
                IsInterlockOk = RFInterlock,
                WorkMode = (int)RfMode.ContinuousWaveMode,
                DisplayName = "Source RF",
            };

        // --------------------------Constructor-----------------------
        //
        public AdTecGenerator(ModuleName mod, VenusDevice device) : base(mod.ToString(), device.ToString())
        {
            var portNum = SC.GetStringValue(device == VenusDevice.Rf ? $"{mod}.Rf.Port" : $"{mod}.BiasRf.Port");
            this.Status = GeneratorStatus.Unknown;
            _device = device;

            _serial = new AsyncSerialPort(portNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "\r\r");

            _scPowerAlarmTime = SC.GetValue<double>($"{Module}.{Name}.PowerAlarmTime");
            _scPowerAlarmRange = SC.GetValue<double>($"{Module}.{Name}.PowerAlarmRange");

            _scPowerWarningTime = SC.GetValue<double>($"{Module}.{Name}.PowerWarningTime");
            _scPowerWarningRange = SC.GetValue<double>($"{Module}.{Name}.PowerWarningRange");

            _scReflectPowerAlarmTime = SC.GetValue<double>($"{Module}.{Name}.ReflectPowerAlarmTime");
            _scReflectPowerAlarmRange = SC.GetValue<double>($"{Module}.{Name}.ReflectPowerAlarmRange");
            _scPowerRange = SC.GetValue<double>($"{Module}.{Name}.PowerRange");
            _scEnableCalibration = SC.GetConfigItem($"{Module}.{Name}.EnableCalibration");
            _scCalibrationTable = SC.GetConfigItem($"{Module}.{Name}.CalibrationTable");

            _diIntlk = IO.DI[$"{Module}.DI_RF_Generator_Interlock"];

            SerachCommandList = new List<string>()
            {
            AdTecRfMessage.QUERY
            };
            intervalTime = 300;
            sendDataChangedEvent += SkyPump_sendDataChangedEvent;
            baseStopwatch.Start();
            baseTimer.Enabled = true;

            monitorStopwatch.Start();
        }
        private void SkyPump_sendDataChangedEvent(string obj)
        {
            var newstr = obj + "\r";
            _serial?.Write(newstr);
        }
        ~AdTecGenerator()
        {
            _serial?.Close();
        }

        public override bool Initialize()
        {
            base.Initialize();

            DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);
            OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetPowerOnOff}", (out string reason, int time, object[] param) =>
            {
                SetPowerOnOff(Convert.ToBoolean((string)param[0]), out reason);
                return true;
            });
            OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetPower}", (out string reason, int time, object[] param) =>
            {
                reason = "";
                ushort val = Convert.ToUInt16(param[0]);
                SetPower(val);
                return true;
            });
            OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetContinuousPower}", (out string reason, int time, object[] param) =>
            {
                reason = "";
                ushort val = Convert.ToUInt16(param[0]);
                SetPower(val);
                return true;
            });

            if (_serial.Open())
            {
                this.ConnectedStatus = true;
                _serial.OnDataChanged += SerialPortDataReceived;
                _serial.OnErrorHappened += SerialPortErrorOccurred;
            }
            else
            {
                this.ConnectedStatus = false;
                LOG.Write(eEvent.ERR_RF, Module, "AD TEC 射频发生器串口无法打开");
                return false;
            }

            _statRFOnTime = StatsDataManager.Instance.GetItemRFAndPump($"{Module}.RfOnTime");

            _timerQueryStatus.Start(QUERY_INTERVAL);

            _checkerPower = new ToleranceChecker(_scPowerAlarmTime);
            _checkerReflectPower = new ToleranceChecker(_scReflectPowerAlarmTime);

            SetCommunicationMode(1);
            return true;
        }

        public override void Monitor()
        {
            // 状态查询
            //if (_timerQueryStatus.IsTimeout())
            //{
            //    this.SendCmd(AdTecRfMessage.QUERY);
            //    _timerQueryStatus.Start(QUERY_INTERVAL);
            //}

            // power on triggered

            _rfOnTrigger.CLK = IsPowerOn;
            if (_rfOnTrigger.R)
            {
                _total = TotalDays;
                _fromLast = DaysFromLastPM;
                _timerTotal.Start(0);
                _timerFromLast.Start(0);
                _powerOnStartTime = DateTime.Now;
                _checkerPower.Reset(_scPowerAlarmTime);
                _checkerReflectPower.Reset(_scReflectPowerAlarmTime);
                _alarmChecker.Reset(_scPowerAlarmTime);
                _warningChecker.Reset(_scPowerWarningTime);
            }

            if (_rfOnTrigger.M)
            {
                TotalDays = _total + _timerTotal.GetElapseTime() / 1000 / 60 / 60;
                DaysFromLastPM = _fromLast + _timerFromLast.GetElapseTime() / 1000 / 60 / 60;

                //_checkerPower.Monitor(ForwardPower, PowerSetPoint - _scPowerAlarmRange, PowerSetPoint + _scPowerAlarmRange, _scPowerAlarmTime);

                //if (_checkerPower.Trig)
                //{
                //    EV.PostAlarmLog($"{Module}",
                //        $"{Display} Forward power {ForwardPower:0} out of range[{PowerSetPoint - _scPowerAlarmRange:0},{PowerSetPoint + _scPowerAlarmRange:0}] in {_scPowerAlarmTime:0} seconds");

                //    SetPowerOnOff(false, out _);
                //}





                //if (_recipeAlarmRange > 0 && _recipeAlarmRange / 100.0 * PowerSetPoint < _scPowerAlarmRange)
                //{
                //    if (_recipeIgnoreTimer.GetElapseTime() > _recipeIgnoreTimeMS)
                //    {
                //        _recipeAlarmChecker.Monitor(ForwardPower, PowerSetPoint - Math.Abs(_recipeAlarmRange / 100.0 * PowerSetPoint), PowerSetPoint + Math.Abs(_recipeAlarmRange / 100.0 * PowerSetPoint), _scPowerAlarmTime);
                //        if (_recipeAlarmChecker.Trig)
                //        {
                //            LOG.Write(eEvent.ERR_RF, Module, Display + $" out of tolerance in {_scPowerAlarmTime:0} seconds");

                //            SetPowerOnOff(false, out _);
                //        }
                //    }
                //}
                //else
                //{
                //    _alarmChecker.Monitor(ForwardPower, PowerSetPoint - Math.Abs(_scPowerAlarmRange), PowerSetPoint + Math.Abs(_scPowerAlarmRange), _scPowerAlarmTime);
                //    if (_alarmChecker.Trig)
                //    {
                //        LOG.Write(eEvent.ERR_RF, Module, Display + $" out of tolerance in {_scPowerAlarmTime:0} seconds");
                //    }
                //}


                //if (_recipeWarningRange > 0 && _recipeWarningRange / 100.0 * PowerSetPoint < _scPowerWarningRange)
                //{
                //    if (_recipeIgnoreTimer.GetElapseTime() > _recipeIgnoreTimeMS)
                //    {
                //        _recipeWarningChecker.Monitor(ForwardPower, PowerSetPoint - Math.Abs(_recipeWarningRange / 100.0 * PowerSetPoint), PowerSetPoint + Math.Abs(_recipeWarningRange / 100.0 * PowerSetPoint), _scPowerWarningTime);
                //        if (_recipeWarningChecker.Trig)
                //        {
                //            EV.PostWarningLog(Module, Display + $" out of tolerance in {_scPowerWarningTime:0} seconds");
                //        }
                //    }
                //}
                //else
                //{
                //    _warningChecker.Monitor(ForwardPower, PowerSetPoint - Math.Abs(_scPowerWarningRange), PowerSetPoint + Math.Abs(_scPowerWarningRange), _scPowerWarningTime);
                //    if (_warningChecker.Trig)
                //    {
                //        EV.PostWarningLog(Module, Display + $" out of tolerance in {_scPowerWarningTime:0} seconds");
                //    }
                //}




                //_checkerReflectPower.Monitor(ReflectPower, double.MinValue, _scReflectPowerAlarmRange, _scReflectPowerAlarmTime);

                //if (_checkerReflectPower.Trig)
                //{
                //    LOG.Write(eEvent.ERR_RF, Module,
                //        $"{Display} Reflect power {ReflectPower:0} out of range[0,{_scReflectPowerAlarmRange:0}] in {_scReflectPowerAlarmTime:0} seconds");

                //    SetPowerOnOff(false, out _);
                //}
            }

            if (PMIntervalDays > 0)
            {
                _trigPMNeeded.CLK = IsPMNeeded;

                if (_trigPMNeeded.Q)
                {
                    if (EnableAlarm)
                    {
                        LOG.Write(eEvent.ERR_RF, Module, "rf on time value larger than setting interval days");
                    }
                }
            }

            if (_rfOnTrigger.T)
                StatsDataManager.Instance.Increase($"{Module}.RfOnTime", $"{Module} RfOnTime", DaysFromLastPM, TotalDays);

            if (!_rfOnTrigger.CLK)
            {
                ForwardPower = 0;
                ReflectPower = 0;
            }

            // 通信 checking, 2 second 一次
            //if (_timerComm.IsTimeout() && !_bQueryComm)
            //{
            //    this.SendCmd(AdTecRfMessage.CHK_COMM);
            //    _bQueryComm = true;
            //    _timerComm.Start(CHK_COMM_INTERVAL);
            //}

            // RF Turn On & Off Timeout Check
            _trigOnOff.CLK = _bRFPowerOn;
            if (_trigOnOff.R)   //RF Turn On
            {
                _timerRFTurnOn.Start(SC.GetValue<int>($"{Module}.Rf.RFTurnOnTimeout") * 1000);
            }
            if (_trigOnOff.M)   //RF Stay On
            {
                if (_timerRFTurnOn.IsTimeout())
                {
                    if (!IsPowerOn)
                    {
                        LOG.Write(eEvent.ERR_RF, Module, "RF Turn On Failed");
                        _timerRFTurnOn.Stop();
                    }
                }
            }
            if (_trigOnOff.T)
            {
                _timerRFTurnOn.Stop();
            }

            if (monitorStopwatch.ElapsedMilliseconds > 500)
            {
                if (IsPowerOn == true && _chamber != null && _chamber.RFInterlock(_device) == false)
                {
                    SetPowerOnOff(false, out _);
                }
                monitorStopwatch.Restart();
            }
            base.Monitor();
        }

        public override void Terminate()
        {
            if (IsPowerOn)
            {
                SetPowerOnOff(false, out _);
            }
            _serial?.Close();
        }

        public override void Reset()
        {
            _rfOnTrigger.RST = true;
            _ErrTrigger.RST = true;
            _trigPMNeeded.RST = true;
            this.SendCmd(AdTecRfMessage.RESET);
            this.Status = GeneratorStatus.OFF;
            _bRFPowerOn = false;

            base.Reset();
        }

        public void SetRfMode(RfMode mode)
        {
            throw new NotImplementedException();
        }

        public override void SetCommunicationMode(int mode)
        {
            CommunicationType t1 = (CommunicationType)mode;
            switch (t1)
            {
                case CommunicationType.Analogue:
                    this.SendCmd(AdTecRfMessage.ANALOG);
                    break;
                case CommunicationType.RS232:
                    this.SendCmd(AdTecRfMessage.RS232);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("Communication mode error");
            }
        }

        public override void SetPower(float val)
        {
            if (!(this.ControlMode == EnumRfPowerControlMode.RS232Mode)) SetCommunicationMode(1);
            ushort a = !_scEnableCalibration.BoolValue ? (ushort)val : (ushort)CalibrationData(val, true);
            if (SendCmd($"{a:D4}{AdTecRfMessage.SET_POWER}"))
            {
                PowerSetPoint = val;
            }
        }

        public override bool SetPowerOnOff(bool on, out string str)
        {
            if (!(this.ControlMode == EnumRfPowerControlMode.RS232Mode)) SetCommunicationMode(1);
            str = "";

            _chamber = DEVICE.GetDevice<JetPMBase>(Module);
            if (on && !_chamber.CheckGeneratorAndHVInterlock(_device))
            {
                return false;
            }

            if (on)
            {
                SendCmd(AdTecRfMessage.RF_ON);
                _bRFPowerOn = true;
                _powerOnStartTime = DateTime.Now;
                QUERY_INTERVAL = 500;
            }
            else
            {
                SendCmd(AdTecRfMessage.RF_OFF);
                _bRFPowerOn = false;
                ForwardPower = 0;
                ReflectPower = 0;
                QUERY_INTERVAL = 500;
                _ErrTrigger.RST = true;
            }

            _timerQueryStatus.Start(QUERY_INTERVAL);
            return true;
        }

        //----------------------------------Private Method-------------------------------
        //
        private void SerialPortDataReceived(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                LOG.Write(eEvent.ERR_RF, Module, "AdTec RFG 无数据反馈");
                return;
            }

            string str2 = str.Trim('\r');
            if (str2 == AdTecRfMessage.ERR_RES)
            {
                LOG.Write(eEvent.WARN_RF, Module, $"AdTEC 收到 [{str2}]");
                return;
            }

            try
            {
                //LOG.Info($"{Module} Generator rec [{str2}]");

                Match match1 = Regex.Match(str2, INFO_PATTERN);
                if (!match1.Success)
                {
                    //EV.PostWarningLog(Module, "AdTec 数据格式错误");

                    if (!SC.GetValue<bool>("System.IsSimulatorMode"))
                    {
                        LOG.Write(eEvent.WARN_RF, Module, $"{Module}, AdTec 数据格式错误");
                    }

                    return;
                }

                string[] str1 =
                {
                    match1.Groups[1].Value,
                    match1.Groups[2].Value,
                    match1.Groups[3].Value,
                    match1.Groups[4].Value,
                    match1.Groups[5].Value
                };

                this.ParseQueryData(str1);
            }
            catch (Exception ex)
            {
                LOG.WriteExeption(ex);
            }
        }

        private void ParseQueryData(string[] strInfo)
        {
            // Control mode
            string s2 = strInfo[0].Substring(0, 1);
            this.ControlMode = (EnumRfPowerControlMode)Convert.ToUInt16(s2);

            // output mode
            string s0 = strInfo[0].Substring(1, 1);
            this.WorkMode = (EnumRfPowerWorkMode)Convert.ToUInt16(s0);

            // ON/OFF
            char s1 = strInfo[0][2];
            if (s1 == '1')
            {
                Status = GeneratorStatus.ON;
            }
            else if (s1 == '0')
            {
                Status = GeneratorStatus.OFF;
            }

            // error code
            string alarm = strInfo[0].Substring(5, 2);
            byte errCode = Convert.ToByte(alarm);

            _ErrTrigger.CLK = errCode > 0;
            if (_ErrTrigger.Q)
            {
                string code = errCode == 1 ? "Ref Over" :
                    errCode == 2 ? "Ref Limit" :
                    errCode == 3 ? "Cur Over" :
                    errCode == 4 ? "Cur Limit" :
                    errCode == 5 ? "Temp Over" :
                    errCode == 6 ? "Temp Sensor Short" :
                    errCode == 7 ? "Temp Sensor Open" :
                    errCode == 8 ? "Sensor Error" :
                    errCode == 9 ? "Fwd Power Over" :
                    errCode == 10 ? "RF ON Timer" :
                    errCode == 11 ? "RS232C error" :
                    errCode == 12 ? "Amp Unbalance" :
                    errCode == 14 ? "Fan error" :
                    errCode == 15 ? "Coolant Error" :
                    errCode == 16 ? "Voltage Error" :
                    errCode == 17 ? "Fwd Power Down" :
                    errCode == 22 ? "PD Over" :
                    errCode == 23 ? "PD Limit" :
                    errCode == 26 ? "Dew Condensation" :
                    errCode == 29 ? "SW Failure" :
                    errCode == 99 ? "Safety Lock" : string.Empty;

                if (!string.IsNullOrEmpty(code))
                {
                    if (errCode == 99)
                        LOG.Write(eEvent.EV_DEVICE_INFO, Module, "Source Generator " + code);
                    else
                        LOG.Write(eEvent.ERR_RF, Module, "Source Generator " + code);
                }
            }

            // forward power
            this.ForwardPower = Convert.ToUInt64(strInfo[2]);

            // reflect power
            this.ReflectPower = Convert.ToUInt64(strInfo[3]);
        }

        private void SerialPortErrorOccurred(string obj)
        {
            Status = GeneratorStatus.ERROR;
            LOG.Write(eEvent.ERR_RF, Module, $"AdTec RFG 串口出错, [{obj}]");
        }

        private bool SendCmd(string str)
        {
            if (str != AdTecRfMessage.QUERY)
            {
                LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Generator send [{str}]");
            }
            SetPointCommandQueue.Add(str);
            return true;
            //return _serial.Write(str + "\r");
        }
    }

    #endregion RFG

    #region match

    static class AdTecMatchMessage
    {
        public const string PRESET = "G";
        public const string AUTO = "L";
        public const string MANUAL = "M";
        public const string PRESET_MEM = "P";
        public const string START_QUERY = "S3";
        public const string STOP_QUERY = "SP";
        public const string WRITE_POS = "$APGR";
        public const string READ_POS = "$APRR";
    }

    class AdTecMatch : RfMatchBase
    {
        // ----------------------------Fields--------------------------
        //
        private readonly AsyncSerialPort _serial;
        private const ushort S3_HEAD_LENGTH = 2;
        private readonly DeviceTimer _timerQueryStatus = new DeviceTimer();
        private int QUERY_INTERVAL = 1000;
        //private int                      _scMatchPresetMode;
        //private int                      _scMatchMode;
        //private readonly SCConfigItem    _scMatchPositionC1;
        //private readonly SCConfigItem    _scMatchPositionC2;
        //private readonly bool            _scEnableC1C2Position;

        // --------------------------Properties------------------------
        //
        [Subscription("MatchWorkMode")]
        public EnumRfMatchTuneMode WorkMode { get; set; }
        public float C1 { get; set; }
        public float C2 { get; set; }

        [Subscription("VPP")]
        public ushort VPP { get; set; }

        public override AITRfMatchData DeviceData
        {
            get
            {
                return new AITRfMatchData
                {
                };
            }
        }

        // --------------------------Constructor-----------------------
        //
        public AdTecMatch(ModuleName mod, VenusDevice device) : base(mod.ToString(), device.ToString())
        {
            var portNum = SC.GetStringValue(device == VenusDevice.Match ? $"{mod}.Match.Port" : $"{mod}.BiasMatch.Port");

            _serial = new AsyncSerialPort(portNum, 9600, 8);

            //_scMatchPresetMode    = SC.GetValue<int>($"{Module}.Rf.PresetMode");
            //_scMatchMode          = SC.GetValue<int>($"{Module}.Rf.MatchMode");
            //_scMatchPositionC1    = SC.GetConfigItem($"{Module}.Rf.MatchPositionC1");
            //_scMatchPositionC2    = SC.GetConfigItem($"{Module}.Rf.MatchPositionC2");
            //_scEnableC1C2Position = SC.GetValue<bool>($"{Module}.Rf.EnableC1C2Position");
            SerachCommandList = new List<string>()
            {
            AdTecMatchMessage.READ_POS,
            AdTecMatchMessage.START_QUERY
            };
            intervalTime = 300;
            sendDataChangedEvent += AdTecMatch_sendDataChangedEvent;
            baseStopwatch.Start();
            baseTimer.Enabled = true;
        }

        private void AdTecMatch_sendDataChangedEvent(string obj)
        {
            this.SendCmd(obj);
        }

        ~AdTecMatch()
        {
            _serial?.Close();
        }

        public override bool Initialize()
        {
            base.Initialize();

            if (_serial.Open())
            {
                _serial.OnDataChanged += SerialPortDataReceived;
                _serial.OnErrorHappened += SerialPortErrorOccurred;
            }
            else
            {
                LOG.Write(eEvent.ERR_RF, Module, "Match 串口无法打开");
                return false;
            }

            DATA.Subscribe($"{Module}.{Name}.C1", () => TunePosition1);
            DATA.Subscribe($"{Module}.{Name}.C2", () => TunePosition2);
            DATA.Subscribe($"{Module}.{Name}.WorkMode", () => WorkMode.ToString());


            OP.Subscribe($"{Module}.{Name}.SetC1", (func, args) =>
            {
                return true;
            });
            OP.Subscribe($"{Module}.{Name}.SetC2", (func, args) =>
            {
                return true;
            });

            OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC1}", (out string reason, int time, object[] param) =>
            {
                SetMatchPositionC1((float)Convert.ToDouble(param[0]), out reason);
                return true;
            });

            OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC2}", (out string reason, int time, object[] param) =>
            {
                SetMatchPositionC2((float)Convert.ToDouble(param[0]), out reason);
                return true;
            });

            OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPosition}", (out string reason, int time, object[] param) =>
            {
                SetMatchPosition((float)Convert.ToDouble(param[0]), (float)Convert.ToDouble(param[1]), out reason);
                return true;
            });

            OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchProcessMode}", (out string reason, int time, object[] param) =>
            {
                SetMatchMode((string)param[0] == "Auto" ? EnumRfMatchTuneMode.Auto : EnumRfMatchTuneMode.Manual, out reason);
                return true;
            });

            _timerQueryStatus.Start(QUERY_INTERVAL);
            this.SendCmd(AdTecMatchMessage.START_QUERY);

            //LOG.Write(eEvent.ERR_RF, Module, "Initialize done.");
            return true;
        }

        public override void Monitor()
        {
            //try
            //{
            //    if (_timerQueryStatus.IsTimeout())
            //    {
            //        this.SendCmd(AdTecMatchMessage.READ_POS);
            //        _timerQueryStatus.Start(QUERY_INTERVAL);
            //    }
            //}
            //catch (Exception ex)
            //{
            //    LOG.WriteExeption(ex);
            //}
        }

        public override void Terminate()
        {
            this.SendCmd(AdTecMatchMessage.STOP_QUERY);
        }

        public override void Reset()
        {
            //SendCmd(AdTecMatchMessage.STOP_QUERY);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="c1,c2">百分比数字</param>
        /// <param name="c2"></param>
        /// 
        private void executeMatchPostion(float c1, float c2)
        {
            SetWorkMode(EnumRfMatchTuneMode.Manual);
            //await Task.Delay(200);

            SetPosition(c1, c2);
            //await Task.Delay(200);

            SetPresetMemory(0);
            //await Task.Delay(200);
            // SetWorkMode(EnumRfMatchTuneMode.Auto);
        }
        public override void SetMatchPosition(float c1, float c2, out string reason)
        {

            //LOG.Write(eEvent.WARN_RF, Module, $"AdTec Match error [{c1}, {c2}]");

            base.SetMatchPosition(c1, c2, out reason);

            executeMatchPostion(c1, c2);

            reason = "";
        }

        public void SetPresetMode(RfMatchPresetMode mode)
        {
        }

        // -----------------------Private Method-------------------------
        //
        private void SerialPortDataReceived(string strOrg)
        {
            if (string.IsNullOrWhiteSpace(strOrg))
            {
                LOG.Write(eEvent.ERR_RF, Module, "收到 Match 数据为空");
                return;
            }

            string[] sContent = strOrg.Split('\r');

            foreach (var sItem in sContent)
            {
                string sItem1 = sItem.TrimStart('\n');

                if (sItem1.Contains(AdTecMatchMessage.START_QUERY))
                {
                    // BYTE 3,4; bit 7
                    string s0 = sItem1.Substring(2 + S3_HEAD_LENGTH, 2);

                    ushort status0 = Convert.ToUInt16(s0, 16);
                    byte[] a1 = BitConverter.GetBytes(status0);

                    BitArray ba1 = new BitArray(a1);

                    this.WorkMode = ba1[7] ? EnumRfMatchTuneMode.Manual : EnumRfMatchTuneMode.Auto;

                    TuneMode1 = WorkMode;
                    TuneMode2 = WorkMode;

                    string sVpp = sItem1.Substring(42 + S3_HEAD_LENGTH, 3);
                    this.VPP = Convert.ToUInt16(sVpp, 16);
                }
                else if (sItem1.Contains(AdTecMatchMessage.READ_POS))
                {
                    string s1 = sItem1.Substring(5);
                    string sLoad = s1.Substring(0, 3);
                    string sPhase = s1.Substring(3, 3);

                    this.TunePosition1 = Convert.ToUInt64(sLoad, 16) * 0.1f;
                    this.TunePosition2 = Convert.ToUInt64(sPhase, 16) * 0.1f;
                }
            }
        }

        private void SerialPortErrorOccurred(string str)
        {
            LOG.Write(eEvent.ERR_RF, Module, $"AdTec Match error [{str}]");
        }

        private void SendCmd(string str)
        {
            _serial?.Write(str + "\r");
            //EV.PostInfoLog(Module.ToString(), $"Match send [{str}]");
        }

        private void SetPosition(float c1val, float c2val)
        {
            ushort val1 = (ushort)(c1val * 10);
            ushort val2 = (ushort)(c2val * 10);

            string cmd = AdTecMatchMessage.WRITE_POS + val1.ToString("X3") + val2.ToString("X3");
            SetPointCommandQueue.Add(cmd);
            //this.SendCmd(cmd);
        }

        public override bool SetMatchMode(EnumRfMatchTuneMode enumRfMatchTuneMode, out string reason)
        {
            reason = string.Empty;
            SetWorkMode(enumRfMatchTuneMode);

            return true;
        }

        private void SetWorkMode(EnumRfMatchTuneMode mode)
        {
            string data = mode == EnumRfMatchTuneMode.Auto ? AdTecMatchMessage.AUTO :
                mode == EnumRfMatchTuneMode.Manual ? AdTecMatchMessage.MANUAL : "";
            //this.SendCmd(mode == EnumRfMatchTuneMode.Auto ? AdTecMatchMessage.AUTO :
            //    mode == EnumRfMatchTuneMode.Manual ? AdTecMatchMessage.MANUAL : "");
            SetPointCommandQueue.Add(data);
        }

        private void SetPresetMemory(byte gear)
        {
            //this.SendCmd(AdTecMatchMessage.PRESET_MEM + gear.ToString());
            SetPointCommandQueue.Add(AdTecMatchMessage.PRESET_MEM + gear.ToString());
        }
    }

    #endregion match
}