2024-11-26 13:45:28 +08:00
|
|
|
|
using Abp.Dependency;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using ToolLibrary.LogHelper;
|
|
|
|
|
using YunDa.ISAS.Redis.Repositories;
|
|
|
|
|
using YunDa.SOMS.Commdb.Models;
|
|
|
|
|
using Yunda.SOMS.DataMonitoringServer.FTPHandle;
|
|
|
|
|
using Yunda.SOMS.DataMonitoringServer.TcpSocket.Server;
|
|
|
|
|
using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto;
|
|
|
|
|
using Yunda.ISAS.DataMonitoringServer.DataAnalysis;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using StackExchange.Redis;
|
|
|
|
|
using Yunda.ISAS.DataMonitoringServer.DataCenter;
|
2024-12-03 16:25:07 +08:00
|
|
|
|
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
|
2024-12-05 11:34:06 +08:00
|
|
|
|
using System.Windows.Interop;
|
|
|
|
|
using FluentFTP;
|
2024-12-06 16:32:13 +08:00
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using Yunda.SOMS.DataMonitoringServer.SQLiteData;
|
|
|
|
|
using Abp;
|
|
|
|
|
using YunDa.SOMS.DataTransferObject.CommonDto;
|
2024-11-26 13:45:28 +08:00
|
|
|
|
|
|
|
|
|
namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
|
|
|
|
|
{
|
|
|
|
|
public class ProtectionDeviceRunInfoHandle : ISingletonDependency
|
|
|
|
|
{
|
|
|
|
|
WebApiRequest _webApiRequest;
|
|
|
|
|
FtpFile _ftpFile;
|
|
|
|
|
DotNettyTcpServer _dotNettyTcpServer;
|
|
|
|
|
private readonly RedisDataRepository _redisDataRepository;
|
2024-12-06 16:50:46 +08:00
|
|
|
|
private readonly IRedisRepository<DeviceBoardStates, string> _deviceBoardStatesRedis;
|
2024-11-26 13:45:28 +08:00
|
|
|
|
public ProtectionDeviceRunInfoHandle(
|
|
|
|
|
FtpFile ftpFile,
|
2024-12-06 16:32:13 +08:00
|
|
|
|
DotNettyTcpServer dotNettyTcpServer,
|
2024-12-06 16:50:46 +08:00
|
|
|
|
IRedisRepository<DeviceBoardStates, string> redisRepository,
|
2024-12-06 16:32:13 +08:00
|
|
|
|
WebApiRequest webApiRequest,
|
2024-11-26 13:45:28 +08:00
|
|
|
|
RedisDataRepository redisDataRepository
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
_webApiRequest = webApiRequest;
|
|
|
|
|
_ftpFile = ftpFile;
|
|
|
|
|
_dotNettyTcpServer = dotNettyTcpServer;
|
|
|
|
|
_redisDataRepository = redisDataRepository;
|
|
|
|
|
_dotNettyTcpServer.MessageReceived += OnMessageReceived; // 订阅事件
|
2024-12-06 16:50:46 +08:00
|
|
|
|
_deviceBoardStatesRedis = redisRepository;
|
2024-11-26 13:45:28 +08:00
|
|
|
|
}
|
2024-12-06 16:32:13 +08:00
|
|
|
|
//Dictionary<byte, DeviceInfo> _deviceRunStates = new Dictionary<byte, DeviceInfo>();
|
|
|
|
|
//private ConcurrentDictionary<byte, int> _communicationStateCounts = new();
|
|
|
|
|
|
2024-11-26 13:45:28 +08:00
|
|
|
|
int _commCount = 0;
|
|
|
|
|
private void OnMessageReceived(byte address, byte[] message, byte functionType)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (functionType == 6) //通信状态
|
|
|
|
|
{
|
2024-12-06 16:32:13 +08:00
|
|
|
|
var device = ProtectionDeviceDataCenter._devices.FirstOrDefault(t => t.DeviceAddr == address);
|
|
|
|
|
if (device != null)
|
2024-11-26 13:45:28 +08:00
|
|
|
|
{
|
2024-12-06 16:32:13 +08:00
|
|
|
|
UpdateDeviceBoardState(address, message, device);
|
|
|
|
|
if (_commCount == 0)
|
2024-11-26 13:45:28 +08:00
|
|
|
|
{
|
2024-12-03 16:25:07 +08:00
|
|
|
|
|
2024-12-06 16:32:13 +08:00
|
|
|
|
SendEquipmentInfoRemainingLifeAssessment(device);
|
2024-12-05 11:34:06 +08:00
|
|
|
|
var bytes = _ftpFile.GetFileFromFtpToMem(device.GatewayIP1, "/nor/root/status/", "status.txt");
|
2024-12-06 16:32:13 +08:00
|
|
|
|
if (bytes != null)
|
2024-12-03 16:25:07 +08:00
|
|
|
|
{
|
2024-12-05 11:34:06 +08:00
|
|
|
|
var data = ParseDeviceStatusFromBytes(bytes);
|
2024-12-06 16:32:13 +08:00
|
|
|
|
if (data != null)
|
2024-12-05 11:34:06 +08:00
|
|
|
|
{
|
|
|
|
|
data.ProtectionDeviceId = device.ProtectionDeviceId;
|
|
|
|
|
data.EquipmentInfoId = device.EquipmentInfoId;
|
|
|
|
|
data.EquipmentInfoName = device.EquipmentInfoName;
|
|
|
|
|
string redisKey = _redisDataRepository.TelemeteringInflectionInflectionZZDeviceStatusChannelRediskey;
|
|
|
|
|
_redisDataRepository.DeviceStatusRedis.PublishAsync(redisKey, data);
|
|
|
|
|
}
|
2024-12-03 16:25:07 +08:00
|
|
|
|
}
|
2024-11-26 13:45:28 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-12-06 16:32:13 +08:00
|
|
|
|
|
2024-11-26 13:45:28 +08:00
|
|
|
|
_commCount++;
|
|
|
|
|
if (_commCount == 10)
|
|
|
|
|
{
|
|
|
|
|
_commCount = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log4Helper.Error(this.GetType(), "初始化装置IO错误", ex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2024-12-03 16:25:07 +08:00
|
|
|
|
private async Task SendEquipmentInfoRemainingLifeAssessment(ProtectionDeviceCommInfoOutput device)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var data = _webApiRequest.GetEquipmentInfoRemainingLifeAssessment(device.EquipmentInfoId);
|
|
|
|
|
string redisChannel = "equipmentInfoRemainingLifeAssessmentChannel";
|
|
|
|
|
await _redisDataRepository.EquipmentInfoRemainingLifeAssessmentRedis.PublishAsync(redisChannel, data);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-12-05 11:34:06 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 格式化FTP数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private DeviceStatus ParseDeviceStatusFromBytes(byte[] data)
|
|
|
|
|
{
|
|
|
|
|
var deviceStatus = new DeviceStatus();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var networkInterfaces = new List<NetworkInterfaceStatus>();
|
|
|
|
|
|
|
|
|
|
string content = System.Text.Encoding.UTF8.GetString(data);
|
|
|
|
|
string[] lines = content.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
|
|
|
|
|
NetworkInterfaceStatus currentInterface = null;
|
|
|
|
|
|
|
|
|
|
foreach (var line in lines)
|
|
|
|
|
{
|
|
|
|
|
var parts = line.Split(':', 2);
|
|
|
|
|
if (parts.Length < 2) continue;
|
2024-11-26 13:45:28 +08:00
|
|
|
|
|
2024-12-05 11:34:06 +08:00
|
|
|
|
string key = parts[0].Trim();
|
|
|
|
|
string value = parts[1].Trim();
|
|
|
|
|
|
|
|
|
|
switch (key)
|
|
|
|
|
{
|
|
|
|
|
case "使用内存":
|
|
|
|
|
deviceStatus.UsedMemory = value;
|
|
|
|
|
break;
|
|
|
|
|
case "空闲内存":
|
|
|
|
|
deviceStatus.FreeMemory = value;
|
|
|
|
|
break;
|
|
|
|
|
case "总磁盘":
|
|
|
|
|
deviceStatus.TotalDisk = value;
|
|
|
|
|
break;
|
|
|
|
|
case "使用磁盘":
|
|
|
|
|
deviceStatus.UsedDisk = value;
|
|
|
|
|
break;
|
|
|
|
|
case "104连接状态":
|
|
|
|
|
deviceStatus.ConnectionStatus104 = int.Parse(value);
|
|
|
|
|
break;
|
|
|
|
|
case "液晶操作密码":
|
|
|
|
|
deviceStatus.LcdOperationPassword = value;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (key.StartsWith("网口"))
|
|
|
|
|
{
|
|
|
|
|
string[] netParts = key.Split(new[] { "网口", "IP", "状态", "速率", "累计时间", "起始时间", "发生帧数", "发送错误帧数", "接收帧数", "接收错误帧数" }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
if (netParts.Length > 0)
|
|
|
|
|
{
|
|
|
|
|
string interfaceName = netParts[0];
|
|
|
|
|
if (currentInterface == null || currentInterface.InterfaceName != interfaceName)
|
|
|
|
|
{
|
|
|
|
|
currentInterface = new NetworkInterfaceStatus { InterfaceName = interfaceName };
|
|
|
|
|
networkInterfaces.Add(currentInterface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (key.EndsWith("IP")) currentInterface.IpAddress = value;
|
|
|
|
|
if (key.EndsWith("状态")) currentInterface.Status = value;
|
|
|
|
|
if (key.EndsWith("速率")) currentInterface.Speed = value;
|
|
|
|
|
if (key.EndsWith("累计时间")) currentInterface.CumulativeTime = int.Parse(value.Replace("s", "").Trim());
|
|
|
|
|
if (key.EndsWith("起始时间")) currentInterface.StartTime = value;
|
|
|
|
|
if (key.EndsWith("发生帧数")) currentInterface.SentFrames = int.Parse(value);
|
|
|
|
|
if (key.EndsWith("发送错误帧数")) currentInterface.SentErrorFrames = int.Parse(value);
|
|
|
|
|
if (key.EndsWith("接收帧数")) currentInterface.ReceivedFrames = int.Parse(value);
|
|
|
|
|
if (key.EndsWith("接收错误帧数")) currentInterface.ReceivedErrorFrames = int.Parse(value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deviceStatus.NetworkInterfaces = networkInterfaces;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
MonitoringEventBus.LogHandler(ex.Message, "格式化FTP数据");
|
2024-11-26 13:45:28 +08:00
|
|
|
|
}
|
|
|
|
|
return deviceStatus;
|
|
|
|
|
}
|
2024-12-06 16:32:13 +08:00
|
|
|
|
|
|
|
|
|
private void UpdateDeviceBoardState(byte address, byte[] data, ProtectionDeviceCommInfoOutput device)
|
|
|
|
|
{
|
|
|
|
|
if (!_deviceBoardStates.TryGetValue(address, out var boardStates))
|
|
|
|
|
{
|
|
|
|
|
boardStates = iopositions.Select(item => new NameIntValueProperty(item.Name, item.Value)).ToList();
|
|
|
|
|
_deviceBoardStates[address] = boardStates;
|
|
|
|
|
}
|
|
|
|
|
boardStates[0].Value = new BitArray(new byte[] { data[0] })[0] ? 0 : 1;//运行状态
|
|
|
|
|
boardStates[1].Value = new BitArray(new byte[] { data[0] })[1] ? 0 : 1;//报警状态
|
2024-12-09 11:05:15 +08:00
|
|
|
|
boardStates[7].Value = new BitArray(new byte[] { data[1] })[7] ? 0 : 1; // 液晶状态
|
2024-12-06 16:32:13 +08:00
|
|
|
|
BitArray bit2 = new BitArray(new byte[] { data[2] });
|
|
|
|
|
boardStates[2].Value = bit2[0] ? 0 : 1;
|
|
|
|
|
boardStates[3].Value = bit2[1] ? 0 : 1;
|
|
|
|
|
boardStates[4].Value = bit2[2] ? 0 : 1;
|
|
|
|
|
boardStates[5].Value = bit2[3] ? 0 : 1;
|
|
|
|
|
boardStates[6].Value = bit2[4] ? 0 : 1;
|
2024-12-06 16:50:46 +08:00
|
|
|
|
DeviceBoardStates deviceBoardStates = new DeviceBoardStates()
|
|
|
|
|
{
|
|
|
|
|
EquipmentInfoId = device.EquipmentInfoId,
|
|
|
|
|
EquipmentInfoName = device.EquipmentInfoName,
|
|
|
|
|
States = boardStates,
|
|
|
|
|
Time = DateTime.Now,
|
|
|
|
|
};
|
|
|
|
|
_deviceBoardStatesRedis.HashSetUpdateOneAsync(deviceBoardStatesRedisKey, address.ToString(), deviceBoardStates);
|
|
|
|
|
_deviceBoardStatesRedis.PublishAsync(deviceBoardStatesRedisChannelKey, deviceBoardStates);
|
2024-12-06 16:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
string deviceBoardStatesRedisKey = "deviceBoardStates";
|
|
|
|
|
string deviceBoardStatesRedisChannelKey = "deviceBoardStatesChannel";
|
2024-12-05 11:34:06 +08:00
|
|
|
|
|
2024-12-06 16:32:13 +08:00
|
|
|
|
ConcurrentDictionary<byte, List<NameIntValueProperty>> _deviceBoardStates = new();
|
|
|
|
|
List<NameIntValueProperty> iopositions = new List<NameIntValueProperty>
|
|
|
|
|
{
|
|
|
|
|
new NameIntValueProperty("运行", 0),
|
|
|
|
|
new NameIntValueProperty("告警", 0),
|
|
|
|
|
new NameIntValueProperty("IO插件1", 0),
|
|
|
|
|
new NameIntValueProperty("IO插件2", 0),
|
|
|
|
|
new NameIntValueProperty("IO插件3", 0),
|
|
|
|
|
new NameIntValueProperty("IO插件4", 0),
|
|
|
|
|
new NameIntValueProperty("电源插件(IO5)", 0),
|
|
|
|
|
new NameIntValueProperty("液晶", 0)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 定义设备信息类
|
|
|
|
|
class DeviceInfo
|
|
|
|
|
{
|
|
|
|
|
public bool Status { get; set; } // 设备状态(运行或离线)
|
|
|
|
|
public DateTime LastUpdate { get; set; } // 最后更新时间
|
|
|
|
|
public int OfflineCount { get; set; } // 连续离线计数
|
2024-11-26 13:45:28 +08:00
|
|
|
|
}
|
|
|
|
|
}
|