290 lines
8.8 KiB
C#
290 lines
8.8 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;
|
|
|
|
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 / 10);
|
|
DATA.Subscribe($"{Module}.{Name}.BatteryVoltage", () => BatteryVoltage / 10);
|
|
DATA.Subscribe($"{Module}.{Name}.BatteryRemainsTime", () => BatteryRemainsTime / 10);
|
|
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 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 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;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
}
|