|
|
|
using DotNetty.Buffers;
|
|
|
|
using DotNetty.Codecs;
|
|
|
|
using DotNetty.Transport.Channels;
|
|
|
|
using HybirdFrameworkCore.Utils;
|
|
|
|
using HybirdFrameworkDriver.Session;
|
|
|
|
using log4net;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using Service.Charger.Client;
|
|
|
|
using Service.Charger.Msg;
|
|
|
|
using Service.Charger.Msg.Charger.Req;
|
|
|
|
using Service.Charger.Msg.Charger.Resp;
|
|
|
|
|
|
|
|
namespace Service.Charger.Codec;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 解码器
|
|
|
|
/// </summary>
|
|
|
|
public class Decoder : ByteToMessageDecoder
|
|
|
|
{
|
|
|
|
private readonly IByteBuffer[] _delimiters = { Unpooled.CopiedBuffer(PlcConst.StartChar) };
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
///
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="chargerSn"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
private ILog Log(string? chargerSn)
|
|
|
|
{
|
|
|
|
if (ObjUtils.IsNotNullOrWhiteSpace(chargerSn))
|
|
|
|
{
|
|
|
|
//return LogManager.GetLogger("Plc" + chargerSn);
|
|
|
|
return LogManager.GetLogger("Plc");
|
|
|
|
}
|
|
|
|
|
|
|
|
return LogManager.GetLogger(typeof(Decoder));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region MyRegion
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
protected override void Decode(IChannelHandlerContext context, IByteBuffer buffer, List<object> output)
|
|
|
|
{
|
|
|
|
string? chargerSn = ChannelUtils.GetAttr(context.Channel, PlcConst.ChargerSn);
|
|
|
|
IByteBuffer? delimiter = FindDelimiter(buffer);
|
|
|
|
if (delimiter != null)
|
|
|
|
{
|
|
|
|
//分隔符索引
|
|
|
|
int delimiterIndex = IndexOf(buffer, delimiter);
|
|
|
|
//帧长索引
|
|
|
|
int frameLengthIndex = delimiterIndex + delimiter.Capacity;
|
|
|
|
|
|
|
|
if (delimiterIndex > 0)
|
|
|
|
{
|
|
|
|
buffer.SkipBytes(delimiterIndex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffer.ReadableBytes < frameLengthIndex + 2)
|
|
|
|
{
|
|
|
|
// 数据不足,等待更多数据
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 读取长度字段
|
|
|
|
int frameLength = buffer.GetUnsignedShortLE(buffer.ReaderIndex + frameLengthIndex);
|
|
|
|
//总帧长
|
|
|
|
int totalFrameLength = delimiterIndex + delimiter.Capacity + 2 + frameLength;
|
|
|
|
// int totalFrameLength = delimiterIndex + frameLength;
|
|
|
|
// 最小总帧长过滤
|
|
|
|
if (totalFrameLength < 21)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buffer.ReadableBytes < totalFrameLength)
|
|
|
|
{
|
|
|
|
// 数据不足,等待更多数据
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
byte[]? data = null;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
ASDU asdu = Parse(buffer, totalFrameLength, delimiter, out data);
|
|
|
|
Log(chargerSn).Info($"receive {BitUtls.BytesToHexStr(data)}:{JsonConvert.SerializeObject(asdu)} from {chargerSn}");
|
|
|
|
output.Add(asdu);
|
|
|
|
}
|
|
|
|
catch (Exception e)
|
|
|
|
{
|
|
|
|
Log(chargerSn).Error($"decode fail msg={BitUtls.BytesToHexStr(data)}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private IByteBuffer? FindDelimiter(IByteBuffer buffer)
|
|
|
|
{
|
|
|
|
foreach (IByteBuffer delimiter in _delimiters)
|
|
|
|
{
|
|
|
|
int delimiterIndex = IndexOf(buffer, delimiter);
|
|
|
|
if (delimiterIndex >= 0)
|
|
|
|
{
|
|
|
|
return delimiter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static int IndexOf(IByteBuffer haystack, IByteBuffer needle)
|
|
|
|
{
|
|
|
|
for (int i = haystack.ReaderIndex; i < haystack.WriterIndex; i++)
|
|
|
|
{
|
|
|
|
int num = i;
|
|
|
|
int j;
|
|
|
|
for (j = 0; j < needle.Capacity && haystack.GetByte(num) == needle.GetByte(j); j++)
|
|
|
|
{
|
|
|
|
num++;
|
|
|
|
if (num == haystack.WriterIndex && j != needle.Capacity - 1)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == needle.Capacity)
|
|
|
|
{
|
|
|
|
return i - haystack.ReaderIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ASDU Parse(IByteBuffer byteBuffer, int totalFrameLength, IByteBuffer delimiter, out byte[] data)
|
|
|
|
{
|
|
|
|
data = new byte[totalFrameLength];
|
|
|
|
byteBuffer.ReadBytes(data);
|
|
|
|
|
|
|
|
int removeIndex = delimiter.Capacity;
|
|
|
|
|
|
|
|
ushort cmd = data[14 + removeIndex];
|
|
|
|
byte[] bytes = new byte[data.Length - (23 + removeIndex)];
|
|
|
|
Array.Copy(data, 23 + removeIndex, bytes, 0, bytes.Length);
|
|
|
|
|
|
|
|
|
|
|
|
ASDU baseMsg = cmd switch
|
|
|
|
{
|
|
|
|
/*0x*/
|
|
|
|
93 => ModelConvert.Decode<StartBatterySwapResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
82 => ModelConvert.Decode<WarehousCompleteReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
76 => ModelConvert.Decode<BatteryStatusReportedReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
106 => ModelConvert.Decode<VehicleModelResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
200 => ModelConvert.Decode<SummaryFailuresReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
83 => ModelConvert.Decode<MigrationCompleteReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
78 => ModelConvert.Decode<PrepareBatteryCompleteReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
77 => ModelConvert.Decode<RemoteSignalReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
95 => ModelConvert.Decode<InboundCommandsResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
92 => ModelConvert.Decode<FaultResetResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
87 => ModelConvert.Decode<PauseCommandResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
84 => ModelConvert.Decode<OutboundCompleteReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
107 => ModelConvert.Decode<BatteryShelfNumberReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
89 => ModelConvert.Decode<InitializeCommandResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
96 => ModelConvert.Decode<OutboundCommandResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
116 => ModelConvert.Decode<StartMovElectricityResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
80 => ModelConvert.Decode<SwapBatteryFinishReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
101 => ModelConvert.Decode<TerminationOrderResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
111 => ModelConvert.Decode<ElectricalConnectorsReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
99 => ModelConvert.Decode<PrepareBatteryOnResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
100 => ModelConvert.Decode<ParameterSettingsResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
113 => ModelConvert.Decode<BatteryPackDisassembledReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
88 => ModelConvert.Decode<ContinueCommandResq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
117 => ModelConvert.Decode<PowerTransferCompletedReq>(bytes),
|
|
|
|
/*0x*/
|
|
|
|
94 => ModelConvert.Decode<MoveCommandResq>(bytes),
|
|
|
|
_ => new ASDU()
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ASDU.ParseHeader(data, baseMsg);
|
|
|
|
|
|
|
|
return baseMsg;
|
|
|
|
}
|
|
|
|
}
|