| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 | using System;using System.Collections.Generic;using System.Diagnostics;using Venus_RT.Modules;using MECF.Framework.Common.Communications;using MECF.Framework.Common.Equipment;using Venus_Core;using Aitex.Core.RT.SCCore;using Aitex.Core.RT.Event;using Aitex.Core.RT.Device;using Aitex.Core.RT.Log;using System.Threading.Tasks;using System.Collections.Concurrent;using Aitex.Core.Common.DeviceData;using MECF.Framework.Common.CommonData.DeviceData;using Aitex.Core.RT.DataCenter;using Venus_RT.Modules.PMs;namespace Venus_RT.Devices{    class PendulumValve : IDevice    {        public enum Operation        {            SetPosition,            GetPositionSP,            Hold,            OpenValve,            CloseValve,            SetPressure,            GetPressureSP,            GetAssembly,            GetPosition,            GetPressure,            GetSensor1Data,            GetSensor2Data,            GetPressureCtrlStatus,            GetDeviceStatus,            GetWarnings,            GetSensorOffset,            GetSensor1Offset,            GetSensor2Offset,            GetLearnStatus,            GetLearnPressureLimit,            GetErrorStatus,            GetFatalErrorStatus,            GetThrottleCycleCounter,            GetIsolationCycleCounter,            GetPowerUpCounter,            GetHardwareConfiguration,            GetFirmwareConfiguration,            GetIdentification,            SetAccessMode,            SetInterfaceConfiguration,            SetValveConfiguration,            SetSensorConfiguration,            SetRangeConfiguration,            SetZero,            SetPressureAlignment,            SetLearn,            DownloadLearnData,            UploadLearnData,            SetPIDConfiguration,            GetPIDConfiguration,            SetValveSpeed,            GetValveSpeed,            Reset,            Invalid,        }        private readonly Dictionary<Operation, string> _noneParaCommandOp = new Dictionary<Operation, string>        {            {Operation.GetPositionSP,               "i:38" },            {Operation.Hold,                        "H:" },            {Operation.CloseValve,                  "C:" },            {Operation.OpenValve,                   "O:" },            {Operation.GetPressureSP,               "i:38" },            {Operation.GetAssembly,                 "i:76" },            {Operation.GetPosition,                 "A:" },            {Operation.GetPressure,                 "P:" },            {Operation.GetSensor1Data,              "i:64" },            {Operation.GetSensor2Data,              "i:65" },            {Operation.GetPressureCtrlStatus,       "i:36" },            {Operation.GetDeviceStatus,             "i:30" },            {Operation.GetWarnings,                 "i:35" },            {Operation.GetSensorOffset,             "i:62" },            {Operation.GetSensor1Offset,            "i:60" },            {Operation.GetSensor2Offset,            "i:61" },            {Operation.GetLearnStatus,              "i:32" },            {Operation.GetLearnPressureLimit,       "i:34" },            {Operation.GetErrorStatus,              "i:52" },            {Operation.GetFatalErrorStatus,         "i:50" },            {Operation.GetThrottleCycleCounter,     "i:70" },            {Operation.GetIsolationCycleCounter,    "i:71" },            {Operation.GetPowerUpCounter,           "i:72" },            {Operation.GetHardwareConfiguration,    "i:80" },            {Operation.GetFirmwareConfiguration,    "i:82" },            {Operation.GetIdentification,           "i:83" },        };        private readonly Dictionary<Operation, string> _singleParaCommandOp = new Dictionary<Operation, string>        {            {Operation.SetPosition,                 "R:{0:D6}" },            {Operation.SetPressure,                 "S:{0:D8}" },            {Operation.SetAccessMode,               "c:01{0:D2}" },            {Operation.SetInterfaceConfiguration,   "s:20{0:D8}" },            {Operation.SetValveConfiguration,       "s:04{0:D2}000000" },            {Operation.SetSensorConfiguration,      "s:01{0:D8}" },            {Operation.SetRangeConfiguration,       "s:21{0:D8}" },            {Operation.SetPressureAlignment,        "c:6002{0:D8}" },            {Operation.SetLearn,                    "L:{0:D8}" },            {Operation.UploadLearnData,             "u:{0:D3}" },            {Operation.SetPIDConfiguration,         "s:02{0:D8}" },            {Operation.SetValveSpeed,               "V:00{0:D4}" }        };        private readonly Dictionary<Operation, string> _twoParaCommandOp = new Dictionary<Operation, string>        {            {Operation.DownloadLearnData, "d:{0:D3}{1:D8}" }        };        private readonly Dictionary<string, string> _deviceError = new Dictionary<string, string>        {            {"000001",  "Parity error" },            {"000002",  "Input buffer overflow (to many characters) " },            {"000003",  "Framing error (data length, number of stop bits)" },            {"000010",  "<CR> or <LF> missing" },            {"000011",  ": missing" },            {"000012",  "Invalid number of characters (between : and [CR][LF])" },            {"000020",  "Unknown command" },            {"000021",  "Unknown command" },            {"000022",  "Invalid value" },            {"000023",  "Invalid value" },            {"000030",  "Value out of range" },            {"000041",  "Command not applicable for hardware configuration" },            {"000060",  "ZERO disabled" },            {"000080",  "Command not accepted due to local operation" },            {"000082",  "Command not accepted due to synchronization, CLOSED or OPEN by digital input, safety mode or fatal error" },        };        public string Module { get; set; }        public string Name { get; set; }        public int Pressure { get; private set; }        public int Position { get; private set; }        public string Status { get; private set; }        public bool IsOpen { get; private set; }        private readonly string EOF = "\r\n";        private readonly int _readInterval = 1000;        private readonly int _position_unit = 100;        private readonly int _pressure_ful_range = 500;        private readonly int _foreLinePressureLimit = 750;        private readonly int _chamberPressureLimit = 600;        private readonly int _turboPumpSpeedLimit = 100;        private int _queryFlag = 0;        private readonly AsyncSerialPort _serial;        private Stopwatch _queryWatch = new Stopwatch();        private string _lastAlarmString = string.Empty;        private Operation[] _querys = new Operation[] { Operation.GetPressure, Operation.GetPosition, Operation.GetDeviceStatus, Operation.GetPressureSP };        BlockingCollection<string> blockingCollection = new BlockingCollection<string>();        public AITPendulumValveData DeviceData        {            get            {                AITPendulumValveData deviceData = new AITPendulumValveData                {                    DeviceName = Name,                    Module = Module,                    Pressure = Pressure,                    IsOpen = IsOpen || Position > 0,                    Position = IsOpen ? Position : 0,                };                return deviceData;            }        }        public PendulumValve(ModuleName mod)        {            Name = VenusDevice.PendulumValve.ToString();            Module = mod.ToString();            var _PortNum = SC.GetStringValue($"{mod}.PendulumValve.Port");            _serial = new AsyncSerialPort(_PortNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, EOF);            _pressure_ful_range = SC.GetValue<int>($"{mod}.PendulumValve.PressureFullRange");            _foreLinePressureLimit = SC.GetValue<int>($"{mod}.PendulumValve.ForelinePressureLimit");            _chamberPressureLimit = SC.GetValue<int>($"{mod}.PendulumValve.ChamberPressureLimit");            _turboPumpSpeedLimit = SC.GetValue<int>($"{mod}.PendulumValve.TurboPumpSpeedLimit");            IsOpen = false;            Task.Run(() =>            {                foreach (var data in blockingCollection.GetConsumingEnumerable())                {                    _serial?.Write(data);                    System.Threading.Thread.Sleep(100);                }            });        }        public bool Initialize()        {            DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData);            if (!_serial.Open())            {                _noRepeatAlarm("Pendulum Valve 串口无法打开");                return false;            }            _serial.OnDataChanged += OnPortDataChanged;            _serial.OnErrorHappened += OnErrorOccurred;            _queryWatch.Restart();            return true;        }        public void Monitor()        {            if (_queryWatch.ElapsedMilliseconds > _readInterval)            {                SendCommand(_querys[_queryFlag++ % 4]);                _queryWatch.Restart();            }        }        public void Reset()        {        }        public void Terminate()        {            _serial?.Close();        }        private void OnErrorOccurred(string obj)        {            _noRepeatAlarm($"[{Module}] VAT Pendulum Valve error: [{obj}]");        }        private void OnPortDataChanged(string obj)        {            if (string.IsNullOrEmpty(obj))            {                _noRepeatAlarm("VAT Pendulum Valve receive empty message");                return;            }            try            {                var data = obj.TrimEnd().Split(':');                switch (data[0])                {                    case "P":                        {                            int pressure;                            if (int.TryParse(data[1], out pressure))                                Pressure = pressure * _pressure_ful_range / 1000000;                        }                        break;                    case "A":                        {                            int position;                            if (int.TryParse(data[1], out position))                                Position = position / _position_unit;                        }                        break;                    case "i":                        {                            _tryParseInqueryData(obj);                        }                        break;                    case "C":                        IsOpen = false;                        break;                    case "O":                        IsOpen = true;                        break;                    case "H":                    case "R":                    case "S":                        break;                    case "E":                        {                            _noRepeatAlarm($"[{Module}] VAT Pendulum Valve device error: {_deviceError[data[1]]}");                        }                        break;                    default:                        {                            _noRepeatAlarm($"VAT Pendulum Valve: unrecognized received data: {obj}");                            break;                        }                }            }            catch (Exception ex)            {                _noRepeatAlarm($"[{Module}] VAT Pendulum Valve error: [{ex.Message}], Data: {obj}");            }        }        private bool SendCommand(Operation op)        {            if (_noneParaCommandOp.ContainsKey(op))            {                blockingCollection.Add(_noneParaCommandOp[op] + EOF);                return true;                //return _serial.Write(_noneParaCommandOp[op] + EOF);            }            else            {                return false;            }        }        private bool SendCommand(Operation op, int data)        {            if (_singleParaCommandOp.ContainsKey(op))            {                var cmd = string.Format(_singleParaCommandOp[op], data) + EOF;                return _sendCmd(cmd);            }            else            {                _noRepeatAlarm("This VAT Pendulum Valve command need 1 data");                return false;            }        }        private bool _sendCmd(string cmd)        {            blockingCollection.Add(cmd);            return true;            //return _serial.Write(cmd);        }        private void _noRepeatAlarm(string alarm)        {            if (_lastAlarmString != alarm)            {                _lastAlarmString = alarm;                LOG.Write(eEvent.ERR_PENDULUM_VALVE, ModuleHelper.Converter(Module), alarm);                EV.PostAlarmLog(Module, alarm);            }        }        private bool _tryParseInqueryData(string data)        {            var cmdPrix = data.Substring(0, 4);            Operation oper = Operation.Invalid;            foreach (var item in _noneParaCommandOp)            {                if (item.Value == cmdPrix)                {                    oper = item.Key;                    break;                }            }            if (oper == Operation.Invalid)            {                return false;            }            switch (oper)            {                case Operation.GetDeviceStatus:                    {                        Status = data.Substring(4, 8);                        if (Status[1] == 'E')                        {                            // Fatal Error                            _noRepeatAlarm($"Device Status error:{Status}");                        }                        else if (Status[3] == '1')                        {                            // Warning Present                            _noRepeatAlarm($"Device Warning Present:{Status}");                        }                        else if (Status[1] == '3')                        {                            IsOpen = false;                        }                        else if (Status[1] == '4')                        {                            IsOpen = true;                        }                    }                    break;                case Operation.GetPressureSP:                case Operation.GetPositionSP:                    {                        string Pressure = data.Substring(4, 8);                        //LOG.Write(eEvent.EV_DEVICE_INFO, Module, $" PV Pressure SetPoint: {Pressure}");                    }                    break;                default:                    break;            }            return true;        }        public bool SetPosition(int postion)        {            if (_CheckStatus())            {                return SendCommand(Operation.SetPosition, postion * _position_unit);            }            return false;        }        public bool SetPressure(int pressure)        {            if (_CheckStatus())            {                //IsOpen = true;                return SendCommand(Operation.SetPressure, pressure * 1000000 / _pressure_ful_range);            }            return false;        }        public bool Hold()        {            return SendCommand(Operation.Hold);        }        public bool TurnValve(bool on)        {            if (on == false)            {                return SendCommand(on ? Operation.OpenValve : Operation.CloseValve);            }            else            {                if (_CheckStatus(on))                {                    return SendCommand(on ? Operation.OpenValve : Operation.CloseValve);                }            }            return false;        }        bool _CheckStatus(bool bTurnOn = false)        {            if (Status != null && Status[1] == 'E')            {                _noRepeatAlarm($"PendulumValve is error status, can do turn on/off operation.");                return false;            }            var _chamber = DEVICE.GetDevice<JetPMBase>(Module);            if (bTurnOn && !_chamber.IsTurboPumpAtSpeed)            {                _noRepeatAlarm($"Turbo Pump not at speed, can not turn on pendulum valve.");                return false;            }            if (_chamber.ForelinePressure > _foreLinePressureLimit)            {                LOG.Write(eEvent.ERR_DEVICE_INFO, Module, $"Foreline Pressure:{_chamber.ForelinePressure} is higher than {_foreLinePressureLimit}mtorr, can not turn on pendulum valve.");                return false;            }            if (_chamber.ChamberPressure > _chamberPressureLimit && _chamber.TurboPumpSpeed > _turboPumpSpeedLimit)            {                LOG.Write(eEvent.ERR_DEVICE_INFO, Module, $"Chamber Pressure:{_chamber.ChamberPressure} is higher than {_chamberPressureLimit}mtorr and Chamber.TurboPumpSpeed is higher than {_turboPumpSpeedLimit}, can not turn on pendulum valve.");                return false;            }            return true;        }    }}
 |