using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Device.Devices; using Aitex.Core.RT.Event; using Aitex.Core.RT.IOCore; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.Util; using MECF.Framework.Common.Communications; using System; using System.Collections.Generic; using System.Linq; using System.Net.NetworkInformation; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.UPS { public class ITAUPS : BaseDevice, IConnection, IDevice { private ITAUPSConnection _connection; private bool _activeMonitorStatus; private int _errorCode; private R_TRIG _trigRetryConnect = new R_TRIG();//断开上升沿 private R_TRIG _trigReconnection = new R_TRIG();//重连上升沿 private R_TRIG _trigPowerLow = new R_TRIG();//缺电上升沿 private PeriodicJob _thread; private int tempCount = 1; private LinkedList _lstHandler = new LinkedList(); private object _locker = new object(); private bool _enableLog = true; private string _scRoot; private string portName; private string _systemStatus; private float _inputVoltage; private float _batteryVoltage; private float _batteryRemainsTime; private float _batteryUnderResidue; public string SystemStatus { get; set; } public float InputVoltage { get; set; } public float BatteryVoltage { get; set; } public float BatteryRemainsTime { get; set; } public float BatteryUnderResidue { get; set; } public bool UPSPowerAlarm { get; set; } public bool UPSLowerBatteryAlarm { get; set; } public int ErrorNum { get; set; } = 0; public string Address { get; set; } public bool IsConnected { get { return _connection != null && _connection.IsConnected; } } public bool Connect() { return true; } public bool Disconnect() { _connection.Disconnect(); return true; } public ITAUPS(string module, string name, string scRoot, DOAccessor BatteryLowVoltage, DOAccessor UpsEnable) : base(module, name, name, name) { _scRoot = scRoot; _activeMonitorStatus = true; } ~ITAUPS() { _connection.Disconnect(); } public bool IsReceive = false; public void QueryOids() { IsReceive = false; //UPS二代 foreach (var oid in Oids) { if (oid.Key != null) { _lstHandler.AddLast(new ITAUPSGetHandler(this, oid.Key, "Get", oid.Value)); } } //if (SystemStatus == "Critical") //{ // _lstHandler.AddLast(new ITAUPSGetBulkHandler(this, "AlarmTrap", "GetBulk", "1.3.6.1.4.1.13400.2.54.3.1.6")); //} } public Dictionary Oids = new Dictionary() { { "SystemStatus",".1.3.6.1.4.1.13400.2.54.2.1.1.0"},//在设备上测试了,返回信息感觉没啥用 { "InputVoltage",".1.3.6.1.4.1.13400.2.54.2.2.1.0"},//输入电压,输入电压为0说明使用UPS,要除10 { "BatteryVoltage",".1.3.6.1.4.1.13400.2.54.2.5.1.0"},//电池当前电压,要除10 { "BatteryRemainsTime",".1.3.6.1.4.1.13400.2.54.2.5.7.0"},//剩余时间,要除10 { "upsOutputSource",".1.3.6.1.4.1.13400.2.54.2.1.2.0"},//当前输出源 { "BatteryUnderResidue",".1.3.6.1.4.1.13400.2.54.2.5.10.0"}//电量剩余百分比,直接用数值 //除10的数据四舍五入 }; public void ResetDevice() { } public void QueryError() { EV.PostInfoLog(Module, "Query error"); } public bool Initialize() { //_connection的底层写死使用161端口号 portName = SC.GetStringValue($"PM.{Module}.{Name}.Address"); Address = portName; int address = SC.GetValue($"PM.{Module}.{Name}.DeviceAddress"); _enableLog = SC.GetValue($"PM.{Module}.{Name}.EnableLogMessage"); _connection = new ITAUPSConnection(portName); _connection.EnableLog(_enableLog); _thread = new PeriodicJob(500, OnTimer, $"{Module}.{Name} MonitorHandler", true); DATA.Subscribe($"{Module}.{Name}.InputVoltage", () => InputVoltage / 10); DATA.Subscribe($"{Module}.{Name}.BatteryVoltage", () => BatteryVoltage / 10); DATA.Subscribe($"{Module}.{Name}.BatteryRemainsTime", () => BatteryRemainsTime / 10); DATA.Subscribe($"{Module}.{Name}.BatteryUnderResidue", () => BatteryUnderResidue); //DATA.Subscribe($"{Module}.{Name}.UtilityPowerFailure", () => _trigUtilityPowerFailure.CLK); //DATA.Subscribe($"{Module}.{Name}.BatteryUnderVoltage", () => _trigBatteryUnderVoltage.CLK); ConnectionManager.Instance.Subscribe($"{Name}", this); return true; } public int _connectTimes { get; set; } bool CanConnect() { IPAddress ip = IPAddress.Parse(portName); Ping ping = new Ping(); try { PingReply reply = ping.Send(ip); return (reply.Status == IPStatus.Success); } catch (PingException) { return false; } } private bool OnTimer() { try { _connection.MonitorTimeout(); if (!_connection.IsConnected || _connection.IsCommunicationError)//测试发现这个条件永远不会满足 { //lock (_locker) //{ // _lstHandler.Clear(); //} //if (!_connection.Connect()) //{ // _trigRetryConnect.CLK = !_connection.IsConnected; // if (_trigRetryConnect.Q) // { // EV.PostAlarmLog(Module, $"Can not connect with {_connection.Address}, {Module}.{Name}"); // } //} //else //{ // _trigRetryConnect.RST = true; // EV.PostInfoLog(Module, $"Connected with {_connection.Address}, {Module}.{Name}"); //} } HandlerBase handler = null; lock (_locker) { if (_lstHandler.Count == 0) QueryOids(); if (_lstHandler.Count > 0 && !_connection.IsBusy) { handler = _lstHandler.First.Value; _lstHandler.RemoveFirst(); if (handler != null) { _connection.Execute(handler); } } } if (!IsReceive) //单纯断联重连判断 { System.Threading.Thread.Sleep(3000);//不加延时第一次启动时未连接,可能不报警 _trigRetryConnect.CLK = true;//断联 if (_trigRetryConnect.Q) { InputVoltage = 0; BatteryUnderResidue = 0; BatteryVoltage = 0; BatteryRemainsTime = 0; EV.PostAlarmLog(Module, $"Can not connect with {_connection.Address}, {Module}.{Name}"); } _trigReconnection.RST = true;//复位重连 } else { _trigReconnection.CLK = true;//重连 if (_trigReconnection.Q) { EV.PostInfoLog(Module, $"Connection with {_connection.Address}, {Module}.{Name}"); } _trigRetryConnect.RST = true;//复位断联 } } catch (Exception ex) { LOG.Write(ex); } return true; } internal void NoteError() { } public void Monitor() { } public void Reset() { _connectTimes = 0; _connection.SetCommunicationError(false, ""); _enableLog = SC.GetValue($"PM.{Module}.{Name}.EnableLogMessage"); _trigRetryConnect.RST = true; _trigReconnection.RST = true; } public void PraseSystemStatus(string value) { if (value == "0") { SystemStatus = "Normal"; } else if (value == "1") { SystemStatus = "Warning"; } else if (value == "2") { if (UPSLowerBatteryAlarm) { SystemStatus = "LowerBattery"; } else if (UPSPowerAlarm) { SystemStatus = "Power"; } else { SystemStatus = "Critical"; } } } public void ParseOutputSource(string value) { if (value == "0") //UPS No Output { UPSPowerAlarm = true; } else if (value == "1") // UPS On Main { UPSPowerAlarm = false; } else if (value == "2") //UPS On Battery { UPSPowerAlarm = true; } } public void SetBatteryUnderResidue(int data) { BatteryUnderResidue = data; //有数据时判断剩余电量百分比 if ( (30 >= BatteryUnderResidue) && (BatteryUnderResidue >= 20) || (10 >= BatteryUnderResidue) && (BatteryUnderResidue >= 1)) { _trigPowerLow.CLK = true; if (_trigPowerLow.Q) EV.PostAlarmLog(Module, $"Attention {Module}.{Name} Is Power Low, Battery Under Residue {BatteryUnderResidue}%"); } else _trigPowerLow.RST = true;//不满足报警条件时自动复位,准备下次报警操作 } public void UtilityPowerAlarm(bool alarm) { UPSPowerAlarm = alarm; } public void BatteryUnderVoltage(bool alarm) { UPSLowerBatteryAlarm = alarm; } public void Terminate() { _connection.Disconnect(); } } }