修改常用信息从FTP下载到内存中

B码对时代码编写
This commit is contained in:
郭睿 2024-12-05 11:34:06 +08:00
parent 24eb261a89
commit bf5a86f996
13 changed files with 453 additions and 46 deletions

View File

@ -58,7 +58,6 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationRepo
/// <summary>
/// 剩余寿命(单位:年)。
/// </summary>
[JsonProperty("剩余寿命评估")]
public string RemainingLifeInYears { get; set; }
}
[MessagePackObject(keyAsPropertyName: true)]

View File

@ -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; }
}
}

View File

@ -97,6 +97,7 @@ 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>>();
}

View File

@ -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>

View File

@ -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)
{

View File

@ -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(),

View File

@ -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();
}

View File

@ -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;
@ -29,6 +30,7 @@ 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(); // 确保连接断开
}
}
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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
)
{

View File

@ -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;
}
}
}

View File

@ -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))

View 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;
}
}
}
}