完成二次回路逻辑推理Merge branch 'master' of http://192.168.110.57:3000/guor/SOMS

This commit is contained in:
郭睿AMD7950X 2024-11-29 16:29:17 +08:00 committed by 郭睿
commit 1c87801075
11 changed files with 169 additions and 75 deletions

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YunDa.SOMS.DataTransferObject.GeneralInformation.SecondaryCircuitDto
{
/// <summary>
/// 逻辑表达式与遥信地址
/// </summary>
public class LogicExpressionTelesignalisation
{
public string LogicExpression { get; set; }
public string TelesignalisationAddr { get; set; }
}
}

View File

@ -15415,6 +15415,11 @@
是否在用
</summary>
</member>
<member name="T:YunDa.SOMS.DataTransferObject.GeneralInformation.SecondaryCircuitDto.LogicExpressionTelesignalisation">
<summary>
逻辑表达式与遥信地址
</summary>
</member>
<member name="T:YunDa.SOMS.DataTransferObject.GeneralInformation.SecondaryCircuitDto.SecondaryCircuitLogicExpressionOutput">
<summary>
二次回路逻辑运算式

View File

@ -3,6 +3,7 @@ using MongoDB.Driver;
using MongoDB.Driver.Linq;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@ -216,8 +217,8 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
Dictionary<int, TelesignalisationModel> TelesignalisationModelDic = new Dictionary<int, TelesignalisationModel>();
List<RECORDYXBURST_New> yxList = new List<RECORDYXBURST_New>();
List<YC_TYPE_New> ycList = new List<YC_TYPE_New>();
ConcurrentBag<RECORDYXBURST_New> yxList = new ConcurrentBag<RECORDYXBURST_New>();
ConcurrentBag<YC_TYPE_New> ycList = new ConcurrentBag<YC_TYPE_New>();
/// <summary>
/// 仅更新遥信数据字典

View File

@ -2,6 +2,7 @@
using Google.Protobuf.WellKnownTypes;
using MongoDB.Driver.Linq;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
@ -24,6 +25,7 @@ using YunDa.ISAS.Entities.DataMonitoring;
using YunDa.ISAS.Redis.Entities.DataMonitorCategory;
using YunDa.ISAS.Redis.Repositories;
using YunDa.SOMS.DataTransferObject.MainStationMaintenanceInfo.OperationReport;
using Z.Expressions;
namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
{
@ -151,76 +153,25 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
string redisKey = _redisDataRepository.TelemeteringModelListRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName);
string redisChannel = _redisDataRepository.TelemeteringInflectionInflectionZZChannelRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName); ;
// 批量获取 Redis 数据以减少读取次数
string hashKey = $"{yc.addr}_{0}_{yc.inf}_{categoriyValue}";
var ycData = _redisDataRepository.TelemeteringModelListRedis.HashSetGetOne(redisKey, hashKey);
string haskey = $"{yc.addr}_{0}_{yc.inf}_{categoriyValue}";
var ycData = _redisDataRepository.TelemeteringModelListRedis.HashSetGetOne(redisKey, haskey);
if (ycData == null)
{
Log4Helper.Error(this.GetType(), $"更新数据失败: 地址:{yc.inf} 类型:{categoriyValue} 键:{hashKey}");
Log4Helper.Error(this.GetType(), $"更新数据失败: 地址:{yc.inf} 类型:{categoriyValue} 键:{haskey}");
return;
}
// 更新对象的数据
ycData.ResultTime = yc.time;
ycData.ResultValue = yc.val;
// 并行处理多个任务以提高性能
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}");
tasks.Add(_redisDataRepository.TelemeteringModelListRedis.HashSetUpdateOneAsync(redisKey, haskey, ycData));
tasks.Add(CheckSecondCuirtAlarm(haskey));
// 将变更的数据添加到变位库 订阅
tasks.Add(Task.Run(() => _redisDataRepository.TelemeteringModelInflectionListRedis.PublishAsync(redisChannel, ycData)));
// 异步任务处理数据保存、告警分析和缓存环境温度
tasks.Add(Task.Run(async () =>
{
var rst = new TelemeteringResult
{
ResultTime = ycData.ResultTime,
ResultValue = ycData.ResultValue,
TelemeteringConfigurationId = ycData.Id,
SaveMethod = 2
};
// 保存变更数据
_telemeteringResultSaveTask.SaveTelemeteringResultActionBlock?.Post(rst);
// 缓存环境温度(如果适用)
if (ycData.IsEnvironmentTemp)
{
var environmentTempValue = new EnvironmentTempValue(yc.val);
await _redisDataRepository.EnvironmentTempValueRedis.HashSetUpdateOneAsync(nameof(EnvironmentTempValue), ycData.Id.ToString(), environmentTempValue);
}
// 处理告警分析
await _alarmAnalysis.HandleTelemeteringAlarmAsync(ycData);
}));
tasks.Add(SetEnvirmentTemp(ycData));
// 执行所有任务并等待完成
await Task.WhenAll(tasks);
@ -231,7 +182,28 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
MonitoringEventBus.LogHandler(ex.Message, "错误信息");
}
}
public async Task SetEnvirmentTemp(TelemeteringModel ycData)
{
var rst = new TelemeteringResult
{
ResultTime = ycData.ResultTime,
ResultValue = ycData.ResultValue,
TelemeteringConfigurationId = ycData.Id,
SaveMethod = 2
};
// 保存变更数据
_telemeteringResultSaveTask.SaveTelemeteringResultActionBlock?.Post(rst);
// 缓存环境温度(如果适用)
if (ycData.IsEnvironmentTemp)
{
var environmentTempValue = new EnvironmentTempValue(ycData.ResultValue);
await _redisDataRepository.EnvironmentTempValueRedis.HashSetUpdateOneAsync(nameof(EnvironmentTempValue), ycData.Id.ToString(), environmentTempValue);
}
// 处理告警分析
await _alarmAnalysis.HandleTelemeteringAlarmAsync(ycData);
}
public async Task UpdateTelesignalDataAsync(RECORDYXBURST_New yx)
{
try
@ -256,7 +228,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
// 1. 更新 Redis 中的数据
tasks.Add(_redisDataRepository.TelesignalisationModelListRedis.HashSetUpdateOneAsync(redisKey, haskey, yxData));
//Log4Helper.Info(this.GetType(), $"更新数据成功: 地址:{yx.dev_inf} 类型:{categoriyValue}");
tasks.Add(CheckSecondCuirtAlarm(haskey));
// 2. 将更新的数据加入到变位库中
tasks.Add(Task.Run(() => _redisDataRepository.TelesignalisationModelInflectionListRedis.PublishAsync(redisChannel, yxData)));
@ -283,7 +255,58 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.DataCollection
MonitoringEventBus.LogHandler(ex.Message, "错误信息");
}
}
private async Task CheckSecondCuirtAlarm(string haskey)
{
if (_runningDataCache.SecondaryCircuitLogicExpressionDic.ContainsKey(haskey))
{
var listLogics = _runningDataCache.SecondaryCircuitLogicExpressionDic[haskey];
foreach (var listLogic in listLogics)
{
// 示例字符串
// 正则表达式匹配花括号中的内容
string pattern = @"\{([^}]*)\}";
Regex regex = new Regex(pattern);
// 提取匹配内容
MatchCollection matches = regex.Matches(listLogic.LogicExpression);
List<string> extractedStrings = new List<string>();
foreach (Match match in matches)
{
var logichasKey = match.Groups[1].Value;
string telemeteringredisKey = _redisDataRepository.TelemeteringModelListRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName);
var ycLiveData = _redisDataRepository.TelemeteringModelListRedis.HashSetGetOne(telemeteringredisKey, logichasKey);
if (ycLiveData != null)
{
listLogic.LogicExpression.Replace(logichasKey, ycLiveData.ResultValue.ToString());
}
string telesignalisationredisKey = _redisDataRepository.TelesignalisationModelListRediskey + "_" + _settingModel.GetDatacatgoryName(_settingModel.DataSourceCategoryName);
var yxLiveData = _redisDataRepository.TelesignalisationModelListRedis.HashSetGetOne(telesignalisationredisKey, logichasKey);
if (yxLiveData != null)
{
listLogic.LogicExpression.Replace(logichasKey, yxLiveData.ResultValue.ToString());
}
}
try
{
var result = Eval.Execute<bool>(listLogic.LogicExpression);
if (result)
{
string telesignalisationredisKey = _redisDataRepository.TelesignalisationModelListRediskey + "_" + _settingModel.GetDatacatgoryName("无");
var yxData = _redisDataRepository.TelesignalisationModelListRedis.HashSetGetOne(telesignalisationredisKey, listLogic.TelesignalisationAddr);
yxData.ResultValue = yxData.RemoteType == RemoteTypeEnum.DoublePoint ? 2 : 1;
_webApiRequest.SendVisualYx(yxData);
}
}
catch (Exception ex)
{
MonitoringEventBus.LogHandler(ex.Message, "错误信息");
}
}
}
}
private Dictionary<TelesignalisationModel, DateTime> TelesignaleAlarmTempBuffDic = new Dictionary<TelesignalisationModel, DateTime>();
/// <summary>
/// 发送装置自检信息

View File

@ -1,6 +1,5 @@
using Abp.Dependency;
using Castle.MicroKernel.Util;
using Microsoft.ClearScript.V8;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@ -18,6 +17,7 @@ using Yunda.ISAS.DataMonitoringServer.WebSocket.Model;
using YunDa.ISAS.DataTransferObject.DataMonitoring.LinkageConditionDto;
using YunDa.ISAS.DataTransferObject.EquipmentLiveData;
using YunDa.ISAS.Entities.MySQL.DataMonitoring;
using Z.Expressions;
using ConstantModel = Yunda.ISAS.DataMonitoringServer.DataAnalysis.Model.ConstantModel;
namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.LinkageAnalysis
@ -245,11 +245,14 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis.LinkageAnalysis
}
string ruleStr = string.Format(linkageStrategy.Rule, conditionStrs.ToArray());
using (var engine = new V8ScriptEngine())
try
{
object isLinkageObj = engine.Evaluate(ruleStr);
bool.TryParse(isLinkageObj.ToString(), out isNeedLinkage);
isNeedLinkage = ruleStr.Execute<bool>();
}
catch (Exception ex)
{
Log4Helper.Error(this.GetType(), "解析联动表达式",ex);
isNeedLinkage = false;
}
}
}

View File

@ -1,4 +1,6 @@
using Abp.Dependency;
using Amazon.Runtime.Internal.Transform;
using MongoDB.Driver.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@ -16,6 +18,7 @@ using Yunda.ISAS.DataMonitoringServer.WebApi;
using Yunda.ISAS.DataMonitoringServer.WebSocket;
using Yunda.SOMS.DataMonitoringServer.ProtectionDeviceHandle;
using Yunda.SOMS.DataMonitoringServer.TcpSocket.Server;
using YunDa.SOMS.DataTransferObject.GeneralInformation.SecondaryCircuitDto;
namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
{
@ -163,17 +166,21 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
var yxlist =await _redisDataRepository.GetTelesignalisationModels();
var yclist =await _redisDataRepository.GetTelemeteringModels();
var ycCheckList =( await _redisDataRepository.GetCheckTelemeteringModels()).ToDictionary(t => t.Id);
var yxSendList =( await _redisDataRepository.GetSendTelesignalisationModels()).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))
if (!ycCheckList.ContainsKey(item.TelemeteringConfigurationId.Value)|| yxSendList.ContainsKey(item.TelesignalisationConfigurationId.Value))
{
Debug.WriteLine("错误,没有找到遥测");
Debug.WriteLine("错误,没有找到遥测/遥信");
continue;
}
var checktelemeteringConfiguration = ycCheckList[item.TelemeteringConfigurationId.Value];
var sendtelesignalConfiguration = yxSendList[item.TelesignalisationConfigurationId.Value];
float? upperLimit = checktelemeteringConfiguration.UpperLimit;
float? lowerLimit = checktelemeteringConfiguration.LowerLimit;
@ -213,13 +220,18 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
foreach (Match match in matches)
{
string key = match.Groups[1].Value;
var logicExpressionTelesignalisation = new LogicExpressionTelesignalisation
{
LogicExpression = logicalExpression,
TelesignalisationAddr = $"{sendtelesignalConfiguration.DeviceAddress}_{sendtelesignalConfiguration.CPUSector}_{sendtelesignalConfiguration.DispatcherAddress}_{(int)sendtelesignalConfiguration.DataSourceCategory}"
};
if (_runningDataCache.SecondaryCircuitLogicExpressionDic.ContainsKey(key))
{
_runningDataCache.SecondaryCircuitLogicExpressionDic[key].Add(logicalExpression);
_runningDataCache.SecondaryCircuitLogicExpressionDic[key].Add(logicExpressionTelesignalisation);
}
else
{
_runningDataCache.SecondaryCircuitLogicExpressionDic.Add(key, new List<string> { logicalExpression });
_runningDataCache.SecondaryCircuitLogicExpressionDic.Add(key, new List<LogicExpressionTelesignalisation> { logicExpressionTelesignalisation });
}
}
}

View File

@ -546,6 +546,12 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
(ConstantModel
.RequestInitYCRedisListUri + "?dataSourceCategory=" + (int)DataSourceCategoryEnum.None
);
var resObj3 = ToolLibrary
.HttpHelper
.HttpGetRequest<JObject>
(ConstantModel
.RequestInitYXRedisListUri + "?dataSourceCategory=" + (int)DataSourceCategoryEnum.None
);
}
catch (Exception ex)
@ -798,7 +804,27 @@ namespace Yunda.ISAS.DataMonitoringServer.DataAnalysis
}
}
public async Task SendVisualYx(TelesignalisationModel telesign)
{
if (telesign != null)
{
var iecdata = new IecServerData();
iecdata.devAddr = (byte)telesign.InfoDeviceAddress;
iecdata.dateTime = DateTime.Now;
iecdata.devCpu = (byte)telesign.InfoCPUSector;
iecdata.inf = telesign.InfoAddress;
iecdata.dataType = 2;
iecdata.devName = "test";
iecdata.yxValue = telesign.ResultValue;
MonitoringEventBus.LogHandler($"装置地址:{telesign.InfoDeviceAddress} cpu扇区{telesign.InfoCPUSector} 信息体地址:{telesign.InfoAddress} 遥信值:{telesign.ResultValue}", "发送虚遥信");
await Task.Run(
() => ToolLibrary.HttpHelper
.HttpPostRequest(_runningDataCache._transformerSubstation.Iec104ServerUrl + "SendData", iecdata)
);
}
}
/// <summary>
/// 获取设备缓存
/// </summary>

View File

@ -117,5 +117,12 @@ namespace Yunda.ISAS.DataMonitoringServer.DataCenter
var ycDatas = await TelemeteringModelListRedis.HashSetGetAllAsync(redisKey);
return ycDatas;
}
public async Task<List<TelesignalisationModel>> GetSendTelesignalisationModels()
{
string redisKey = TelesignalisationModelListRediskey + "_" + _settingModel.GetDatacatgoryName("无"); ;
// 从 Redis 中批量获取所有遥测数据
var yxDatas = await TelesignalisationModelListRedis.HashSetGetAllAsync(redisKey);
return yxDatas;
}
}
}

View File

@ -133,7 +133,7 @@ namespace Yunda.ISAS.DataMonitoringServer.DataCenter
/// <summary>
/// 逻辑表达式策略缓存
/// </summary>
public Dictionary<string, List<string>> SecondaryCircuitLogicExpressionDic { get; set; } = new ();
public Dictionary<string, List<LogicExpressionTelesignalisation>> SecondaryCircuitLogicExpressionDic { get; set; } = new ();

View File

@ -103,10 +103,10 @@
<PackageReference Include="FluentFTP" Version="51.1.0" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="2.0.1" />
<PackageReference Include="MaterialDesignThemes" Version="5.1.0" />
<PackageReference Include="Microsoft.ClearScript.V8" Version="7.4.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
<PackageReference Include="SkiaSharp" Version="2.88.9" />
<PackageReference Include="Z.Expressions.Eval" Version="6.2.3" />
</ItemGroup>
<ItemGroup>

View File

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