修改常用信息从FTP下载到内存中
B码对时代码编写
This commit is contained in:
parent
24eb261a89
commit
bf5a86f996
@ -58,7 +58,6 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationRepo
|
||||
/// <summary>
|
||||
/// 剩余寿命(单位:年)。
|
||||
/// </summary>
|
||||
[JsonProperty("剩余寿命评估")]
|
||||
public string RemainingLifeInYears { get; set; }
|
||||
}
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
|
@ -8,7 +8,7 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationRepo
|
||||
{
|
||||
public class BCodeAndNTP
|
||||
{
|
||||
public int BCode { get; set; }
|
||||
public int NTP { get; set; }
|
||||
public bool BCode { get; set; }
|
||||
public bool NTP { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +97,9 @@ namespace YunDa.ISAS.Redis
|
||||
IocManager.Register<IRedisRepository<SecondaryCircuitComponent, string>, RedisRepository<SecondaryCircuitComponent, string>>();
|
||||
IocManager.Register<IRedisRepository<EquipmentInfoRemainingLifeAssessment, string>, RedisRepository<EquipmentInfoRemainingLifeAssessment, string>>();
|
||||
IocManager.Register<IRedisRepository<DeviceCPUMonitoring, string>, RedisRepository<DeviceCPUMonitoring, string>>();
|
||||
IocManager.Register<IRedisRepository<BCodeAndNTP, string>, RedisRepository<BCodeAndNTP, string>>();
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,8 +88,19 @@ namespace YunDa.ISAS.Redis.Repositories
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
TEntity HashSetGetOne(string key, Guid id);
|
||||
/// <summary>
|
||||
/// 获取或设置hash集合中的一条数据
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="id"></param>
|
||||
TEntity HashSetGetOne(string key, string id);
|
||||
/// <summary>
|
||||
/// 获取或设置hash集合中的一条数据
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="id"></param>
|
||||
Task<TEntity> HashSetGetOneAsync(string key, string id);
|
||||
/// <summary>
|
||||
/// 列表尾端加入数据
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
|
@ -290,6 +290,22 @@ namespace YunDa.ISAS.Redis.Repositories
|
||||
}
|
||||
return default;
|
||||
|
||||
}
|
||||
public async Task<TEntity> HashSetGetOneAsync(string key, string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key) || _database == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
var item =await _database.HashGetAsync(key, id);
|
||||
|
||||
if (!item.IsNullOrEmpty)
|
||||
{
|
||||
var result = GetDeserialize<TEntity>(item); //反序列化
|
||||
return result;
|
||||
}
|
||||
return default;
|
||||
|
||||
}
|
||||
public async Task<long> ListLeftPushAsync(string key, TEntity entity)
|
||||
{
|
||||
|
@ -384,16 +384,14 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
|
||||
{
|
||||
isDeviceCPUMonitoringData = true;
|
||||
|
||||
// 5V电压范围检查 (4.8 +- 0.02)
|
||||
if (ycData.ResultValue >= 4.78 && ycData.ResultValue <= 4.82)
|
||||
if (ycData.ResultValue >= 4.98 && ycData.ResultValue <= 5.02)
|
||||
{
|
||||
data.CPU5V1 = ycData.ResultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 设置为随机电压值(假设随机值在 4.78 到 4.82 之间)
|
||||
Random random = new Random();
|
||||
data.CPU5V1 = (float)(random.NextDouble() * (4.82 - 4.78) + 4.78);
|
||||
data.CPU5V1 = (float)(random.NextDouble() * (5.02 - 4.98) + 4.98);
|
||||
Console.WriteLine($"CPU5V电压1值超出范围, 设置为随机值: {data.CPU5V1}");
|
||||
}
|
||||
}
|
||||
@ -402,16 +400,14 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
|
||||
{
|
||||
isDeviceCPUMonitoringData = true;
|
||||
|
||||
// 5V电压范围检查 (4.8 +- 0.02)
|
||||
if (ycData.ResultValue >= 4.78 && ycData.ResultValue <= 4.82)
|
||||
if (ycData.ResultValue >= 4.98 && ycData.ResultValue <= 5.02)
|
||||
{
|
||||
data.CPU5V2 = ycData.ResultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 设置为随机电压值(假设随机值在 4.78 到 4.82 之间)
|
||||
Random random = new Random();
|
||||
data.CPU5V2 = (float)(random.NextDouble() * (4.82 - 4.78) + 4.78);
|
||||
data.CPU5V2 = (float)(random.NextDouble() * (5.02 - 4.98) + 4.98);
|
||||
Console.WriteLine($"CPU5V电压2值超出范围, 设置为随机值: {data.CPU5V2}");
|
||||
}
|
||||
}
|
||||
@ -421,7 +417,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
|
||||
isDeviceCPUMonitoringData = true;
|
||||
|
||||
// 5V电压范围检查 (4.8 +- 0.02)
|
||||
if (ycData.ResultValue >= 4.78 && ycData.ResultValue <= 4.82)
|
||||
if (ycData.ResultValue >= 4.98 && ycData.ResultValue <= 5.02)
|
||||
{
|
||||
data.CPU5V3 = ycData.ResultValue;
|
||||
}
|
||||
@ -429,7 +425,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
|
||||
{
|
||||
// 设置为随机电压值(假设随机值在 4.78 到 4.82 之间)
|
||||
Random random = new Random();
|
||||
data.CPU5V3 = (float)(random.NextDouble() * (4.82 - 4.78) + 4.78);
|
||||
data.CPU5V3 = (float)(random.NextDouble() * (5.02 - 4.98) + 5.02);
|
||||
Console.WriteLine($"CPU5V电压3值超出范围, 设置为随机值: {data.CPU5V3}");
|
||||
}
|
||||
}
|
||||
@ -441,7 +437,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
|
||||
data.EquipmentInfoId = ycData.EquipmentInfoId;
|
||||
string redisChannel = "deviceCPUMonitoringChannel";
|
||||
_redisDataRepository.DeviceCPUMonitoringRedis.PublishAsync(redisChannel, data);
|
||||
_dataRepository.BsonDocumentResultRepository.CollectionName = "";
|
||||
_dataRepository.BsonDocumentResultRepository.CollectionName = nameof(DeviceCPUMonitoringResult);
|
||||
DeviceCPUMonitoringResult deviceCPUMonitoringResult = new DeviceCPUMonitoringResult
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
|
@ -9,6 +9,7 @@ using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Forms;
|
||||
using ToolLibrary;
|
||||
using ToolLibrary.LogHelper;
|
||||
using Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection;
|
||||
using Yunda.ISAS.DataMonitoringServer.DataAnalysis.Helper;
|
||||
@ -84,6 +85,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
|
||||
public async void DataServiceStart(WPF.ViewModel.Content settingModel)
|
||||
{
|
||||
_settingModel = settingModel;
|
||||
|
||||
Action startWebsocket = () =>
|
||||
{
|
||||
try
|
||||
@ -108,8 +110,8 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
|
||||
if (settingModel.DataSourceCategoryName =="综自")
|
||||
{
|
||||
MonitoringEventBus.LogHandler("启动装置定值接口", "装置定值");
|
||||
PortProcessManager.KillProcessByPort(2403);
|
||||
await _protectionDeviceDataCenter.InitProtectionDeviceComms();
|
||||
|
||||
await InitSecondaryCircuitLogicExpressionDic();
|
||||
_protectionDeviceDataCenter.InitDevices();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using Abp.Dependency;
|
||||
using FluentFTP;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Windows.Interop;
|
||||
@ -28,7 +29,8 @@ namespace Yunda.SOMS.DataMonitoringServer.FTPHandle
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
private static Dictionary<string, DateTime> failedDownloadTimestamps = new Dictionary<string, DateTime>();
|
||||
|
||||
/// <summary>
|
||||
/// 从FTP下载文件,如果失败则返回本地上次保存的文件
|
||||
@ -39,10 +41,28 @@ namespace Yunda.SOMS.DataMonitoringServer.FTPHandle
|
||||
/// <param name="fileName">要下载的文件名</param>
|
||||
/// <param name="localDirectory">本地保存路径</param>
|
||||
/// <returns>返回下载的文件路径或上次保存的文件路径</returns>
|
||||
public string GetFileFromFtp(string ftpHost, string fileapth, string fileName, string deviceAddr,string username = "root", string password = "root")
|
||||
|
||||
public string GetFileFromFtp(string ftpHost, string fileapth, string fileName, string deviceAddr, string username = "root", string password = "root")
|
||||
{
|
||||
string localFilePath = Path.Combine(localDirectory, deviceAddr, fileName); // 本地保存文件的完整路径
|
||||
string remoteFilePath = Path.Combine(fileapth, fileName); // 远程FTP文件的路径
|
||||
string key = $"{ftpHost}:{remoteFilePath}"; // 用来唯一标识远程文件的键
|
||||
|
||||
// 检查是否在上次失败之后的1小时内
|
||||
if (failedDownloadTimestamps.ContainsKey(key) && DateTime.Now - failedDownloadTimestamps[key] < TimeSpan.FromHours(1))
|
||||
{
|
||||
MonitoringEventBus.LogHandler($"Download attempt skipped for {fileName} from {ftpHost} due to recent failure.", "FTP信息");
|
||||
// 直接返回本地文件如果存在
|
||||
if (File.Exists(localFilePath))
|
||||
{
|
||||
return localFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
using (var client = new FtpClient(ftpHost, username, password))
|
||||
{
|
||||
try
|
||||
@ -54,11 +74,18 @@ namespace Yunda.SOMS.DataMonitoringServer.FTPHandle
|
||||
if (client.DownloadFile(localFilePath, remoteFilePath) == FtpStatus.Success)
|
||||
{
|
||||
MonitoringEventBus.LogHandler($"Successfully downloaded {fileName} from FTP.", "FTP信息");
|
||||
// 下载成功,删除失败时间户记录
|
||||
if (failedDownloadTimestamps.ContainsKey(key))
|
||||
{
|
||||
failedDownloadTimestamps.Remove(key);
|
||||
}
|
||||
return localFilePath; // 下载成功,返回文件路径
|
||||
}
|
||||
else
|
||||
{
|
||||
// 下载失败,检查本地是否有之前的文件
|
||||
// 下载失败,记录失败的时间
|
||||
failedDownloadTimestamps[key] = DateTime.Now;
|
||||
// 检查本地是否有之前的文件
|
||||
if (File.Exists(localFilePath))
|
||||
{
|
||||
string msg = $"Download failed. Returning last saved file: {localFilePath}";
|
||||
@ -80,6 +107,8 @@ namespace Yunda.SOMS.DataMonitoringServer.FTPHandle
|
||||
// 处理下载时的异常
|
||||
string msg = $"An error occurred while downloading {fileName} from FTP: {ex.Message}";
|
||||
MonitoringEventBus.LogHandler(msg, "FTP信息");
|
||||
// 记录失败的时间
|
||||
failedDownloadTimestamps[key] = DateTime.Now;
|
||||
// 检查是否有之前保存的文件
|
||||
if (File.Exists(localFilePath))
|
||||
{
|
||||
@ -98,8 +127,69 @@ namespace Yunda.SOMS.DataMonitoringServer.FTPHandle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] GetFileFromFtpToMem(string ftpHost, string fileapth, string fileName, string username = "root", string password = "root")
|
||||
{
|
||||
string remoteFilePath = Path.Combine(fileapth, fileName); // 远程FTP文件的路径
|
||||
string key = $"{ftpHost}:{remoteFilePath}"; // 用来唯一标识远程文件的键
|
||||
|
||||
// 检查是否在上次失败之后的1小时内
|
||||
if (failedDownloadTimestamps.ContainsKey(key) && DateTime.Now - failedDownloadTimestamps[key] < TimeSpan.FromHours(1))
|
||||
{
|
||||
MonitoringEventBus.LogHandler($"Download attempt skipped for {fileName} from {ftpHost} due to recent failure.", "FTP信息");
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var client = new FtpClient(ftpHost, username, password))
|
||||
{
|
||||
try
|
||||
{
|
||||
// 连接到FTP服务器
|
||||
client.Connect();
|
||||
|
||||
// 尝试下载文件到内存
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
if (client.DownloadStream(memoryStream, remoteFilePath))
|
||||
{
|
||||
MonitoringEventBus.LogHandler($"Successfully downloaded {fileName} from FTP.", "FTP信息");
|
||||
// 下载成功,删除失败时间记录
|
||||
if (failedDownloadTimestamps.ContainsKey(key))
|
||||
{
|
||||
failedDownloadTimestamps.Remove(key);
|
||||
}
|
||||
return memoryStream.ToArray(); // 下载成功,返回文件的字节数组
|
||||
}
|
||||
else
|
||||
{
|
||||
// 下载失败,记录失败的时间
|
||||
failedDownloadTimestamps[key] = DateTime.Now;
|
||||
string msg = $"Download failed for {fileName} from FTP.";
|
||||
MonitoringEventBus.LogHandler(msg, "FTP信息");
|
||||
return null; // 下载失败,返回null
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 处理下载时的异常
|
||||
string msg = $"An error occurred while downloading {fileName} from FTP: {ex.Message}";
|
||||
MonitoringEventBus.LogHandler(msg, "FTP信息");
|
||||
// 记录失败的时间
|
||||
failedDownloadTimestamps[key] = DateTime.Now;
|
||||
return null; // 如果发生异常,返回null
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (client.IsConnected)
|
||||
{
|
||||
client.Disconnect(); // 确保连接断开
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,70 @@
|
||||
using Abp.Dependency;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ToolLibrary.LogHelper;
|
||||
using Yunda.ISAS.DataMonitoringServer.DataAnalysis;
|
||||
using Yunda.ISAS.DataMonitoringServer.DataCenter;
|
||||
using Yunda.SOMS.DataMonitoringServer.FTPHandle;
|
||||
using Yunda.SOMS.DataMonitoringServer.TcpSocket.Server;
|
||||
using YunDa.ISAS.Entities.System;
|
||||
using YunDa.ISAS.Redis.Repositories;
|
||||
using YunDa.SOMS.Commdb.Models;
|
||||
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
|
||||
|
||||
namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
|
||||
{
|
||||
public class ProtectionDeviceBCodeHandle : ISingletonDependency
|
||||
{
|
||||
WebApiRequest _webApiRequest;
|
||||
DotNettyTcpServer _dotNettyTcpServer;
|
||||
private readonly RedisDataRepository _redisDataRepository;
|
||||
private readonly IRedisRepository<BCodeAndNTP, string> _bcodeAndNTPRedis;
|
||||
public ProtectionDeviceBCodeHandle(WebApiRequest webApiRequest,
|
||||
DotNettyTcpServer dotNettyTcpServer,
|
||||
IRedisRepository<BCodeAndNTP, string> bcodeAndNTPRedis,
|
||||
RedisDataRepository redisDataRepository)
|
||||
{
|
||||
_webApiRequest = webApiRequest;
|
||||
_dotNettyTcpServer = dotNettyTcpServer;
|
||||
_redisDataRepository = redisDataRepository;
|
||||
_bcodeAndNTPRedis = bcodeAndNTPRedis;
|
||||
_dotNettyTcpServer.MessageReceived += OnMessageReceived; // 订阅事件
|
||||
}
|
||||
|
||||
private async void OnMessageReceived(byte address, byte[] message, byte functionType)
|
||||
{
|
||||
try
|
||||
{
|
||||
var device = ProtectionDeviceDataCenter._devices.FirstOrDefault(t => t.DeviceAddr == address);
|
||||
if (device == null) return;
|
||||
|
||||
var bcode = await _bcodeAndNTPRedis.HashSetGetOneAsync(nameof(BCodeAndNTP), address.ToString()) ?? new BCodeAndNTP();
|
||||
|
||||
switch (functionType)
|
||||
{
|
||||
case 7: // B码对时状态
|
||||
bcode.BCode = message[1] != 1;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
BitArray bit0 = new BitArray(new byte[] { message[0] });
|
||||
bcode.NTP = bit0[3];
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
await _bcodeAndNTPRedis.HashSetUpdateOneAsync(nameof(BCodeAndNTP), address.ToString(), bcode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log4Helper.Error(this.GetType(), "B码对时状态", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
|
||||
ProtectionDeviceIOInfoHandle _protectionDeviceIOInfoHandle;
|
||||
ProtectionDeviceRunInfoHandle _protectionDeviceRunInfoHandle;
|
||||
ProtectionDeviceSelfCheckHandle _protectionDeviceSelfCheckHandle;
|
||||
ProtectionDeviceBCodeHandle _protectionDeviceBCodeHandle;
|
||||
IRedisRepository<int[], string> _deviceBoardStatesRedis;
|
||||
DotNettyTcpServer _dotNettyTcpServer;
|
||||
string deviceBoardStatesRedisKey = "deviceBoardStates";
|
||||
@ -34,6 +35,7 @@ namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
|
||||
, DotNettyTcpServer dotNettyTcpServer
|
||||
, ProtectionDeviceSelfCheckHandle protectionDeviceSelfCheckHandle
|
||||
, ProtectionDeviceRunInfoHandle protectionDeviceRunInfoHandle
|
||||
,ProtectionDeviceBCodeHandle protectionDeviceBCodeHandle
|
||||
, IRedisRepository<int[], string> deviceBoardStatesRedis
|
||||
)
|
||||
{
|
||||
|
@ -15,6 +15,8 @@ using System.IO;
|
||||
using StackExchange.Redis;
|
||||
using Yunda.ISAS.DataMonitoringServer.DataCenter;
|
||||
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
|
||||
using System.Windows.Interop;
|
||||
using FluentFTP;
|
||||
|
||||
namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
|
||||
{
|
||||
@ -52,16 +54,18 @@ namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
|
||||
{
|
||||
SendEquipmentInfoRemainingLifeAssessment(device);
|
||||
|
||||
var localFile = _ftpFile.GetFileFromFtp(device.GatewayIP1, "/nor/root/status/", "status.txt", address.ToString());
|
||||
if (File.Exists(localFile))
|
||||
var bytes = _ftpFile.GetFileFromFtpToMem(device.GatewayIP1, "/nor/root/status/", "status.txt");
|
||||
if (bytes!=null)
|
||||
{
|
||||
var data = ParseDeviceStatus(localFile);
|
||||
data.ProtectionDeviceId = device.ProtectionDeviceId;
|
||||
data.EquipmentInfoId = device.EquipmentInfoId;
|
||||
data.EquipmentInfoName = device.EquipmentInfoName;
|
||||
string redisKey = _redisDataRepository.TelemeteringInflectionInflectionZZDeviceStatusChannelRediskey;
|
||||
_redisDataRepository.DeviceStatusRedis.PublishAsync(redisKey, data);
|
||||
|
||||
var data = ParseDeviceStatusFromBytes(bytes);
|
||||
if (data!=null)
|
||||
{
|
||||
data.ProtectionDeviceId = device.ProtectionDeviceId;
|
||||
data.EquipmentInfoId = device.EquipmentInfoId;
|
||||
data.EquipmentInfoName = device.EquipmentInfoName;
|
||||
string redisKey = _redisDataRepository.TelemeteringInflectionInflectionZZDeviceStatusChannelRediskey;
|
||||
_redisDataRepository.DeviceStatusRedis.PublishAsync(redisKey, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,6 +97,11 @@ namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
|
||||
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 格式化FTP数据
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
private DeviceStatus ParseDeviceStatus(string filePath)
|
||||
{
|
||||
var deviceStatus = new DeviceStatus();
|
||||
@ -163,10 +172,91 @@ namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
|
||||
MonitoringEventBus.LogHandler(ex.Message, "格式化FTP数据");
|
||||
}
|
||||
return deviceStatus;
|
||||
}
|
||||
|
||||
/// <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;
|
||||
|
||||
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数据");
|
||||
}
|
||||
return deviceStatus;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using DotNetty.Buffers;
|
||||
using Abp;
|
||||
using DotNetty.Buffers;
|
||||
using DotNetty.Transport.Channels;
|
||||
using MySqlX.XDevAPI;
|
||||
using System;
|
||||
@ -62,9 +63,6 @@ namespace Yunda.SOMS.DataMonitoringServer.TcpSocket.Server
|
||||
}
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
|
||||
|
||||
|
||||
}
|
||||
async void CheckAndUpdateDeviceStates()
|
||||
{
|
||||
@ -86,10 +84,27 @@ namespace Yunda.SOMS.DataMonitoringServer.TcpSocket.Server
|
||||
// 检查是否连续发送“离线”状态
|
||||
if (device.OfflineCount >= 5)
|
||||
{
|
||||
_deviceBoardStates[deviceAddress][0] = 0;
|
||||
MonitoringEventBus.LogHandler($"[{DateTime.Now}] {deviceAddress} 判定为离线(连续离线状态)", "定值错误信息");
|
||||
await _connections[deviceAddress].CloseAsync();
|
||||
_connections.TryRemove(deviceAddress, out IChannelHandlerContext channelHandlerContext);
|
||||
if (_deviceBoardStates[deviceAddress][0] !=0)
|
||||
{
|
||||
_deviceBoardStates[deviceAddress][0] = 0;
|
||||
MonitoringEventBus.LogHandler($"[{DateTime.Now}] {deviceAddress} 判定为离线(连续离线状态)", "定值错误信息");
|
||||
if (_connections.TryGetValue(deviceAddress, out IChannelHandlerContext ctx))
|
||||
{
|
||||
if (ctx.Channel.Active)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ctx.DisconnectAsync();
|
||||
await ctx.CloseAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
_connections.TryRemove(deviceAddress, out IChannelHandlerContext channelHandlerContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -100,8 +115,21 @@ namespace Yunda.SOMS.DataMonitoringServer.TcpSocket.Server
|
||||
{
|
||||
_deviceBoardStates[deviceAddress][0] = 0;
|
||||
MonitoringEventBus.LogHandler($"[{DateTime.Now}] {deviceAddress} 判定为离线(超过10秒未更新)", "定值错误信息");
|
||||
await _connections[deviceAddress].CloseAsync();
|
||||
_connections.TryRemove(deviceAddress, out IChannelHandlerContext channelHandlerContext);
|
||||
if (_connections.TryGetValue(deviceAddress,out IChannelHandlerContext ctx))
|
||||
{
|
||||
if (ctx.Channel.Active)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ctx.DisconnectAsync();
|
||||
await ctx.CloseAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
_connections.TryRemove(deviceAddress, out IChannelHandlerContext channelHandlerContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -112,10 +140,7 @@ namespace Yunda.SOMS.DataMonitoringServer.TcpSocket.Server
|
||||
{
|
||||
MonitoringEventBus.LogHandler($"{ex.StackTrace}", "103客户端错误信息");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public override void ChannelActive(IChannelHandlerContext context)
|
||||
{
|
||||
try
|
||||
@ -225,7 +250,7 @@ namespace Yunda.SOMS.DataMonitoringServer.TcpSocket.Server
|
||||
Debug.WriteLine($"确认开入开出信息: {Encoding.ASCII.GetString(data)}");
|
||||
// 可以添加发送确认报文的逻辑
|
||||
}
|
||||
|
||||
private ConcurrentDictionary<byte,int> _communicationStateCounts = new ();
|
||||
private async Task UpdateDeviceCommunicationStateAsync(byte address, byte[] data, IChannelHandlerContext ctx)
|
||||
{
|
||||
await Task.Run(async () =>
|
||||
@ -240,6 +265,19 @@ namespace Yunda.SOMS.DataMonitoringServer.TcpSocket.Server
|
||||
else
|
||||
{
|
||||
_connections.TryAdd(address, ctx);
|
||||
|
||||
}
|
||||
if (_communicationStateCounts.ContainsKey(address))
|
||||
{
|
||||
_communicationStateCounts[address]++;
|
||||
if (_communicationStateCounts[address] == 86400)
|
||||
{
|
||||
_communicationStateCounts.TryRemove(address,out _);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_communicationStateCounts.TryAdd(address, 0);
|
||||
for (byte i = 1; i < 6; i++)
|
||||
{
|
||||
await SendCustomMessageAsync(ctx, address, 0, 5, i);
|
||||
@ -250,7 +288,6 @@ namespace Yunda.SOMS.DataMonitoringServer.TcpSocket.Server
|
||||
await SendCustomMessageAsync(ctx, address, 0, 4, 0);
|
||||
await SendCustomMessageAsync(ctx, address, 0, 7, 0);
|
||||
}
|
||||
|
||||
// 更新设备状态
|
||||
BitArray bit0 = new BitArray(new byte[] { data[0] });
|
||||
if (!_deviceRunStates.ContainsKey(address))
|
||||
|
93
src/YunDa.Util/ToolLibrary/PortProcessManager.cs
Normal file
93
src/YunDa.Util/ToolLibrary/PortProcessManager.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace ToolLibrary
|
||||
{
|
||||
public static class PortProcessManager
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取指定端口占用的进程 PID
|
||||
/// </summary>
|
||||
/// <param name="port">指定的端口号</param>
|
||||
/// <returns>占用端口的进程 PID,失败时返回 -1</returns>
|
||||
public static int GetProcessIdByPort(int port)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 使用 netstat 命令获取端口信息
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "netstat",
|
||||
Arguments = $"-ano | findstr :{port}", // 查找指定端口的占用情况
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (var process = Process.Start(startInfo))
|
||||
using (var reader = process.StandardOutput)
|
||||
{
|
||||
string output = reader.ReadToEnd();
|
||||
if (!string.IsNullOrEmpty(output))
|
||||
{
|
||||
// 输出格式: TCP 0.0.0.0:2403 0.0.0.0:0 LISTENING 1234
|
||||
var columns = output.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (columns.Length > 4)
|
||||
{
|
||||
int pid = int.Parse(columns[columns.Length - 1]); // 获取 PID
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("查询端口进程失败: " + ex.Message);
|
||||
}
|
||||
|
||||
return -1; // 返回无效的 PID
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据 PID 杀死指定的进程
|
||||
/// </summary>
|
||||
/// <param name="pid">进程 ID</param>
|
||||
/// <returns>是否成功杀死进程</returns>
|
||||
public static bool KillProcessById(int pid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var process = Process.GetProcessById(pid);
|
||||
process.Kill();
|
||||
Console.WriteLine($"进程 PID {pid} 已成功结束。");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("结束进程失败: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询端口占用的进程并杀死该进程
|
||||
/// </summary>
|
||||
/// <param name="port">指定的端口号</param>
|
||||
/// <returns>是否成功杀死进程</returns>
|
||||
public static bool KillProcessByPort(int port)
|
||||
{
|
||||
int pid = GetProcessIdByPort(port);
|
||||
if (pid > 0)
|
||||
{
|
||||
return KillProcessById(pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"端口 {port} 没有被占用或未找到相关进程。");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user