diff --git a/src/YunDa.Application/YunDa.ISAS.DataTransferObject/MainStationMaintenanceInfo/OperationReport/AbnormalComponent.cs b/src/YunDa.Application/YunDa.ISAS.DataTransferObject/MainStationMaintenanceInfo/OperationReport/AbnormalComponent.cs
index d999e36..c3a3d59 100644
--- a/src/YunDa.Application/YunDa.ISAS.DataTransferObject/MainStationMaintenanceInfo/OperationReport/AbnormalComponent.cs
+++ b/src/YunDa.Application/YunDa.ISAS.DataTransferObject/MainStationMaintenanceInfo/OperationReport/AbnormalComponent.cs
@@ -58,7 +58,6 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationRepo
///
/// 剩余寿命(单位:年)。
///
- [JsonProperty("剩余寿命评估")]
public string RemainingLifeInYears { get; set; }
}
[MessagePackObject(keyAsPropertyName: true)]
diff --git a/src/YunDa.Application/YunDa.ISAS.DataTransferObject/MainStationMaintenanceInfo/OperationReport/BCodeAndNTP.cs b/src/YunDa.Application/YunDa.ISAS.DataTransferObject/MainStationMaintenanceInfo/OperationReport/BCodeAndNTP.cs
index dd06750..447507a 100644
--- a/src/YunDa.Application/YunDa.ISAS.DataTransferObject/MainStationMaintenanceInfo/OperationReport/BCodeAndNTP.cs
+++ b/src/YunDa.Application/YunDa.ISAS.DataTransferObject/MainStationMaintenanceInfo/OperationReport/BCodeAndNTP.cs
@@ -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; }
}
}
diff --git a/src/YunDa.Domain/YunDa.ISAS.Redis/ISASRedisModule.cs b/src/YunDa.Domain/YunDa.ISAS.Redis/ISASRedisModule.cs
index 4a85508..f38cd55 100644
--- a/src/YunDa.Domain/YunDa.ISAS.Redis/ISASRedisModule.cs
+++ b/src/YunDa.Domain/YunDa.ISAS.Redis/ISASRedisModule.cs
@@ -97,8 +97,9 @@ namespace YunDa.ISAS.Redis
IocManager.Register, RedisRepository>();
IocManager.Register, RedisRepository>();
IocManager.Register, RedisRepository>();
+ IocManager.Register, RedisRepository>();
+
-
}
}
}
diff --git a/src/YunDa.Domain/YunDa.ISAS.Redis/Repositories/IRedisRepository.cs b/src/YunDa.Domain/YunDa.ISAS.Redis/Repositories/IRedisRepository.cs
index 221a743..5fa473b 100644
--- a/src/YunDa.Domain/YunDa.ISAS.Redis/Repositories/IRedisRepository.cs
+++ b/src/YunDa.Domain/YunDa.ISAS.Redis/Repositories/IRedisRepository.cs
@@ -88,8 +88,19 @@ namespace YunDa.ISAS.Redis.Repositories
///
///
TEntity HashSetGetOne(string key, Guid id);
+ ///
+ /// 获取或设置hash集合中的一条数据
+ ///
+ ///
+ ///
TEntity HashSetGetOne(string key, string id);
///
+ /// 获取或设置hash集合中的一条数据
+ ///
+ ///
+ ///
+ Task HashSetGetOneAsync(string key, string id);
+ ///
/// 列表尾端加入数据
///
///
diff --git a/src/YunDa.Domain/YunDa.ISAS.Redis/Repositories/RedisRepository.cs b/src/YunDa.Domain/YunDa.ISAS.Redis/Repositories/RedisRepository.cs
index 82941cc..abaffc0 100644
--- a/src/YunDa.Domain/YunDa.ISAS.Redis/Repositories/RedisRepository.cs
+++ b/src/YunDa.Domain/YunDa.ISAS.Redis/Repositories/RedisRepository.cs
@@ -290,6 +290,22 @@ namespace YunDa.ISAS.Redis.Repositories
}
return default;
+ }
+ public async Task 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(item); //反序列化
+ return result;
+ }
+ return default;
+
}
public async Task ListLeftPushAsync(string key, TEntity entity)
{
diff --git a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/DataAnalysis/DataCollection/DataSendTask.cs b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/DataAnalysis/DataCollection/DataSendTask.cs
index 65bebac..5e6423a 100644
--- a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/DataAnalysis/DataCollection/DataSendTask.cs
+++ b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/DataAnalysis/DataCollection/DataSendTask.cs
@@ -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(),
diff --git a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/DataAnalysis/MonitoringDataService.cs b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/DataAnalysis/MonitoringDataService.cs
index 657d3d9..e4360eb 100644
--- a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/DataAnalysis/MonitoringDataService.cs
+++ b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/DataAnalysis/MonitoringDataService.cs
@@ -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();
}
diff --git a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/FTPHandle/FtpFile.cs b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/FTPHandle/FtpFile.cs
index 96b8c4b..6aa6a31 100644
--- a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/FTPHandle/FtpFile.cs
+++ b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/FTPHandle/FtpFile.cs
@@ -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 failedDownloadTimestamps = new Dictionary();
///
/// 从FTP下载文件,如果失败则返回本地上次保存的文件
@@ -39,10 +41,28 @@ namespace Yunda.SOMS.DataMonitoringServer.FTPHandle
/// 要下载的文件名
/// 本地保存路径
/// 返回下载的文件路径或上次保存的文件路径
- 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(); // 确保连接断开
+ }
+ }
+ }
+ }
+
}
}
diff --git a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceBCodeHandle.cs b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceBCodeHandle.cs
new file mode 100644
index 0000000..814a1a2
--- /dev/null
+++ b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceBCodeHandle.cs
@@ -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 _bcodeAndNTPRedis;
+ public ProtectionDeviceBCodeHandle(WebApiRequest webApiRequest,
+ DotNettyTcpServer dotNettyTcpServer,
+ IRedisRepository 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);
+ }
+ }
+ }
+}
diff --git a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceDataCenter.cs b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceDataCenter.cs
index 1bf3dab..f149bdc 100644
--- a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceDataCenter.cs
+++ b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceDataCenter.cs
@@ -23,6 +23,7 @@ namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
ProtectionDeviceIOInfoHandle _protectionDeviceIOInfoHandle;
ProtectionDeviceRunInfoHandle _protectionDeviceRunInfoHandle;
ProtectionDeviceSelfCheckHandle _protectionDeviceSelfCheckHandle;
+ ProtectionDeviceBCodeHandle _protectionDeviceBCodeHandle;
IRedisRepository _deviceBoardStatesRedis;
DotNettyTcpServer _dotNettyTcpServer;
string deviceBoardStatesRedisKey = "deviceBoardStates";
@@ -34,6 +35,7 @@ namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
, DotNettyTcpServer dotNettyTcpServer
, ProtectionDeviceSelfCheckHandle protectionDeviceSelfCheckHandle
, ProtectionDeviceRunInfoHandle protectionDeviceRunInfoHandle
+ ,ProtectionDeviceBCodeHandle protectionDeviceBCodeHandle
, IRedisRepository deviceBoardStatesRedis
)
{
diff --git a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceRunInfoHandle.cs b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceRunInfoHandle.cs
index 1c9f2b7..054aa60 100644
--- a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceRunInfoHandle.cs
+++ b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/ProtectionDeviceHandle/ProtectionDeviceRunInfoHandle.cs
@@ -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
}
}
+ ///
+ /// 格式化FTP数据
+ ///
+ ///
+ ///
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;
}
+
+ ///
+ /// 格式化FTP数据
+ ///
+ ///
+ ///
+ private DeviceStatus ParseDeviceStatusFromBytes(byte[] data)
+ {
+ var deviceStatus = new DeviceStatus();
+ try
+ {
+ var networkInterfaces = new List();
+
+ 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;
+ }
+
}
}
diff --git a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/TcpSocket/Server/DotNettyServerHandler.cs b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/TcpSocket/Server/DotNettyServerHandler.cs
index 32e21e6..351ba83 100644
--- a/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/TcpSocket/Server/DotNettyServerHandler.cs
+++ b/src/YunDa.Server/Yunda.ISAS.DataMonitoringServer/TcpSocket/Server/DotNettyServerHandler.cs
@@ -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 _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))
diff --git a/src/YunDa.Util/ToolLibrary/PortProcessManager.cs b/src/YunDa.Util/ToolLibrary/PortProcessManager.cs
new file mode 100644
index 0000000..5005e65
--- /dev/null
+++ b/src/YunDa.Util/ToolLibrary/PortProcessManager.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+
+namespace ToolLibrary
+{
+ public static class PortProcessManager
+ {
+ ///
+ /// 获取指定端口占用的进程 PID
+ ///
+ /// 指定的端口号
+ /// 占用端口的进程 PID,失败时返回 -1
+ 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
+ }
+
+ ///
+ /// 根据 PID 杀死指定的进程
+ ///
+ /// 进程 ID
+ /// 是否成功杀死进程
+ 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;
+ }
+ }
+
+ ///
+ /// 查询端口占用的进程并杀死该进程
+ ///
+ /// 指定的端口号
+ /// 是否成功杀死进程
+ public static bool KillProcessByPort(int port)
+ {
+ int pid = GetProcessIdByPort(port);
+ if (pid > 0)
+ {
+ return KillProcessById(pid);
+ }
+ else
+ {
+ Console.WriteLine($"端口 {port} 没有被占用或未找到相关进程。");
+ return false;
+ }
+ }
+ }
+
+}