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; using Aitex.Core.Common.DeviceData.IoDevice; using MECF.Framework.Common.Aitex.Core.Common.DeviceData.IoDevice; namespace Aitex.Core.RT.Device.Devices { public class IoPSU : BaseDevice, IDevice { #region Variables private readonly string _scResLimitMax; private float _resLimitMax; private readonly bool _isFloatAioType; private readonly AIAccessor _aiOutputVoltage; private readonly AIAccessor _aiOutputArms; private readonly AIAccessor _aiOutputPower; private readonly AIAccessor _aiSimVoltage; private readonly AIAccessor _aiSimArms; //private AOAccessor _aoEnable = null; //private AOAccessor _aoReset = null; private readonly AOAccessor _aoConstant; private readonly DIAccessor _diStatus; private readonly DIAccessor _diAlarm; private readonly DIAccessor _diHeatEnable; private DIAccessor _diCommunicationError; private readonly DOAccessor _doReset; private readonly DOAccessor _doStatus; private readonly DOAccessor _doHeatEnable; private readonly DOAccessor _doRelatedEnable; //每个Enable同时关联的Inner,Middle,Out Enable private string _infoText = ""; private string _commInfoText = ""; private readonly R_TRIG _alarmTrig = new(); private readonly R_TRIG _commAlarmTrig = new(); private readonly R_TRIG _enableTrig = new(); private readonly R_TRIG _enableTrig2 = new(); private readonly R_TRIG _trigVoltage = new(); private readonly R_TRIG _trigCurrent = new(); private readonly R_TRIG _trigResistance = new(); private readonly DeviceTimer _timer = new(); private readonly DeviceTimer _timerResistance = new(); private readonly IoPsuData _deviceData = new(); #endregion #region Constructors public IoPSU(string module, XmlElement node, string ioModule = "") : base(module, node, ioModule) { _aiOutputVoltage = ParseAiNode("aiOutputVoltage", node, ioModule); _aiOutputArms = ParseAiNode("aiOutputArms", node, ioModule); _aiOutputPower = ParseAiNode("aiOutputPower", node, ioModule); _aiSimVoltage = ParseAiNode("aiSimVoltage", node, ioModule); _aiSimArms = ParseAiNode("aiSimArms", node, ioModule); _aoConstant = ParseAoNode("aoConstant", node, ioModule); _doReset = ParseDoNode("doReset", node, ioModule); _doStatus = ParseDoNode("doStatus", node, ioModule); _diStatus = ParseDiNode("diStatus", node, ioModule); _diAlarm = ParseDiNode("diAlarm", node, ioModule); _doHeatEnable = ParseDoNode("doHeatEnable", node, ioModule); _diHeatEnable = ParseDiNode("diHeatEnable", node, ioModule); _doRelatedEnable = ParseDoNode("doRelatedEnable", node, ioModule); _diCommunicationError = ParseDiNode("diCommunicationError", node, ioModule); _infoText = node.GetAttribute("AlarmText"); _commInfoText = node.GetAttribute("commAlarmText"); _isFloatAioType = !string.IsNullOrEmpty(node.GetAttribute("aioType")) && (node.GetAttribute("aioType") == "float"); // 读取电阻上限设定值 _scResLimitMax = node.GetAttribute("scResLimitMax"); LoadConfig(); } #endregion #region Properties public float OutputVoltageFeedBack => _aiOutputVoltage == null ? 0 : (_isFloatAioType ? _aiOutputVoltage.FloatValue : _aiOutputVoltage.Value); public float OutputArmsFeedBack => _aiOutputArms == null ? 0 : (_isFloatAioType ? _aiOutputArms.FloatValue : _aiOutputArms.Value); public float ResistanceLimitMax => _resLimitMax; public float Resistance => OutputArmsFeedBack == 0 ? 0 : OutputVoltageFeedBack / OutputArmsFeedBack; public bool IsResistanceOutOfRange => IsResistanceTooHigh; public bool IsResistanceTooHigh => Resistance > ResistanceLimitMax; public float OutputPowerFeedBack => _aiOutputPower == null ? 0 : (_isFloatAioType ? _aiOutputPower.FloatValue : _aiOutputPower.Value); public bool StatusFeedBack => _diStatus?.Value ?? false; public float SimVoltageFeedBack => _aiSimVoltage == null ? 0 : (_isFloatAioType ? _aiSimVoltage.FloatValue : _aiSimVoltage.Value); public float SimArmsFeedBack => _aiSimArms == null ? 0 : (_isFloatAioType ? _aiSimArms.FloatValue : _aiSimArms.Value); public bool AlarmFeedBack => _diAlarm?.Value ?? false; public float ConstantSetPoint { get => _aoConstant == null ? 0 : (_isFloatAioType ? _aoConstant.FloatValue : _aoConstant.Value); set { if (_isFloatAioType) { _aoConstant.FloatValue = value; } else { _aoConstant.Value = (short)value; } } } public bool AllHeatEnable => _diHeatEnable?.Value ?? false; private IoPsuData DeviceData { get { _deviceData.IsAlarm = AlarmFeedBack; _deviceData.OutputStatusFeedBack = StatusFeedBack; _deviceData.AllHeatEnable = AllHeatEnable; _deviceData.ConstantSetPoint = ConstantSetPoint; _deviceData.OutputArmsFeedBack = OutputArmsFeedBack; _deviceData.OutputPowerFeedBack = OutputPowerFeedBack; _deviceData.OutputVoltageFeedback = OutputVoltageFeedBack; _deviceData.ResistanceLimitMax = ResistanceLimitMax; _deviceData.Resistance = Resistance; _deviceData.IsResistanceOutOfRange = IsResistanceOutOfRange; _deviceData.IsResistanceTooHigh = IsResistanceTooHigh; return _deviceData; } } public Func FuncCheckInterLock { get; set; } #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}.OutputVoltageFeedBack", () => OutputVoltageFeedBack); DATA.Subscribe($"{Module}.{Name}.OutputArmsFeedBack", () => OutputArmsFeedBack); DATA.Subscribe($"{Module}.{Name}.ResistanceLimitMax", () => ResistanceLimitMax); DATA.Subscribe($"{Module}.{Name}.Resistance", () => Resistance); DATA.Subscribe($"{Module}.{Name}.IsResistanceOutOfRange", () => IsResistanceOutOfRange); DATA.Subscribe($"{Module}.{Name}.IsResistanceTooHigh", () => IsResistanceTooHigh); DATA.Subscribe($"{Module}.{Name}.OutputPowerFeedBack", () => OutputPowerFeedBack); DATA.Subscribe($"{Module}.{Name}.StatusFeedBack", () => StatusFeedBack); DATA.Subscribe($"{Module}.{Name}.SimVoltageFeedBack", () => SimVoltageFeedBack); DATA.Subscribe($"{Module}.{Name}.SimArmsFeedBack", () => SimArmsFeedBack); DATA.Subscribe($"{Module}.{Name}.ConstantSetPoint", () => ConstantSetPoint); DATA.Subscribe($"{Module}.{Name}.AlarmFeedBack", () => AlarmFeedBack); DATA.Subscribe($"{Module}.{Name}.AllHeatEnable", () => AllHeatEnable); DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData); OP.Subscribe($"{Module}.{Name}.SetHeadHeaterEnable", (function, args) => { var isTrue = Convert.ToBoolean(args[0]); SetHeadHeaterEnable(isTrue, out _); return true; }); OP.Subscribe($"{Module}.{Name}.SetPSUEnable", (function, args) => { var isTrue = Convert.ToBoolean(args[0]); SetPSUEnable(isTrue, out _); return true; }); OP.Subscribe($"{Module}.{Name}.SetPSUReset", (function, args) => { var isTrue = Convert.ToBoolean(args[0]); SetPSUReset(isTrue, out _); return true; }); return true; } public bool SetPSUEnable(bool setValue, out string reason) { if (!_doStatus.Check(setValue, out reason)) { EV.PostWarningLog(Module, reason); return false; } if (!_doRelatedEnable.Check(setValue, out reason)) { EV.PostWarningLog(Module, reason); return false; } if (!_doStatus.SetValue(setValue, out reason)) { EV.PostWarningLog(Module, reason); return false; } if (!_doRelatedEnable.SetValue(setValue, out reason)) { EV.PostWarningLog(Module, reason); return false; } return true; } public bool SetHeadHeaterEnable(bool setValue, out string reason) { reason = ""; if (FuncCheckInterLock != null) { if (!FuncCheckInterLock(setValue)) { EV.PostInfoLog(Module, $"Set PSU Enable fialed for Interlock!"); return false; } } if (!_doHeatEnable.Check(setValue, out reason)) { EV.PostWarningLog(Module, reason); return false; } if (!_doHeatEnable.SetValue(setValue, out reason)) { EV.PostWarningLog(Module, reason); return false; } return true; } public bool SetPSUReset(bool setValue, out string reason) { if (!_doReset.Check(setValue, out reason)) { EV.PostWarningLog(Module, reason); return false; } if (!_doReset.SetValue(setValue, out reason)) { EV.PostWarningLog(Module, reason); return false; } _timer.Start(1000); return true; } public bool CheckPSUEnable() { return _doStatus.Value; } public void Terminate() { } protected override void HandleMonitor() { try { MonitorEnableTimer(); 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() { _alarmTrig.RST = true; _commAlarmTrig.RST = true; _trigVoltage.RST = true; _trigCurrent.RST = true; } 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}"); } } private void MonitorEnableTimer() { if (Name == "PSU2") { _enableTrig.CLK = !_diHeatEnable.Value; if (_enableTrig.Q) { SC.SetItemValue($"PM.{Module}.OpenLidCountDownTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); } _enableTrig2.CLK = _diHeatEnable.Value; if (_enableTrig2.Q) { SC.SetItemValue($"PM.{Module}.OpenLidCountDownTime", ""); } } } 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 } }