This commit is contained in:
zenghongyao 2025-04-30 17:26:27 +08:00
commit 53fa6f503c
10 changed files with 168 additions and 59 deletions

View File

@ -250,7 +250,8 @@ namespace JiShe.CollectBus.Protocol.T37612012.SendData
Pn = request.Pn, Pn = request.Pn,
Fn = request.Fn Fn = request.Fn
}; };
var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter);
var bytes = Build3761SendData.BuildSendCommandBytes(reqParameter,request.DataUnit);
return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, }; return new Telemetry3761PacketResponse() { Seq = reqParameter.Seq.PRSEQ, Data = bytes, MSA = reqParameter.MSA, };
} }
#endregion #endregion

View File

@ -706,6 +706,36 @@ namespace JiShe.CollectBus.Protocol.T37612012
/// <returns></returns> /// <returns></returns>
public static int CalculateFn(string dt1, string dt2) => dt2.HexToDec() * 8 + (8 - dt1.HexTo4BinZero().IndexOf("1")); public static int CalculateFn(string dt1, string dt2) => dt2.HexToDec() * 8 + (8 - dt1.HexTo4BinZero().IndexOf("1"));
#region
/// <summary>
/// 生成二类项采集项时间数据单元
/// </summary>
/// <param name="timeMark"></param>
/// <param name="validLength"></param>
/// <returns></returns>
public virtual List<string> Generate_DataUnit(DataTimeMark timeMark)
{
List<string> values = new List<string>
{
SplitDataTime(timeMark.DataTime)//数据时间
};
if (timeMark.Density > 0)
values.Add(timeMark.Density.HexToDecStr().PadLeft(2, '0'));//密度
if (timeMark.Point > 0)
values.Add(timeMark.Point.HexToDecStr().PadLeft(2, '0'));//数据点数
return values;
}
private string SplitDataTime(DateTime dataTime)
{
//2101060815
List<string> values = new List<string>() { $"{dataTime}:YY", $"{dataTime}:MM", $"{dataTime}:dd", $"{dataTime}:HH", $"{dataTime}:mm", };
values.Reverse();
return string.Join("", values);
}
#endregion
#region #region

View File

@ -113,6 +113,11 @@ namespace JiShe.CollectBus.Protocol.T6452007
} }
} }
if (aFNStr == "0D")//二类数据
{
dataUnit = Generate_DataUnit(request.DataTimeMark);
}
string afnMethonCode = $"AFN{aFNStr}_Fn_Send"; string afnMethonCode = $"AFN{aFNStr}_Fn_Send";
if (base.T3761AFNHandlers != null && base.T3761AFNHandlers.TryGetValue(afnMethonCode if (base.T3761AFNHandlers != null && base.T3761AFNHandlers.TryGetValue(afnMethonCode
, out var handler)) , out var handler))

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.Protocol
{
/// <summary>
/// 数据时间标记
/// </summary>
public class DataTimeMark
{
/// <summary>
/// 数据时间
/// </summary>
public DateTime DataTime { get; set;}
/// <summary>
/// 数据点数
/// </summary>
public int Point { get; set; }
/// <summary>
/// 冻结密度(-1、采集项本身无密度位0、无1、15分钟2、30分钟3、60分钟245、5分钟255、1分钟
/// </summary>
public int Density { get; set; }
}
}

View File

@ -1,4 +1,6 @@
namespace JiShe.CollectBus.Protocol.Models using JiShe.CollectBus.Common.BuildSendDatas;
namespace JiShe.CollectBus.Protocol.Models
{ {
/// <summary> /// <summary>
/// 报文构建参数 /// 报文构建参数
@ -21,9 +23,9 @@
public required string ItemCode { get; set; } public required string ItemCode { get; set; }
/// <summary> /// <summary>
/// 任务时间 /// 任务时间
/// </summary> /// </summary>
public long TimeStamp { get; set; } public DataTimeMark DataTimeMark { get; set; }
/// <summary> /// <summary>
/// 集中器转发协议构建构建参数 /// 集中器转发协议构建构建参数

View File

@ -72,51 +72,77 @@ namespace JiShe.CollectBus.DataChannels
/// <returns></returns> /// <returns></returns>
public async Task ScheduledMeterTaskReadding(ChannelReader<Tuple<string, List<MeterReadingTelemetryPacketInfo>>> _telemetryPacketInfoReader) public async Task ScheduledMeterTaskReadding(ChannelReader<Tuple<string, List<MeterReadingTelemetryPacketInfo>>> _telemetryPacketInfoReader)
{ {
var metadata = await _dbProvider.GetMetadata<MeterReadingTelemetryPacketInfo>(); try
var batchSize = 10000;
var timeout = TimeSpan.FromSeconds(5); // 默认超时时间为5秒
List<MeterReadingTelemetryPacketInfo> taskInfoList = new List<MeterReadingTelemetryPacketInfo>();
var startTime = DateTime.Now;
var timer = new Stopwatch();
while (true)
{ {
var canRead = await _telemetryPacketInfoReader.WaitToReadAsync(); var metadata = await _dbProvider.GetMetadata<MeterReadingTelemetryPacketInfo>();
if (!canRead) var batchSize = 200_00;
{ var timeout = TimeSpan.FromSeconds(5); // 默认超时时间为5秒
continue; var timer = Stopwatch.StartNew();
} long timeoutMilliseconds = 0;
while (taskInfoList != null && taskInfoList.Count < batchSize && (DateTime.Now - startTime) < timeout) List<MeterReadingTelemetryPacketInfo> taskInfoList = new List<MeterReadingTelemetryPacketInfo>();
while (true)
{ {
if (_telemetryPacketInfoReader.TryRead(out var dataItem)) var canRead = _telemetryPacketInfoReader.Count;
if (canRead <= 0)
{ {
taskInfoList.AddRange(dataItem.Item2); if (timeoutMilliseconds > 0)
}
else
{
//无消息时短暂等待
await Task.Delay(5);
}
}
if (taskInfoList != null && taskInfoList.Count > 0)
{
await _dbProvider.BatchInsertAsync(metadata, taskInfoList);
await DeviceGroupBalanceControl.ProcessWithThrottleAsync<MeterReadingTelemetryPacketInfo>(
items: taskInfoList.ToList(),
deviceIdSelector: data => data.DeviceId,
processor: (data, groupIndex) =>
{ {
// _ = KafkaProducerIssuedMessageAction(dateItem.Item1, data, groupIndex); _logger.LogError($"{nameof(ScheduledMeterTaskReadding)} 通道处理数据耗时{timeoutMilliseconds}毫秒");
} }
); timeoutMilliseconds = 0;
//无消息时短等待1秒
await Task.Delay(100_0);
continue;
}
timer.Restart();
taskInfoList.Clear(); var startTime = DateTime.Now;
string topicName = string.Empty;
while (taskInfoList != null && taskInfoList.Count < batchSize && (DateTime.Now - startTime) < timeout)
{
try
{
if (_telemetryPacketInfoReader.TryRead(out var dataItem))
{
topicName = dataItem.Item1;
taskInfoList.AddRange(dataItem.Item2);
}
}
catch (Exception ee)
{
throw;
}
}
if (taskInfoList != null && taskInfoList.Count > 0)
{
await _dbProvider.BatchInsertAsync(metadata, taskInfoList);
await DeviceGroupBalanceControl.ProcessWithThrottleAsync<MeterReadingTelemetryPacketInfo>(
items: taskInfoList.ToList(),
deviceIdSelector: data => data.DeviceId,
processor: (data, groupIndex) =>
{
//_ = KafkaProducerIssuedMessageAction(dateItem.Item1, data, groupIndex);
}
);
taskInfoList.Clear();
}
timer.Stop();
timeoutMilliseconds = timeoutMilliseconds + timer.ElapsedMilliseconds;
startTime = DateTime.Now;
} }
}
catch (Exception ex)
{
startTime = DateTime.Now; throw;
} }
} }

View File

@ -32,6 +32,7 @@ using static IdentityModel.ClaimComparer;
using JiShe.CollectBus.DataChannels; using JiShe.CollectBus.DataChannels;
using JiShe.CollectBus.DataMigration.Options; using JiShe.CollectBus.DataMigration.Options;
using static System.Runtime.InteropServices.JavaScript.JSType; using static System.Runtime.InteropServices.JavaScript.JSType;
using static System.Formats.Asn1.AsnWriter;
namespace JiShe.CollectBus.ScheduledMeterReading namespace JiShe.CollectBus.ScheduledMeterReading
{ {
@ -169,7 +170,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
meterType: MeterTypeEnum.Ammeter, meterType: MeterTypeEnum.Ammeter,
taskCreateAction: async (timeDensity, data, groupIndex, timestamps) => taskCreateAction: async (timeDensity, data, groupIndex, timestamps) =>
{ {
var tempTask = await ConcentratorScheduledAutomaticGetTerminalVersion(timeDensity, data, groupIndex, timestamps); var tempTask = await ConcentratorScheduledAutomaticGetTerminalVersion(timeDensity, data, groupIndex, timestamps);
if (tempTask == null || tempTask.Count <= 0) if (tempTask == null || tempTask.Count <= 0)
{ {
_logger.LogWarning($"集中器 {data.Name} 任务数据构建失败:{data.Serialize()}"); _logger.LogWarning($"集中器 {data.Name} 任务数据构建失败:{data.Serialize()}");
@ -257,7 +258,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
var tempTask = await AmmerterCreatePublishTaskAction(timeDensity, data, groupIndex, timestamps); var tempTask = await AmmerterCreatePublishTaskAction(timeDensity, data, groupIndex, timestamps);
if (tempTask == null || tempTask.Count <= 0) if (tempTask == null || tempTask.Count <= 0)
{ {
_logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}"); //_logger.LogWarning($"电表 {data.Name} 任务数据构建失败:{data.Serialize()}");
return; return;
} }
_ = _dataChannelManage.ScheduledMeterTaskWriter(DataChannelManage.TaskDataChannel.Writer, Tuple.Create(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, tempTask)); _ = _dataChannelManage.ScheduledMeterTaskWriter(DataChannelManage.TaskDataChannel.Writer, Tuple.Create(ProtocolConst.AmmeterSubscriberWorkerAutoValveControlIssuedEventName, tempTask));
@ -298,7 +299,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
} }
//电表定时阀控任务处理。 //电表定时阀控任务处理。
var autoValveControlTask = await AmmeterScheduledAutoValveControl(); var autoValveControlTask = await AmmeterScheduledAutoValveControl();
if (autoValveControlTask == null || autoValveControlTask.Count <= 0) if (autoValveControlTask == null || autoValveControlTask.Count <= 0)
{ {
@ -332,9 +333,10 @@ namespace JiShe.CollectBus.ScheduledMeterReading
//此处代码不要删除 //此处代码不要删除
#if DEBUG #if DEBUG
var timeDensity = "15"; var timeDensity = "15";
var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, "JiSheCollectBus2", MeterTypeEnum.Ammeter, timeDensity)}"; var serverTagName = "JiSheCollectBus2";
var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, "JiSheCollectBus2", MeterTypeEnum.Ammeter, timeDensity)}"; var redisCacheMeterInfoHashKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoHashKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}";
var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, "JiSheCollectBus2", MeterTypeEnum.Ammeter, timeDensity)}"; var redisCacheMeterInfoSetIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoSetIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}";
var redisCacheMeterInfoZSetScoresIndexKeyTemp = $"{string.Format(RedisConst.CacheMeterInfoZSetScoresIndexKey, SystemType, serverTagName, MeterTypeEnum.Ammeter, timeDensity)}";
List<AmmeterInfo> meterInfos = new List<AmmeterInfo>(); List<AmmeterInfo> meterInfos = new List<AmmeterInfo>();
List<string> focusAddressDataLista = new List<string>(); List<string> focusAddressDataLista = new List<string>();
@ -734,6 +736,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading
FocusAddress = ammeterInfo.FocusAddress, FocusAddress = ammeterInfo.FocusAddress,
Pn = ammeterInfo.MeteringCode, Pn = ammeterInfo.MeteringCode,
ItemCode = tempItem, ItemCode = tempItem,
DataTimeMark = new Protocol.DataTimeMark()
{
Density = ammeterInfo.TimeDensity,//todo 转换成协议的值
Point = 1,
DataTime = timestamps,
}
}); });
if (builderResponse == null || builderResponse.Data.Length <= 0) if (builderResponse == null || builderResponse.Data.Length <= 0)
{ {
@ -1499,8 +1507,8 @@ namespace JiShe.CollectBus.ScheduledMeterReading
List<T> meterInfos = new List<T>(); List<T> meterInfos = new List<T>();
decimal? cursor = null; decimal? cursor = null;
string member = null; string member = null;
bool hasNext;
do while (true)
{ {
var page = await _redisDataCacheService.GetAllPagedData<T>( var page = await _redisDataCacheService.GetAllPagedData<T>(
redisCacheMeterInfoHashKeyTemp, redisCacheMeterInfoHashKeyTemp,
@ -1510,11 +1518,14 @@ namespace JiShe.CollectBus.ScheduledMeterReading
lastMember: member); lastMember: member);
meterInfos.AddRange(page.Items); meterInfos.AddRange(page.Items);
cursor = page.HasNext ? page.NextScore : null; if (!page.HasNext)
member = page.HasNext ? page.NextMember : null; {
hasNext = page.HasNext; break;
} while (hasNext); }
cursor = page.NextScore;
member = page.NextMember;
}
//var page = await _redisDataCacheService.GetAllPagedData<T>( //var page = await _redisDataCacheService.GetAllPagedData<T>(
// redisCacheMeterInfoHashKeyTemp, // redisCacheMeterInfoHashKeyTemp,
@ -1530,8 +1541,12 @@ namespace JiShe.CollectBus.ScheduledMeterReading
_logger.LogError($"{nameof(CreateMeterPublishTask)} {meterType}的{timeDensity}分钟采集待下发任务创建失败,没有获取到缓存信息,-105"); _logger.LogError($"{nameof(CreateMeterPublishTask)} {meterType}的{timeDensity}分钟采集待下发任务创建失败,没有获取到缓存信息,-105");
return; return;
} }
timer.Stop();
_logger.LogError($"{nameof(CreateMeterPublishTask)} 构建采集待下发任务,缓存获取信息共花费{timer.ElapsedMilliseconds}毫秒"); _logger.LogError($"{nameof(CreateMeterPublishTask)} 构建采集待下发任务,缓存获取信息共花费{timer.ElapsedMilliseconds}毫秒");
timer.Restart();
await DeviceGroupBalanceControl.ProcessWithThrottleAsync( await DeviceGroupBalanceControl.ProcessWithThrottleAsync(
items: meterInfos, items: meterInfos,
deviceIdSelector: data => data.MeterId.ToString(), deviceIdSelector: data => data.MeterId.ToString(),

View File

@ -166,7 +166,7 @@ namespace JiShe.CollectBus.ScheduledMeterReading
INNER JOIN TB_AmmeterInfo(nolock) AS C ON B.AmmeterID=C.ID INNER JOIN TB_AmmeterInfo(nolock) AS C ON B.AmmeterID=C.ID
INNER JOIN TB_FocusInfo(nolock) AS D ON D.ID=C.FocusID INNER JOIN TB_FocusInfo(nolock) AS D ON D.ID=C.FocusID
INNER JOIN TB_GatherInfo(NOLOCK) AS E ON E.ID=D.GatherInfoID INNER JOIN TB_GatherInfo(NOLOCK) AS E ON E.ID=D.GatherInfoID
WHERE A.IsForbid=0 and A.State<>-1 and E.GatherCode LIKE '%V4%' and A.TripTime"; WHERE A.IsForbid=0 and A.State<>-1 and E.GatherCode LIKE '%V4%' ";
if (!string.IsNullOrWhiteSpace(currentTime)) if (!string.IsNullOrWhiteSpace(currentTime))
{ {

View File

@ -204,6 +204,7 @@ namespace JiShe.CollectBus.Common.DeviceBalanceControl
int actualThreads = maxConcurrency ?? recommendedThreads; int actualThreads = maxConcurrency ?? recommendedThreads;
// 创建节流器 // 创建节流器
using var throttler = new SemaphoreSlim(initialCount: actualThreads); using var throttler = new SemaphoreSlim(initialCount: actualThreads);

View File

@ -245,7 +245,7 @@ namespace JiShe.CollectBus.Common.Extensions
/// <param name="dateLong"></param> /// <param name="dateLong"></param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentException"></exception>
public static DateTime ParseIntToDate(long dateLong) public static DateTime ParseIntToDate(this long dateLong)
{ {
if (dateLong < 10000101 || dateLong > 99991231) if (dateLong < 10000101 || dateLong > 99991231)
{ {