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

356 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<HandlerBase> _lstHandler = new LinkedList<HandlerBase>();
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<string, string> Oids = new Dictionary<string, string>()
{
{ "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<int>($"PM.{Module}.{Name}.DeviceAddress");
_enableLog = SC.GetValue<bool>($"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<bool>($"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();
}
}
}