2026-01-08 15:51:20 +08:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
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.Configurations;
|
|
|
|
|
|
|
|
|
|
|
|
namespace YunDa.Server.ISMSTcp.Services
|
|
|
|
|
|
{
|
|
|
|
|
|
public class YcIdExInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
public string Id { get; set; } = string.Empty;
|
|
|
|
|
|
public string DeviceId { get; set; } = string.Empty;
|
|
|
|
|
|
public bool DeviceCommState { get; set; } = true;
|
|
|
|
|
|
|
|
|
|
|
|
public YcIdExInfo(string id)
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = id;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class ZzDataIdList
|
|
|
|
|
|
{
|
|
|
|
|
|
private ConcurrentDictionary<string, YcIdExInfo> _ids = new ConcurrentDictionary<string, YcIdExInfo>();
|
|
|
|
|
|
|
|
|
|
|
|
public void Clear()
|
|
|
|
|
|
{
|
|
|
|
|
|
_ids.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool AddId(string id)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _ids.TryAdd(id, new YcIdExInfo(id));
|
|
|
|
|
|
}
|
|
|
|
|
|
public void AddIds(string ids, string keyword, string separator)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(ids))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
string[] list = ids.Trim().Split(separator);
|
|
|
|
|
|
foreach (string id in list)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(string.IsNullOrWhiteSpace(id))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
if(id.Contains(keyword))
|
|
|
|
|
|
_ids.TryAdd(id, new YcIdExInfo(id));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void UpdateDeviceCommState(string deviceId, bool commState)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var yc in _ids.Values)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (yc.Id.Contains(deviceId))
|
|
|
|
|
|
{
|
|
|
|
|
|
yc.DeviceCommState = commState;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public List<string> GetIds(bool? commState)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(commState.HasValue)
|
|
|
|
|
|
return _ids.Where(kvp => kvp.Value.DeviceCommState == commState)
|
|
|
|
|
|
.Select(kvp => kvp.Key)
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
else
|
|
|
|
|
|
return _ids.Keys.ToList();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public class ZzDataCmdService
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
private readonly ILogger<ZzDataCmdService> _logger;
|
|
|
|
|
|
private readonly ZzTcpService _zTcpService = null;
|
|
|
|
|
|
|
|
|
|
|
|
private ZzDataIdList _ycIds = new ZzDataIdList();
|
|
|
|
|
|
|
|
|
|
|
|
public ZzDataCmdService(
|
|
|
|
|
|
ILogger<ZzDataCmdService> logger,
|
|
|
|
|
|
ZzTcpService zTcpService)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger = logger;
|
|
|
|
|
|
_zTcpService = zTcpService;
|
|
|
|
|
|
|
|
|
|
|
|
StartAsync();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async Task StartAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
await AppInit.WaitAsync(AppInit.DefaultTimeOut);
|
|
|
|
|
|
|
|
|
|
|
|
_ = Task.Run(async () =>
|
|
|
|
|
|
{
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
{//每秒发送一次遥测命令(只发送用到的id)
|
|
|
|
|
|
|
|
|
|
|
|
await SendYcCmd();
|
|
|
|
|
|
|
|
|
|
|
|
await Task.Delay(TimeSpan.FromSeconds(1));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-08 16:27:36 +08:00
|
|
|
|
//暂时屏蔽发送虚点命令,不然李老师那边会卡
|
|
|
|
|
|
//_ = Task.Run(async () =>
|
|
|
|
|
|
//{
|
|
|
|
|
|
// while (true)
|
|
|
|
|
|
// {//每30秒发送一次虚点命令(全体)
|
2026-01-08 15:51:20 +08:00
|
|
|
|
|
2026-01-08 16:27:36 +08:00
|
|
|
|
// await SendVaCmd();
|
2026-01-08 15:51:20 +08:00
|
|
|
|
|
2026-01-08 16:27:36 +08:00
|
|
|
|
// await Task.Delay(TimeSpan.FromSeconds(30));
|
|
|
|
|
|
// }
|
|
|
|
|
|
//});
|
2026-01-08 15:51:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<string> GetValidZzCmd(string cmdName, List<string> ids)
|
|
|
|
|
|
{
|
|
|
|
|
|
const int maxLength = 25000;
|
|
|
|
|
|
|
|
|
|
|
|
var cmds = new List<string>();
|
|
|
|
|
|
|
|
|
|
|
|
// 开始构建
|
|
|
|
|
|
string prefix = cmdName + "|"; // 固定前缀
|
|
|
|
|
|
int prefixLength = prefix.Length;
|
|
|
|
|
|
|
|
|
|
|
|
var currentIds = new List<string>();
|
|
|
|
|
|
int currentLength = prefixLength; // 当前命令的长度(含前缀)
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var id in ids)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 如果添加这个ID会超长,则先生成一个命令
|
|
|
|
|
|
int idLength = (currentIds.Count == 0 ? id.Length : (1 + id.Length)); // 第一个ID不需要 '#'
|
|
|
|
|
|
|
|
|
|
|
|
if (currentLength + idLength > maxLength)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 将当前批次加入 cmds
|
|
|
|
|
|
cmds.Add(prefix + string.Join("#", currentIds));
|
|
|
|
|
|
|
|
|
|
|
|
// 清空并重建
|
|
|
|
|
|
currentIds.Clear();
|
|
|
|
|
|
currentLength = prefixLength;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 添加新的 ID
|
|
|
|
|
|
currentIds.Add(id);
|
|
|
|
|
|
currentLength += idLength;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 收尾:如果还有剩余 IDs,生成最后一个命令
|
|
|
|
|
|
if (currentIds.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
cmds.Add(prefix + string.Join("#", currentIds));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return cmds;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//更新装置状态
|
|
|
|
|
|
public void UpdateDeviceCommState(string deviceId, bool commState)
|
|
|
|
|
|
{
|
|
|
|
|
|
_ycIds.UpdateDeviceCommState(deviceId, commState);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/////遥测
|
|
|
|
|
|
|
|
|
|
|
|
public void ClearYcIds()
|
|
|
|
|
|
{
|
|
|
|
|
|
_ycIds.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//计划巡检配置
|
|
|
|
|
|
public void AddCircuitPlanYcIds(SecondaryCircuitInspectionPlanStateModel[] planList)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var plan in planList)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach(var inspection in plan.Plan.InspectionItems)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var item in inspection.TelemetryConfigs)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!string.IsNullOrWhiteSpace(item.TelemetryConfigurationIsmsId) && item.TelemetryConfigurationIsmsId.StartsWith("YC"))
|
|
|
|
|
|
_ycIds.AddId(item.TelemetryConfigurationIsmsId);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//事件巡检配置
|
|
|
|
|
|
public void AddEventPlanYcIds(SecondaryCircuitEventDrivenConfigOutput[] planList)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var plan in planList)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach(var item in plan.TelemetryConfigs)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(item.TelemetryConfigurationIsmsId) && item.TelemetryConfigurationIsmsId.StartsWith("YC"))
|
|
|
|
|
|
_ycIds.AddId(item.TelemetryConfigurationIsmsId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var inspection in plan.SecondaryCircuitInspectionEventItems)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var item in inspection.TelemetryConfigs)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(item.TelemetryConfigurationIsmsId) && item.TelemetryConfigurationIsmsId.StartsWith("YC"))
|
|
|
|
|
|
_ycIds.AddId(item.TelemetryConfigurationIsmsId);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private int _sendCnt = 0;
|
|
|
|
|
|
private async Task SendYcCmd()
|
|
|
|
|
|
{
|
|
|
|
|
|
var ids = _ycIds.GetIds(null);
|
|
|
|
|
|
var cmds = GetValidZzCmd("CallYCByDataID", ids);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var cmd in cmds)
|
|
|
|
|
|
{
|
|
|
|
|
|
await _zTcpService.SendTcpMessageAsync(cmd, CancellationToken.None);
|
|
|
|
|
|
|
|
|
|
|
|
if(_sendCnt % 60 == 0)
|
|
|
|
|
|
_logger.LogWarning($"发送命令:{ids.Count}个id");
|
|
|
|
|
|
|
|
|
|
|
|
_sendCnt++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private async Task SendVaCmd()
|
|
|
|
|
|
{
|
|
|
|
|
|
string cmd = "CallVAByStat|B001";
|
|
|
|
|
|
await _zTcpService.SendTcpMessageAsync(cmd, CancellationToken.None);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|