2025-04-21 23:47:11 +08:00
|
|
|
|
using JiShe.CollectBus.Common.Extensions;
|
|
|
|
|
|
using JiShe.CollectBus.IotSystems.Protocols;
|
|
|
|
|
|
using JiShe.CollectBus.Protocol.Contracts.Interfaces;
|
|
|
|
|
|
using JiShe.CollectBus.Protocol.Contracts.Models;
|
|
|
|
|
|
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;
|
|
|
|
|
|
public ProtocolPlugin(IServiceProvider serviceProvider, ILogger logger)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger = logger;
|
|
|
|
|
|
_protocolInfoRepository = serviceProvider.GetRequiredService<IRepository<ProtocolInfo, Guid>>();
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public abstract ProtocolInfo Info { get; }
|
|
|
|
|
|
|
|
|
|
|
|
public virtual async Task<ProtocolInfo> GetAsync() => await Task.FromResult(Info);
|
|
|
|
|
|
|
|
|
|
|
|
public virtual async Task AddAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Info == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new ArgumentNullException(nameof(Info));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await _protocolInfoRepository.DeleteDirectAsync(a => a.Name == Info.Name);
|
|
|
|
|
|
await _protocolInfoRepository.InsertAsync(Info);
|
|
|
|
|
|
//await _protocolInfoCache.Get()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
{
|
|
|
|
|
|
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)
|
|
|
|
|
|
{
|
|
|
|
|
|
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;
|
2025-04-22 09:34:59 +08:00
|
|
|
|
string binStr = baseHexMessage.HexMessageString.HexTo4BinZero();
|
2025-04-21 23:47:11 +08:00
|
|
|
|
C 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 null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 地址域A解析
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="hexStringList"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public virtual A? Analysis_A(List<string> hexStringList)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (hexStringList.Count > 7)
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage baseHexMessage = new BaseHexMessage
|
|
|
|
|
|
{
|
|
|
|
|
|
HexMessageList = hexStringList.GetRange(7, 5) // 地址域 5个字节
|
|
|
|
|
|
};
|
|
|
|
|
|
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
|
|
|
|
|
|
if (baseHexMessage.HexMessageList.Count == 0)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
A 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')}";
|
|
|
|
|
|
return a;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogError($"解析Analysis_A错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 站地址和组地址标志A3
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="hexAList">地址域A集合</param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public virtual A3? Analysis_A3(List<string> hexAList)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage baseHexMessage = new BaseHexMessage
|
|
|
|
|
|
{
|
|
|
|
|
|
HexMessageList = hexAList.GetRange(4, 1) // 站地址和组地址标志A3 1个字节
|
|
|
|
|
|
};
|
|
|
|
|
|
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
|
|
|
|
|
|
if (baseHexMessage.HexMessageList.Count == 0)
|
|
|
|
|
|
return null;
|
2025-04-22 09:34:59 +08:00
|
|
|
|
var binStr = baseHexMessage.HexMessageString.HexTo4BinZero();
|
2025-04-21 23:47:11 +08:00
|
|
|
|
A3 a3 = new A3
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage = baseHexMessage,
|
|
|
|
|
|
D0 = binStr.Substring(binStr.Length - 1, 1).BinToDec(),
|
|
|
|
|
|
D1_D7 = binStr.Substring(0, binStr.Length - 1).BinToDec()
|
|
|
|
|
|
};
|
|
|
|
|
|
return a3;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogError($"解析Analysis_A3错误,报文:{string.Join("", hexAList)},异常:{ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// AFN_FC功能码
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public virtual AFN_FC? Analysis_AFN_FC(List<string> hexStringList)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage baseHexMessage = new BaseHexMessage
|
|
|
|
|
|
{
|
|
|
|
|
|
HexMessageList = hexStringList.GetRange(12, 1) //AFN功能码 1个字节
|
|
|
|
|
|
};
|
|
|
|
|
|
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
|
|
|
|
|
|
if (baseHexMessage.HexMessageList.Count == 0)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
AFN_FC aFN_FC = new AFN_FC
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage = baseHexMessage,
|
|
|
|
|
|
AFN = baseHexMessage.HexMessageString.HexToDec(),
|
|
|
|
|
|
};
|
|
|
|
|
|
return aFN_FC;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogError($"解析Analysis_AFN_FC错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 解析帧序列域SEQ
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public virtual SEQ? Analysis_SEQ(List<string> hexStringList)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage baseHexMessage = new BaseHexMessage
|
|
|
|
|
|
{
|
|
|
|
|
|
HexMessageList = hexStringList.GetRange(13, 1) //帧序列域 SEQ 1个字节
|
|
|
|
|
|
};
|
|
|
|
|
|
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
|
|
|
|
|
|
if (baseHexMessage.HexMessageList.Count == 0)
|
|
|
|
|
|
return null;
|
2025-04-22 09:34:59 +08:00
|
|
|
|
var binStr = baseHexMessage.HexMessageString.HexTo4BinZero();
|
2025-04-21 23:47:11 +08:00
|
|
|
|
SEQ 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()
|
|
|
|
|
|
};
|
|
|
|
|
|
return seq;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogError($"解析Analysis_SEQ错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 数据单元标识及数据单元数据
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public virtual UnitData? Analysis_UnitData(List<string> hexStringList)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
UnitData unitData = new UnitData
|
|
|
|
|
|
{
|
|
|
|
|
|
HexMessageList = hexStringList.GetRange(14, hexStringList.Count - 14 - 2) //总数字节数-固定长度报文头-控制域C-地址域A-校验和CS-结束字符(16H)
|
|
|
|
|
|
};
|
|
|
|
|
|
unitData.HexMessageString = string.Join("", unitData.HexMessageList);
|
|
|
|
|
|
if (unitData.HexMessageList.Count == 0)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
return unitData;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogError($"解析Analysis_UnitData错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 信息点DA Pn
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public virtual DA? Analysis_DA(List<string> hexStringList)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage baseHexMessage = new BaseHexMessage
|
|
|
|
|
|
{
|
|
|
|
|
|
HexMessageList = hexStringList.GetRange(14, 2) //信息点DA Pn 2个字节
|
|
|
|
|
|
};
|
|
|
|
|
|
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
|
|
|
|
|
|
if (baseHexMessage.HexMessageList.Count == 0)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
var da1 = baseHexMessage.HexMessageList[0];
|
|
|
|
|
|
var da2 = baseHexMessage.HexMessageList[1];
|
|
|
|
|
|
DA da = new DA()
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage = baseHexMessage,
|
|
|
|
|
|
Pn = CalculatePn(da1, da2)
|
|
|
|
|
|
};
|
|
|
|
|
|
return da;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogError($"解析Analysis_DA错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 信息类DT Fn
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public virtual DT? Analysis_DT(List<string> hexStringList)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage baseHexMessage = new BaseHexMessage
|
|
|
|
|
|
{
|
|
|
|
|
|
HexMessageList = hexStringList.GetRange(16, 2) //信息类DT Fn 2个字节
|
|
|
|
|
|
};
|
|
|
|
|
|
baseHexMessage.HexMessageString = string.Join("", baseHexMessage.HexMessageList);
|
|
|
|
|
|
if (baseHexMessage.HexMessageList.Count == 0)
|
|
|
|
|
|
return null;
|
|
|
|
|
|
var dt1 = baseHexMessage.HexMessageList[0];
|
|
|
|
|
|
var dt2 = baseHexMessage.HexMessageList[1];
|
|
|
|
|
|
DT dt = new DT()
|
|
|
|
|
|
{
|
|
|
|
|
|
BaseHexMessage = baseHexMessage,
|
|
|
|
|
|
Fn = CalculateFn(dt1, dt2)
|
|
|
|
|
|
};
|
|
|
|
|
|
return dt;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
_logger.LogError($"解析Analysis_DT错误,报文:{string.Join("", hexStringList)},异常:{ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 计算Pn
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="da1"></param>
|
|
|
|
|
|
/// <param name="da2"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-04-22 09:34:59 +08:00
|
|
|
|
public int CalculatePn(string da1, string da2) => (da2.HexToDec() - 1) * 8 + (8 - da1.HexTo4BinZero().IndexOf(da1.Equals("00") ? "0" : "1"));
|
2025-04-21 23:47:11 +08:00
|
|
|
|
|
2025-04-22 10:05:38 +08:00
|
|
|
|
|
2025-04-21 23:47:11 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 计算Fn
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="dt1"></param>
|
|
|
|
|
|
/// <param name="dt2"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2025-04-22 09:34:59 +08:00
|
|
|
|
public int CalculateFn(string dt1, string dt2) => dt2.HexToDec() * 8 + (8 - dt1.HexTo4BinZero().IndexOf("1"));
|
2025-04-21 23:47:11 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|