using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Fsm; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using CyberX8_RT.Devices.Facilities; using CyberX8_RT.Devices.Reservoir; using CyberX8_RT.Modules; using CyberX8_RT.Modules.Reservoir; using MECF.Framework.Common.CommonData.TemperatureControl; using MECF.Framework.Common.Device.TemperatureController; using MECF.Framework.Common.Persistent.Temperature; using MECF.Framework.Common.ToolLayout; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace CyberX8_RT.Devices.Temperature { public class TemperatureController : BaseDevice, IDevice { #region 常量 private const string STRATUS = "Stratus"; private const string TARGET_TEMPERATURE = "TargetTemperature"; private const string RESERVIOR_TEMPERATURE = "ReserviorTemperature"; private const string HEAT_EXCHANGER_TEMPERATURE = "HeatExchangerTemperature"; private const string ALARM = "Alarm"; private const string OFFSET = "Offset"; private const string CONTROL_OPERATION_MODEL="ControlOperationModel"; private const string PB_RANGE = "PBRange"; private const string ARW_RANGE = "ARWRange"; private const string I_CONSTANT = "IConstant"; private const string D_CONSTANT = "DConstant"; private const string HEATING_POWER_UPPER_LIMIT = "HeatingPowerUpperLimit"; private const string COOLING_POWER_UPPER_LIMIT="CoolingPowerUpperLimit"; private const string OUT_PUT_RATIO="OutputRatio"; private const string TEMPERATURE_DATA = "TemperatureData"; private const string IS_CONNECTED = "IsConnected"; private const int ENABLE = 5; private const int DISABLE = 0; private const string PERSISTENT_VALUE = "PersistentValue"; #endregion #region 内部变量 private byte _address; private TemperatureControllerData _temperatureData = new TemperatureControllerData(); private PeriodicJob _periodicJob = null; private bool _startMonitorData = false; private bool _readAlarm = false; private double _temeratureDeltaLimit = SC.GetValue("System.TemeratureDelatLimit"); private bool _isApplying = false; //用于判断是否在apply中 private bool _isAlarmErrorLoged = false; //用于判断是否打印过alarm触发 private bool _isAlarmWarningLoged = false; //用于判断是否打印过alarm warning触发 private bool _isTCConnect = false; /// /// TC 持久性数值对象 /// private TCPersistentValue _tCPersistentValue; private Dictionary _errorMessage = new Dictionary { { 3, " HighTempCutoff Property" }, { 2, " LowTempCutoff Property" }, { 1, " Fan Property" }, { 0, " OutputFailure Property" }, { 7, " TempLimitWarn Property" }, { 6, " RemoteOff Property" }, { 5, " Thermostat Property" }, { 4, " PowerFailure Property" }, { 11, " ExtSensorFailure Property" }, { 10, " IntSensorFailure Property" }, { 9, " AutoTuning Property" }, { 8, " Leak Property" }}; #endregion #region 属性 /// /// 连接状态 /// public bool IsConnected { get { return TemperatureConfigManager.Instance.GetDeviceConnect(Module); } } /// /// 数据 /// public TemperatureControllerData TemperatureData { get { return _temperatureData; } } #endregion /// /// 构造函数 /// ; /// public TemperatureController(string moduleName) : base(moduleName, moduleName, moduleName, moduleName) { SubscribeValueAction(); InitializeData(); InitializeOperation(); _periodicJob = new PeriodicJob(5000, OnTimer, $"{moduleName}_reader"); _temperatureData.Name = $"{moduleName}"; _isAlarmErrorLoged = false; _isAlarmWarningLoged = false; } /// /// 初始化 /// /// public bool Initialize() { TemperatureConfigManager.Instance.InitialDevice(Module); _periodicJob.Start(); return true; } /// /// 初始化操作 /// private void InitializeOperation() { OP.Subscribe($"{Module}.Apply", SetTargetTemperatureOperation); OP.Subscribe($"{Module}.Enable", EnableOperation); OP.Subscribe($"{Module}.Disable", DisableOperation); } /// /// 监控TC电源 /// /// private bool CheckTCIsConnect() { return TemperatureConfigManager.Instance.GetDevicePowerConnect(Module); } /// /// 应用 /// /// /// /// public bool SetTargetTemperatureOperation(string cmd,object[] param) { _isApplying = true; //表示正在调温 _temperatureData.HeatExchangerSeries = new List(); _temperatureData.ReserviorSeries = new List(); if (param.Length == 3 && double.TryParse(param[0].ToString(), out double targetTemperature) && double.TryParse(param[1].ToString(), out double targetTemperatureLowLimit) && double.TryParse(param[2].ToString(), out double targetTemperatureHighLimit)) { TemperatureConfigManager.Instance.SetTargetTemperature(Module, _address, targetTemperature); if (TemperatureData.ControlOperationModel == ENABLE) { _startMonitorData = true; } //将前端输入的数据存入持久化文件 TCPersistentManager.Instance.UpdateTemperatureValue(Module, targetTemperature, targetTemperatureLowLimit, targetTemperatureHighLimit); return true; } if (param.Length == 1 && double.TryParse(param[0].ToString(), out double targetTemperature1)) { TemperatureConfigManager.Instance.SetTargetTemperature(Module, _address, targetTemperature1); if (TemperatureData.ControlOperationModel == ENABLE) { _startMonitorData = true; } //将前端输入的数据存入持久化文件 TCPersistentManager.Instance.UpdateTemperatureValue(Module, targetTemperature1, 0, 0); // 0 0是上下限 return true; } else { LOG.WriteLog(eEvent.INFO_TEMPERATURE, Module, $"{param[0]} is invalid"); return false; } } /// /// 启用 /// /// /// /// public bool EnableOperation(string cmd, object[] param) { if (!JudgeReservoirCondition()) { return false; } if (!CheckTCIsConnect()) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"TC is not connect"); return false ; } //校验TC状态 if (TemperatureData.Alarm != null && TemperatureData.Alarm.Contains("1")) { string errorItemString = TemperatureData.Alarm.Substring(0, 11) + TemperatureData.Alarm.Substring(13, 1) + TemperatureData.Alarm.Substring(15); if (errorItemString.Contains("1")) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"TC is in error state"); return false; } } TemperatureData.ControlOperationModel = ENABLE; bool result= TemperatureConfigManager.Instance.EnableControl(Module, _address,ENABLE); if (result) { LOG.WriteLog(eEvent.INFO_TEMPERATURE, Module, "control operation set enable"); _startMonitorData = true; } return result; } /// /// 禁用 /// /// /// /// public bool DisableOperation(string cmd, object[] param) { _isApplying = false; TemperatureData.ControlOperationModel = DISABLE; bool result= TemperatureConfigManager.Instance.DisableController(Module, _address,DISABLE); if(result) { if (result) { ReservoirPostError(); LOG.WriteLog(eEvent.INFO_TEMPERATURE, Module, "control operation set disable"); } _startMonitorData = false; if(TemperatureData.ReserviorSeries != null && TemperatureData.HeatExchangerSeries != null) { _temperatureData.HeatExchangerSeries.Clear(); _temperatureData.ReserviorSeries.Clear(); } } return result; } /// /// Reservoir通知进入错误状态 /// private void ReservoirPostError() { string reservoir = ReservoirItemManager.Instance.GetReservoirByTC(Module); IModuleEntity reservoirEntity = Singleton.Instance.GetModule(reservoir); if (reservoirEntity != null) { if (!reservoirEntity.IsError && !reservoirEntity.IsDisable) { reservoirEntity.PostMsg(ReservoirMsg.Error); LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"TC is abnormal,notify Reservoir {reservoir} enter error"); } } } /// /// 访问数据变更 /// private void SubscribeValueAction() { TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, TARGET_TEMPERATURE, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, RESERVIOR_TEMPERATURE, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, HEAT_EXCHANGER_TEMPERATURE, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, ALARM, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, OFFSET, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, CONTROL_OPERATION_MODEL, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, PB_RANGE, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, ARW_RANGE, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, I_CONSTANT, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, D_CONSTANT, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, OUT_PUT_RATIO, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, HEATING_POWER_UPPER_LIMIT, UpdateVariableValue); TemperatureConfigManager.Instance.SubscribeModuleVariable(Module, COOLING_POWER_UPPER_LIMIT, UpdateVariableValue); } /// /// 初始化数据 /// private void InitializeData() { _address= TemperatureConfigManager.Instance.GetAddress(Module); _tCPersistentValue = TCPersistentManager.Instance.GetTCPersistentValue(Module); DATA.Subscribe($"{Module}.{TEMPERATURE_DATA}", () => _temperatureData, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{IS_CONNECTED}", () => _isTCConnect, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _tCPersistentValue, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.TargetTemperature", () => _temperatureData.TargetTemperature, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.Status", () => _temperatureData.Status, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.Alarm", () => _temperatureData.Alarm, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.ReserviorTemperature", () => _temperatureData.ReserviorTemperature, SubscriptionAttribute.FLAG.IgnoreSaveDB); DATA.Subscribe($"{Module}.HeatExchangerTemperature", () => _temperatureData.HeatExchangerTemperature, SubscriptionAttribute.FLAG.IgnoreSaveDB); } /// /// 更新变量数值 /// /// /// private void UpdateVariableValue(string variable, object value) { if(!TemperatureData.IsInitialized) { TemperatureData.IsInitialized = true; TemperatureConfigManager.Instance.ReadControlOperationModel(Module, _address); TemperatureConfigManager.Instance.ReadTargetTemperature(Module, _address); } PropertyInfo property = TemperatureData.GetType().GetProperty(variable); if (property != null) { property.SetValue(TemperatureData, value); } //判断temperatureReached AtTemperatureRange double atTemperatureRange = SC.GetValue("System.AtTemperatureRange"); atTemperatureRange = atTemperatureRange == 0 ? 0.1 : atTemperatureRange; if (Math.Abs(TemperatureData.ReserviorTemperature - TemperatureData.TargetTemperature) < atTemperatureRange) { TemperatureData.TemperatureReached = true; //_startMonitorData = false; } else { TemperatureData.TemperatureReached = false; } //判断deltaexceed if (Math.Abs(TemperatureData.ReserviorTemperature - TemperatureData.ReserviorTemperature) > _temeratureDeltaLimit) { TemperatureData.DeltaExceed = true; } else { TemperatureData.DeltaExceed = false; } if (_startMonitorData && TemperatureData.ReserviorSeries!=null && TemperatureData.HeatExchangerSeries!=null) { if (TemperatureData.ReserviorSeries.Count == 20) { TemperatureData.ReserviorSeries.RemoveAt(0); for (int i = 1; i < TemperatureData.ReserviorSeries.Count; i++) { TemperatureData.ReserviorSeries[i - 1] = TemperatureData.ReserviorSeries[i]; } TemperatureData.ReserviorSeries.Add(TemperatureData.ReserviorTemperature); } else { TemperatureData.ReserviorSeries.Add(TemperatureData.ReserviorTemperature); } if (TemperatureData.HeatExchangerSeries.Count == 20) { TemperatureData.HeatExchangerSeries.RemoveAt(0); for (int i = 1; i < TemperatureData.HeatExchangerSeries.Count; i++) { TemperatureData.HeatExchangerSeries[i - 1] = TemperatureData.HeatExchangerSeries[i]; } TemperatureData.HeatExchangerSeries.Add(TemperatureData.HeatExchangerTemperature); } else { TemperatureData.HeatExchangerSeries.Add(TemperatureData.HeatExchangerTemperature); } } } /// /// 定时器 /// /// private bool OnTimer() { _isTCConnect = CheckTCIsConnect(); if (!_isTCConnect) { string reservoir = ReservoirItemManager.Instance.GetReservoirByTC(Module); if (!string.IsNullOrEmpty(reservoir)) { ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(reservoir); if(reservoirEntity != null && !reservoirEntity.IsError) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"{Module} is disconnect,releate reservoir into error"); reservoirEntity.PostMsg(ReservoirMsg.Error); } } } TemperatureConfigManager.Instance.ReadReserviorExtendSensorTemperature(Module, _address); TemperatureConfigManager.Instance.ReadHeatExchangerInternelSensorTemperature(Module, _address); if (_readAlarm) { TemperatureConfigManager.Instance.ReadAlarmStatus(Module, _address); _readAlarm= false; } else { _readAlarm = true; } double rampStepSize = SC.GetValue("System.RampStepSize"); rampStepSize = rampStepSize == 0 ? 0.11 : rampStepSize; if (TemperatureData.TargetTemperature - TemperatureData.ReserviorTemperature > rampStepSize + 0.1 && _isApplying == true) { TemperatureData.Status = "RampingUp"; } else if(TemperatureData.TargetTemperature - TemperatureData.ReserviorTemperature < -rampStepSize - 0.1 && _isApplying == true) { TemperatureData.Status = "RampingDown"; } else if (TemperatureData.TargetTemperature - TemperatureData.ReserviorTemperature <= rampStepSize + 0.1 && TemperatureData.TargetTemperature - TemperatureData.ReserviorTemperature >= - rampStepSize - 0.1 && _isApplying == true) { TemperatureData.Status = "Maintaining"; } else if(TemperatureData.Alarm!=null&&TemperatureData.Alarm.Contains("1")) { string errorItemString = TemperatureData.Alarm.Substring(0, 11) + TemperatureData.Alarm.Substring(13, 1) + TemperatureData.Alarm.Substring(15); if (TemperatureData.Alarm.Substring(12,1) == "1" || TemperatureData.Alarm.Substring(14, 1)== "1") { TemperatureData.Status = "Warning"; if (!_isAlarmWarningLoged) { LOG.WriteLog(eEvent.WARN_TEMPERATURE, Module, $"{Module} Warning is activate"); _isAlarmWarningLoged = true; } } if(errorItemString.Contains("1")) { if (!_isAlarmErrorLoged) { string errormessage = ""; string[] strAry = TemperatureData.Alarm.ToString().Split('-'); if (strAry.Length > 0) { for (int i = 0; i < strAry.Length; i++) { if (strAry[i] == "1") { errormessage += _errorMessage[i]; } } } LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"{Module} {errormessage} is activate"); ReservoirPostError();//将对应的reservoir切成error _isAlarmErrorLoged = true; } } } else { TemperatureData.Status = "Normal"; _isAlarmErrorLoged = false; //用于控制触发alarm要不要打印error日志 _isAlarmWarningLoged = false; //用于控制触发alarm要不要打印error日志 } if (TemperatureData.ControlOperationModel != 0) { if (!JudgeReservoirCondition()) { DisableOperation("", null); } } if (TemperatureData.Alarm!=null && TemperatureData.Alarm.Contains("1") && _isApplying == true) { string errorItemString = TemperatureData.Alarm.Substring(0, 11) + TemperatureData.Alarm.Substring(13, 1) + TemperatureData.Alarm.Substring(15); if (errorItemString.Contains("1")) { DisableOperation("", null); string errormessage = ""; string[] strAry = errorItemString.ToString().Split('-'); if (strAry.Length > 0) { for (int i = 0; i < strAry.Length; i++) { if (strAry[i] == "1") { errormessage += _errorMessage[i]; } } } ReservoirPostError();//将对应的reservoir切成error LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"{Module} {errormessage} is activate"); _isApplying = false; } } return true; } /// /// 检验Reservoir条件 /// private bool JudgeReservoirCondition() { SystemFacilities systemFacilities = DEVICE.GetDevice("System.Facilities"); if (systemFacilities == null) { return false; } //冷却水没开 if (!systemFacilities.HouseChilledWaterEnable) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, "Facilities HouseChilledWaterEnable is off"); return false; } var houseChilledResult = systemFacilities.CheckHouseChilledWaterResult(); if (!houseChilledResult.result) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, houseChilledResult.reason); return false; } string reservoir = ReservoirItemManager.Instance.GetReservoirByTC(Module); if (string.IsNullOrEmpty(reservoir)) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"{Module} reservoir is empty"); return false; } ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(reservoir); if (reservoirItem.SubType == STRATUS) { StandardHotReservoirDevice reservoirDevice = DEVICE.GetDevice(reservoir); if (reservoirDevice == null) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"{Module} reservoir is null"); return false; } bool result= reservoirDevice.ReservoirData.HedFlow > 0; if (!result) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"{Module} reservoir HED flow is 0"); } return result; } else { CompactMembranReservoirDevice reservoirDevice = DEVICE.GetDevice(reservoir); if (reservoirDevice == null) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"{Module} reservoir is null"); return false; } bool result = reservoirDevice.ReservoirData.CAHedFlow > 0; if (!result) { LOG.WriteLog(eEvent.ERR_TEMPERATURE, Module, $"{Module} reservoir CA HED flow is 0"); } return result; } } /// /// 设置Enable并设置温度 /// /// /// public bool SetEnableTargetTemperature(double targetTemperature) { TemperatureConfigManager.Instance.SetTargetTemperature(Module, _address, targetTemperature); if (_temperatureData.ControlOperationModel == DISABLE) { EnableOperation("", null); } return true; } /// /// 监控 /// public void Monitor() { } public void Reset() { } public void Terminate() { } } }