using Aitex.Core.Common.DeviceData.IoDevice; 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.Util; using System; using System.Xml; namespace Aitex.Core.RT.Device.Devices { public class IoSCR : BaseDevice, IDevice { #region Variables private readonly string _scResLimitMax; 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 _timer = new(); private string _infoText = ""; private R_TRIG _alarmTrig = new(); private readonly R_TRIG _trigResistance = new(); private readonly DeviceTimer _timerResistance = 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); _infoText = node.GetAttribute("AlarmText"); _isFloatAioType = !string.IsNullOrEmpty(node.GetAttribute("aioType")) && (node.GetAttribute("aioType") == "float"); // 读取电阻上限设定值 _scResLimitMax = node.GetAttribute("scResLimitMax"); LoadConfig(); } #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 => Resistance > ResistanceLimitMax; 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 /// /// 加载必要的配置。 /// private void LoadConfig() { const float DEF_RES_LIMIT_MAX_OHM = 3; LoadSC($"{ScBasePath}.{_scResLimitMax}", $"PM.{Module}.Heater.{Name}ResistanceLimitMax", DEF_RES_LIMIT_MAX_OHM, ref _resLimitMax, f => { _resLimitMax = f; }); } 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; } _timer.Start(1000); return true; } public bool CheckSCREnable() { return _doStatus.Value; } public void Terminate() { } protected override void HandleMonitor() { try { MonitorAlarm(); if (_timer.IsTimeout()) { _timer.Stop(); } else if (_timer.IsIdle()) { if (_doReset.Value) { _doReset.Value = false; } } } catch (Exception ex) { LOG.Write(ex); } } public void Reset() { } private void MonitorAlarm() { //检查电阻值是否在合理范围 var dbResistorMax = SC.GetValue($"PM.{Module}.Heater.{Name}ResistanceMax"); var timeOut = SC.GetValue($"PM.{Module}.Heater.ResistanceCheckTimeOut"); if (Resistance > dbResistorMax && _timerResistance.IsIdle()) { _timerResistance.Start(timeOut); } if (Resistance <= dbResistorMax) { _timerResistance.Stop(); } _trigResistance.CLK = _timerResistance.IsTimeout(); if (_trigResistance.Q) { EV.PostWarningLog(Module, $"{Name} Resistance is out of range.Current Resistance is {Resistance}"); } } 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 } }