SOMS/src/YunDa.Server/YunDa.Server.ISMSTcp/Services/SecondaryCircuitInspectionPlanService.cs

289 lines
8.9 KiB
C#
Raw Normal View History

2025-10-26 15:12:32 +08:00
using Jint;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Numerics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using YunDa.Server.ISMSTcp.Domain;
using YunDa.Server.ISMSTcp.Interfaces;
using YunDa.Server.ISMSTcp.Models;
using YunDa.SOMS.DataTransferObject.DataMonitoring.SecondaryCircuitInspection;
namespace YunDa.Server.ISMSTcp.Services
{
public class WebApiSettings
{
public int Port { get; set; }
}
public class SecondaryCircuitInspectionPlanStateModel
{
//执行时间
public DateTime ExecuteTime { get; set; } = DateTime.MinValue;
public SecondaryCircuitInspectionPlanOutput Plan { get; set; }
public SecondaryCircuitInspectionPlanStateModel()
{
Plan = new SecondaryCircuitInspectionPlanOutput();
}
}
//二次回路巡检计划
public class SecondaryCircuitInspectionPlanService
{
private readonly ILogger<SecondaryCircuitInspectionPlanService> _logger;
private readonly IApiEndpoints _apiEndpoints;
private readonly WebApiRequest _webApiRequest;
private readonly WebApiSettings _webApiSettings;
private bool _updatedPlanOk = false;
private Queue<SecondaryCircuitInspectionPlanStateModel> _planList;
private readonly object _planLock = new object();
private int _planCheckDay = 0;
public SecondaryCircuitInspectionPlanService(
ILogger<SecondaryCircuitInspectionPlanService> logger,
IApiEndpoints apiEndpoints,
WebApiRequest webApiRequest,
IOptions<WebApiSettings> webApiOptions
)
{
_apiEndpoints = apiEndpoints ?? throw new ArgumentNullException(nameof(apiEndpoints));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_webApiRequest = webApiRequest ?? throw new ArgumentNullException(nameof(webApiRequest));
_webApiSettings = webApiOptions.Value;
_planList = new Queue<SecondaryCircuitInspectionPlanStateModel>();
StartAsync();
}
private async Task StartAsync()
{
//更新计划
_ = Task.Run(async () =>
{
while (true)
{//每30秒更新一下配置
await UpdatePlans();
await Task.Delay(30000);
}
});
//执行计划
_ = Task.Run(async () =>
{
while (true)
{//每个小时,更新一下全体孪生状态
if (_updatedPlanOk)
{
await CheckPlan();
await Task.Delay(10 * 1000);
}
else
{
await Task.Delay(10000);
}
}
});
await Task.CompletedTask;
}
//更新计划
private async Task UpdatePlans()
{
try
{
var list = await _webApiRequest.GetSecondaryCircuitInspectionPlanListAsync();
if (list != null)
{
lock (_planLock)
{
var oldPlan = _planList.ToArray();
_planList.Clear();
List<SecondaryCircuitInspectionPlanStateModel> planlist = new List<SecondaryCircuitInspectionPlanStateModel>();
foreach (var item in list)
{
planlist.Add(new SecondaryCircuitInspectionPlanStateModel() { Plan = item });
}
foreach (var item in planlist)
{
var plan = oldPlan.FirstOrDefault(x => x.Plan.Name == item.Plan.Name && x.Plan.ScheduledTimeString == item.Plan.ScheduledTimeString);
if (plan != null)
{
item.ExecuteTime = plan.ExecuteTime;
}
_planList.Enqueue(item);
}
//获取到绑定信息,可以更新全部状态了
if (planlist.Count > 0)
_updatedPlanOk = true;
}
}
}
catch (Exception ex)
{
_updatedPlanOk = false;
}
await Task.CompletedTask;
}
//检测计划,判断计划是否该执行
private async Task<bool> CheckPlan()
{
bool ret = false;
if (_planList == null)
return ret;
try
{
SecondaryCircuitInspectionPlanStateModel[] planList;
lock (_planLock)
{
planList = _planList.ToArray();
}
DateTime now = DateTime.Now;
int week = DateTime.Now.DayOfWeek == DayOfWeek.Sunday ? 7 : (int)DateTime.Now.DayOfWeek;
if (now.Day != _planCheckDay)
{//翻天,清空已执行标记
lock (_planLock)
{
foreach (var item in _planList)
item.ExecuteTime = DateTime.MinValue;
}
}
_planCheckDay = now.Day;
foreach (var item in planList)
{
if (item.ExecuteTime == DateTime.MinValue && item.Plan.IsActive)
{//当天未执行
if (now.Hour == item.Plan.ScheduledHour && now.Minute == item.Plan.ScheduledMinute)
{
if (item.Plan.ScheduledWeekDaysList.IndexOf(week) != -1)
{
if (await ExecutePlan(item.Plan))
{//执行成功
lock (_planLock)
{
item.ExecuteTime = DateTime.Now;
}
ret = true;
}
}
}
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "SecondaryCircuitInspectionPlanService - CheckPlan发生错误");
}
return ret;
}
//执行计划
private async Task<bool> ExecutePlan(SecondaryCircuitInspectionPlanOutput plan)
{
try
{
bool ret = true;
var engine = new Jint.Engine();
foreach (var item in plan.InspectionItems)
{
if(!string.IsNullOrWhiteSpace(item.CalculationExpression))
{
engine.Execute(item.CalculationExpression);
var result = engine.Invoke("calculate", new List<YCResultData>()).AsNumber();
}
}
return ret;
}
catch (Exception ex)
{
_logger.LogError(ex, "SecondaryCircuitInspectionPlanService - ExecutePlan发生错误");
}
return false;
}
//获取遥测数据
public async Task<List<YCResultData>> CallYCByDataIdAsync(CallYCByDataIdRequest request, CancellationToken cancellationToken = default)
{
try
{
using var httpClient = new HttpClient();
string url = $"http://127.0.0.1:{_webApiSettings.Port}/api/CallYCByDataId";
var response = await httpClient.PostAsJsonAsync(url, request);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
JObject obj = JObject.Parse(result);
if (obj.ContainsKey("data"))
{
JArray jArray = obj.Value<JArray>("data");
if (jArray != null)
{
List<YCResultData> list = jArray.ToObject<List<YCResultData>>();
return list;
}
}
}
catch(Exception ex)
{
_logger.LogError(ex, "SecondaryCircuitInspectionPlanService - CallYCByDataIdAsync发生错误");
}
return null;
}
}
}