运维测试接口

This commit is contained in:
郭睿 2024-11-29 09:03:54 +08:00
parent 190700ccf2
commit 350b58fa3a
55 changed files with 7088 additions and 303 deletions

View File

@ -1,15 +1,22 @@
using System;
using Abp;
using Castle.Core;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server;
using Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.TestData;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceHistoryChange;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceTcpData;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
namespace Yunda.SOMS.OperationsMainSiteGatewayServer
{
public class Program
{
private static AbpBootstrapper _bootstrapper;
private static DotNettyTcpServer _dotNettyTcpServer;
public static async Task Main(string[] args)
{
@ -36,6 +43,53 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer
try
{
// 创建一个任务来监听用户输入
var inputTask = Task.Run(() =>
{
while (!cts.Token.IsCancellationRequested)
{
Console.WriteLine("请输入数字选择操作:");
Console.WriteLine("1: 执行装置履历测试");
Console.WriteLine("2: 执行设备参数报文测试");
Console.WriteLine("3: 执行运行诊断报文测试");
Console.WriteLine("4: 执行运行状态报文测试");
Console.WriteLine("按 'q' 退出程序");
string input = Console.ReadLine();
if (input == "1")
{
SimulateData.Test1(_dotNettyTcpServer);
// 在这里执行操作1的逻辑
}
else if (input == "2")
{
SimulateData.Test2(_dotNettyTcpServer);
// 在这里执行操作2的逻辑
}
else if (input == "3")
{
SimulateData.Test3(_dotNettyTcpServer);
// 在这里执行操作3的逻辑
}
else if (input == "4")
{
SimulateData.Test4(_dotNettyTcpServer);
// 在这里执行操作3的逻辑
}
else if (input?.ToLower() == "q")
{
Log.Information("退出程序...");
cts.Cancel(); // 用户选择退出时触发取消
break;
}
else
{
Log.Information("无效的输入,请重新选择...");
}
}
});
await Task.Delay(Timeout.Infinite, cts.Token); // 无限等待,直到取消
}
catch (TaskCanceledException)
@ -85,8 +139,8 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer
/// </summary>
private static async Task RunApplication(byte addr)
{
var service = _bootstrapper.IocManager.Resolve<DotNettyTcpServer>();
await service.RunServerAsync(addr);
_dotNettyTcpServer = _bootstrapper.IocManager.Resolve<DotNettyTcpServer>();
await _dotNettyTcpServer.RunServerAsync(addr);
}
/// <summary>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net8.0\publish\win-x64\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun>
<PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@ -2,12 +2,16 @@
using DotNetty.Transport.Channels;
using Newtonsoft.Json.Linq;
using Serilog;
using System;
using System.Collections;
using System.Diagnostics;
using System.Net;
using System.Text;
using System.Threading.Channels;
using Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Models;
using Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.TestData;
using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
{
@ -20,35 +24,25 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
public DateTime LastUpdate { get; set; } // 最后更新时间
public int OfflineCount { get; set; } // 连续离线计数
}
private IChannelHandlerContext _context;
public IChannelHandlerContext _context;
// 定义事件,事件处理程序包含消息和功能描述
private readonly Dictionary<byte, IChannelHandlerContext> _connections;
private readonly Action<byte, byte[], byte> _onMessageReceived;
private readonly Action<byte> _onDeviceConnection;
Dictionary<byte, DateTime> _deviceRunStates = new Dictionary<byte, DateTime>();
private readonly Action<string> _channelInactiveCallback;
private DateTime _deviceRunStateTime = DateTime.Now;
byte _serverAddr;
public DotNettyServerHandler(Dictionary<byte, IChannelHandlerContext> connections,
Action<byte, byte[], byte> onMessageReceived, Action<Dictionary<byte, int[]>> deviceBoardStatesAction, byte addr)
public DotNettyServerHandler(
Action<byte, byte[], byte> messageReceived, Action<string> channelInactiveCallback , byte addr)
{
_serverAddr = addr;
_connections = connections;
_onMessageReceived = onMessageReceived;
//_onDeviceConnection = onDeviceConnection;
_onMessageReceived = messageReceived;
_channelInactiveCallback = channelInactiveCallback;
Task.Factory.StartNew(async () =>
{
while (true)
{
try
{
CheckAndUpdateDeviceStates();
SendTestData();
await Task.Delay(1000);
}
catch (Exception ex)
{
//MonitoringEventBus.LogHandler($"客户端连接错误:{ex.StackTrace}", "定值错误信息");
}
CheckAndUpdateDeviceStates();
await Task.Delay(1000);
}
}, TaskCreationOptions.LongRunning);
@ -59,28 +53,22 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
{
try
{
if (_context == null || !_context.Channel.Open || !_context.Channel.Active)
{
return;
}
if (heartbeatDelayCount ==0)
{
await HandleHeartbeat(_context, _serverAddr, heartbeatCount);
foreach (var entry in _deviceRunStates)
if ((DateTime.Now - _deviceRunStateTime).TotalSeconds > 65)
{
var deviceAddress = entry.Key;
var date = entry.Value;
// 检查是否超过10秒未更新
if ((DateTime.Now - date).TotalSeconds > 65)
{
Log.Warning($"[{DateTime.Now}] {deviceAddress} 判定为离线超过65秒未更新");
await _context.CloseAsync();
_connections.Remove(deviceAddress);
}
Log.Warning($" {_context.Channel.RemoteAddress.ToString()} 判定为离线超过65秒未更新");
await _context.CloseAsync();
}
}
else
{
heartbeatDelayCount++;
}
heartbeatDelayCount++;
if (heartbeatDelayCount == 30)
{
heartbeatDelayCount = 0;
@ -92,37 +80,38 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
Log.Error(ex,$"状态检测");
}
}
int sequence = 31;
void SendTestData()
{
var data = SimulateData.SendProductionInformation();
// 创建一个应用控制字实例
ApplicationControlWord controlWord = new ApplicationControlWord(fir: true, fin: true, con: true, sequence: sequence);
// 将控制字转换为字节
byte controlByte = controlWord.ToByte();
Log.Information($"Control Byte: 0x{controlByte:X2}"); // 输出控制字的十六进制表示
SendCustomMessageAsync(_context, _serverAddr, controlByte, 1,data);
sequence--;
if (sequence == 15)
{
sequence = 31;
}
}
bool IsConfirm = false;
//int sequence = 15;
//void SendTestData()
//{
// var data = SimulateData.SendProductionInformation();
// // 创建一个应用控制字实例
// ApplicationControlWord controlWord = new ApplicationControlWord(fir: true, fin: true, con: true, sequence: sequence);
// // 将控制字转换为字节
// byte controlByte = controlWord.ToByte();
// Log.Information($"Control Byte: 0x{controlByte:X2}"); // 输出控制字的十六进制表示
// SendCustomMessageAsync(_serverAddr, controlByte, 1, data);
// sequence++;
// if (sequence == 15)
// {
// sequence = 31;
// }
//}
public async override void ChannelActive(IChannelHandlerContext context)
{
try
{
string clientIp = context.Channel.RemoteAddress.ToString();
Log.Information($"客户端连接:{clientIp}", "103客户端发送消息");
await HandleHeartbeat(context, _serverAddr, heartbeatCount);
Log.Information($"客户端主动连接:{clientIp}");
//await HandleHeartbeat(context, _serverAddr, heartbeatCount);
base.ChannelActive(context);
}
catch (Exception ex)
{
Log.Information($"{ex.StackTrace}", "103客户端错误信息");
Log.Information($"{ex.StackTrace}");
}
}
@ -132,20 +121,30 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
try
{
string clientIp = context.Channel.RemoteAddress.ToString();
Log.Information($"客户端断开连接:{clientIp}", "103客户端发送消息");
Log.Information($"客户端主动断开连接:{clientIp}");
_channelInactiveCallback(clientIp);
base.ChannelInactive(context);
}
catch (Exception ex)
{
Log.Information($"{ex.StackTrace}", "103客户端错误信息");
Log.Error(ex,$"客户端主动断开连接错误");
}
}
protected async override void ChannelRead0(IChannelHandlerContext ctx, IByteBuffer msg)
{
_context = ctx;
try
{
// 将 IByteBuffer 转换为字节数组
byte[] dataSrc = new byte[msg.ReadableBytes];
msg.GetBytes(msg.ReaderIndex, dataSrc);
// 转换为十六进制字符串
string hexString = BitConverter.ToString(dataSrc).Replace("-", " ");
Log.Information($"收到 Hex Data: {hexString}");
//// 确保释放 ByteBufNetty 的缓冲区需要手动释放)
//msg.Release();
byte startByte = msg.ReadByte();
ushort length = msg.ReadUnsignedShort();
byte address = msg.ReadByte();
@ -156,7 +155,7 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
}
byte controlWord = msg.ReadByte();
byte functionType = msg.ReadByte();
// 计算数据长度
int dataLength = length - 6;
if (msg.ReadableBytes < dataLength)
@ -164,21 +163,32 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
// 数据不足,等待更多数据
return;
}
HanleRecvConfirmInfo(ctx, controlWord);
byte[] data = new byte[dataLength];
msg.ReadBytes(data);
string clientIp = ctx.Channel.RemoteAddress.ToString();
Log.Information($"客户端ip地址{clientIp}");
string description = FunctionCodeDescriptions.GetDescription(functionType);
Log.Information($"地址 {address} 功能码:{functionType} 数据长度:{dataLength}", "103客户端消息");
Log.Information($"地址 {address} 功能码:{functionType} 数据长度:{dataLength}", "103客户端消息");
Log.Information($"主站地址: {address} 功能码:{functionType} 数据长度:{dataLength} 数据:{BitConverter.ToString(data).Replace("-", "")}");
Task.Run(() => _onMessageReceived?.Invoke(address, data, functionType));
HandleFunctionCodeAsync(functionType, address, controlWord, data, ctx);
}
catch (Exception ex)
{
Log.Information($"Error in ChannelRead0: {ex.StackTrace}", "103客户端发送消息");
Log.Error(ex,$"Error in ChannelRead0: {ex.StackTrace}");
}
}
private async void HanleRecvConfirmInfo(IChannelHandlerContext ctx,byte controlWord)
{
int bit5 = (controlWord >> 5) & 1;
if (bit5 == 1)
{
// 提取低四位
byte lower4Bits = (byte)(controlWord & 0x1F); // 使用掩码 0x0F00001111保留低四位
// 创建一个应用控制字实例
ApplicationControlWord controlWordObj = new ApplicationControlWord(fir: true, fin: true, con: false, sequence: lower4Bits);
// 将控制字转换为字节
byte controlByte = controlWordObj.ToByte();
await SendCustomByteMessageAsync( _serverAddr, controlByte, 0, 0);
}
}
private void HandleHeatbeatInfo(IByteBuffer msg, byte address, IChannelHandlerContext ctx)
@ -187,58 +197,26 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
byte handleHeardata = msg.ReadByte();
if (handleHearfunctionType == 7)
{
if (_connections.ContainsKey(address))
{
_connections[address] = ctx;
}
else
{
_connections.Add(address, ctx);
}
string clientIp = ctx.Channel.RemoteAddress.ToString();
Log.Information($"接受到心跳信息:地址:{address} 序列号:{handleHeardata}");
if (_deviceRunStates.ContainsKey(address))
{
_deviceRunStates[address] = DateTime.Now;
}
else
{
_deviceRunStates.Add(address, DateTime.Now);
}
//await HandleHeartbeat(ctx, _serverAddr, handleHeardata);
_deviceRunStateTime = DateTime.Now;
}
}
private async Task HandleFunctionCodeAsync(byte functionType, byte address, byte controlWord, byte[] data, IChannelHandlerContext ctx)
{
switch (functionType)
{
case 0:
case 0: //确认报文
IsConfirm = true;
Log.Information("确认报文");
//
break;
case 1: //装置生产信息报文
Log.Information($"收到装置生产信息报文: {BitConverter.ToString(data)}");
break;
case 2:
// 装置版本信息报文
break;
case 3: //装置运行信息报文
Log.Information($"版本信息: {Encoding.ASCII.GetString(data)}", "103客户端信息");
break;
case 4:
// 板件状态自诊断信息报文
break;
case 5:
//装置运行状态自诊断信息报文
//MonitoringEventBus.LogHandler($"开入开出信息: {Encoding.ASCII.GetString(data)}", "103客户端信息");
break;
case 6:
//二次回路智能诊断信息报文
//await UpdateDeviceCommunicationStateAsync(address, data, ctx);
break;
case 10:
// 信息召唤
Log.Information("信息召唤");
//SendTestData();
break;
default:
//MonitoringEventBus.LogHandler("未知的功能码", "103客户端信息");
@ -254,11 +232,10 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
/// <returns></returns>
private async Task HandleHeartbeat(IChannelHandlerContext context, byte address, byte data)
{
if (context == null)
if (context == null|| !context.Channel.Open|| !context.Channel.Active)
{
return;
}
try
{
// 构建数据帧
@ -279,9 +256,14 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
await context.WriteAndFlushAsync(wrappedBuffer);
Log.Information($"发送心跳信息:序号:{data} 地址:{address}");
}
catch (ClosedChannelException ex)
{
await context.CloseAsync();
Log.Error(ex, "心跳信息ClosedChannelException");
}
catch (Exception ex)
{
Log.Error(ex, "心跳信息");
Log.Error(ex, "心跳信息Exception");
}
heartbeatCount++;
// 防止溢出
@ -294,27 +276,28 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
public override async void ExceptionCaught(IChannelHandlerContext context, Exception ex)
{
try
if (ex is ClosedChannelException)
{
//MonitoringEventBus.LogHandler(ex.Message, "103客户端错误消息");
Log.Information(ex, "错误消息");
await context.CloseAsync();
// 处理 Channel 被关闭的异常,关闭客户端连接
Log.Error(ex, "ClosedChannelException异常 连接已关闭,正在关闭客户端...");
await context.CloseAsync();
}
catch (Exception ex1)
else
{
//MonitoringEventBus.LogHandler($"Error: {ex1.StackTrace}", "关闭tcp客户端");
// 处理其他异常
Log.Error(ex, $"发生异常: {ex.Message}");
await context.CloseAsync();
}
}
// 发送自定义消息
public async Task SendCustomByteMessageAsync(IChannelHandlerContext context, byte address, byte controlWord, byte functionType, byte data)
private async Task SendCustomByteMessageAsync( byte address, byte controlWord, byte functionType, byte data)
{
try
{
await SendCustomMessageAsync(context, address, controlWord, functionType, new byte[] { data });
await SendCustomMessageAsync(address, controlWord, functionType, new byte[] { data });
}
catch (Exception ex)
{
@ -323,14 +306,16 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
}
// 发送自定义消息
public async Task SendCustomMessageAsync(IChannelHandlerContext context, byte address, byte controlWord, byte functionType, byte[] data)
private async Task SendCustomMessageAsync(byte address, byte controlWord, byte functionType, byte[] data)
{
try
{
if (context==null|| data == null|| data.Length==0)
if (_context==null || !_context.Channel.Open || !_context.Channel.Active || data == null|| data.Length==0)
{
return;
}
IsConfirm = false;
ushort dataLength = (ushort)(6 + data.Length);
// 构建数据帧
byte[] buffer = new byte[dataLength];
@ -338,8 +323,8 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
buffer[0] = 0x68;
// 填入长度假设数据部分为50字节2字节长度字段+1字节地址+1字节标志位
byte[] bytes = BitConverter.GetBytes(dataLength);
buffer[1] = bytes[0]; // 长度低字节
buffer[2] = bytes[1]; // 长度高字节
buffer[1] = bytes[1]; // 长度低字节
buffer[2] = bytes[0]; // 长度高字节
// 填入地址、应用控制字、功能类型
buffer[3] = address; // 示例地址
buffer[4] = controlWord; // 示例应用控制字
@ -348,17 +333,103 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
{
buffer[i] = data[i-6];
}
string hexString = BitConverter.ToString(buffer).Replace("-", " ");
Log.Information($"发送数据: 地址:{address} 功能码:{functionType} 控制字:{Convert.ToString(controlWord, 2).PadLeft(8, '0')} 数据:{hexString}");
// 填入数据部分
IByteBuffer wrappedBuffer = Unpooled.WrappedBuffer(buffer);
// 发送数据
await context.WriteAndFlushAsync(wrappedBuffer);
string hexString = BitConverter.ToString(buffer).Replace("-", " ");
Log.Information($"地址:{address} 功能码:{functionType} 数据:{hexString}");
await Task.Delay(100);
await _context.WriteAndFlushAsync(wrappedBuffer);
}
catch (ClosedChannelException ex)
{
await _context.CloseAsync();
}
catch (Exception ex)
{
Log.Information($"Error: {ex.StackTrace}");
Log.Error($"Error: {ex.StackTrace}");
}
}
private byte _controlWord = 15;
// 发送自定义消息
public async Task SendCustomMessageAsync(byte address, byte functionType, byte[] data)
{
try
{
if (_context == null || !_context.Channel.Open || !_context.Channel.Active || data == null || data.Length == 0)
{
return;
}
// 创建一个应用控制字实例
ApplicationControlWord controlWordObj = new ApplicationControlWord(fir: true, fin: true, con: true, sequence: _controlWord);
// 将控制字转换为字节
byte controlByte = controlWordObj.ToByte();
_controlWord++;
if (_controlWord == 31)
{
_controlWord = 15;
}
IsConfirm = false;
ushort dataLength = (ushort)(6 + data.Length);
// 构建数据帧
byte[] buffer = new byte[dataLength];
// 填入启动字符
buffer[0] = 0x68;
// 填入长度假设数据部分为50字节2字节长度字段+1字节地址+1字节标志位
byte[] bytes = BitConverter.GetBytes(dataLength);
buffer[1] = bytes[1]; // 长度低字节
buffer[2] = bytes[0]; // 长度高字节
// 填入地址、应用控制字、功能类型
buffer[3] = address; // 示例地址
buffer[4] = controlByte; // 示例应用控制字
buffer[5] = functionType; // 示例功能类型
for (ushort i = 6; i < dataLength; i++)
{
buffer[i] = data[i - 6];
}
string hexString = BitConverter.ToString(buffer).Replace("-", " ");
Log.Information($"发送数据: 地址:{address} 功能码:{functionType} 控制字:{Convert.ToString(controlByte, 2).PadLeft(8, '0')} 数据:{hexString}");
// 填入数据部分
IByteBuffer wrappedBuffer = Unpooled.WrappedBuffer(buffer);
// 发送数据
await _context.WriteAndFlushAsync(wrappedBuffer)
.ContinueWith(async task =>
{
await Task.Delay(300);
bool isSendSuccess = false;
for (ushort i = 0; i < 3; i++)
{
if (!IsConfirm)
{
await _context.WriteAndFlushAsync(wrappedBuffer);
}
else
{
isSendSuccess = true;
Log.Information($"成功确认");
break;
}
await Task.Delay(3000);
}
if (!isSendSuccess)
{
Log.Information($"超过三次未收到确认,断开连接");
await _context.CloseAsync();
}
});
}
catch (ClosedChannelException ex)
{
await _context.CloseAsync();
}
catch (Exception ex)
{
Log.Error($"Error: {ex.StackTrace}");
}
}

View File

@ -7,20 +7,40 @@ using DotNetty.Transport.Channels.Sockets;
using Serilog;
using System.Diagnostics;
using System.Runtime;
using Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.TestData;
namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
{
public class DotNettyTcpServer : ISingletonDependency
{
private readonly Dictionary<byte, IChannelHandlerContext> connections = new Dictionary<byte, IChannelHandlerContext>();
// 定义 MessageReceived 事件
public event Action< byte, byte[], byte> MessageReceived; // 装置地址,功能码,消息
public event Action<Dictionary<byte, int[]>> deviceBoardStatesAction;
public Dictionary<string,DotNettyServerHandler> dotNettyServerHandlers = new ();
public DotNettyTcpServer()
{
//_dotNettyServerHandler = dotNettyServerHandler;
MessageReceived += DotNettyTcpServer_MessageReceived;
}
private async void DotNettyTcpServer_MessageReceived(byte addr, byte[] data, byte functype)
{
if (functype == 10) //总召
{
SimulateData.Test1(this);
await Task.Delay(1000);
SimulateData.Test2(this);
await Task.Delay(1000);
SimulateData.Test3(this);
await Task.Delay(1000);
SimulateData.Test4(this);
await Task.Delay(1000);
}
}
MultithreadEventLoopGroup bossGroup ;
MultithreadEventLoopGroup workerGroup ;
int maxFrameLength = 65536; // 设置最大帧长度
@ -42,6 +62,7 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
.Option(ChannelOption.SoBacklog, 100)
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
var serverHandler = new DotNettyServerHandler(MessageReceived, OnChannelInactive, addr);
channel.Pipeline.AddLast(new LengthFieldBasedFrameDecoder(
maxFrameLength,
lengthFieldOffset,
@ -49,8 +70,18 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
lengthAdjustment,
initialBytesToStrip
));
channel.Pipeline.AddLast(new DotNettyServerHandler(connections, MessageReceived, deviceBoardStatesAction,addr));
channel.Pipeline.AddLast(serverHandler);
channel.Pipeline.AddLast("hexDumpHandler", new HexDumpHandler());
string ip = channel.RemoteAddress.ToString();
if (!dotNettyServerHandlers.ContainsKey(ip))
{
dotNettyServerHandlers.Add(ip, serverHandler);
}
else
{
dotNettyServerHandlers[ip] = serverHandler;
}
}));
IChannel boundChannel = await bootstrap.BindAsync(3000);
@ -60,8 +91,14 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
{
}
}
}
// 客户端断开连接时的回调
private void OnChannelInactive(string channelIp)
{
Console.WriteLine($"客户端断开连接: {channelIp}");
dotNettyServerHandlers.Remove(channelIp);
}
public async Task StopSeverAsync()
{
try
@ -76,65 +113,24 @@ namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.Server
}
}
public async void SendMessageByIp(byte address, byte controlWord, byte functionCode , byte message)
public async void SendMessage(byte address, byte functionType, string data)
{
if (connections.TryGetValue(address, out IChannelHandlerContext context))
try
{
try
foreach (var item in dotNettyServerHandlers.Values)
{
//var buffer = Unpooled.WrappedBuffer(System.Text.Encoding.UTF8.GetBytes(message));
//context.WriteAndFlushAsync(buffer);
// 构建数据帧
byte[] buffer = new byte[7];
// 填入启动字符
buffer[0] = 0x16;
// 填入长度假设数据部分为50字节2字节长度字段+1字节地址+1字节标志位
byte dataLength = 7;
buffer[1] = 0; // 长度低字节
buffer[2] = dataLength; // 长度高字节
// 填入地址、应用控制字、功能类型
buffer[3] = address; // 示例地址
buffer[4] = controlWord; // 示例应用控制字
buffer[5] = functionCode; // 示例功能类型
buffer[6] = message;
// 填入数据部分
IByteBuffer wrappedBuffer = Unpooled.WrappedBuffer(buffer);
// 发送数据
await context.WriteAndFlushAsync(wrappedBuffer);
//Debug.WriteLine($"发送消息到 装置:{address}: {message}");
string hexString = BitConverter.ToString(buffer);
//MonitoringEventBus.LogHandler($"地址:{address} 功能码:{functionCode} 数据:{hexString}", "103客户端发送消息");
//byte addr = byte(new Random().Next(1,99));
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(data);
await item.SendCustomMessageAsync(address, functionType, utf8Bytes);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString() );
}
}
else
catch (Exception ex)
{
Debug.WriteLine($"未找到 装置 为 {address} 的连接");
}
}
// 断开指定 IP 地址的连接
public void DisconnectByIp(byte addr)
{
if (connections.TryGetValue(addr, out IChannelHandlerContext context))
{
context.CloseAsync(); // 关闭连接
connections.Remove(addr); // 从字典中移除该连接
Debug.WriteLine($"断开 地址 为 {addr} 的连接");
}
else
{
Debug.WriteLine($"未找到 地址 为 {addr} 的连接");
Log.Error(ex,"");
}
}
}
}

View File

@ -3,16 +3,185 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceTcpData;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceHistoryChange;
using Serilog;
using Newtonsoft.Json;
namespace Yunda.SOMS.OperationsMainSiteGatewayServer.TcpSocket.TestData
{
public class SimulateData
{
private static int _sendNo = 1;
public static byte[] SendProductionInformation()
{
string msg = "{\r\n \"station\":\"Bengbu_South_Station\",\r\n \"device\":\"KX211\",\r\n\"timestamp\":\"2024-10-09 12:12:12\",\r\n\"reason\":1,\r\n\"param\":{\r\n \"type\":\" Production_Information\",\r\n\"paras\":\r\n {\r\n \"number\":\"202400xxxxxx\",\r\n \"date\":\"2024-10-09\",\r\n}\r\n}\r\n}\r\n";
byte[] utf8Bytes = System.Text.Encoding.UTF8.GetBytes(msg);
return utf8Bytes;
}
public static void Test1(Server.DotNettyTcpServer _dotNettyTcpServer)
{
Log.Information("执行装置履历测试...");
UploadMainstationBaseInfo<DeviceProductionInfo> uploadMainstationBaseInfo = new UploadMainstationBaseInfo<DeviceProductionInfo>()
{
Station = "德州变电所",
Device = "JDA-211 馈线保护测控装置",
EventType = "设备履历",
Subtype = "装置信息",
EventTime = "2024-15-16",
DATANO = _sendNo,
Info = "周期上送",
Detail = new DeviceProductionInfo
{
DeviceId = "240531914",
ManufacturerModel = "JDA-201",
InternalName = "201主变保护装置",
ManufacturerName = "交大运达电气",
DeviceSpecification = "DC110V/1A",
DeviceVersion = "4.0",
ManufacturingDate = "20240131",
B01PluginId = "1933CA00300001",
B02PluginId = "1933JA04100001",
B03PluginId = "2233IA220V400001",
B04PluginId = "2233IA220V400002",
B05PluginId = "2233OA0000400001",
B06PluginId = "2233OC220V400001",
B07PluginId = "1933DA00100001",
LCDBoardCardId = "1933YA01200001",
RepairRecords = "无维修" // 维修记录为空
}
};
var json = JsonConvert.SerializeObject(uploadMainstationBaseInfo, Formatting.Indented);
_dotNettyTcpServer.SendMessage(20, 1, json);
_sendNo++;
}
public static void Test2(Server.DotNettyTcpServer _dotNettyTcpServer)
{
Log.Information("执行设备参数报文测试...");
UploadMainstationBaseInfo<CommunicationParameters> uploadMainstationBaseInfo = new UploadMainstationBaseInfo<CommunicationParameters>()
{
Station = "德州变电所",
Device = "JDA-211 馈线保护测控装置",
EventType = "运行诊断",
Subtype = "装置自检",
EventTime = "2024-15-16",
DATANO = _sendNo,
Info = "周期上送",
Detail = new CommunicationParameters
{
IpPort1 = "192.168.1.110",
MaskPort1 = "255.255.255.0",
IpPort2 = "192.168.2.110",
MaskPort2 = "255.255.255.0",
IpPort3 = "192.168.3.110",
MaskPort3 = "255.255.255.0",
Gateway = "192.168.1.1",
SntpServer1Ip = "192.168.4.11",
SntpServer2Ip = "192.168.4.12"
}
};
var json = JsonConvert.SerializeObject(uploadMainstationBaseInfo, Formatting.Indented);
_dotNettyTcpServer.SendMessage(20, 2, json);
_sendNo++;
}
public static void Test3(Server.DotNettyTcpServer _dotNettyTcpServer)
{
Log.Information("执行运行诊断操作...");
UploadMainstationBaseInfo<AbnormalComponent> uploadMainstationBaseInfo = new UploadMainstationBaseInfo<AbnormalComponent>()
{
Station = "德州变电所",
Device = "JDA-211 馈线保护测控装置",
EventType = "运行诊断",
Subtype = "装置自检",
EventTime = "2024-15-16",
DATANO = _sendNo,
Info = "周期上送",
Detail = new AbnormalComponent
{
ComponentName = "机箱温度",
AbnormalReason = "当前值63°超过门限60°",
HandlingMeasures = "XXXXX"
}
};
var json = JsonConvert.SerializeObject(uploadMainstationBaseInfo, Formatting.Indented);
_dotNettyTcpServer.SendMessage(20, 3, json);
_sendNo++;
}
public static void Test4(Server.DotNettyTcpServer _dotNettyTcpServer)
{
Log.Information("执行运行状态操作...");
UploadMainstationBaseInfo<NetworkStatus> uploadMainstationBaseInfo = new UploadMainstationBaseInfo<NetworkStatus>()
{
Station = "德州变电所",
Device = "JDA-211 馈线保护测控装置",
EventType = "运行状态",
Subtype = "通信状态",
EventTime = "2024-15-16",
DATANO = _sendNo,
Info = "周期上送",
Detail = new NetworkStatus
{
// 网口1信息
Port1IpAddress = "192.168.1.11",
Port1Status = "up",
Port1SpeedType = "100M/s",
Port1StartTime = "2024-10-15 11:00:00",
Port1TotalTime = "12000s",
Port1SentFrames = 100,
Port1SentErrorFrames = 0,
Port1ReceivedFrames = 100,
Port1ReceivedErrorFrames = 0,
// 网口2信息
Port2IpAddress = "192.168.2.11",
Port2Status = "up",
Port2SpeedType = "100M/s",
Port2StartTime = "2024-10-15 11:00:00",
Port2TotalTime = "12000s",
Port2SentFrames = 100,
Port2SentErrorFrames = 0,
Port2ReceivedFrames = 100,
Port2ReceivedErrorFrames = 0,
// 网口3信息
Port3IpAddress = "192.168.3.11",
Port3Status = "up",
Port3SpeedType = "100M/s",
Port3StartTime = "2024-10-15 11:00:00",
Port3TotalTime = "12000s",
Port3SentFrames = 100,
Port3SentErrorFrames = 0,
Port3ReceivedFrames = 100,
Port3ReceivedErrorFrames = 0,
// 插件通信状态
Plugin1Status = "正常",
Plugin3Status = "正常",
Plugin4Status = "正常",
Plugin5Status = "异常",
Plugin7Status = "正常",
// 网络通信连接状态
NetworkConnection1Status = "连接",
NetworkConnection2Status = "断开",
NetworkConnection3Status = "连接",
NetworkConnection4Status = "连接",
NetworkConnection5Status = "断开",
NetworkConnection6Status = "连接",
NetworkConnection7Status = "断开",
NetworkConnection8Status = "连接"
}
};
var json = JsonConvert.SerializeObject(uploadMainstationBaseInfo, Formatting.Indented);
_dotNettyTcpServer.SendMessage(20, 4, json);
_sendNo++;
}
}
}

View File

@ -29,4 +29,10 @@
<PackageReference Include="Serilog.Sinks.Seq" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\YunDa.Application\YunDa.ISAS.DataTransferObject\YunDa.SOMS.DataTransferObject.csproj" />
<ProjectReference Include="..\src\YunDa.Domain\YunDa.ISAS.Redis.Entities\YunDa.SOMS.Redis.Entities.csproj" />
<ProjectReference Include="..\src\YunDa.Domain\YunDa.ISAS.Redis\YunDa.SOMS.Redis.csproj" />
</ItemGroup>
</Project>

View File

@ -112,7 +112,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RedisSubscriberConsole", "t
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yunda.SOMS.OperationsMainSiteGatewayServer", "OperationsMainSiteGatewayServer\Yunda.SOMS.OperationsMainSiteGatewayServer.csproj", "{505F0B5A-4AEB-499C-8937-19FE950B0354}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestCPU", "test\TestCPU\TestCPU.csproj", "{7D90211D-07EA-436E-8147-9D3296CEF400}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestCPU", "test\TestCPU\TestCPU.csproj", "{7D90211D-07EA-436E-8147-9D3296CEF400}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTest", "test\ConsoleTest\ConsoleTest.csproj", "{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -829,6 +831,24 @@ Global
{7D90211D-07EA-436E-8147-9D3296CEF400}.Template|x64.Build.0 = Debug|Any CPU
{7D90211D-07EA-436E-8147-9D3296CEF400}.Template|x86.ActiveCfg = Debug|Any CPU
{7D90211D-07EA-436E-8147-9D3296CEF400}.Template|x86.Build.0 = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Debug|x64.ActiveCfg = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Debug|x64.Build.0 = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Debug|x86.ActiveCfg = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Debug|x86.Build.0 = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Release|Any CPU.Build.0 = Release|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Release|x64.ActiveCfg = Release|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Release|x64.Build.0 = Release|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Release|x86.ActiveCfg = Release|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Release|x86.Build.0 = Release|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Template|Any CPU.ActiveCfg = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Template|Any CPU.Build.0 = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Template|x64.ActiveCfg = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Template|x64.Build.0 = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Template|x86.ActiveCfg = Debug|Any CPU
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E}.Template|x86.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -880,9 +900,10 @@ Global
{C63CFC48-EA3A-4EFA-83D9-693CF00C4424} = {F10AA149-2626-486E-85BB-9CD5365F3016}
{505F0B5A-4AEB-499C-8937-19FE950B0354} = {A49CD7CD-52BA-48F3-83D5-D6CA072F8849}
{7D90211D-07EA-436E-8147-9D3296CEF400} = {F10AA149-2626-486E-85BB-9CD5365F3016}
{3BE9DBEE-1FE7-44C7-93DA-7F213D43C44E} = {F10AA149-2626-486E-85BB-9CD5365F3016}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B516B1E8-1CEC-4BCC-BA92-93CB32845E37}
VisualSVNWorkingCopyRoot = .
SolutionGuid = {B516B1E8-1CEC-4BCC-BA92-93CB32845E37}
EndGlobalSection
EndGlobal

View File

@ -158,6 +158,14 @@ namespace YunDa.ISAS.Application.Core
string basePath = "";
return SetAttachmentFolder(ref basePath, ISASConsts.RobotAliasPathFolder);
}
/// <summary>
/// 获取机器人FTP文件保存路径使用带有appServiceConfiguration参数的构造器
/// </summary>
/// <returns></returns>
protected string GetAttachmentDirectory()
{
return _appServiceConfiguration?.SysAttachmentFolder;
}
///// <summary>
///// 获取
///// </summary>
@ -219,7 +227,30 @@ namespace YunDa.ISAS.Application.Core
}
}
protected string GetImageBase64(string imagePath)
{
if (!File.Exists(imagePath))
{
return "";
}
// 读取图片文件为字节数组
byte[] imageBytes = File.ReadAllBytes(imagePath);
// 转换为 Base64 编码字符串
return Convert.ToBase64String(imageBytes);
}
protected void Base64ToImage(string base64String, string outputPath)
{
// 确保目录存在
string directory = Path.GetDirectoryName(outputPath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
// 将 Base64 字符串转换为字节数组
byte[] imageBytes = Convert.FromBase64String(base64String);
// 将字节数组写入文件
File.WriteAllBytes(outputPath, imageBytes);
}
/// <summary>
/// 根据开始时间和结束时间生成yyyyMM字符串数组
/// </summary>

View File

@ -1215,6 +1215,12 @@
</summary>
<returns></returns>
</member>
<member name="M:YunDa.ISAS.Application.Core.ISASAppServiceBase.GetAttachmentDirectory">
<summary>
获取机器人FTP文件保存路径使用带有appServiceConfiguration参数的构造器
</summary>
<returns></returns>
</member>
<member name="M:YunDa.ISAS.Application.Core.ISASAppServiceBase.SpawnMongoCollectionMonthTailArray(System.DateTime,System.DateTime)">
<summary>
根据开始时间和结束时间生成yyyyMM字符串数组

View File

@ -486,7 +486,7 @@ namespace YunDa.ISAS.Application.GeneralInformation
return rst;
}
/// <summary>
/// 初始化遥队列
/// 初始化遥队列
/// </summary>
[HttpGet, AbpAllowAnonymous]
[ShowApi]
@ -522,13 +522,11 @@ namespace YunDa.ISAS.Application.GeneralInformation
.GroupBy(t => $"{t.DeviceAddress}_{t.CPUSector}_{t.DispatcherAddress}_{(int)t.DataSourceCategory}")
.Select(g => g.First()) // 只保留每组的第一个
.ToList();
// 输出去重后的数据
telemeterings = uniqueTelemeterings;
List<TelemeteringModel> telemeteringsRedis = await _telemeteringModelListRedis.HashSetGetAllAsync(rediskey);
if (telemeteringsRedis != null && telemeteringsRedis.Count > 0)
{
//// 假设 TelesignalisationModel 有一个 Id 属性作为比较依据
var difference = telemeterings
.Where(localItem => !telemeteringsRedis.Any(redisItem => redisItem.Id == localItem.Id))
@ -543,14 +541,11 @@ namespace YunDa.ISAS.Application.GeneralInformation
var entities = ObjectMapper.Map<List<TelemeteringModel>>(telemeterings);
_telemeteringModelListRedis.HashSetUpdateManyAsync(rediskey, ids, entities);
}
}
catch (Exception ex)
{
Log4Helper.Error(this.GetType(), "初始化遥测", ex);
}
}
/// <summary>
/// 初始化遥信队列

View File

@ -0,0 +1,174 @@
using Abp.Application.Services;
using Abp.Authorization;
using Abp.Collections.Extensions;
using Abp.Domain.Repositories;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YunDa.ISAS.Application.Core;
using YunDa.ISAS.Application.Core.Session;
using YunDa.ISAS.Application.Core.SwaggerHelper;
using YunDa.ISAS.DataTransferObject;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
using YunDa.SOMS.Entities.GeneralInformation;
namespace YunDa.ISAS.Application.GeneralInformation.ProtectionDevice
{
public class ProtecttionDeviceRedisAppService : ISASAppServiceBase, IApplicationService
{
private readonly IRepository<ProtectionDeviceInfo, Guid> _protectionDeviceInfoRepository;
private readonly IRepository<SecondaryCircuit, Guid> _secondaryCircuitRepository;
private readonly IRepository<SecondaryCircuitProtectionDevice, Guid> _secondaryCircuitProtectionDeviceRepository;
public ProtecttionDeviceRedisAppService(ISessionAppService sessionAppService,
IRepository<SecondaryCircuit, Guid> secondaryCircuitRepository,
IRepository<ProtectionDeviceInfo, Guid> protectionDeviceInfoRepository,
IRepository<SecondaryCircuitProtectionDevice, Guid> secondaryCircuitProtectionDeviceRepository
) : base(sessionAppService)
{
_protectionDeviceInfoRepository = protectionDeviceInfoRepository;
_secondaryCircuitRepository = secondaryCircuitRepository;
_secondaryCircuitProtectionDeviceRepository = secondaryCircuitProtectionDeviceRepository;
}
/// <summary>
/// 获取装置自检信息
/// </summary>
/// <returns></returns>
[AbpAllowAnonymous]
[ShowApi]
[HttpGet]
public RequestResult<List<EquipmentInfoAbnormalComponent>> GetEquipmentInfoAbnormalComponents(Guid stationId, Guid equipmentInfoId)
{
RequestResult<List<EquipmentInfoAbnormalComponent>> rst = new RequestResult<List<EquipmentInfoAbnormalComponent>>();
try
{
// 从仓库中获取所有保护设备信息
var devices = _protectionDeviceInfoRepository.GetAll()
.WhereIf(equipmentInfoId!=default,t=>t.EquipmentInfoId == equipmentInfoId)
.ToList();
// 定义可能的异常列表
var possibleAbnormalities = new List<(string ComponentName, string AbnormalReason, string HandlingMeasures)>
{
("DC5V电压1", "电压超出正常范围", "检查电源线路"),
("DC5V电压2", "电压过低", "更换电源模块"),
("DC5V电压3", "电压过高", "调节电源输出"),
("版本", "版本不匹配", "更新软件版本"),
("插件1通信", "通信中断", "检查插件连接"),
("插件3通信", "通信中断", "检查插件连接"),
("插件4通信", "通信中断", "检查插件连接"),
("插件5通信", "通信中断", "检查插件连接"),
("插件7通信", "通信中断", "检查插件连接"),
("机箱温度", "温度异常", "检查散热系统"),
("CPU温度", "温度异常", "检查CPU运行状态")
};
Random random = new Random();
var data = new List<EquipmentInfoAbnormalComponent>();
foreach (var device in devices)
{
foreach (var abnormality in possibleAbnormalities)
{
// 随机生成正常或异常状态
bool isNormal = random.NextDouble() > 0.5; // 50% 概率
data.Add(new EquipmentInfoAbnormalComponent
{
EquipmentInfoId = device.EquipmentInfoId,
ComponentName = isNormal ? $"{abnormality.ComponentName}正常" : $"{abnormality.ComponentName}异常",
AbnormalReason = isNormal ? "无" : abnormality.AbnormalReason,
HandlingMeasures = isNormal ? "无需处理" : abnormality.HandlingMeasures
});
}
}
rst.ResultData = data;
rst.Flag = true;
}
catch (Exception ex)
{
throw;
}
return rst;
}
/// <summary>
/// 获取二次回路诊断信息
/// </summary>
/// <returns></returns>
[AbpAllowAnonymous]
[ShowApi]
[HttpGet]
public RequestResult<List<SecondaryCircuitComponent>> GetSecondaryCircuitComponents(Guid stationId, Guid equipmentInfoId)
{
RequestResult<List<SecondaryCircuitComponent>> rst = new RequestResult<List<SecondaryCircuitComponent>>();
try
{
var secondaryCircuitProtectionDevice = _secondaryCircuitProtectionDeviceRepository
.GetAllIncluding(t => t.ProtectionDevice,t=>t.SecondaryCircuit)
.WhereIf(equipmentInfoId!=default,t=>t.ProtectionDevice.EquipmentInfoId == equipmentInfoId)
.ToList();
var data = secondaryCircuitProtectionDevice.Select(t => new SecondaryCircuitComponent
{
SecondaryCircuitName = t.SecondaryCircuit.Name,
ComponentName = "回路正常",
AbnormalReason = "表达式(900A)值在范围1000A内",
SecondaryCircuitId = t.SecondaryCircuitId,
EquipmentInfoId = t.ProtectionDevice.EquipmentInfoId
});
rst.ResultData = data.ToList();
rst.Flag = true;
}
catch (Exception ex)
{
throw;
}
return rst;
}
/// <summary>
/// 获取装置寿命预测信息
/// </summary>
/// <returns></returns>
[AbpAllowAnonymous]
[ShowApi]
[HttpGet]
public RequestResult<List<EquipmentInfoRemainingLifeAssessment>> GetEquipmentInfoRemainingLifeAssessments(Guid stationId, Guid equipmentInfoId)
{
RequestResult<List<EquipmentInfoRemainingLifeAssessment>> rst = new RequestResult<List<EquipmentInfoRemainingLifeAssessment>>();
try
{
var decices = _protectionDeviceInfoRepository
.GetAllIncluding()
.WhereIf(equipmentInfoId != default, t => t.EquipmentInfoId == equipmentInfoId)
.ToList();
var data = decices.Select(t => new EquipmentInfoRemainingLifeAssessment
{
EquipmentInfoId = t.EquipmentInfoId,
RemainingLifeInYears ="5.8年"
});
rst.ResultData = data.ToList();
rst.Flag = true;
}
catch (Exception ex)
{
throw;
}
return rst;
}
}
}

View File

@ -3,10 +3,12 @@ using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.EntityFrameworkCore.Repositories;
//using Google.Protobuf.WellKnownTypes;
using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -66,6 +68,8 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
return result;
}
ObjectMapper.Map(input, entity);
entity.PicturePath = Path.Combine(base.GetAttachmentDirectory(), "images","circuit", $"{input.Name}.jpg");
base.Base64ToImage(input.PictureBase64, entity.PicturePath);
entity.LastModificationTime = DateTime.Now;
entity.LastModifierUserId = base.GetCurrentUser().Id;
}
@ -75,9 +79,10 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
entity = ObjectMapper.Map<SecondaryCircuit>(input);
entity.CreationTime = DateTime.Now;
entity.CreatorUserId = base.GetCurrentUser().Id;
entity.PicturePath = Path.Combine(base.GetAttachmentDirectory(), "images","circuit", $"{input.Name}.jpg");
base.Base64ToImage(input.PictureBase64, entity.PicturePath);
await _secondaryCircuitRepository.InsertAsync(entity);
}
result.ResultData = ObjectMapper.Map<SecondaryCircuitOutput>(entity);
result.Flag = true;
}
@ -178,7 +183,8 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
{
query = query.Where(x => x.IsActive == searchCondition.SearchCondition.IsOnlyActive.Value);
}
if (searchCondition.SearchCondition.CircuitType.HasValue)
if (searchCondition.SearchCondition.CircuitType.HasValue&& Enum.IsDefined(typeof(CircuitTypeEnum), searchCondition.SearchCondition.CircuitType.Value))
{
query = query.Where(x => x.CircuitType == searchCondition.SearchCondition.CircuitType.Value);
}
@ -315,7 +321,10 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
}
#if DEBUG
// 生成测试数据方法
/// <summary>
/// 生成10个测试回路信息
/// </summary>
/// <returns></returns>
[HttpGet]
[ShowApi]
[DisableAuditing]
@ -324,10 +333,9 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
{
Guid transstationId = new Guid("08d87a1b-f61d-4673-8532-680d307e5d12");
var currentUserId = base.GetCurrentUser().Id;
// 测试数据列表
var testData = new List<SecondaryCircuit>();
string base64png = GetImageBase64(Path.Combine(base.GetAttachmentDirectory(), "images","circuit", "断路器控制回路.png"));
// 生成交流回路 20 条数据
for (int i = 1; i <= 20; i++)
{
@ -336,7 +344,8 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
SeqNo = i,
Name = $"交流回路_{i}",
CircuitType = CircuitTypeEnum.ACCircuit,
PicturePath = $"/images/accircuit_{i}.png",
PicturePath = $"/images/circuit/断路器控制回路.png",
PictureBase64 = base64png,
Code = $"ACC{i:D3}",
TransformerSubstationId = transstationId, // 生成一个随机的变电站ID可根据实际情况调整
Description = $"交流回路描述_{i}",
@ -356,7 +365,8 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
SeqNo = i + 20,
Name = $"控制回路_{i}",
CircuitType = CircuitTypeEnum.ControlCircuit,
PicturePath = $"/images/controlcircuit_{i}.png",
PicturePath = $"/images/circuit/断路器控制回路.png",
PictureBase64 = base64png,
Code = $"CTRL{i:D3}",
TransformerSubstationId = transstationId, // 生成一个随机的变电站ID可根据实际情况调整
Description = $"控制回路描述_{i}",
@ -376,7 +386,8 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
SeqNo = i + 40,
Name = $"光纤回路_{i}",
CircuitType = CircuitTypeEnum.OpticalFiberCircuit,
PicturePath = $"/images/opticalfibercircuit_{i}.png",
PicturePath = $"/images/circuit/断路器控制回路.png",
PictureBase64 = base64png,
Code = $"OFC{i:D3}",
TransformerSubstationId = transstationId, // 生成一个随机的变电站ID可根据实际情况调整
Description = $"光纤回路描述_{i}",

View File

@ -1,4 +1,5 @@
using Abp.Authorization;
using Abp.Domain.Entities;
using Abp.Domain.Repositories;
using Microsoft.AspNetCore.Mvc;
using System;
@ -12,9 +13,12 @@ using YunDa.ISAS.Application.Core.Configuration;
using YunDa.ISAS.Application.Core.Session;
using YunDa.ISAS.Application.Core.SwaggerHelper;
using YunDa.ISAS.DataTransferObject;
using YunDa.ISAS.Entities.DataMonitoring;
using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto.SearchCondition;
using YunDa.SOMS.DataTransferObject.GeneralInformation.SecondaryCircuitDto;
using YunDa.SOMS.Entities.GeneralInformation;
using static iText.StyledXmlParser.Jsoup.Select.Evaluator;
using static NetMQ.NetMQSelector;
namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
{
@ -25,15 +29,25 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
{
private readonly IRepository<SecondaryCircuit, Guid> _secondaryCircuitRepository;
private readonly IRepository<SecondaryCircuitLogicExpression, Guid> _secondaryCircuitLogicExpressionRepository;
private readonly IRepository<SecondaryCircuitProtectionDevice, Guid> _secondaryCircuitProtectionDeviceRepository;
private readonly IRepository<TelemeteringConfiguration, Guid> _telemeteringConfigurationRepository;
private readonly IRepository<TelesignalisationConfiguration, Guid> _telesignalisationConfigurationRepository;
public SecondaryCircuitLogicExpressionAppService(ISessionAppService sessionAppService,
IRepository<SecondaryCircuitLogicExpression, Guid> secondaryCircuitLogicExpressionRepository,
IRepository<SecondaryCircuit, Guid> secondaryCircuitRepository,
IAppServiceConfiguration appServiceConfiguration) : base(sessionAppService, appServiceConfiguration)
IRepository<SecondaryCircuitProtectionDevice, Guid> secondaryCircuitProtectionDeviceRepository,
IRepository<TelemeteringConfiguration, Guid> telemeteringConfigurationRepository,
IRepository<TelesignalisationConfiguration, Guid> telesignalisationConfigurationRepository,
IAppServiceConfiguration appServiceConfiguration) : base(sessionAppService, appServiceConfiguration)
{
_secondaryCircuitLogicExpressionRepository = secondaryCircuitLogicExpressionRepository;
_secondaryCircuitRepository = secondaryCircuitRepository;
_secondaryCircuitProtectionDeviceRepository = secondaryCircuitProtectionDeviceRepository;
_telemeteringConfigurationRepository = telemeteringConfigurationRepository;
_telesignalisationConfigurationRepository = telesignalisationConfigurationRepository;
}
/// <summary>
/// 添加或者修改二次回路的逻辑表达式
@ -67,9 +81,26 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
// 新建逻辑
entity = ObjectMapper.Map<SecondaryCircuitLogicExpression>(input);
entity.CreationTime = DateTime.Now;
var secondaryCircuitProtectionDevice = _secondaryCircuitProtectionDeviceRepository.GetAllIncluding(t => t.ProtectionDevice, t => t.ProtectionDevice.EquipmentInfo)
.Where(t => t.SecondaryCircuitId == input.SecondaryCircuitId).FirstOrDefault();
if (secondaryCircuitProtectionDevice != null)
{
var dispatchaddr = _telemeteringConfigurationRepository.GetAll().Where(t => t.DataSourceCategory == DataSourceCategoryEnum.None).Select(t => t.DispatcherAddress).Max() + 1;
var telemetering = InsertTelemetering(secondaryCircuitProtectionDevice, entity.Name, dispatchaddr);
var telemeteringId = await _telemeteringConfigurationRepository.InsertAndGetIdAsync(telemetering);
if (telemeteringId!=default)
{
entity.TelemeteringConfigurationId = telemeteringId;
}
var telesignal = InsertTelesignal(secondaryCircuitProtectionDevice, entity.Name);
var telesignalId = await _telesignalisationConfigurationRepository.InsertAndGetIdAsync(telesignal);
if (telesignalId!= default)
{
entity.TelesignalisationConfigurationId = telesignalId;
}
}
await _secondaryCircuitLogicExpressionRepository.InsertAsync(entity);
}
result.ResultData = null;// ObjectMapper.Map<SecondaryCircuitLogicExpressionOutput>(entity);
result.Flag = true;
}
@ -81,7 +112,67 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
}
return result;
}
private TelemeteringConfiguration InsertTelemetering(SecondaryCircuitProtectionDevice secondaryCircuitProtectionDevice, string secondaryCircuitName, int dispatchaddr)
{
if (secondaryCircuitProtectionDevice!=null)
{
// 新增的记录
var entity = new TelemeteringConfiguration();
entity.DispatcherAddress = 0;
entity.CPUSector = 0;
entity.DeviceAddress = 0;
entity.InfoAddress = 0;
entity.InfoCPUSector = 0;
entity.InfoDeviceAddress = dispatchaddr;
entity.IsVirtualDevice = true;
entity.IsSelfCheckingValue = false;
entity.Name = $"{secondaryCircuitName}_判定遥测";
entity.SeqNo = 100000;
entity.IsActive = true;
entity.IsSave = false;
entity.IsSendDispatcher = false;
entity.IsVisible = true;
entity.UpperLimit = 10;
entity.LowerLimit = 0;
entity.DecimalDigits = 2;
entity.Coefficient = 1;
entity.Unit = "";
entity.TransformerSubstationId = secondaryCircuitProtectionDevice.ProtectionDevice.TransformerSubstationId;
entity.DataSourceCategory = DataSourceCategoryEnum.None;
entity.EquipmentInfoId = secondaryCircuitProtectionDevice.ProtectionDevice.EquipmentInfoId;
entity.EquipmentTypeId = secondaryCircuitProtectionDevice.ProtectionDevice.EquipmentInfo.EquipmentTypeId;
return entity;
}
return null;
}
private TelesignalisationConfiguration InsertTelesignal(SecondaryCircuitProtectionDevice secondaryCircuitProtectionDevice, string secondaryCircuitName)
{
// 新增的记录
var entity = new TelesignalisationConfiguration
{
Name = $"{secondaryCircuitName}_判定虚遥信",
DispatcherAddress = 0,
CPUSector = 0,
DeviceAddress = 0,
InfoAddress = 0,
InfoCPUSector = 0,
InfoDeviceAddress = 0,
IsVirtualDevice = true,
IsSelfCheckingValue = false,
SeqNo = 100000,
IsActive = true,
IsSave = false,
IsSendDispatcher = true,
IsVisible = true,
RemoteType = RemoteTypeEnum.DoublePoint,
YesContent = "故障",
NoContent = "消失",
UnsurenessContent = "不定",
IsCommStatus = false,
TransformerSubstationId = secondaryCircuitProtectionDevice.ProtectionDevice.TransformerSubstationId,
};
return entity;
}
[HttpGet]
[ShowApi]
[AbpAllowAnonymous]
@ -90,6 +181,12 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
RequestEasyResult result = new RequestEasyResult();
try
{
var entity = await _secondaryCircuitLogicExpressionRepository.FirstOrDefaultAsync(id);
if (entity != null)
{
await _telesignalisationConfigurationRepository.DeleteAsync(entity.TelesignalisationConfigurationId.Value);
await _telemeteringConfigurationRepository.DeleteAsync(entity.TelemeteringConfigurationId.Value);
}
await _secondaryCircuitLogicExpressionRepository.DeleteAsync(id);
result.Flag = true;
}
@ -116,6 +213,12 @@ namespace YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo
{
foreach (var id in ids)
{
var entity = await _secondaryCircuitLogicExpressionRepository.FirstOrDefaultAsync(id);
if (entity != null)
{
await _telesignalisationConfigurationRepository.DeleteAsync(entity.TelesignalisationConfigurationId.Value);
await _telemeteringConfigurationRepository.DeleteAsync(entity.TelemeteringConfigurationId.Value);
}
await _secondaryCircuitLogicExpressionRepository.DeleteAsync(id);
}
result.Flag = true;

View File

@ -2709,7 +2709,7 @@
</member>
<member name="M:YunDa.ISAS.Application.GeneralInformation.EquipmentInfoExAppService.InitYCListAsync(YunDa.ISAS.Entities.DataMonitoring.DataSourceCategoryEnum)">
<summary>
初始化遥队列
初始化遥队列
</summary>
</member>
<member name="M:YunDa.ISAS.Application.GeneralInformation.EquipmentInfoExAppService.InitYXListAsync(YunDa.ISAS.Entities.DataMonitoring.DataSourceCategoryEnum)">
@ -3592,6 +3592,24 @@
写装置履历xml文件
</summary>
</member>
<member name="M:YunDa.ISAS.Application.GeneralInformation.ProtectionDevice.ProtecttionDeviceRedisAppService.GetEquipmentInfoAbnormalComponents(System.Guid,System.Guid)">
<summary>
获取装置自检信息
</summary>
<returns></returns>
</member>
<member name="M:YunDa.ISAS.Application.GeneralInformation.ProtectionDevice.ProtecttionDeviceRedisAppService.GetSecondaryCircuitComponents(System.Guid,System.Guid)">
<summary>
获取二次回路诊断信息
</summary>
<returns></returns>
</member>
<member name="M:YunDa.ISAS.Application.GeneralInformation.ProtectionDevice.ProtecttionDeviceRedisAppService.GetEquipmentInfoRemainingLifeAssessments(System.Guid,System.Guid)">
<summary>
获取装置寿命预测信息
</summary>
<returns></returns>
</member>
<member name="M:YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo.IProtectionSettingAppService.FindDZDataByEquipmentInfoId(System.Nullable{System.Guid},System.String)">
<summary>
查询定值信息
@ -3637,6 +3655,12 @@
</summary>
<returns></returns>
</member>
<member name="M:YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo.SecondaryCircuitAppService.GenerateSecondaryCircuitTestData">
<summary>
生成10个测试回路信息
</summary>
<returns></returns>
</member>
<member name="T:YunDa.ISAS.Application.GeneralInformation.SecondaryCircuitInfo.SecondaryCircuitLogicExpressionAppService">
<summary>
二次回路逻辑表达式类

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YunDa.SOMS.DataTransferObject.CommonDto
{
public struct TimeValue
{
public DateTime Time { get; set; }
public double Value { get; set; }
}
}

View File

@ -39,7 +39,7 @@ namespace YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionSettingDto
/// <summary>
/// 数值(统一使用字符串表示)
/// </summary>
public string Value { get; set; } = "";
public string Value { get; set; } =( new Random().Next(0,10)).ToString();
}
}

View File

@ -32,11 +32,6 @@ namespace YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoD
/// </summary>
public virtual CircuitTypeEnum CircuitType { get; set; }
/// <summary>
/// 关联显示图片路径
/// </summary>
public virtual string PicturePath { get; set; }
/// <summary>
/// 编码
/// </summary>
@ -45,7 +40,7 @@ namespace YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoD
/// 所属变电站
/// </summary>
public virtual Guid TransformerSubstationId { get; set; }
public virtual string PictureBase64 { get; set; }
/// <summary>
/// 描述
/// </summary>

View File

@ -11,6 +11,7 @@ using YunDa.SOMS.Entities.GeneralInformation;
using Abp.AutoMapper;
using YunDa.ISAS.DataTransferObject.DataMonitoring.TelemeteringConfigurationDto;
using Abp.Application.Services.Dto;
using YunDa.ISAS.DataTransferObject.DataMonitoring.TelesignalisationConfigurationDto;
namespace YunDa.SOMS.DataTransferObject.GeneralInformation.SecondaryCircuitDto
{
@ -48,7 +49,7 @@ namespace YunDa.SOMS.DataTransferObject.GeneralInformation.SecondaryCircuitDto
/// </summary>
public virtual Guid? TelesignalisationConfigurationId { get; set; }
public virtual TelemeteringConfigurationProperty TelesignalisationConfiguration { get; set; }
public virtual TelesignalisationConfigurationProperty TelesignalisationConfiguration { get; set; }
/// <summary>
/// 备注

View File

@ -49,8 +49,8 @@ namespace YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoD
/// 所属变电站
/// </summary>
public virtual Guid TransformerSubstationId { get; set; }
public virtual string PictureBase64 { get; set; }
public virtual TransformerSubstation TransformerSubstation { get; set; }
/// <summary>
/// 描述
/// </summary>

View File

@ -7,34 +7,55 @@ using System.Threading.Tasks;
namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceHistoryChange
{
public class DeviceProductionInfo: UploadMainstationBaseDetailInfo
public class DeviceProductionInfo
{
[JsonProperty("装置名称")]
public string DeviceName { get; set; }
[JsonProperty("装置编号")]
public string DeviceId { get; set; }
[JsonProperty("装置型号")]
public string DeviceModel { get; set; }
[JsonProperty("厂家型号")]
public string ManufacturerModel { get; set; }
[JsonProperty("厂家内部名称")]
public string InternalName { get; set; }
[JsonProperty("厂家名称")]
public string ManufacturerName { get; set; }
[JsonProperty("装置规格")]
public string DeviceSpecification { get; set; }
[JsonProperty("装置出厂编号")]
public string DeviceSerialNumber { get; set; }
[JsonProperty("装置版本")]
public string DeviceVersion { get; set; }
[JsonProperty("装置生产日期")]
public DateTime ProductionDate { get; set; }
[JsonProperty("出厂日期")]
public string ManufacturingDate { get; set; }
[JsonProperty("装置检验日期")]
public DateTime InspectionDate { get; set; }
[JsonProperty("B01插件编号")]
public string B01PluginId { get; set; }
[JsonProperty("装置检验人员")]
public string Inspector { get; set; }
[JsonProperty("B02插件编号")]
public string B02PluginId { get; set; }
[JsonProperty("装置检验结果")]
public string InspectionResult { get; set; }
[JsonProperty("B03插件编号")]
public string B03PluginId { get; set; }
[JsonProperty("板卡信息")]
public List<BoardProductionInfo> BoardInfoList { get; set; }
[JsonProperty("B04插件编号")]
public string B04PluginId { get; set; }
[JsonProperty("B05插件编号")]
public string B05PluginId { get; set; }
[JsonProperty("B06插件编号")]
public string B06PluginId { get; set; }
[JsonProperty("B07插件编号")]
public string B07PluginId { get; set; }
[JsonProperty("液晶板卡编号")]
public string LCDBoardCardId { get; set; }
[JsonProperty("维修记录")]
public string RepairRecords { get; set; }
}
public class BoardProductionInfo

View File

@ -10,7 +10,7 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceOperati
/// <summary>
/// 设备参数信息
/// </summary>
public class DeviceParameterInfo: UploadMainstationBaseDetailInfo
public class DeviceParameterInfo
{
[JsonProperty("通道参数")]
public List<ChannelParameter> ChannelParameters { get; set; }

View File

@ -10,7 +10,7 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceOperati
/// <summary>
/// 运行信息
/// </summary>
public class RunningInfo: UploadMainstationBaseDetailInfo
public class RunningInfo
{
[JsonProperty("对时信息")]
public string TimeSyncInfo { get; set; }

View File

@ -10,7 +10,7 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceOperati
/// <summary>
/// 定值信息
/// </summary>
public class SettingSolidificationInfo: UploadMainstationBaseDetailInfo
public class SettingSolidificationInfo
{
[JsonProperty("定值固化信息")]
public SettingSolidification SettingSolidification { get; set; }

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceOperationWarning
{
public class VersionInfo: UploadMainstationBaseDetailInfo
public class VersionInfo
{
[JsonProperty("基线板本")]
public string BaselineBoard { get; set; }

View File

@ -10,7 +10,7 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceParamet
/// <summary>
/// 回路诊断
/// </summary>
public class CircuitWarning: UploadMainstationBaseDetailInfo
public class CircuitWarning
{
[JsonProperty("回路名称")]
public string CircuitName { get; set; }

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceParameterChange
{
public class LifeSpanWarning: UploadMainstationBaseDetailInfo
public class LifeSpanWarning
{
[JsonProperty("状态")]
public string Status { get; set; }

View File

@ -10,7 +10,7 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.DeviceParamet
/// <summary>
/// 自检信息
/// </summary>
public class SelfCheckWarning : UploadMainstationBaseDetailInfo
public class SelfCheckWarning
{
[JsonProperty("插件板件信息")]
public List<PluginBoardInfo> PluginBoardInfo { get; set; }

View File

@ -0,0 +1,72 @@
using MessagePack;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport
{
/// <summary>
/// 装置自检
/// </summary>
[MessagePackObject(keyAsPropertyName: true)]
public class AbnormalComponent
{
/// <summary>
/// 异常元件的名称
/// </summary>
[JsonProperty("异常元件")]
public string ComponentName { get; set; }
/// <summary>
/// 异常原因描述
/// </summary>
[JsonProperty("异常原因")]
public string AbnormalReason { get; set; }
/// <summary>
/// 建议的处理措施
/// </summary>
[JsonProperty("处理措施")]
public string HandlingMeasures { get; set; }
}
/// <summary>
/// 装置自检信息
/// </summary>
[MessagePackObject(keyAsPropertyName: true)]
public class EquipmentInfoAbnormalComponent: AbnormalComponent
{
public Guid EquipmentInfoId { get; set; }
}
[MessagePackObject(keyAsPropertyName: true)]
public class SecondaryCircuitComponent : AbnormalComponent
{
public Guid EquipmentInfoId { get; set; }
public string SecondaryCircuitName { get; set; }
public Guid SecondaryCircuitId { get; set; }
}
/// <summary>
/// 寿命诊断
/// </summary>
[MessagePackObject(keyAsPropertyName: true)]
public class RemainingLifeAssessment
{
/// <summary>
/// 剩余寿命(单位:年)。
/// </summary>
[JsonProperty("剩余寿命评估")]
public string RemainingLifeInYears { get; set; }
}
[MessagePackObject(keyAsPropertyName: true)]
public class EquipmentInfoRemainingLifeAssessment: RemainingLifeAssessment
{
/// <summary>
/// 设备名称。
/// </summary>
public Guid EquipmentInfoId { get; set; }
}
}

View File

@ -0,0 +1,138 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport
{
public class NetworkStatus
{
// 网口1信息
[JsonProperty("网口1IP地址")]
public string Port1IpAddress { get; set; }
[JsonProperty("网口1状态")]
public string Port1Status { get; set; }
[JsonProperty("网口1速率类型")]
public string Port1SpeedType { get; set; }
[JsonProperty("网口1起始时间")]
public string Port1StartTime { get; set; }
[JsonProperty("网口1累计时间")]
public string Port1TotalTime { get; set; }
[JsonProperty("网口1发送帧数")]
public long Port1SentFrames { get; set; }
[JsonProperty("网口1发送错误帧数")]
public long Port1SentErrorFrames { get; set; }
[JsonProperty("网口1接收帧数")]
public long Port1ReceivedFrames { get; set; }
[JsonProperty("网口1接收错误帧数")]
public long Port1ReceivedErrorFrames { get; set; }
// 网口2信息
[JsonProperty("网口2IP地址")]
public string Port2IpAddress { get; set; }
[JsonProperty("网口2状态")]
public string Port2Status { get; set; }
[JsonProperty("网口2速率类型")]
public string Port2SpeedType { get; set; }
[JsonProperty("网口2起始时间")]
public string Port2StartTime { get; set; }
[JsonProperty("网口2累计时间")]
public string Port2TotalTime { get; set; }
[JsonProperty("网口2发送帧数")]
public long Port2SentFrames { get; set; }
[JsonProperty("网口2发送错误帧数")]
public long Port2SentErrorFrames { get; set; }
[JsonProperty("网口2接收帧数")]
public long Port2ReceivedFrames { get; set; }
[JsonProperty("网口2接收错误帧数")]
public long Port2ReceivedErrorFrames { get; set; }
// 网口3信息
[JsonProperty("网口3IP地址")]
public string Port3IpAddress { get; set; }
[JsonProperty("网口3状态")]
public string Port3Status { get; set; }
[JsonProperty("网口3速率类型")]
public string Port3SpeedType { get; set; }
[JsonProperty("网口3起始时间")]
public string Port3StartTime { get; set; }
[JsonProperty("网口3累计时间")]
public string Port3TotalTime { get; set; }
[JsonProperty("网口3发送帧数")]
public long Port3SentFrames { get; set; }
[JsonProperty("网口3发送错误帧数")]
public long Port3SentErrorFrames { get; set; }
[JsonProperty("网口3接收帧数")]
public long Port3ReceivedFrames { get; set; }
[JsonProperty("网口3接收错误帧数")]
public long Port3ReceivedErrorFrames { get; set; }
// 插件通信状态
[JsonProperty("插件1通信状态")]
public string Plugin1Status { get; set; }
[JsonProperty("插件3通信状态")]
public string Plugin3Status { get; set; }
[JsonProperty("插件4通信状态")]
public string Plugin4Status { get; set; }
[JsonProperty("插件5通信状态")]
public string Plugin5Status { get; set; }
[JsonProperty("插件7通信状态")]
public string Plugin7Status { get; set; }
// 网络通信连接状态
[JsonProperty("网络通信连接1状态")]
public string NetworkConnection1Status { get; set; }
[JsonProperty("网络通信连接2状态")]
public string NetworkConnection2Status { get; set; }
[JsonProperty("网络通信连接3状态")]
public string NetworkConnection3Status { get; set; }
[JsonProperty("网络通信连接4状态")]
public string NetworkConnection4Status { get; set; }
[JsonProperty("网络通信连接5状态")]
public string NetworkConnection5Status { get; set; }
[JsonProperty("网络通信连接6状态")]
public string NetworkConnection6Status { get; set; }
[JsonProperty("网络通信连接7状态")]
public string NetworkConnection7Status { get; set; }
[JsonProperty("网络通信连接8状态")]
public string NetworkConnection8Status { get; set; }
}
}

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport
{
public class RunningStatus: UploadMainstationBaseDetailInfo
public class RunningStatus
{
[JsonProperty("MMS连接状态")]
public List<MMSConnectionStatus> MMSConnectionStatus { get; set; }

View File

@ -7,12 +7,5 @@ using System.Threading.Tasks;
namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo
{
public abstract class UploadMainstationBaseDetailInfo
{
/// <summary>
/// 序号
/// </summary>
[JsonProperty(nameof(DATANO))]
public virtual int DATANO { get; set; }
}
}

View File

@ -1,4 +1,5 @@
using System;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -11,36 +12,41 @@ namespace YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo
/// <summary>
/// 获取或设置厂站名称。
/// </summary>
public string Station { get; set; }
[JsonProperty("所亭")]public string Station { get; set; }
/// <summary>
/// 获取或设置设备名称。
/// </summary>
public string Device { get; set; }
[JsonProperty("装置名称")] public string Device { get; set; }
/// <summary>
/// 获取或设置事件类型。
/// </summary>
public string EventType { get; set; }
[JsonProperty("信息大类")] public string EventType { get; set; }
/// <summary>
/// 获取或设置事件子类型。
/// </summary>
public string Subtype { get; set; }
[JsonProperty("信息子类")] public string Subtype { get; set; }
/// <summary>
/// 获取或设置事件发生时间。
/// </summary>
public DateTime EventTime { get; set; }
[JsonProperty("信息更新时间")] public string EventTime { get; set; }
/// <summary>
/// 序号
/// </summary>
[JsonProperty("信息更新序号")]
public virtual int DATANO { get; set; }
/// <summary>
/// 获取或设置事件的简要信息。
/// </summary>
public string Info { get; set; }
[JsonProperty("上送原因")] public string Info { get; set; }
/// <summary>
/// 获取或设置事件的详细信息。
/// </summary>
public T Detail { get; set; }
[JsonProperty("详细信息")] public T Detail { get; set; }
}
}

View File

@ -15295,11 +15295,6 @@
回路类型
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto.EditSecondaryCircuitInput.PicturePath">
<summary>
关联显示图片路径
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto.EditSecondaryCircuitInput.Code">
<summary>
编码
@ -15585,9 +15580,44 @@
板卡信息
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.UploadMainstationBaseDetailInfo.DATANO">
<member name="T:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport.AbnormalComponent">
<summary>
序号
装置自检
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport.AbnormalComponent.ComponentName">
<summary>
异常元件的名称
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport.AbnormalComponent.AbnormalReason">
<summary>
异常原因描述
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport.AbnormalComponent.HandlingMeasures">
<summary>
建议的处理措施
</summary>
</member>
<member name="T:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport.EquipmentInfoAbnormalComponent">
<summary>
装置自检信息
</summary>
</member>
<member name="T:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport.RemainingLifeAssessment">
<summary>
寿命诊断
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport.RemainingLifeAssessment.RemainingLifeInYears">
<summary>
剩余寿命(单位:年)。
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport.EquipmentInfoRemainingLifeAssessment.EquipmentInfoId">
<summary>
设备名称。
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.UploadMainstationBaseInfo`1.Station">
@ -15615,6 +15645,11 @@
获取或设置事件发生时间。
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.UploadMainstationBaseInfo`1.DATANO">
<summary>
序号
</summary>
</member>
<member name="P:YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.UploadMainstationBaseInfo`1.Info">
<summary>
获取或设置事件的简要信息。

View File

@ -17,9 +17,14 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<None Remove="MainStationMaintenanceInfo\OperationReport\RunningStatus.cs~RF6ef2e4.TMP" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Abp" Version="9.4.2" />
<PackageReference Include="Abp.AutoMapper" Version="9.4.2" />
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
<PackageReference Include="MessagePack" Version="2.5.192" />
</ItemGroup>

View File

@ -0,0 +1,81 @@
using Abp.Application.Services;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YunDa.ISAS.Application.Core;
using YunDa.ISAS.Application.Core.Session;
using YunDa.ISAS.Application.Core.SwaggerHelper;
using YunDa.ISAS.DataTransferObject;
using YunDa.SOMS.DataTransferObject.CommonDto;
using YunDa.SOMS.Entities.GeneralInformation;
namespace YunDa.ISAS.MongoDB.Application.DataMonitoring
{
public class ProtectionDeviceYCResultAppService : ISASAppServiceBase, IApplicationService
{
private readonly IRepository<ProtectionDeviceInfo, Guid> _protectionDeviceInfoRepository;
public ProtectionDeviceYCResultAppService(ISessionAppService sessionAppService,
IRepository<ProtectionDeviceInfo, Guid> protectionDeviceInfoRepository
) : base(sessionAppService)
{
_protectionDeviceInfoRepository = protectionDeviceInfoRepository;
}
/// <summary>
/// 获取装置5V电压曲线图
/// </summary>
/// <returns></returns>
[AbpAllowAnonymous]
[ShowApi]
[HttpGet]
public RequestResult<List<TimeValue>> Get5VTimeSeries(Guid equipmentInfoId,int index,DateTime startTime,DateTime endTime)
{
RequestResult<List<TimeValue>> rst = new RequestResult<List<TimeValue>>();
try
{
// 验证时间范围
if (startTime >= endTime)
{
throw new ArgumentException("Start time must be earlier than end time.");
}
// 初始化数据结果集
List<TimeValue> timeSeries = new List<TimeValue>();
Random random = new Random();
DateTime currentTime = startTime;
// 按随机间隔生成数据
while (currentTime <= endTime)
{
// 生成随机电压值 (假设范围为 4.8V 到 5.2V)
double voltage = 4.8 + random.NextDouble() * 0.4;
// 添加时间点和电压值
timeSeries.Add(new TimeValue
{
Time = currentTime,
Value = voltage
});
// 随机增加 1-3 秒
int randomSeconds = random.Next(1, 4); // [1, 3]
currentTime = currentTime.AddSeconds(randomSeconds);
}
rst.ResultData = timeSeries;
}
catch (Exception ex)
{
throw;
}
return rst;
}
}
}

View File

@ -476,6 +476,12 @@
<param name="input"></param>
<returns></returns>
</member>
<member name="M:YunDa.ISAS.MongoDB.Application.DataMonitoring.ProtectionDeviceYCResultAppService.Get5VTimeSeries(System.Guid,System.Int32,System.DateTime,System.DateTime)">
<summary>
获取装置5V电压曲线图
</summary>
<returns></returns>
</member>
<member name="T:YunDa.ISAS.MongoDB.Application.DataMonitoring.TelemeteringResultAppService">
<summary>
遥测结果管理服务

View File

@ -40,7 +40,11 @@ namespace YunDa.SOMS.Entities.GeneralInformation
/// </summary>
[StringLength(MaxDescriptionLength)]
public virtual string PicturePath { get; set; }
/// <summary>
/// 关联显示图片路径
/// </summary>
[Column(TypeName = "nvarchar(max)")]
public virtual string PictureBase64 { get; set; }
/// <summary>
/// 编码
/// </summary>

View File

@ -52,11 +52,13 @@ namespace YunDa.SOMS.Entities.GeneralInformation
[ForeignKey(nameof(TelesignalisationConfigurationId))]
public virtual TelesignalisationConfiguration TelesignalisationConfiguration { get; set; }
/// <summary>
/// 备注
/// </summary>
public virtual string Remark { get; set; }
/// <summary>
/// 是否在用
/// </summary>

View File

@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace YunDa.ISAS.Migrations
{
/// <inheritdoc />
public partial class update_table_v91 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "PictureBase64",
table: "gi_secondary_circuit",
type: "MEDIUMTEXT",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PictureBase64",
table: "gi_secondary_circuit");
}
}
}

View File

@ -17,7 +17,7 @@ namespace YunDa.ISAS.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.8")
.HasAnnotation("ProductVersion", "8.0.11")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
@ -3951,6 +3951,9 @@ namespace YunDa.ISAS.Migrations
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("PictureBase64")
.HasColumnType("nvarchar(max)");
b.Property<string>("PicturePath")
.HasMaxLength(500)
.HasColumnType("varchar(500)");

View File

@ -25,6 +25,10 @@
<ItemGroup>
<PackageReference Include="Abp.EntityFrameworkCore" Version="9.4.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.11" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
</ItemGroup>

View File

@ -21,6 +21,7 @@ using YunDa.ISAS.Redis.Repositories;
using YunDa.SOMS.DataTransferObject.EquipmentLiveData;
using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto;
using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionSettingDto;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
namespace YunDa.ISAS.Redis
{
@ -90,12 +91,13 @@ namespace YunDa.ISAS.Redis
IocManager.Register<IRedisRepository<IOState, string>, RedisRepository<IOState, string>>();
IocManager.Register<IRedisRepository<DeviceStatus, string>, RedisRepository<DeviceStatus, string>>();
IocManager.Register<IRedisRepository<EquipmentInfoDiagnoseResult, string>, RedisRepository<EquipmentInfoDiagnoseResult, string>>();
IocManager.Register<IRedisRepository<EquipmentInfoSearchRecord, string>, RedisRepository<EquipmentInfoSearchRecord, string>>();
/*运维相关*/
IocManager.Register<IRedisRepository<EquipmentInfoAbnormalComponent, string>, RedisRepository<EquipmentInfoAbnormalComponent, string>>();
IocManager.Register<IRedisRepository<SecondaryCircuitComponent, string>, RedisRepository<SecondaryCircuitComponent, string>>();
IocManager.Register<IRedisRepository<EquipmentInfoRemainingLifeAssessment, string>, RedisRepository<EquipmentInfoRemainingLifeAssessment, string>>();
}
}
}

View File

@ -5,6 +5,7 @@ using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using ToolLibrary.LogHelper;
@ -22,6 +23,7 @@ using YunDa.ISAS.DataTransferObject.EquipmentLiveData;
using YunDa.ISAS.Entities.DataMonitoring;
using YunDa.ISAS.Redis.Entities.DataMonitorCategory;
using YunDa.ISAS.Redis.Repositories;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
{
@ -97,6 +99,19 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
}
}, new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = 1 });
//测试代码
#warning
Task.Run(async () => {
while (true)
{
await SendDeviceSlefCheckInfo();
await Task.Delay(3000);
await SendSecondaryCircuitDiagnosticsInfo();
await Task.Delay(3000);
await SendEquipmentInfoRemainingLifeAssessmentInfo();
await Task.Delay(3000);
}
});
}
public ActionBlock<RECORDYXBURST_New> RECORDYXBURSTActionBlock = default;
@ -150,6 +165,32 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
// 并行处理多个任务以提高性能
var tasks = new List<Task>();
if (_runningDataCache.SecondaryCircuitLogicExpressionDic.ContainsKey(hashKey))
{
var listLogics = _runningDataCache.SecondaryCircuitLogicExpressionDic[hashKey];
foreach (var listLogic in listLogics)
{
// 示例字符串
// 正则表达式匹配花括号中的内容
string pattern = @"\{([^}]*)\}";
Regex regex = new Regex(pattern);
// 提取匹配内容
MatchCollection matches = regex.Matches(listLogic);
List<string> extractedStrings = new List<string>();
foreach (Match match in matches)
{
var logichasKey = match.Groups[1].Value;
var ycLiveData = _redisDataRepository.TelemeteringModelListRedis.HashSetGetOne(redisKey, logichasKey);
if (ycLiveData!=null)
{
listLogic.Replace(logichasKey, ycLiveData.ResultValue.ToString());
}
}
}
}
// 更新到内存数据库中
tasks.Add(_redisDataRepository.TelemeteringModelListRedis.HashSetUpdateOneAsync(redisKey, hashKey, ycData));
//Log4Helper.Info(this.GetType(), $"更新数据成功: 地址:{yc.inf} 类型:{categoriyValue}");
@ -196,8 +237,8 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
try
{
var categoriyValue = _settingModel.GetDatacatgoryValue(_settingModel.DataSourceCategoryName);
string redisKey = _redisDataRepository.TelesignalisationModelListRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName); ;
string redisChannel = _redisDataRepository.TelesignalisationInflectionInflectionZZChannelRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName); ;
string redisKey = _redisDataRepository.TelesignalisationModelListRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName);
string redisChannel = _redisDataRepository.TelesignalisationInflectionInflectionZZChannelRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName);
string haskey = $"{yx.dev_addr}_{yx.dev_sector}_{yx.dev_inf}_{categoriyValue}";
// 从 Redis 中批量获取遥信数据
var yxData = _redisDataRepository.TelesignalisationModelListRedis.HashSetGetOne(redisKey, haskey);
@ -244,8 +285,54 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
}
private Dictionary<TelesignalisationModel, DateTime> TelesignaleAlarmTempBuffDic = new Dictionary<TelesignalisationModel, DateTime>();
/// <summary>
/// 发送装置自检信息
/// </summary>
/// <returns></returns>
public async Task SendDeviceSlefCheckInfo()
{
string redisChannel = "deviceSelfTestChannel";
await _redisDataRepository.AbnormalComponentRedis.PublishAsync(redisChannel, new EquipmentInfoAbnormalComponent
{
EquipmentInfoId = Guid.Parse("08dd0eb5-f8b7-48a4-81da-2f531d0f614a"),
AbnormalReason = "当前值63°超过门限60°",
ComponentName = "机箱温度",
HandlingMeasures= "注意关注温度状态",
});
}
/// <summary>
/// 发送回路诊断信息
/// </summary>
/// <returns></returns>
public async Task SendSecondaryCircuitDiagnosticsInfo()
{
string redisChannel = "secondaryCircuitDiagnosticsChannel";
await _redisDataRepository.SecondaryCircuitComponentRedis.PublishAsync(redisChannel, new SecondaryCircuitComponent
{
EquipmentInfoId = Guid.Parse("08dd0eb5-f8b7-48a4-81da-2f531d0f614a"),
SecondaryCircuitId = Guid.Parse("08dd0eba-d37b-4920-811c-40b7c29f69fe"),
AbnormalReason = "表达式1200A超范围1000A",
ComponentName = "交流回路_1",
HandlingMeasures = "",
});
}
/// <summary>
/// 发送寿命预估
/// </summary>
/// <returns></returns>
public async Task SendEquipmentInfoRemainingLifeAssessmentInfo()
{
string redisChannel = "equipmentInfoRemainingLifeAssessmentChannel";
await _redisDataRepository.EquipmentInfoRemainingLifeAssessmentRedis.PublishAsync(redisChannel, new EquipmentInfoRemainingLifeAssessment
{
EquipmentInfoId = Guid.Parse("08dd0eb5-f8b7-48a4-81da-2f531d0f614a"),
RemainingLifeInYears = "5.8年",
});
}
/// <summary>
/// 发送遥测数据到主界面日志显示
/// </summary>

View File

@ -198,8 +198,8 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.Model
public static string RequestPatternRecogbnizeUri => $"http://127.0.0.1:35689/api/recognize";
//public static string RequestPatternRecogbnizeUri => $"http://127.0.0.1:35689/api/recognize";
public static string RequestInitYXRedisListUri => $"{WebAddr}/api/services/isas/EquipmentInfoEx/InitYCList";
public static string RequestInitYCRedisListUri => $"{WebAddr}/api/services/isas/EquipmentInfoEx/InitYXList";
public static string RequestInitYXRedisListUri => $"{WebAddr}/api/services/isas/EquipmentInfoEx/InitYXList";
public static string RequestInitYCRedisListUri => $"{WebAddr}/api/services/isas/EquipmentInfoEx/InitYCList";
public static string RequestEquipmentSimDatasUri => $"{WebAddr}/api/services/isas/EquipmentInfo/FindSimDatas";
public static string RequestEquipmentTypeSimDatasUri => $"{WebAddr}/api/services/isas/EquipmentType/FindSimDatas";
@ -213,5 +213,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.Model
/// 修改板卡版本信息
/// </summary>
public static string RequestModifyBoardInfoList => $"{WebAddr}/api/services/isas/BoardCardInfo/ModifyBoardInfoList";
public static string RequestSecondaryCircuitLogicExpressionList => $"{WebAddr}/api/services/isas/SecondaryCircuitLogicExpression/FindDatas";
}
}

View File

@ -1,6 +1,11 @@
using Abp.Dependency;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Forms;
using ToolLibrary.LogHelper;
using Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection;
@ -32,6 +37,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
private readonly DotNettyTcpServer _dotNettyTcpServer;
private readonly ProtectionDeviceDataCenter _protectionDeviceDataCenter;
private readonly ProtectionDeviceDZDataHandle _protectionDeviceDZDataHandle;
private readonly RedisDataRepository _redisDataRepository;
WPF.ViewModel.Content _settingModel;
public MonitoringDataService(WebApiRequest webApiRequest,
RunningDataCache runningDataCache,
@ -42,7 +48,8 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
TelecomDataCenter telecomDataCenter,
DotNettyTcpServer dotNettyTcpServer,
ProtectionDeviceDZDataHandle protectionDeviceDZDataHandle,
ProtectionDeviceDataCenter protectionDeviceDataCenter
ProtectionDeviceDataCenter protectionDeviceDataCenter,
RedisDataRepository redisDataRepository
//WebApiServer webApiServer
)
{
@ -58,6 +65,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
//var webapiPort = _configurationHepler.GetAppsettingsValue("ConnectionStrings", "WebApi", "Port");
_protectionDeviceDZDataHandle = protectionDeviceDZDataHandle;
_protectionDeviceDataCenter = protectionDeviceDataCenter;
_redisDataRepository = redisDataRepository;
//_webApiServer.RunServerAsync(int.Parse(webapiPort));
}
private bool IsOpenWebSocket = false;
@ -97,6 +105,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
{
MonitoringEventBus.LogHandler("启动装置定值接口", "装置定值");
await _protectionDeviceDataCenter.InitProtectionDeviceComms();
await InitSecondaryCircuitLogicExpressionDic();
}
_dataCollectionTask.CollectionStart(settingModel, startWebsocket);//开启数据采集
}
@ -104,6 +113,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
{
_dataCollectionTask.CallAllData();
}
/// <summary>
/// 停止服务
/// </summary>
@ -145,5 +155,80 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
MonitoringEventBus.LogHandler(ex.Message, "异常信息");
}
}
private async Task InitSecondaryCircuitLogicExpressionDic()
{
try
{
_runningDataCache.SecondaryCircuitLogicExpressionDic.Clear();
var yxlist =await _redisDataRepository.GetTelesignalisationModels();
var yclist =await _redisDataRepository.GetTelemeteringModels();
var ycCheckList =( await _redisDataRepository.GetCheckTelemeteringModels()).ToDictionary(t => t.Id);
var yxDic = yxlist.ToDictionary(t => t.Id);
var ycDic = yclist.ToDictionary(t => t.Id);
var list = _webApiRequest.GetSecondaryCircuitLogicExpressionList();
foreach (var item in list)
{
if (!ycCheckList.ContainsKey(item.TelemeteringConfigurationId.Value))
{
Debug.WriteLine("错误,没有找到遥测");
continue;
}
var checktelemeteringConfiguration = ycCheckList[item.TelemeteringConfigurationId.Value];
float? upperLimit = checktelemeteringConfiguration.UpperLimit;
float? lowerLimit = checktelemeteringConfiguration.LowerLimit;
// 正则表达式匹配花括号中的内容,包括 GUID
string pattern = @"\{([^}]*:([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}))\}";
Regex regex = new Regex(pattern);
item.LogicalExpression = regex.Replace(item.LogicalExpression, match =>
{
// 提取 GUID
var guidStr = match.Groups[2].Value;
var guid = Guid.Parse(guidStr);
// 查找对应的 key
if (yxDic.TryGetValue(guid, out var yx))
{
return $"{{{yx.DeviceAddress}_{yx.CPUSector}_{yx.DispatcherAddress}_{(int)yx.DataSourceCategory}}}";
}
else if (ycDic.TryGetValue(guid, out var yc))
{
// 构造 key 替换
return $"{{{yc.DeviceAddress}_{yc.CPUSector}_{yc.DispatcherAddress}_{(int)yc.DataSourceCategory}}}";
}
// 如果未找到,保留原内容
return match.Value;
});
// 输出替换后的 LogicalExpression
Debug.WriteLine($"替换后的 LogicalExpression: {item.LogicalExpression}");
// 正则表达式匹配花括号中的内容
string pattern1 = @"\{([^}]*)\}";
Regex regex1 = new Regex(pattern1);
// 提取匹配结果
MatchCollection matches = regex.Matches(item.LogicalExpression);
List<string> extractedValues = new List<string>();
var logicalExpression = $"({item.LogicalExpression})>={lowerLimit}&&({item.LogicalExpression})<={upperLimit}";
foreach (Match match in matches)
{
string key = match.Groups[1].Value;
if (_runningDataCache.SecondaryCircuitLogicExpressionDic.ContainsKey(key))
{
_runningDataCache.SecondaryCircuitLogicExpressionDic[key].Add(logicalExpression);
}
else
{
_runningDataCache.SecondaryCircuitLogicExpressionDic.Add(key, new List<string> { logicalExpression });
}
}
}
}
catch (Exception ex)
{
MonitoringEventBus.LogHandler(ex.Message, "异常信息");
}
}
}
}

View File

@ -1,4 +1,5 @@
using Abp.Dependency;
using Amazon.SecurityToken.Model.Internal.MarshallTransformations;
using MongoDB.Driver.Linq;
using MySqlX.XDevAPI.Relational;
using Newtonsoft.Json;
@ -37,6 +38,7 @@ using YunDa.ISAS.ExternalInteraction.DataTransferObject.InspectionEquipment;
using YunDa.ISAS.ExternalInteraction.DataTransferObject.InspectionEquipment.RequestInput;
using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto;
using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionSettingDto;
using YunDa.SOMS.DataTransferObject.GeneralInformation.SecondaryCircuitDto;
using ConstantModel = Yunda.ISAS.DataMonitoringServer.DataAnalysis.Model.ConstantModel;
namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
@ -528,16 +530,23 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
.HttpHelper
.HttpGetRequest<JObject>
(ConstantModel
.RequestInitYXRedisListUri+ "?dataSourceCategory="+ dataSourceCategory
.RequestInitYXRedisListUri+ "?dataSourceCategory="+ (int)dataSourceCategory
);
var resObj1 = ToolLibrary
.HttpHelper
.HttpGetRequest<JObject>
(ConstantModel
.RequestInitYCRedisListUri + "?dataSourceCategory=" + dataSourceCategory
.RequestInitYCRedisListUri + "?dataSourceCategory=" + (int)dataSourceCategory
);
var resObj2 = ToolLibrary
.HttpHelper
.HttpGetRequest<JObject>
(ConstantModel
.RequestInitYCRedisListUri + "?dataSourceCategory=" + (int)DataSourceCategoryEnum.None
);
}
catch (Exception ex)
{
@ -1041,6 +1050,35 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
}
return false;
}
public List<SecondaryCircuitLogicExpressionOutput> GetSecondaryCircuitLogicExpressionList()
{
try
{
JObject rstDataJObject = ToolLibrary
.HttpHelper
.HttpPostRequest<JObject>
(ConstantModel
.RequestSecondaryCircuitLogicExpressionList, new
{
searchCondition = new
{
isOnlyActive = true
}
}
);
var rst = rstDataJObject?["result"]?["resultData"];//获取结果集
var res = rst.ToObject<List<SecondaryCircuitLogicExpressionOutput>>();
return res;
}
catch (Exception ex)
{
MonitoringEventBus.LogHandler(ex.Message, "获取遥测报警配置缓存");
}
return null;
}
}
}

View File

@ -1,6 +1,7 @@
using Abp.Dependency;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using YunDa.ISAS.DataTransferObject.EquipmentLiveData;
using YunDa.ISAS.Redis.Entities.AlarmCategory;
using YunDa.ISAS.Redis.Entities.CameraAuthCategory;
@ -8,6 +9,7 @@ using YunDa.ISAS.Redis.Entities.DataMonitorCategory;
using YunDa.ISAS.Redis.Entities.LinkageCategory;
using YunDa.ISAS.Redis.Repositories;
using YunDa.SOMS.DataTransferObject.GeneralInformation.ProtectionDeviceInfoDto;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
namespace Yunda.ISAS.DataMonitoringServer.DataCenter
{
@ -18,7 +20,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataCenter
public IRedisRepository<AlarmListRedis, string> AlarmListRedis { get; }
public IRedisRepository<EnvironmentTempValue, string> EnvironmentTempValueRedis { get; }
public IRedisRepository<EquipmentDataModel, string> EquipmentDataModelDicRedis { get; }
private readonly WPF.ViewModel.Content _settingModel;
//public string TelemeteringModelInflectionInflectionListRediskey = "telemeteringModelInflectionList";
public string TelemeteringInflectionInflectionZZChannelRediskey = "telemeteringInflection_ZZ_Channel";
public string TelemeteringInflectionInflectionZZDeviceStatusChannelRediskey = "telemeteringInflection_ZZ_Device_Status_Channel";
@ -40,7 +42,11 @@ namespace Yunda.ISAS.DataMonitoringServer.DataCenter
/// 遥信数据变位库
/// </summary>
public IRedisRepository<TelesignalisationModel, string> TelesignalisationModelInflectionListRedis { get; }
public IRedisRepository<EquipmentInfoAbnormalComponent, string> AbnormalComponentRedis { get; }
public IRedisRepository<SecondaryCircuitComponent, string> SecondaryCircuitComponentRedis { get; }
public IRedisRepository<EquipmentInfoRemainingLifeAssessment, string> EquipmentInfoRemainingLifeAssessmentRedis { get; }
public string TelemeteringModelListRediskey = "telemeteringModelList";
/// <summary>
/// 遥测数据实时库
@ -65,7 +71,11 @@ namespace Yunda.ISAS.DataMonitoringServer.DataCenter
IRedisRepository<TelesignalisationModel, string> telesignalisationModelInflectionListRedis,
IRedisRepository<TelemeteringModel, string> telemeteringModelListRedis,
IRedisRepository<TelesignalisationModel, string> telesignalisationModelListRedis,
RedisRepository<DeviceStatus, string> deviceStatusRedis
RedisRepository<DeviceStatus, string> deviceStatusRedis,
IRedisRepository<EquipmentInfoAbnormalComponent, string> abnormalComponentRedis,
IRedisRepository<SecondaryCircuitComponent, string> secondaryCircuitComponentRedis,
IRedisRepository<EquipmentInfoRemainingLifeAssessment, string> equipmentInfoRemainingLifeAssessmentRedis,
WPF.ViewModel.Content settingModel
)
{
CameraAuthTimeRepository = cameraAuthTimeRepository;
@ -80,6 +90,32 @@ namespace Yunda.ISAS.DataMonitoringServer.DataCenter
TelesignalisationModelInflectionListRedis = telesignalisationModelInflectionListRedis;
TelemeteringModelListRedis = telemeteringModelListRedis;
TelesignalisationModelListRedis = telesignalisationModelListRedis;
AbnormalComponentRedis = abnormalComponentRedis;
SecondaryCircuitComponentRedis = secondaryCircuitComponentRedis;
EquipmentInfoRemainingLifeAssessmentRedis = equipmentInfoRemainingLifeAssessmentRedis;
_settingModel = settingModel;
}
public async Task<List<TelesignalisationModel>> GetTelesignalisationModels()
{
string redisKey = TelesignalisationModelListRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName);
// 从 Redis 中批量获取所有数据
var yxDatas = await TelesignalisationModelListRedis.HashSetGetAllAsync(redisKey);
return yxDatas;
}
public async Task<List<TelemeteringModel>> GetTelemeteringModels()
{
string redisKey = TelemeteringModelListRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName); ;
// 从 Redis 中批量获取所有遥测数据
var ycDatas = await TelemeteringModelListRedis.HashSetGetAllAsync(redisKey);
return ycDatas;
}
public async Task<List<TelemeteringModel>> GetCheckTelemeteringModels()
{
string redisKey = TelemeteringModelListRediskey + "_" + _settingModel.GetDatacatgoryName("无"); ;
// 从 Redis 中批量获取所有遥测数据
var ycDatas = await TelemeteringModelListRedis.HashSetGetAllAsync(redisKey);
return ycDatas;
}
}
}

View File

@ -17,6 +17,7 @@ using YunDa.ISAS.DataTransferObject.GeneralInformation.TransformerSubstationDto;
using YunDa.ISAS.Redis.Repositories;
using ConstantModel = YunDa.ISAS.DataTransferObject.EquipmentLiveData.ConstantModel;
using YunDa.SOMS.DataTransferObject.GeneralInformation.SecondaryCircuitDto;
namespace Yunda.ISAS.DataMonitoringServer.DataCenter
{
public class RunningDataCache : ISingletonDependency
@ -129,6 +130,13 @@ namespace Yunda.ISAS.DataMonitoringServer.DataCenter
public ConcurrentBag<LinkageExecuteActivityOutput> LinkageExecuteActivities { get; set; }
= new ConcurrentBag<LinkageExecuteActivityOutput>();
/// <summary>
/// 逻辑表达式策略缓存
/// </summary>
public Dictionary<string, List<string>> SecondaryCircuitLogicExpressionDic { get; set; } = new ();
/// <summary>
/// 摄像头数据缓存
/// </summary>

View File

@ -42,17 +42,28 @@ namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
}
public void Init(List<ProtectionDeviceCommInfoOutput> divices)
{
foreach (var item in divices)
try
{
//系统定值
var tempSystemDZs = _webApiRequest.GetDzByDeviceAddr(item.DeviceAddr, 9);
systemDzs.Add((byte)item.DeviceAddr, tempSystemDZs);
systemDzs.Clear();
userDzs.Clear();
foreach (var item in divices)
{
//系统定值
var tempSystemDZs = _webApiRequest.GetDzByDeviceAddr(item.DeviceAddr, 9);
//用户定值
var tempUserDZs = _webApiRequest.GetDzByDeviceAddr(item.DeviceAddr, 1);
userDzs.Add((byte)item.DeviceAddr, tempUserDZs);
systemDzs.Add((byte)item.DeviceAddr, tempSystemDZs);
//用户定值
var tempUserDZs = _webApiRequest.GetDzByDeviceAddr(item.DeviceAddr, 1);
userDzs.Add((byte)item.DeviceAddr, tempUserDZs);
}
}
catch (Exception ex)
{
MonitoringEventBus.LogHandler(ex.Message, "定值错误信息");
}
}
private object locker = new object();
private void OnMessageReceived(byte address, byte[] message, byte functionType)

View File

@ -60,18 +60,20 @@ namespace Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle
MonitoringEventBus.LogHandler("开始启动103客户端", "装置定值");
await Task.Run(async () =>
{
List<ProtectionDeviceCommInfoOutput> devices = _webApiRequest.GetProtectionDeviceCommInfos("神池南");
if (devices == null)
{
MonitoringEventBus.LogHandler("没有获取到装置数据","获取信息");
MonitoringEventBus.LogHandler("没有获取到装置数据", "获取信息");
return;
}
_protectionDeviceDZDataHandle.Init(devices);
MonitoringEventBus.LogHandler($"共获取{devices.Count}条装置数据", "装置定值");
string currentDirectory = AppDomain.CurrentDomain.BaseDirectory;
string sourceDirectory = Path.Combine(currentDirectory, "DeviceComm");
string destDirectoryBase = Path.Combine(currentDirectory, "DeviceComms", "DeviceComm");
_protectionDeviceDZDataHandle.Init(devices);
MonitoringEventBus.LogHandler($"共获取{devices.Count}条装置数据", "装置定值");
string currentDirectory = AppDomain.CurrentDomain.BaseDirectory;
string sourceDirectory = Path.Combine(currentDirectory, "DeviceComm");
string destDirectoryBase = Path.Combine(currentDirectory, "DeviceComms", "DeviceComm");
// 定义一个并行处理每个设备的过程
Parallel.ForEach(devices, device =>

View File

@ -31,7 +31,7 @@
"FunctionName": "综自(配电)"
},
"SysBaseConfig": {
"WebAddrUrl": "http://192.168.81.22:38090",
"WebAddrUrl": "http://192.168.81.229:38091",
"WebExternBaseUrl": "https://127.0.0.1:4431",
"OpenVideoLog": false,
"LinkAgingSecond": 60 //6060

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,10 @@
namespace ConsoleTest
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Channels;
using MessagePack;
@ -10,7 +11,13 @@ class Subscriber
static void Main(string[] args)
{
Console.WriteLine("请输入redis的ip地址");
Console.WriteLine("直接回车默认使用127.0.0.1");
string ip = Console.ReadLine();
if (string.IsNullOrWhiteSpace(ip))
{
ip = "127.0.0.1";
}
var connectStr = $"{ip}:36379,defaultDatabase=0,password=yunda123";
var configurationOptions = new ConfigurationOptions
{
@ -37,11 +44,15 @@ class Subscriber
receivedCount++;
// 解析 JSON 消息
dynamic entity = MessagePackSerializer.Deserialize<dynamic>(message, MessagePack.Resolvers.ContractlessStandardResolver.Options);
var entity = MessagePackSerializer.Deserialize<Dictionary<string, object>>(message, MessagePack.Resolvers.ContractlessStandardResolver.Options);
try
{
Console.WriteLine("收到消息");
Console.WriteLine("解析到的键值对:");
foreach (var kvp in entity)
{
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
}
catch (Exception ex)
{