305 lines
9.4 KiB
C#
Raw Normal View History

using Microsoft.Extensions.Logging;
using Org.BouncyCastle.Utilities;
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;
namespace YunDa.Server.ISMSTcp.Services
{
public class ZzDataPoint
{
public DateTime TimeStamp { get; set; }
public double Value { get; }
public string ValueStr { get; }
public ZzDataPoint(DateTime time, double value, string valueStr)
{
TimeStamp = time;
Value = value;
ValueStr = valueStr;
}
}
public class ZzData
{
public TimeSpan Retention { get; set; }
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public int? DispatcherAddress { get; set; } = null;
/////////////////////////////////////////////////////////////////////////////////////
public double Value { get; set; }
public string ValueStr { get; set; } = string.Empty;
public DateTime TimeStamp { get; set; }
/////////////////////////////////////////////////////////////////////////////////////
private readonly ConcurrentQueue<(DateTime time, ZzDataPoint point)> _queue = new ConcurrentQueue<(DateTime time, ZzDataPoint point)>();
public ZzData(int minutes, string id, string name, int dispatcherAddress)
{
Retention = TimeSpan.FromMinutes(minutes);
Id = id;
Name = name;
DispatcherAddress = dispatcherAddress;
}
public void AddData(ZzDataPoint point)
{
DateTime now = DateTime.Now;
point.TimeStamp = now; //2025-11-18 用当前时间(临时修改)
_queue.Enqueue((now, point));
TimeStamp = point.TimeStamp;
Value = point.Value;
ValueStr = point.ValueStr;
CleanupOldData();
}
private void CleanupOldData()
{
DateTime limit = DateTime.Now - Retention;
while (_queue.TryPeek(out var dp) && dp.time < limit)
{
_queue.TryDequeue(out _);
}
}
public List<ZzDataPoint> GetData(DateTime start, DateTime end)
{
return _queue.Where(dp => dp.point.TimeStamp >= start && dp.point.TimeStamp <= end)
.Select(x => x.point)
.ToList();
}
}
public class ZzDataRequestModel
{
public List<string> Id { get; set; }
public int Times { get; set; }
public int TimeWindowType { get; set; }
}
public class ZzDataResultModel
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string DeviceName { get; set; } = string.Empty;
public int? DispatcherAddress { get; set; } = null;
public double Value { get; set; }
public string ValueStr { get; set; } = string.Empty;
public DateTime TimeStamp { get; set; } = DateTime.MinValue;
public List<ZzDataPoint> Data { get; set; } = new List<ZzDataPoint>();
public ZzDataResultModel()
{
}
public ZzDataResultModel(ZzData data)
{
Id = data.Id;
Name = data.Name;
Value = data.Value;
ValueStr = data.ValueStr;
TimeStamp = data.TimeStamp;
DispatcherAddress = data.DispatcherAddress;
}
}
public class ZzDataHistoryModel
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
}
public class ZzDataCacheContainer
{
private readonly ConcurrentDictionary<string, ZzData> _datas = new ConcurrentDictionary<string, ZzData>();
private readonly int _cleanupMinutes = 5;
public ZzDataCacheContainer(int cleanupMinutes)
{
_cleanupMinutes = cleanupMinutes;
}
public void Write(string id, double val, DateTime time, string name)
{
var data = _datas.GetOrAdd(id, _ => new ZzData(_cleanupMinutes, id, name, 0));
data.AddData(new ZzDataPoint(time, val, ""));
}
public void Write(string id, double val, DateTime time, string name, string valStr)
{
var data = _datas.GetOrAdd(id, _ => new ZzData(_cleanupMinutes, id, name, 0));
data.AddData(new ZzDataPoint(time, val, valStr));
}
public void Write(string id, double val, DateTime time, string name, string valStr, int dispatcherAddress)
{
//if (id == "YCB001101001")
//{
// int kk = 0;
//}
var data = _datas.GetOrAdd(id, _ => new ZzData(_cleanupMinutes, id, name, dispatcherAddress));
data.AddData(new ZzDataPoint(time, val, valStr));
}
public Dictionary<string, ZzDataResultModel> Read(List<string> ids, DateTime start, DateTime end)
{
var result = new Dictionary<string, ZzDataResultModel>();
foreach (var id in ids)
{
//if (id == "YCB001101001")
//{
// int kk = 0;
//}
if (_datas.TryGetValue(id, out var channel))
{
ZzDataResultModel data = new ZzDataResultModel(channel);
data.Data = channel.GetData(start, end);
if(data.Data.Count == 0 && data.TimeStamp != DateTime.MinValue)
{
ZzDataPoint zzDataPoint = new ZzDataPoint(DateTime.Now, data.Value, data.ValueStr);
data.Data.Add(zzDataPoint);
}
result[id] = data;
}
}
return result;
}
public async Task<List<ZzDataResultModel>> Read(List<string> ids, int seconds, int timeWindowType, CancellationToken cancellationToken, DateTime now = default)
{
try
{
if(now == default)
now = DateTime.Now;
//寻找匹配的值
Dictionary<string, ZzDataResultModel> matched1 = new Dictionary<string, ZzDataResultModel>();
Dictionary<string, ZzDataResultModel> matched2 = new Dictionary<string, ZzDataResultModel>();
if (timeWindowType == 0 || timeWindowType == 2)
{
matched1 = Read(ids, now.AddSeconds(-seconds), now);
}
if (timeWindowType == 1 || timeWindowType == 2)
{
int span = seconds*1000 - (int)(DateTime.Now - now).TotalMilliseconds;
if(span > 0)
await Task.Delay(span, cancellationToken);
matched2 = Read(ids, now, DateTime.Now);
}
foreach (var kv in matched2)
{
if (!matched1.TryAdd(kv.Key, kv.Value))
{
matched1[kv.Key].Data.AddRange(kv.Value.Data);
}
}
return matched1.Values.ToList();
}
catch (Exception ex)
{
return new List<ZzDataResultModel>();
}
}
}
public class ZzDataCacheContainerInit
{
private readonly ILogger<SecondaryCircuitInspectionPlanService> _logger;
private readonly WebApiRequest _webApiRequest;
private readonly ZzTcpService _zTcpService = null;
public ZzDataCacheContainerInit(ILogger<SecondaryCircuitInspectionPlanService> logger, WebApiRequest webApiRequest, ZzTcpService zTcpService)
{
_logger = logger;
_webApiRequest = webApiRequest;
_zTcpService = zTcpService;
}
public void InitTcpService(ITcpClient tcpClient)
{
_zTcpService.Init(tcpClient);
}
//初始化虚点信息
public async Task InitVariantBaseinfo(ZzDataCacheContainer cache)
{
//从数据库获取
var list = await _webApiRequest.GetVariantBaseinfoAsync();
if (list != null)
{
foreach (var item in list)
{
cache.Write(item.Id, 2, DateTime.Now, item.Name, "不定");
}
}
//发送命令从综自获取
if(_zTcpService != null)
{
string cmd = "CallVAByStat|B001";
2025-11-21 10:24:04 +08:00
for (int i = 0; i < 5; i++)
{
var sendResult = await _zTcpService.SendTcpMessageAsync(cmd, CancellationToken.None);
if (sendResult.Success)
{
break;
}
2025-11-21 10:24:04 +08:00
await Task.Delay(2000);
}
}
}
//初始化网关信息
public async Task InitGateWayBaseInfo(ZzDataCacheContainer cache)
{
var list = await _webApiRequest.GetGateWayBaseInfoAsync();
if (list != null)
{
foreach (var item in list)
{
cache.Write(item.Id, 0, DateTime.Now, item.Name, "0.00 %");
}
}
}
}
}