2025-04-25 13:42:08 +08:00

400 lines
15 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.Consts;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.FreeRedis;
using JiShe.CollectBus.IotSystems.Protocols;
using JiShe.CollectBus.Protocol.Contracts.SendData;
using JiShe.CollectBus.Protocol.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TouchSocket.Sockets;
using Volo.Abp.Domain.Repositories;
namespace JiShe.CollectBus.Protocol.Contracts.Abstracts
{
public abstract class ProtocolPlugin : IProtocolPlugin
{
//头部字节长度
public const int hearderLen = 6;
public const int tPLen = 6;
public const string errorData = "EE";
private readonly ILogger _logger;
private readonly IRepository<ProtocolInfo, Guid> _protocolInfoRepository;
private readonly IFreeRedisProvider _redisProvider;
public ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger)
{
_logger = logger;
_protocolInfoRepository = serviceProvider.GetRequiredService<IRepository<ProtocolInfo, Guid>>();
_redisProvider = serviceProvider.GetRequiredService<IFreeRedisProvider>();
}
public abstract ProtocolInfo Info { get; }
public virtual async Task<ProtocolInfo> GetAsync() => await Task.FromResult(Info);
public virtual async Task LoadAsync()
{
if (Info == null)
{
throw new ArgumentNullException(nameof(Info));
}
await _protocolInfoRepository.DeleteDirectAsync(a => a.Name == Info.Name);
await _protocolInfoRepository.InsertAsync(Info);
await _redisProvider.Instance.HDelAsync($"{RedisConst.ProtocolKey}", Info.Name);
await _redisProvider.Instance.HSetAsync($"{RedisConst.ProtocolKey}", Info.Name, Info);
}
public abstract Task<T> AnalyzeAsync<T>(ITcpSessionClient client, string messageReceived, Action<T>? receivedAction = null) where T : class;
/// <summary>
/// 解析376.1帧
/// </summary>
/// <param name="messageReceived"></param>
/// <returns></returns>
public virtual TB3761? Analysis3761(string messageReceived)
{
try
{
var hexStringList = messageReceived.StringToPairs();
// 初步校验
if (hexStringList.Count < 6 || hexStringList.FirstOrDefault() != "68" || hexStringList.Skip(5).Take(1).FirstOrDefault() != "68" || hexStringList.Count < 18 || hexStringList.LastOrDefault() != "16")
{
_logger.LogError($"解析Analysis3761校验不通过,报文:{messageReceived}");
}
else
{
TB3761 tB3761 = new TB3761
{
BaseHexMessage = new BaseHexMessage
{
HexMessageString = messageReceived,
HexMessageList = hexStringList
},
C = Analysis_C(hexStringList),
A = Analysis_A(hexStringList),
AFN_FC = Analysis_AFN_FC(hexStringList),
SEQ = Analysis_SEQ(hexStringList),
UnitData = Analysis_UnitData(hexStringList),
DA = Analysis_DA(hexStringList),
DT = Analysis_DT(hexStringList)
};
return tB3761;
}
}
catch (Exception ex)
{
_logger.LogError($"解析Analysis3761错误,报文:{messageReceived},异常:{ex.Message}");
}
return null;
}
/// <summary>
/// 控制域C解析
/// </summary>
/// <returns></returns>
public virtual C Analysis_C(List<string> hexStringList)
{
C c = new C();
try
{
if (hexStringList.Count > 6)
{
BaseHexMessage baseHexMessage = new BaseHexMessage
{
HexMessageList = hexStringList.GetRange(6, 1) // 控制域 1字节
};
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
if (baseHexMessage.HexMessageList.Count == 0)
return null;
string binStr = baseHexMessage.HexMessageString.HexTo4BinZero();
c = new C
{
BaseHexMessage = baseHexMessage,
FC = binStr.Substring(binStr.Length - 4, 4).BinToDec(),
FCV = binStr.Substring(3, 1).BinToDec(),
FCB = binStr.Substring(2, 1).BinToDec(),
PRM = binStr.Substring(1, 1).BinToDec(),
DIR = binStr.Substring(0, 1).BinToDec()
};
return c;
}
}
catch (Exception ex)
{
_logger.LogError($"解析Analysis_C错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
}
return c;
}
/// <summary>
/// 地址域A解析
/// </summary>
/// <param name="hexStringList"></param>
/// <returns></returns>
public virtual A Analysis_A(List<string> hexStringList)
{
A a = new A();
try
{
if (hexStringList.Count > 7)
{
BaseHexMessage baseHexMessage = new BaseHexMessage
{
HexMessageList = hexStringList.GetRange(7, 5) // 地址域 5个字节
};
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
a = new A
{
BaseHexMessage = baseHexMessage,
A1 = baseHexMessage.HexMessageList.ListReverseToStr(0, 2),//.DataConvert(10);//行政区划码A1
A2 = baseHexMessage.HexMessageList.ListReverseToStr(2, 2).PadLeft(5, '0').HexToDec(),//终端地址A2
A3 = Analysis_A3(baseHexMessage.HexMessageList) //主站地址和组地址标志A3
};
a.Code = $"{a.A1.PadLeft(4, '0')}{a.A2.ToString()!.PadLeft(5, '0')}";
}
}
catch (Exception ex)
{
_logger.LogError($"解析Analysis_A错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
}
return a;
}
/// <summary>
/// 站地址和组地址标志A3
/// </summary>
/// <param name="hexAList">地址域A集合</param>
/// <returns></returns>
public virtual A3 Analysis_A3(List<string> hexAList)
{
A3 a3 = new A3();
try
{
if (hexAList.Count != 0)
{
BaseHexMessage baseHexMessage = new BaseHexMessage
{
HexMessageList = hexAList.GetRange(4, 1) // 站地址和组地址标志A3 1个字节
};
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
var binStr = baseHexMessage.HexMessageString.HexTo4BinZero();
a3 = new A3
{
BaseHexMessage = baseHexMessage,
D0 = binStr.Substring(binStr.Length - 1, 1).BinToDec(),
D1_D7 = binStr.Substring(0, binStr.Length - 1).BinToDec()
};
}
}
catch (Exception ex)
{
_logger.LogError($"解析Analysis_A3错误,报文:{string.Join("", hexAList)},异常:{ex.Message}");
}
return a3;
}
/// <summary>
/// AFN_FC功能码
/// </summary>
/// <returns></returns>
public virtual AFN_FC Analysis_AFN_FC(List<string> hexStringList)
{
AFN_FC aFN_FC = new AFN_FC();
try
{
if (hexStringList.Count == 0)
{
BaseHexMessage baseHexMessage = new BaseHexMessage
{
HexMessageList = hexStringList.GetRange(12, 1) //AFN功能码 1个字节
};
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
aFN_FC = new AFN_FC
{
BaseHexMessage = baseHexMessage,
AFN = baseHexMessage.HexMessageString.HexToDec(),
};
}
}
catch (Exception ex)
{
_logger.LogError($"解析Analysis_AFN_FC错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
}
return aFN_FC;
}
/// <summary>
/// 解析帧序列域SEQ
/// </summary>
/// <returns></returns>
public virtual SEQ Analysis_SEQ(List<string> hexStringList)
{
SEQ seq = new SEQ();
try
{
if (hexStringList.Count != 0)
{
BaseHexMessage baseHexMessage = new BaseHexMessage
{
HexMessageList = hexStringList.GetRange(13, 1) //帧序列域 SEQ 1个字节
};
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
var binStr = baseHexMessage.HexMessageString.HexTo4BinZero();
seq = new SEQ
{
PSEQ = binStr.Substring(binStr.Length - 4, 4).BinToDec(),
CON = binStr.Substring(3, 1).BinToDec(),
FIN = binStr.Substring(2, 1).BinToDec(),
FIR = binStr.Substring(1, 1).BinToDec(),
TpV = binStr.Substring(0, 1).BinToDec()
};
}
}
catch (Exception ex)
{
_logger.LogError($"解析Analysis_SEQ错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
}
return seq;
}
/// <summary>
/// 数据单元标识及数据单元数据
/// </summary>
public virtual UnitData Analysis_UnitData(List<string> hexStringList)
{
UnitData unitData = new UnitData();
try
{
if (hexStringList.Count != 0)
{
unitData = new UnitData
{
HexMessageList = hexStringList.GetRange(14, hexStringList.Count - 14 - 2) //总数字节数-固定长度报文头-控制域C-地址域A-校验和CS-结束字符16H
};
unitData.HexMessageString = string.Join("", unitData.HexMessageList);
}
}
catch (Exception ex)
{
_logger.LogError($"解析Analysis_UnitData错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
}
return unitData;
}
/// <summary>
/// 信息点DA Pn
/// </summary>
/// <returns></returns>
public virtual DA Analysis_DA(List<string> hexStringList)
{
DA da = new DA();
try
{
if (hexStringList.Count != 0)
{
BaseHexMessage baseHexMessage = new BaseHexMessage
{
HexMessageList = hexStringList.GetRange(14, 2) //信息点DA Pn 2个字节
};
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
var da1 = baseHexMessage.HexMessageList[0];
var da2 = baseHexMessage.HexMessageList[1];
da = new DA()
{
BaseHexMessage = baseHexMessage,
Pn = CalculatePn(da1, da2)
};
}
}
catch (Exception ex)
{
_logger.LogError($"解析Analysis_DA错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
}
return da;
}
/// <summary>
/// 信息类DT Fn
/// </summary>
/// <returns></returns>
public virtual DT Analysis_DT(List<string> hexStringList)
{
DT dt = new DT();
try
{
if (hexStringList.Count != 0)
{
BaseHexMessage baseHexMessage = new BaseHexMessage
{
HexMessageList = hexStringList.GetRange(16, 2) //信息类DT Fn 2个字节
};
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
var dt1 = baseHexMessage.HexMessageList[0];
var dt2 = baseHexMessage.HexMessageList[1];
dt = new DT()
{
BaseHexMessage = baseHexMessage,
Fn = CalculateFn(dt1, dt2)
};
}
}
catch (Exception ex)
{
_logger.LogError($"解析Analysis_DT错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
}
return dt;
}
/// <summary>
/// 计算Pn
/// </summary>
/// <param name="da1"></param>
/// <param name="da2"></param>
/// <returns></returns>
public static int CalculatePn(string da1, string da2) => (da2.HexToDec() - 1) * 8 + (8 - da1.HexTo4BinZero().IndexOf(da1.Equals("00") ? "0" : "1"));
/// <summary>
/// 计算Fn
/// </summary>
/// <param name="dt1"></param>
/// <param name="dt2"></param>
/// <returns></returns>
public static int CalculateFn(string dt1, string dt2) => dt2.HexToDec() * 8 + (8 - dt1.HexTo4BinZero().IndexOf("1"));
#region
/// <summary>
/// 组装报文
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity">设备数据实体</param>
/// <param name="afnFnCode">映射读取执行方法的Code例如10_1表示 10H_F1_00000,10H_F1_00001统一英文下划线分隔</param>
/// <returns></returns>
public abstract Task<ProtocolBuildResponse> BuildAsync(ProtocolBuildRequest request);
#endregion
}
}