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; using System.Security.Cryptography; using System.Timers; namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.UPS { public class UPSBase :BaseDevice, IConnection, IDevice { #region Properties private UPSConnection _connection; //ITAUPSConnection 和 UPS类 是相互绑定的,既然这样应该写到一起才对,自上而下原则 private bool _activeMonitorStatus; 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 LinkedList _lstHandler = new LinkedList(); private object _locker = new object(); private bool _enableLog = true; private string _scRoot; private string portName; public bool IsReceive = false; public int _connectTimes { get; set; } public string Address { get; set; } public bool IsConnected { get { return _connection != null && _connection.IsConnected; } } public float InputVoltage { get; set; } public float BatteryVoltage { get; set; } public float BatteryRemainsTime { get; set; } public float BatteryUnderResidue { get; set; } public Dictionary Oids = new Dictionary(); #endregion #region Constructors public UPSBase(string module, string name, string scRoot) : base(module, name, name, name) { _scRoot = scRoot; _activeMonitorStatus = true; } ~UPSBase() { _connection.Disconnect(); } #endregion #region Function public bool Connect() { return true; } public bool Disconnect() { _connection.Disconnect(); return true; } 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 Terminate() { _connection.Disconnect(); } 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 UPSConnection(portName); _connection.EnableLog(_enableLog); _thread = new PeriodicJob(500, OnTimer, $"{Module}.{Name} MonitorHandler", true); InitData(); ConnectionManager.Instance.Subscribe($"{Name}", this); return true; } private void InitData() { } 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); //执行成功_connection会将IsReceive置为true } } } 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; } public void QueryOids() { IsReceive = false; //UPS二代 foreach (var oid in Oids) { if (oid.Key != null) { _lstHandler.AddLast(new UPSGetHandler(this, oid.Key, "Get", oid.Value)); } } } 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;//不满足报警条件时自动复位,准备下次报警操作 } #endregion } }