using System.Text; using DotNetty.Buffers; using DotNetty.Codecs; using DotNetty.Transport.Channels; using HybirdFrameworkCore.Utils; using HybirdFrameworkDriver.Session; using log4net; using Newtonsoft.Json; using Service.Ups.Common; using Service.Ups.Msg; namespace Service.Ups.Codec; public class Decoder: ByteToMessageDecoder { private readonly IByteBuffer[] _delimitersStart = { Unpooled.CopiedBuffer(UpsConst.StartChar) }; private readonly IByteBuffer[] _delimitersEnd = { Unpooled.CopiedBuffer(UpsConst.EndChar) }; private ILog Log(string? chargerSn) { if (ObjUtils.IsNotNullOrWhiteSpace(chargerSn)) { return LogManager.GetLogger("Charger" + chargerSn); } return LogManager.GetLogger(typeof(Decoder)); } protected override void Decode(IChannelHandlerContext context, IByteBuffer buffer, List output) { string? chargerSn = ChannelUtils.GetAttr(context.Channel, UpsConst.UpsSn); IByteBuffer? delimiterStart = FindDelimiterStart(buffer); IByteBuffer? delimiterEnd = FindDelimiterEnd(buffer); if (delimiterStart != null&&delimiterEnd!=null) { //分隔符索引 int delimiterIndex = IndexOf(buffer, delimiterStart); int delimiterFinish = IndexOf(buffer, delimiterEnd); //计算帧长 int frameLengthIndex = delimiterFinish - delimiterIndex + 1; if (delimiterIndex > 0) { buffer.SkipBytes(delimiterIndex); return; } //没有帧长 /*if (buffer.ReadableBytes < frameLengthIndex + 2) { // 数据不足,等待更多数据 return; }*/ // 读取长度字段 /*byte frameLength = buffer.GetByte(buffer.ReaderIndex + frameLengthIndex); //总帧长 int totalFrameLength = delimiterIndex + delimiter.Capacity + 2 + 2 + frameLength;*/ // 最小总帧长过滤 /*if (totalFrameLength < 5) { return; }*/ /*if (buffer.ReadableBytes < totalFrameLength) { // 数据不足,等待更多数据 return; }*/ byte[]? data = null; try { ASDU asdu = Parse(buffer, frameLengthIndex, delimiterStart, 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? FindDelimiterStart(IByteBuffer buffer) { foreach (IByteBuffer delimiter in _delimitersStart) { int delimiterIndex = IndexOf(buffer, delimiter); if (delimiterIndex >= 0) { return delimiter; } } return null; } private IByteBuffer? FindDelimiterEnd(IByteBuffer buffer) { foreach (IByteBuffer delimiter in _delimitersEnd) { int delimiterIndex = IndexOf(buffer, delimiter); if (delimiterIndex >= 0) { return delimiter; } } return null; } #region 查找帧头 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; } #endregion #region 查找帧尾 #endregion public ASDU Parse(IByteBuffer byteBuffer, int totalFrameLength, IByteBuffer delimiter, out byte[] data) { //这里转成ascll码 data = new byte[totalFrameLength]; byteBuffer.ReadBytes(data); //data就是数据 string stRAsicll= Encoding.ASCII.GetString(data ).ToUpper(); string[] strLst = stRAsicll.Split(" "); int removeIndex = delimiter.Capacity; //TODO::后续处理 ushort cmd = data[2 + removeIndex]; byte[] bytes = new byte[data[2]]; Array.Copy(data, 2 + removeIndex, bytes, 0, bytes.Length); byte length = data[2]; ASDU asdu = cmd switch { _ => new ASDU(), }; ASDU.ParseHeader(data, asdu); return asdu; } }