using Aitex.Core.Common.DeviceData.IoDevice; 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.Util; using System; using System.Xml; namespace Aitex.Core.RT.Device.Devices { public class IoSCR : BaseDevice, IDevice { #region Variables private float _resLimitMax; private readonly bool _isFloatAioType = true; private readonly AIAccessor _aiVoltage; private readonly AIAccessor _aiArms; private readonly AIAccessor _aiPower; private readonly DIAccessor _diStatus; private DIAccessor _diAlarm; private readonly DOAccessor _doStatus; private readonly DOAccessor _doReset; private readonly DeviceTimer _timResetPulse = new(); private readonly R_TRIG _trigResOutOfRange = new(); private readonly DeviceTimer _timResOutOfRange = new(); private readonly IoPsuData _deviceData = new(); #endregion #region Constructors public IoSCR(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule) { _aiVoltage = ParseAiNode("aiVoltage", node, ioModule); _aiArms = ParseAiNode("aiArms", node, ioModule); _aiPower = ParseAiNode("aiPower", node, ioModule); _diStatus = ParseDiNode("diStatus", node, ioModule); _doReset = ParseDoNode("doReset", node, ioModule); _doStatus = ParseDoNode("doStatus", node, ioModule); _diAlarm = ParseDiNode("diAlarm", node, ioModule); _isFloatAioType = !string.IsNullOrEmpty(node.GetAttribute("aioType")) && (node.GetAttribute("aioType") == "float"); } #endregion #region Properties public float VoltageFeedBack => _aiVoltage == null ? 0 : (_isFloatAioType ? _aiVoltage.FloatValue : _aiVoltage.Value); public float ArmsFeedBack => _aiArms == null ? 0 : (_isFloatAioType ? _aiArms.FloatValue : _aiArms.Value); public float ResistanceLimitMax => _resLimitMax; public float Resistance => ArmsFeedBack == 0 ? 0 : VoltageFeedBack / ArmsFeedBack; public bool IsResistanceOutOfRange => IsResistanceTooHigh; public bool IsResistanceTooHigh { get; private set; } public float PowerFeedBack => _aiPower == null ? 0 : (_isFloatAioType ? _aiPower.FloatValue : _aiPower.Value); public bool StatusFeedBack => _diStatus == null ? false : _diStatus.Value; private IoPsuData DeviceData { get { _deviceData.IsAlarm = false; _deviceData.OutputStatusFeedBack = StatusFeedBack; _deviceData.OutputArmsFeedBack = ArmsFeedBack; _deviceData.OutputPowerFeedBack = PowerFeedBack; _deviceData.OutputVoltageFeedback = VoltageFeedBack; _deviceData.ResistanceLimitMax = ResistanceLimitMax; _deviceData.Resistance = Resistance; _deviceData.IsResistanceOutOfRange = IsResistanceOutOfRange; _deviceData.IsResistanceTooHigh = IsResistanceTooHigh; return _deviceData; } } #endregion #region Methods public bool Initialize() { DATA.Subscribe($"{Module}.{Name}.VoltageFeedBack", () => VoltageFeedBack); DATA.Subscribe($"{Module}.{Name}.ArmsFeedBack", () => ArmsFeedBack); DATA.Subscribe($"{Module}.{Name}.Resistance", () => Resistance); DATA.Subscribe($"{Module}.{Name}.PowerFeedBack", () => PowerFeedBack); DATA.Subscribe($"{Module}.{Name}.StatusFeedBack", () => StatusFeedBack); DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData); OP.Subscribe($"{Module}.{Name}.SetEnable", (function, args) => { var isTrue = Convert.ToBoolean(args[0]); SetEnable(isTrue, out _); return true; }); OP.Subscribe($"{Module}.{Name}.SetReset", (function, args) => { var isTrue = Convert.ToBoolean(args[0]); SetReset(isTrue, out _); return true; }); return true; } public bool SetEnable(bool setValue, out string reason) { if (!_doStatus.Check(setValue, out reason)) return false; if (!_doStatus.SetValue(setValue, out reason)) { return false; } return true; } public bool SetReset(bool setValue, out string reason) { if (!_doReset.Check(setValue, out reason)) return false; if (!_doReset.SetValue(setValue, out reason)) { return false; } _timResetPulse.Start(1000); return true; } public bool CheckSCREnable() { return _doStatus.Value; } public void Terminate() { } protected override void HandleMonitor() { try { MonitorAlarm(); if (_timResetPulse.IsTimeout()) { _timResetPulse.Stop(); if (_doReset.Value) _doReset.Value = false; ResetResistanceMonitorResult(); } } catch (Exception ex) { LOG.Write(ex); } } public void Reset() { ResetResistanceMonitorResult(); } /// /// 复位加热器电阻监测结果。 /// private void ResetResistanceMonitorResult() { IsResistanceTooHigh = false; _trigResOutOfRange.RST = true; _timResOutOfRange.Stop(); } private void MonitorAlarm() { //检查电阻值是否在合理范围 _resLimitMax = (float)SC.GetValue($"PM.{Module}.Heater.{Name}ResistanceMax"); var timeOut = SC.GetValue($"PM.{Module}.Heater.ResistanceMonitorHysteresis"); if (Resistance > _resLimitMax && _timResOutOfRange.IsIdle()) { _timResOutOfRange.Start(timeOut * 1000); } if (Resistance <= _resLimitMax) { IsResistanceTooHigh = false; _timResOutOfRange.Stop(); } _trigResOutOfRange.CLK = _timResOutOfRange.IsTimeout(); if (_trigResOutOfRange.Q) { IsResistanceTooHigh = true; EV.PostWarningLog(Module, $"{Name} Current resistance {Resistance}ohm exceeds the high limit {_resLimitMax}ohm."); } } public double AETemp { get { var temp = new object(); if (SC.GetConfigItem("AETemp.EnableDevice").BoolValue) { temp = DATA.Poll($"{Module}.AETemp.Middle"); } if (SC.GetConfigItem("AKunTemp.EnableDevice").BoolValue) { temp = DATA.Poll($"{Module}.AKunTemp.Middle"); } return temp == null ? 0 : (double)temp; } } #endregion } }