410 lines
16 KiB
C#
Raw Permalink Normal View History

2025-04-27 17:23:26 +08:00
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
2025-04-27 17:23:26 +08:00
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using NUglify.JavaScript.Syntax;
2025-04-24 19:31:28 +08:00
using System.Text.RegularExpressions;
2025-05-08 15:12:37 +08:00
using YamlDotNet.Core.Tokens;
2025-04-24 19:31:28 +08:00
namespace JiShe.CollectBus.Protocol.T37612012
2025-04-24 19:31:28 +08:00
{
public static class Protocol3761Extensions
{
/// <summary>
/// 3761协议数据字节校验
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static bool Check3761Byte(this string value)
{
if (!value.ToUpper().Equals("FF") && !value.ToUpper().Equals("EE"))
return true;
return false;
}
/// <summary>
/// 字符串中是否包含字母
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static bool IsLetterExists(this string value)
{
return Regex.Matches(value, "[a-zA-Z]").Count > 0;
}
/// <summary>
/// 判断错误代码
/// </summary>
public static Tuple<string,string>? CheckErrorCode(this List<string> data)
{
var value = string.Join("", data);
if (value.IsLetterExists())
{
var code = ErrorCodes().Where(f => value.Contains(f.Key)).FirstOrDefault();
if (code.Key != null)
return Tuple.Create(code.Key,code.Value);
else
return Tuple.Create("EE", "未知数据错误");
}
return null;
}
/// <summary>
/// 判断错误代码
/// </summary>
public static Tuple<string, string>? CheckErrorCode(this string value)
{
if (value.IsLetterExists())
{
var code = ErrorCodes().Where(f => value.Contains(f.Key)).FirstOrDefault();
if (code.Key != null)
return Tuple.Create(code.Key, code.Value);
else
return Tuple.Create("EE", "未知数据错误");
}
return null;
}
/// <summary>
/// 错误信息
/// </summary>
/// <returns></returns>
public static Dictionary<string, string> ErrorCodes()
{
return new Dictionary<string, string>()
{
{ "FF", "电表无此数据项" },
{ "EE", "未知数据错误" },
{ "E1", "数据点缺少(停电)" },
{ "E2", "通讯异常" },
{ "E3", "集中器未配置数据项" },
{ "E4", "电表档案无效" },
{ "E5", "电表无此数据项" },
{ "E6", "电表时间异常" },
{ "E7","暂停抄表" }
};
}
/// <summary>
/// 费率数
/// </summary>
/// <param name="index"></param>
/// <param name="len"></param>
/// <returns></returns>
public static int GetRatingCount(this List<string> hexMessageList ,int index, int len)
{
var list = hexMessageList.GetRange(index, len);
return list.Count > 0 ? list[0].HexToDec() : 0;
}
/// <summary>
/// 抄表时间
/// </summary>
/// <param name="index"></param>
/// <param name="len"></param>
/// <returns></returns>
public static string GetReadTime(this List<string> hexMessageList, int index, int len)
{
var list = hexMessageList.GetRange(index, len);
return list.GetReadTime();
}
/// <summary>
/// 抄表时间
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static string GetReadTime(this List<string> data)
{
data.Reverse();
data.Insert(0, DateTime.Now.ToString("yyyy").Substring(0, 2));
return string.Join("", data);
}
/// <summary>
/// 判断当前时间所在时标(15分钟)
/// </summary>
/// <param name="curTime"></param>
/// <returns></returns>
public static DateTime CheckTimePoint(this DateTime curTime)
{
var curMinute = Convert.ToInt32(curTime.ToString("mm"));
string dataTime;
if (curMinute >= 0 && curMinute < 15)
dataTime = curTime.ToString("yyyy-MM-dd HH:00:00");
else if (curMinute >= 15 && curMinute < 30)
dataTime = curTime.ToString("yyyy-MM-dd HH:15:00");
else if (curMinute >= 30 && curMinute < 45)
dataTime = curTime.ToString("yyyy-MM-dd HH:30:00");
else
dataTime = curTime.ToString("yyyy-MM-dd HH:45:00");
return DateTime.Parse(dataTime);
}
2025-04-29 11:43:16 +08:00
/// <summary>
/// 判断当前时间所在时标(5分钟)
/// </summary>
/// <param name="curTime"></param>
/// <returns></returns>
public static DateTime CheckTimeFivePoint(this DateTime curTime)
{
string dataTime;
var curMinute = Convert.ToInt32(curTime.ToString("mm"));
if (curMinute >= 0 && curMinute < 5)
dataTime = curTime.ToString("yyyy-MM-dd HH:00:00");
else if (curMinute >= 5 && curMinute < 10)
dataTime = curTime.ToString("yyyy-MM-dd HH:5:00");
else if (curMinute >= 10 && curMinute < 15)
dataTime = curTime.ToString("yyyy-MM-dd HH:10:00");
else if (curMinute >= 15 && curMinute < 20)
dataTime = curTime.ToString("yyyy-MM-dd HH:15:00");
else if (curMinute >= 20 && curMinute < 25)
dataTime = curTime.ToString("yyyy-MM-dd HH:20:00");
else if (curMinute >= 25 && curMinute < 30)
dataTime = curTime.ToString("yyyy-MM-dd HH:25:00");
else if (curMinute >= 30 && curMinute < 35)
dataTime = curTime.ToString("yyyy-MM-dd HH:30:00");
else if (curMinute >= 35 && curMinute < 40)
dataTime = curTime.ToString("yyyy-MM-dd HH:35:00");
else if (curMinute >= 40 && curMinute < 45)
dataTime = curTime.ToString("yyyy-MM-dd HH:40:00");
else if (curMinute >= 45 && curMinute < 50)
dataTime = curTime.ToString("yyyy-MM-dd HH:45:00");
else if (curMinute >= 50 && curMinute < 55)
dataTime = curTime.ToString("yyyy-MM-dd HH:50:00");
else
dataTime = curTime.ToString("yyyy-MM-dd HH:55:00");
return DateTime.Parse(dataTime);
}
2025-04-30 17:25:35 +08:00
/// <summary>
/// 格式化时间
/// </summary>
/// <param name="dateTime"></param>
/// <param name="densityUnit"></param>
/// <param name="timeDensity"></param>
/// <returns></returns>
public static DateTime GetFormatTime(this DateTime dateTime, DensityUnit densityUnit, int timeDensity)
{
switch (densityUnit)
{
case DensityUnit.Minute:
if (timeDensity == 1 || timeDensity == 30)
return DateTime.Parse(dateTime.ToString("yyyy-MM-dd HH:mm:00"));
if (timeDensity == 5)
return dateTime.CheckTimeFivePoint();
if (timeDensity == 15)
return dateTime.CheckTimePoint();
if (timeDensity == 60)
return DateTime.Parse(dateTime.ToString("yyyy-MM-dd HH:00:00"));
break;
case DensityUnit.Day:
return DateTime.Parse(dateTime.ToString("yyyy-MM-dd 00:00:00"));
case DensityUnit.Month:
return DateTime.Parse(dateTime.ToString("yyyy-MM-01 00:00:00"));
}
return dateTime;
}
/// <summary>
2025-04-30 17:25:35 +08:00
/// 数据时标(曲线类型)
/// </summary>
/// <param name="hexMessageList"></param>
/// <param name="index"></param>
/// <param name="len"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static List<string> GetReadTimeTd_c(this List<string> hexMessageList, int index, int len)
{
if (len != 7)
throw new ArgumentException("数据时标 Td_c参数为不标准长度");
var list = hexMessageList.GetRange(index, len);
List<string> values = new List<string>
{
GetReadTime(list.GetRange(0, 5)),
list[5].HexToDec().ToString(),//密度
list[6].HexToDec().ToString()//数据点数
};
return values;
}
/// <summary>
/// 数据时标型(曲线类型)
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
2025-05-08 15:12:37 +08:00
public static List<AnalysisBaseDto<decimal?>> GenerateFinalResultTd_c(this List<string> data, int index,int density,string dataType, string filedDesc = "")
{
2025-05-08 15:12:37 +08:00
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
for (int i = index; i < data.Count; i++)
{
2025-05-08 15:12:37 +08:00
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
{
meter.ValidData = false;
meter.ErrorCodeMsg = errorCode.Item2;
}
else
2025-05-08 15:12:37 +08:00
{
if(decimal.TryParse(data[i], out decimal value))
{
meter.DataValue = value;
}
}
meter.ItemType = dataType;
2025-04-27 09:31:12 +08:00
meter.FiledDesc = filedDesc;
meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
if (DateTime.TryParse(CalculateTimeSpan(i - 3, data[0], density), out DateTime readingDate))
meter.TimeSpan = readingDate;
list.Add(meter);
}
return list;
}
/// <summary>
2025-04-30 17:25:35 +08:00
/// 月冻结(曲线类型)
/// </summary>
/// <param name="data"></param>
/// <param name="index"></param>
/// <param name="dataType"></param>
/// <param name="timeSpan"></param>
2025-04-30 17:25:35 +08:00
/// <param name="filedDesc"></param>
/// <returns></returns>
2025-05-08 15:12:37 +08:00
public static List<AnalysisBaseDto<decimal?>> GenerateFinalResultTd_m(this List<string> data, int index,string dataType,string timeSpan, string filedDesc = "")
{
2025-05-08 15:12:37 +08:00
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
for (int i = index; i < data.Count; i++)
{
2025-05-08 15:12:37 +08:00
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>();
2025-05-07 11:53:50 +08:00
meter.DeviceType = MeterTypeEnum.Ammeter;
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
{
meter.ValidData = false;
meter.ErrorCodeMsg = errorCode.Item2;
}
else
2025-05-08 15:12:37 +08:00
{
if(decimal.TryParse(data[i], out decimal value))
{
meter.DataValue = value;
}
}
if (DateTime.TryParse(timeSpan, out DateTime readingDate))
{
meter.TimeSpan = readingDate;
}
meter.ItemType = i - index == 0 ? dataType : $"{dataType}_{i - index}";
2025-04-27 09:31:12 +08:00
meter.FiledDesc = filedDesc;
meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
}
return list;
}
/// <summary>
2025-04-30 17:25:35 +08:00
/// 日冻结(曲线类型)
/// </summary>
/// <param name="index"></param>
/// <param name="data"></param>
/// <param name="remark"></param>
/// <returns></returns>
2025-05-08 15:12:37 +08:00
public static List<AnalysisBaseDto<decimal?>> GenerateFinalResultTd_d(this List<string> data, int index,string dataType, string timeSpan, string filedDesc = "")
{
2025-05-08 15:12:37 +08:00
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
int typeIndex = 0;
for (int i = index; i < data.Count; i++)
{
2025-05-08 15:12:37 +08:00
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>
{
2025-05-07 11:53:50 +08:00
DeviceType = MeterTypeEnum.Ammeter
};
decimal value = 0;
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
{
meter.ValidData = false;
meter.ErrorCodeMsg = errorCode.Item2;
}
else
2025-05-08 15:12:37 +08:00
{
if(decimal.TryParse(data[i], out value))
{
meter.DataValue = value;
}
}
if (DateTime.TryParse(timeSpan, out DateTime readingDate))
{
meter.TimeSpan = readingDate;
}
meter.ItemType = i - index == 0 ? dataType : $"{dataType}_{i - index}";
2025-04-27 09:31:12 +08:00
meter.FiledDesc = filedDesc;
meter.FiledName = meter.ItemType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
typeIndex++;
}
return list;
}
/// <summary>
/// 计算时标
/// </summary>
/// <param name="index"></param>
/// <param name="time"></param>
/// <param name="intervalTime"></param>
/// <returns></returns>
private static string CalculateTimeSpan(int index, string time, int intervalTime)
{
var startTime = Convert.ToDateTime($"{time.Substring(0, 4)}-{time.Substring(4, 2)}-{time.Substring(6, 2)} {time.Substring(8, 2)}:{time.Substring(10, 2)}");
return startTime.AddMinutes(index * intervalTime).ToString("yyyy-MM-dd HH:mm:ss");
}
/// <summary>
/// 校验数据值精度
/// </summary>
/// <param name="meterDatas"></param>
/// <param name="mark"></param>
/// <returns></returns>
2025-05-08 15:12:37 +08:00
public static List<AnalysisBaseDto<decimal?>> IsValidData(this List<AnalysisBaseDto<decimal?>> meterDatas, List<string> mark)
{
bool isUpload = false;
var jfpgSum = 0M;
2025-05-08 15:12:37 +08:00
foreach (var item in meterDatas)
{
2025-05-08 15:12:37 +08:00
if (item.ValidData && item.DataValue.HasValue)
jfpgSum += item.DataValue.Value;
}
var totalItem = meterDatas.FirstOrDefault(f => f.ItemType.Equals(mark[0]));//meterDatas.Find(f => f.DataType.Equals(mark[0]));
2025-05-08 15:12:37 +08:00
if (totalItem != null)
{
var floatingNum = (jfpgSum * 5 / 100);//上下浮动数据
var minjfpgSum = jfpgSum - floatingNum;//100-(100*5/100);
var maxjfpgSum = jfpgSum + floatingNum;
if ((totalItem.DataValue <= maxjfpgSum || totalItem.DataValue >= minjfpgSum))//总值在JFPG之和的浮动范围内
isUpload = true;
else
isUpload = false;
}
if (!isUpload)
2025-05-08 15:12:37 +08:00
{
meterDatas.ForEach(f =>
{
f.ValidData = false;
});
2025-05-08 15:12:37 +08:00
}
return meterDatas;
}
2025-04-24 19:31:28 +08:00
}
}