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;
///
/// 解码器
///
public class Decoder : ByteToMessageDecoder
{
private readonly IByteBuffer[] _delimiters = { Unpooled.CopiedBuffer(PlcConst.StartChar) };
///
///
///
///
///
private ILog Log(string? chargerSn)
{
if (ObjUtils.IsNotNullOrWhiteSpace(chargerSn))
{
return LogManager.GetLogger("Plc" + chargerSn);
}
return LogManager.GetLogger(typeof(Decoder));
}
#region MyRegion
#endregion
protected override void Decode(IChannelHandlerContext context, IByteBuffer buffer, List 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(bytes),
/*0x*/
82 => ModelConvert.Decode(bytes),
/*0x*/
76 => ModelConvert.Decode(bytes),
/*0x*/
106 => ModelConvert.Decode(bytes),
/*0x*/
200 => ModelConvert.Decode(bytes),
/*0x*/
83 => ModelConvert.Decode(bytes),
/*0x*/
78 => ModelConvert.Decode(bytes),
/*0x*/
77 => ModelConvert.Decode(bytes),
/*0x*/
95 => ModelConvert.Decode(bytes),
/*0x*/
92 => ModelConvert.Decode(bytes),
/*0x*/
87 => ModelConvert.Decode(bytes),
/*0x*/
84 => ModelConvert.Decode(bytes),
/*0x*/
107 => ModelConvert.Decode(bytes),
/*0x*/
89 => ModelConvert.Decode(bytes),
/*0x*/
96 => ModelConvert.Decode(bytes),
/*0x*/
116 => ModelConvert.Decode(bytes),
/*0x*/
80 => ModelConvert.Decode(bytes),
/*0x*/
101 => ModelConvert.Decode(bytes),
/*0x*/
111 => ModelConvert.Decode(bytes),
/*0x*/
99 => ModelConvert.Decode(bytes),
/*0x*/
100 => ModelConvert.Decode(bytes),
/*0x*/
113 => ModelConvert.Decode(bytes),
/*0x*/
88 => ModelConvert.Decode(bytes),
/*0x*/
117 => ModelConvert.Decode(bytes),
/*0x*/
94 => ModelConvert.Decode(bytes),
_ => new ASDU()
};
ASDU.ParseHeader(data, baseMsg);
return baseMsg;
}
}