410 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Protocol.Contracts.Protocol.Dto;
using NUglify.JavaScript.Syntax;
using System.Text.RegularExpressions;
using YamlDotNet.Core.Tokens;
namespace JiShe.CollectBus.Protocol.T37612012
{
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);
}
/// <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);
}
/// <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>
/// 数据时标(曲线类型)
/// </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>
public static List<AnalysisBaseDto<decimal?>> GenerateFinalResultTd_c(this List<string> data, int index,int density,string dataType, string filedDesc = "")
{
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
for (int i = index; i < data.Count; i++)
{
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
{
if(decimal.TryParse(data[i], out decimal value))
{
meter.DataValue = value;
}
}
meter.DataType = dataType;
meter.FiledDesc = filedDesc;
meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty;
if (DateTime.TryParse(CalculateTimeSpan(i - 3, data[0], density), out DateTime readingDate))
meter.TimeSpan = readingDate;
list.Add(meter);
}
return list;
}
/// <summary>
/// 月冻结(曲线类型)
/// </summary>
/// <param name="data"></param>
/// <param name="index"></param>
/// <param name="dataType"></param>
/// <param name="timeSpan"></param>
/// <param name="filedDesc"></param>
/// <returns></returns>
public static List<AnalysisBaseDto<decimal?>> GenerateFinalResultTd_m(this List<string> data, int index,string dataType,string timeSpan, string filedDesc = "")
{
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
for (int i = index; i < data.Count; i++)
{
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>();
meter.DeviceType = MeterTypeEnum.Ammeter;
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
{
meter.ValidData = false;
meter.ErrorCodeMsg = errorCode.Item2;
}
else
{
if(decimal.TryParse(data[i], out decimal value))
{
meter.DataValue = value;
}
}
if (DateTime.TryParse(timeSpan, out DateTime readingDate))
{
meter.TimeSpan = readingDate;
}
meter.DataType = i - index == 0 ? dataType : $"{dataType}_{i - index}";
meter.FiledDesc = filedDesc;
meter.FiledName = meter.DataType.GetDataFieldByGatherDataType() ?? string.Empty;
list.Add(meter);
}
return list;
}
/// <summary>
/// 日冻结(曲线类型)
/// </summary>
/// <param name="index"></param>
/// <param name="data"></param>
/// <param name="remark"></param>
/// <returns></returns>
public static List<AnalysisBaseDto<decimal?>> GenerateFinalResultTd_d(this List<string> data, int index,string dataType, string timeSpan, string filedDesc = "")
{
List<AnalysisBaseDto<decimal?>> list = new List<AnalysisBaseDto<decimal?>>();
int typeIndex = 0;
for (int i = index; i < data.Count; i++)
{
AnalysisBaseDto<decimal?> meter = new AnalysisBaseDto<decimal?>
{
DeviceType = MeterTypeEnum.Ammeter
};
decimal value = 0;
var errorCode = data[i].CheckErrorCode();
if (errorCode != null)
{
meter.ValidData = false;
meter.ErrorCodeMsg = errorCode.Item2;
}
else
{
if(decimal.TryParse(data[i], out value))
{
meter.DataValue = value;
}
}
if (DateTime.TryParse(timeSpan, out DateTime readingDate))
{
meter.TimeSpan = readingDate;
}
meter.DataType = i - index == 0 ? dataType : $"{dataType}_{i - index}";
meter.FiledDesc = filedDesc;
meter.FiledName = meter.DataType.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>
public static List<AnalysisBaseDto<decimal?>> IsValidData(this List<AnalysisBaseDto<decimal?>> meterDatas, List<string> mark)
{
bool isUpload = false;
var jfpgSum = 0M;
foreach (var item in meterDatas)
{
if (item.ValidData && item.DataValue.HasValue)
jfpgSum += item.DataValue.Value;
}
var totalItem = meterDatas.FirstOrDefault(f => f.DataType.Equals(mark[0]));//meterDatas.Find(f => f.DataType.Equals(mark[0]));
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)
{
meterDatas.ForEach(f =>
{
f.ValidData = false;
});
}
return meterDatas;
}
}
}