using DotNetty.Buffers; using DotNetty.Codecs; using DotNetty.Transport.Channels; using HybirdFrameworkCore.Utils; using HybirdFrameworkDriver.Session; using log4net; using Newtonsoft.Json; using Service.Charger.Common; using Service.Charger.Msg; using Service.Charger.Msg.Bms; using Service.Charger.Msg.Charger.Req; using Service.Charger.Msg.Charger.Resp; using Service.Charger.Msg.Host.Req; using static System.Net.Mime.MediaTypeNames; namespace Service.Charger.Codec; public class Decoder : ByteToMessageDecoder { private static readonly ILog Log = LogManager.GetLogger(typeof(Decoder)); private readonly IByteBuffer[] _delimiters = { Unpooled.CopiedBuffer(ChargerConst.StartChar) }; protected override void Decode(IChannelHandlerContext context, IByteBuffer buffer, List output) { 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; if (buffer.ReadableBytes < totalFrameLength) { // 数据不足,等待更多数据 return; } ASDU asdu = Parse(buffer, totalFrameLength, out var data); Log.Info($"receive {JsonConvert.SerializeObject(asdu)}:{data} from {ChannelUtils.GetAttr(context.Channel, ChargerConst.ChargerSn)}"); output.Add(asdu); buffer.Clear(); } } 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, out byte[] data) { data = new byte[totalFrameLength]; byteBuffer.ReadBytes(data); //string ou = string.Empty; //for (int i = 0; i < data.Length; i++) //{ // ou += data[i].ToString("X2") + " "; //} //TODO bug length取值不对,上述测试使用 int removeIndex = _delimiters.Length; ushort cmd = byteBuffer.GetByte(14 + removeIndex); ushort recordType = byteBuffer.GetByte(23 + removeIndex); byte[] bytes = new byte[data.Length - (23 + removeIndex)]; Array.Copy(data, 23 + removeIndex, bytes, 0, bytes.Length); ASDU asdu = cmd switch { 5 => ModelConvert.Decode(bytes), #region 45 45 => recordType switch { 1 => ModelConvert.Decode(bytes), 3 => ModelConvert.Decode(bytes), 6 => ModelConvert.Decode(bytes), 10 => ModelConvert.Decode(bytes), 11 => ModelConvert.Decode(bytes), 13 => ModelConvert.Decode(bytes), 21 => ModelConvert.Decode(bytes), 25 => ModelConvert.Decode(bytes), 34 => ModelConvert.Decode(bytes), 35 => ModelConvert.Decode(bytes), 41 => ModelConvert.Decode(bytes), 44 => ModelConvert.Decode(bytes), 48 => ModelConvert.Decode(bytes), 47 => ModelConvert.Decode(bytes), 49 => ModelConvert.Decode(bytes), 50 => ModelConvert.Decode(bytes), 52 => ModelConvert.Decode(bytes), 75 => ModelConvert.Decode(bytes), 80 => ModelConvert.Decode(bytes), 81 => ModelConvert.Decode(bytes), 82 => ModelConvert.Decode(bytes), 83 => ModelConvert.Decode(bytes), 84 => ModelConvert.Decode(bytes), 85 => ModelConvert.Decode(bytes), 86 => ModelConvert.Decode(bytes), 87 => ModelConvert.Decode(bytes), _ => throw new InvalidOperationException("This should never be reached"), }, #endregion #region 46 46 => recordType switch { 2 => ModelConvert.Decode(bytes), 3 => ModelConvert.Decode(bytes), 4 => ModelConvert.Decode(bytes), 5 => ModelConvert.Decode(bytes), 6 => ModelConvert.Decode(bytes), 7 => ModelConvert.Decode(bytes), 8 => ModelConvert.Decode(bytes), 9 => ModelConvert.Decode(bytes), 10 => ModelConvert.Decode(bytes), 11 => ModelConvert.Decode(bytes), 12 => ModelConvert.Decode(bytes), 13 => ModelConvert.Decode(bytes), 14 => ModelConvert.Decode(bytes), 15 => ModelConvert.Decode(bytes), 16 => ModelConvert.Decode(bytes), 17 => ModelConvert.Decode(bytes), 18 => ModelConvert.Decode(bytes), 19 => ModelConvert.Decode(bytes), 20 => ModelConvert.Decode(bytes), 21 => ModelConvert.Decode(bytes), 22 => ModelConvert.Decode(bytes), 23 => ModelConvert.Decode(bytes), 24 => ModelConvert.Decode(bytes), 25 => ModelConvert.Decode(bytes), 26 => ModelConvert.Decode(bytes), 27 => ModelConvert.Decode(bytes), 28 => ModelConvert.Decode(bytes), 29 => ModelConvert.Decode(bytes), 30 => ModelConvert.Decode(bytes), 31 => ModelConvert.Decode(bytes), 32 => ModelConvert.Decode(bytes), 33 => ModelConvert.Decode(bytes), 34 => ModelConvert.Decode(bytes), 35 => ModelConvert.Decode(bytes), 36 => ModelConvert.Decode(bytes), 37 => ModelConvert.Decode(bytes), 38 => ModelConvert.Decode(bytes), 39 => ModelConvert.Decode(bytes), 40 => ModelConvert.Decode(bytes), 41 => ModelConvert.Decode(bytes), 42 => ModelConvert.Decode(bytes), 43 => ModelConvert.Decode(bytes), 44 => ModelConvert.Decode(bytes), 45 => ModelConvert.Decode(bytes), 46 => ModelConvert.Decode(bytes), 47 => ModelConvert.Decode(bytes), 48 => ModelConvert.Decode(bytes), 49 => ModelConvert.Decode(bytes), 50 => ModelConvert.Decode(bytes), 51 => ModelConvert.Decode(bytes), 52 => ModelConvert.Decode(bytes), 53 => ModelConvert.Decode(bytes), 54 => ModelConvert.Decode(bytes), 55 => ModelConvert.Decode(bytes), 56 => ModelConvert.Decode(bytes), 57 => ModelConvert.Decode(bytes), 58 => ModelConvert.Decode(bytes), 59 => ModelConvert.Decode(bytes), 62 => ModelConvert.Decode(bytes), 81 => ModelConvert.Decode(bytes), 142 => ModelConvert.Decode(bytes), 143 => ModelConvert.Decode(bytes), 144 => ModelConvert.Decode(bytes), 145 => ModelConvert.Decode(bytes), 146 => ModelConvert.Decode(bytes), 147 => ModelConvert.Decode(bytes), 148 => ModelConvert.Decode(bytes), _ => throw new InvalidOperationException("This should never be reached"), }, #endregion 42 => ModelConvert.Decode(bytes), 11 => ModelConvert.Decode(bytes), 49 => ModelConvert.Decode(bytes), 50 => ModelConvert.Decode(bytes), _ => new ASDU() }; ASDU.ParseHeader(byteBuffer, asdu); return asdu; } }