using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; 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 MECF.Framework.Common.Device.Bases; namespace Aitex.Core.RT.Device.Unit { public class IoRf : RfPowerBase { public const ushort ANALOG_TRANS_RANGE = 4000; //IO public bool IsOffline => _diOffline != null && _diOffline.RawData; public float ScalePower => (float)_scPowerRange; public float ScaleFrequency => 1000; public float ScaleDuty => 100; public string UnitPower => "w"; public string UnitFrequency => "Hz"; public string UnitDuty => "%"; [Subscription(AITRfProperty.IsOverTemp)] public bool IsOverTemp => _diOverTemp != null && _diOverTemp.Value; [Subscription(AITRfProperty.RFEnable)] public override bool IsPowerOn //True:on { get { if (_diStatus != null) return _diStatus.Value; return _doPowerOn.Value; } } [Subscription(AITRfProperty.RFSetPoint)] public override float PowerSetPoint { get { if (_aoPower != null) { byte[] high = BitConverter.GetBytes(_aoPower.Buffer[_aoPower.Index]); byte[] low = BitConverter.GetBytes(_aoPower.Buffer[_aoPower.Index + 1]); float flow = BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0); return flow * ScalePower / ANALOG_TRANS_RANGE; //return _aoPower.Value* ScalePower / RtInstance.ANALOG_TRANS_RANGE; } return 0; } set { if (_aoPower != null) { byte[] flow = BitConverter.GetBytes((float)(value * ANALOG_TRANS_RANGE / ScalePower)); _aoPower.Buffer[_aoPower.Index] = BitConverter.ToInt16(flow, 0); _aoPower.Buffer[_aoPower.Index + 1] = BitConverter.ToInt16(flow, 2); //_aoPower.Value = (short)(value * RtInstance.ANALOG_TRANS_RANGE / ScalePower); } } } [Subscription(AITRfProperty.RFDuty)] public float DutySetPoint => _aoPulsingDutyCycle?.Value ?? 0; [Subscription(AITRfProperty.RFFrequency)] public float FrequencySetPoint => _aoPulsingFrency?.Value ?? 0; [Subscription(AITRfProperty.RFForwardPower)] public float RFForwardPower { get { if (_aiForwardPower == null) return 0; byte[] high = BitConverter.GetBytes(_aiForwardPower.Buffer[_aiForwardPower.Index]); byte[] low = BitConverter.GetBytes(_aiForwardPower.Buffer[_aiForwardPower.Index + 1]); float flow = BitConverter.ToSingle(new[] { high[0], high[1], low[0], low[1] }, 0); return (_scRegulationFactor > 0) ? (float)(flow * ScalePower / ANALOG_TRANS_RANGE / _scRegulationFactor) : flow * ScalePower / ANALOG_TRANS_RANGE; } } [Subscription(AITRfProperty.RFReflectPower)] public float RFReflectPower => _aiReflectedPower?.Value ?? 0; [Subscription(AITRfProperty.RFInterlock)] public bool RFInterlock => _diIntlk == null || _diIntlk.Value; public new AITRfData DeviceData { get { return new AITRfData() { Module = Module, DeviceName = Name, DeviceSchematicId = DeviceID, DisplayName = Display, ForwardPower = RFForwardPower, ReflectPower = RFReflectPower, IsInterlockOk = RFInterlock, IsRfOn = IsPowerOn, PowerSetPoint = PowerSetPoint, FrequencySetPoint = FrequencySetPoint, DutySetPoint = DutySetPoint, ScalePower = ScalePower, ScaleDuty = ScaleDuty, ScaleFrequency = ScaleFrequency, UnitDuty = UnitDuty, UnitFrequency = UnitFrequency, UnitPower = UnitPower, WorkMode = (int)RfMode.ContinuousWaveMode, PowerOnElapsedTime = PowerOnTime, EnablePulsing = EnablePulsing, EnableReflectPower = EnableReflectPower, EnableVoltageCurrent = EnableVoltageCurrent, Voltage = Voltage, Current = Current, }; } } [Subscription(AITRfProperty.Voltage)] public float Voltage => _aiVoltage?.Value ?? 0; [Subscription(AITRfProperty.Current)] public float Current => _aiCurrent?.Value ?? 0; private DateTime _powerOnStartTime; private TimeSpan _powerOnElapsedTime; [Subscription("PowerOnTime")] public string PowerOnTime { get { if (IsPowerOn) _powerOnElapsedTime = DateTime.Now - _powerOnStartTime; return $"{(int)_powerOnElapsedTime.TotalHours:00}:{_powerOnElapsedTime.Minutes:00}:{(_powerOnElapsedTime.Seconds > 0 ? (_powerOnElapsedTime.Seconds + 1) : 0):00}"; } } public bool EnablePulsing => _scEnablePulsingFunction; public bool EnableReflectPower => _scEnableReflectPower; public bool EnableVoltageCurrent => _scEnableVoltageCurrent; private readonly DIAccessor _diStatus; private readonly DIAccessor _diIntlk; private readonly DIAccessor _diOffline; private readonly DIAccessor _diOverTemp; private DIAccessor _diIArc; private DIAccessor _diVArc; private DIAccessor _diBreakState; private readonly DIAccessor _diHighReflectPower; private readonly DIAccessor _diMatchCommWithGenerator; private readonly DOAccessor _doPowerOn; private readonly AIAccessor _aiReflectedPower; private readonly AIAccessor _aiForwardPower; private readonly AIAccessor _aiVoltage; private readonly AIAccessor _aiCurrent; private readonly AOAccessor _aoPower; //private AOAccessor _aoWorkMode; private readonly AOAccessor _aoPulsingFrency; private readonly AOAccessor _aoPulsingDutyCycle; private readonly AOAccessor _aoCoefficient; private readonly double _scPowerAlarmRange; private readonly double _scPowerAlarmTime; private readonly double _scReflectPowerAlarmRange; private readonly double _scReflectPowerAlarmTime; private readonly double _scPowerRange; private readonly double _scCoefficient; private readonly bool _scEnablePulsingFunction; private readonly bool _scEnableReflectPower; private readonly bool _scEnableVoltageCurrent; private readonly double _scRegulationFactor; private readonly F_TRIG _interlockTrig = new F_TRIG(); private readonly R_TRIG _rfOnTrigger = new R_TRIG(); private readonly R_TRIG _trigOffline = new R_TRIG(); private readonly R_TRIG _trigOverTemp = new R_TRIG(); private readonly R_TRIG _trigHighReflectPower = new R_TRIG(); private readonly R_TRIG _trigMatchCommWithGenerator = new R_TRIG(); private ToleranceChecker _checkerPower; private ToleranceChecker _checkerReflectPower; public IoRf(string module, XmlElement node, string ioModule = "") { base.Module = module; base.Name = node.GetAttribute("id"); base.Display = node.GetAttribute("display"); base.DeviceID = node.GetAttribute("schematicId"); _diStatus = ParseDiNode("diOnOffFeedback", node, ioModule); _diOffline = ParseDiNode("diOffline", node, ioModule); _diIntlk = ParseDiNode("diInterlock", node, ioModule); _diOverTemp = ParseDiNode("diOverTemp", node, ioModule); _diIArc = ParseDiNode("diIArc", node, ioModule); _diVArc = ParseDiNode("diVArc", node, ioModule); _diBreakState = ParseDiNode("diBreakerState", node, ioModule); _diHighReflectPower = ParseDiNode("diHighReflectPower", node, ioModule); _diMatchCommWithGenerator = ParseDiNode("diMatchCommWithGenerator", node, ioModule); _doPowerOn = ParseDoNode("doOnOff", node, ioModule); _aiReflectedPower = ParseAiNode("aiReflectPower", node, ioModule); _aiForwardPower = ParseAiNode("aiForwardPower", node, ioModule); _aiVoltage = ParseAiNode("aiVoltage", node, ioModule); _aiCurrent = ParseAiNode("aiCurrent", node, ioModule); _aoPower = ParseAoNode("aoPower", node, ioModule); //_aoWorkMode = ParseAoNode("aoWorkMode", node); _aoPulsingFrency = ParseAoNode("aoFrequency", node, ioModule); _aoPulsingDutyCycle = ParseAoNode("aoDuty", node, ioModule); _aoCoefficient = ParseAoNode("aoCoefficient", node, ioModule); _scPowerAlarmRange = SC.GetValue($"{Module}.{Name}.PowerAlarmRange"); _scPowerAlarmTime = SC.GetValue($"{Module}.{Name}.PowerAlarmTime"); _scReflectPowerAlarmRange = SC.GetValue($"{Module}.{Name}.ReflectPowerAlarmRange"); _scReflectPowerAlarmTime = SC.GetValue($"{Module}.{Name}.ReflectPowerAlarmTime"); _scPowerRange = SC.GetValue($"{Module}.{Name}.PowerRange"); _scCoefficient = SC.GetValue($"{Module}.{Name}.Coefficient"); _scEnablePulsingFunction = SC.GetValue($"{Module}.{Name}.EnablePulsingFunction"); _scEnableReflectPower = SC.GetValue($"{Module}.{Name}.EnableReflectPower"); _scEnableVoltageCurrent = SC.GetValue($"{Module}.{Name}.EnableVoltageCurrent"); _scRegulationFactor = SC.GetValue($"{Module}.{Name}.PowerRegulationFactor"); Debug.Assert(null != _doPowerOn && null != _aoPower); } public override bool Initialize() { base.Initialize(); DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData); DEVICE.Register($"{Module}.{Name}.{AITRfOperation.SetPowerOnOff}", SetPowerOnOff); DEVICE.Register($"{Module}.{Name}.{AITRfOperation.SetContinuousPower}", SetContinuousPower); DEVICE.Register($"{Module}.{Name}.{AITRfOperation.SetPower}", SetPower); 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.SetContinuousPower}", (out string reason, int time, object[] param) => { SetContinuousPower(out reason, 0, param); return true; }); OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetPower}", (out string reason, int time, object[] param) => { SetPower(out reason, 0, param); return true; }); OP.Subscribe($"{Module}.Match.{AITRfOperation.SetMatchProcessMode}", (out string reason, int time, object[] param) => { reason = ""; return true; }); OP.Subscribe($"{Module}.Match.{AITRfOperation.SetMatchPositionC1}", (out string reason, int time, object[] param) => { reason = ""; return true; }); OP.Subscribe($"{Module}.Match.{AITRfOperation.SetMatchPositionC2}", (out string reason, int time, object[] param) => { reason = ""; return true; }); OP.Subscribe($"{Module}.Match.{AITRfOperation.SetMatchPosition}", (out string reason, int time, object[] param) => { reason = ""; return true; }); return true; } public override void SetPower(float val) { this.SetPower(out _, 0, new object[] { val }); } public override bool SetPowerOnOff(bool isOn, out string reason) { if (!_diIntlk.Value) { reason = "RF interlock is not satisfied,can not be on"; EV.PostAlarmLog($"{Module}.{Name}", reason); return false; } if (!isOn) { PowerSetPoint = 0; } return _doPowerOn.SetValue(isOn, out reason); } private bool? SetPowerOnOff(out string reason, int time, object[] param) { bool isOn = Convert.ToBoolean((string)param[0]); if (!_diIntlk.Value) { reason = "RF interlock is not satisfied,can not power on"; EV.PostAlarmLog($"{Module}.{Name}", reason); return false; } bool result = _doPowerOn.SetValue(isOn, out reason); if (result) reason = string.Format("Set RF power " + (isOn ? "On" : "Off")); return result; } public bool? SetContinuousPower(out string reason, int time, object[] param) { float power = (float)Convert.ToDouble((string)param[0]); power = Math.Max(0, power); power = Math.Min(ScalePower, power); byte[] flow = BitConverter.GetBytes((float)(power * ANALOG_TRANS_RANGE / ScalePower)); _aoPower.Buffer[_aoPower.Index] = BitConverter.ToInt16(flow, 0); _aoPower.Buffer[_aoPower.Index + 1] = BitConverter.ToInt16(flow, 2); //_aoPower.Value = (short)(power * RtInstance.ANALOG_TRANS_RANGE / ScalePower); reason = $"RF set Power {power}"; return true; } private bool? SetPower(out string reason, int time, object[] param) { reason = string.Empty; float power = (float)Convert.ToDouble(param[0]); power = Math.Max(0, power); power = Math.Min(ScalePower, power); byte[] flow = BitConverter.GetBytes((float)(power * ANALOG_TRANS_RANGE / ScalePower)); _aoPower.Buffer[_aoPower.Index] = BitConverter.ToInt16(flow, 0); _aoPower.Buffer[_aoPower.Index + 1] = BitConverter.ToInt16(flow, 2); //_aoPower.Value = (short)(power * RtInstance.ANALOG_TRANS_RANGE / ScalePower); reason = $"RF set Power:{power}"; return true; } public void Stop() { string reason = String.Empty; _aoPower.Value = 0; } public override void Terminate() { } public override void Monitor() { try { if (_aoCoefficient != null) { _aoCoefficient.Value = (short)_scCoefficient; } if (_checkerPower == null) _checkerPower = new ToleranceChecker(_scPowerAlarmTime); if (_checkerReflectPower == null) _checkerReflectPower = new ToleranceChecker(_scReflectPowerAlarmTime); _interlockTrig.CLK = _diIntlk.Value; if (_interlockTrig.Q) { //EV.PostMessage(Module, EventEnum.RFInterlockFailed); } _rfOnTrigger.CLK = IsPowerOn; if (_rfOnTrigger.Q) { _powerOnStartTime = DateTime.Now; _checkerPower.Reset(_scPowerAlarmTime); _checkerReflectPower.Reset(_scReflectPowerAlarmTime); } if (_rfOnTrigger.M) { _checkerPower.Monitor(RFForwardPower, PowerSetPoint - _scPowerAlarmRange, PowerSetPoint + _scPowerAlarmRange, _scPowerAlarmTime); if (_checkerPower.Trig) { string reason; EV.PostMessage(Module, EventEnum.ToleranceAlarm, Module, Display, $"Forward power {RFForwardPower:0} out of range[{(PowerSetPoint - _scPowerAlarmRange):0},{(PowerSetPoint + _scPowerAlarmRange):0}] in {_scPowerAlarmTime:0} seconds"); SetPowerOnOff(false, out reason); } _checkerReflectPower.Monitor(RFReflectPower, double.MinValue, _scReflectPowerAlarmRange, _scReflectPowerAlarmTime); if (_checkerReflectPower.Trig) { EV.PostMessage(Module, EventEnum.ToleranceAlarm, Module, Display, $"Reflect power {RFReflectPower:0} out of range[0,{_scReflectPowerAlarmRange:0}] in {_scReflectPowerAlarmTime:0} seconds"); SetPowerOnOff(false, out _); } } _trigOffline.CLK = IsOffline; if (_trigOffline.Q) { EV.PostMessage(Module, EventEnum.DefaultAlarm, "The RF generator is offline"); } _trigOverTemp.CLK = IsOverTemp; if (_trigOverTemp.Q) { EV.PostAlarmLog(Module, $"{Name} over temperature"); } if (_diHighReflectPower != null) { _trigHighReflectPower.CLK = _diHighReflectPower.Value; if (_trigOffline.Q) { EV.PostMessage(Module, EventEnum.DefaultAlarm, "RF trig high reflect power"); } } if (_diMatchCommWithGenerator != null) { _trigMatchCommWithGenerator.CLK = !_diMatchCommWithGenerator.Value; if (_trigMatchCommWithGenerator.Q) { EV.PostMessage(Module, EventEnum.DefaultAlarm, "RF trig match not communicate with generator"); } } } catch (Exception ex) { LOG.Write(ex); throw ex; } } public override void Reset() { _interlockTrig.RST = true; _trigOffline.RST = true; _trigOverTemp.RST = true; _trigMatchCommWithGenerator.RST = true; _trigHighReflectPower.RST = true; } public void SetRfMode(RfMode mode) { throw new NotImplementedException(); } } }