|
@@ -0,0 +1,357 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using MECF.Framework.Common.Communications;
|
|
|
+using MECF.Framework.Common.Equipment;
|
|
|
+
|
|
|
+using Aitex.Core.RT.SCCore;
|
|
|
+using Aitex.Core.RT.Event;
|
|
|
+using Aitex.Core.RT.Device;
|
|
|
+
|
|
|
+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; set; }
|
|
|
+ public int Position { get; set; }
|
|
|
+
|
|
|
+ private readonly string EOF = "\r\n";
|
|
|
+ private readonly int _readInterval = 1000;
|
|
|
+ private readonly AsyncSerialPort _serial;
|
|
|
+ private Stopwatch _queryWatch = new Stopwatch();
|
|
|
+ private string _lastAlarmString = string.Empty;
|
|
|
+
|
|
|
+ public PendulumValve(ModuleName mod)
|
|
|
+ {
|
|
|
+ Module = mod.ToString();
|
|
|
+ var _PortNum = SC.GetStringValue($"{mod}.PendulumValve.Port");
|
|
|
+ _serial = new AsyncSerialPort(_PortNum, 9600, 7, System.IO.Ports.Parity.Even, System.IO.Ports.StopBits.One, EOF);
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool Initialize()
|
|
|
+ {
|
|
|
+ if (!_serial.Open())
|
|
|
+ {
|
|
|
+ _noRepeatAlarm("Pendulum Valve 串口无法打开");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ _serial.OnDataChanged += OnPortDataChanged;
|
|
|
+ _serial.OnErrorHappened += OnErrorOccurred;
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Monitor()
|
|
|
+ {
|
|
|
+ if(_queryWatch.ElapsedMilliseconds > _readInterval)
|
|
|
+ {
|
|
|
+ SendCommand(Operation.GetPressure);
|
|
|
+ _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":
|
|
|
+ {
|
|
|
+ Pressure = int.Parse(data[1]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case "A":
|
|
|
+ {
|
|
|
+ Position = int.Parse(data[1]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case "i":
|
|
|
+ {
|
|
|
+ _tryParseInqueryData(obj);
|
|
|
+ }
|
|
|
+ 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}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool SendCommand(Operation op)
|
|
|
+ {
|
|
|
+ if(_noneParaCommandOp.ContainsKey(op))
|
|
|
+ {
|
|
|
+ return _serial.Write(_noneParaCommandOp[op] + EOF);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public 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)
|
|
|
+ {
|
|
|
+ return _serial.Write(cmd);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void _noRepeatAlarm(string alarm)
|
|
|
+ {
|
|
|
+ if (_lastAlarmString != alarm)
|
|
|
+ {
|
|
|
+ _lastAlarmString = 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.GetAssembly:
|
|
|
+ case Operation.GetDeviceStatus:
|
|
|
+ case Operation.GetLearnStatus:
|
|
|
+ case Operation.GetPressureCtrlStatus:
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case Operation.GetIdentification:
|
|
|
+ case Operation.GetIsolationCycleCounter:
|
|
|
+ case Operation.GetPowerUpCounter:
|
|
|
+ case Operation.GetThrottleCycleCounter:
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case Operation.GetWarnings:
|
|
|
+ case Operation.GetErrorStatus:
|
|
|
+ case Operation.GetFatalErrorStatus:
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case Operation.GetFirmwareConfiguration:
|
|
|
+ case Operation.GetHardwareConfiguration:
|
|
|
+ case Operation.GetPIDConfiguration:
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case Operation.GetSensor1Data:
|
|
|
+ case Operation.GetSensor2Data:
|
|
|
+ case Operation.GetSensor1Offset:
|
|
|
+ case Operation.GetSensor2Offset:
|
|
|
+ case Operation.GetSensorOffset:
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|