394 lines
15 KiB
C#
394 lines
15 KiB
C#
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;
|
||
|
||
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>();
|
||
meter.MeterType= MeterTypeEnum.Ammeter;
|
||
|
||
decimal value = 0;
|
||
var errorCode = data[i].CheckErrorCode();
|
||
if (errorCode != null)
|
||
{
|
||
meter.ValidData = false;
|
||
meter.ErrorCodeMsg = errorCode.Item2;
|
||
}
|
||
else
|
||
decimal.TryParse(data[i], out 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.MeterType = MeterTypeEnum.Ammeter;
|
||
decimal value = 0;
|
||
var errorCode = data[i].CheckErrorCode();
|
||
if (errorCode != null)
|
||
{
|
||
meter.ValidData = false;
|
||
meter.ErrorCodeMsg = errorCode.Item2;
|
||
}
|
||
else
|
||
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);
|
||
}
|
||
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>
|
||
{
|
||
MeterType = MeterTypeEnum.Ammeter
|
||
};
|
||
decimal value = 0;
|
||
var errorCode = data[i].CheckErrorCode();
|
||
if (errorCode != null)
|
||
{
|
||
meter.ValidData = false;
|
||
meter.ErrorCodeMsg = errorCode.Item2;
|
||
}
|
||
else
|
||
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;
|
||
var totalItem = meterDatas.Find(f => f.DataType.Equals(mark[0]));//meterDatas.Find(f => f.DataType.Equals(mark[0]));
|
||
for (int i = 1; i <= meterDatas.Count - 1; i++)
|
||
{
|
||
var value = meterDatas[i];//meterDatas.Find(f => f.DataType.Equals(mark[i]));
|
||
if (value.ValidData)
|
||
jfpgSum += value.DataValue;
|
||
}
|
||
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;
|
||
}
|
||
}
|
||
}
|