Sic.Framework-Nanjing-Baishi/MECF.Framework.RT.Equipment.../HardwareUnits/UPS/UPSBase.cs

298 lines
8.9 KiB
C#

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;
using Aitex.Core.Backend;
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<HandlerBase> _lstHandler = new LinkedList<HandlerBase>();
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 bool UPSPowerAlarm { get; set; }
public bool UPSLowerBatteryAlarm { get; set; }
public Dictionary<string, string> Oids = new Dictionary<string, string>();
#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<bool>($"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<int>($"PM.{Module}.{Name}.DeviceAddress");
_enableLog = SC.GetValue<bool>($"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()
{
DATA.Subscribe($"{Module}.{Name}.InputVoltage", () => InputVoltage);
DATA.Subscribe($"{Module}.{Name}.BatteryVoltage", () => BatteryVoltage);
DATA.Subscribe($"{Module}.{Name}.BatteryRemainsTime", () => BatteryRemainsTime);
DATA.Subscribe($"{Module}.{Name}.BatteryUnderResidue", () => BatteryUnderResidue);
}
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 CheckBatteryUnderResidue()
{
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 virtual void SetBatteryUnderResidue(int data)
{
BatteryUnderResidue = data;
CheckBatteryUnderResidue();
}
public virtual void ParseOutputSource(string value)
{
return;
}
public virtual void ParseBatteryRemainsTime(string value)
{
return;
}
public virtual void ParseBatteryVoltage(string value)
{
return;
}
public virtual void ParseInputVoltage(string value)
{
return;
}
#endregion
}
}