怪奇物语

怪奇物语

首页 新随笔 联系 管理

secs gem 解包

using System.Text;
public enum SECSFormat
{
    List,
    Binary,
    Boolean,
    Ascii,
    Char,
    I1,
    I2,
    I4,
    I8,
    U1,
    U2,
    U4,
    U8,
    F4,
    F8,
    UNRECOGNIZE_FORMAT
}

public class Logger
{
    private int _indentationLevel;
    private readonly StringBuilder _logBuilder = new StringBuilder();
    public void Indent() => _indentationLevel++;
    public void Unindent() => _indentationLevel = Math.Max(0, _indentationLevel - 1);
    public void Print(string message)
    {
        var spaces = new string(' ', _indentationLevel * 3);
        _logBuilder.AppendLine(spaces + message);
    }
    public string GetLog() => _logBuilder.ToString();
    public void Clear() => _logBuilder.Clear();
}

class Program
{
    private static readonly Logger Logger = new Logger();

    static void Main(string[] args)
    {
        // Console.WriteLine("请输入十六进制报文(空格分隔,例如: 01 0A FF):");
        // var input = Console.ReadLine();
        var input = "00 00 81 0D 00 00 00 00 00 22 01 02 41 04 54 45 53 54 41 03 31 2E 31";
        // Console.WriteLine("包含头报文?(Y/N)");
        // var hasHeader = Console.ReadLine()?.Trim().ToUpper() == "Y";
        var hasHeader = true;
        try
        {
            var bytes = HexStringToByteArray(input);
            ParseMessage(bytes, hasHeader);
            Console.WriteLine("\n解析结果:");
            Console.WriteLine(Logger.GetLog());
        }
        catch (Exception ex)
        {
            Console.WriteLine($"解析错误: {ex.Message}");
        }
    }

    private static byte[] HexStringToByteArray(string hex)
    {
        if (string.IsNullOrWhiteSpace(hex))
            return Array.Empty<byte>();

        var hexValues = hex.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        var bytes = new byte[hexValues.Length];

        for (var i = 0; i < hexValues.Length; i++)
        {
            bytes[i] = Convert.ToByte(hexValues[i], 16);
        }
        return bytes;
    }

    private static void ParseMessage(byte[] message, bool hasHeader)
    {
        Logger.Clear();
        var index = 0;

        if (hasHeader && message.Length >= 10)
        {
            var header = ParseHeader(message);
            Logger.Print($"S{header.StreamID}F{header.FunctionID} {header.Wait}");
            index = 10;
        }

        ParseMessageBody(message, ref index);
    }

    private static (int StreamID, int FunctionID, string Wait) ParseHeader(byte[] header)
    {
        var waitBit = (header[2] & 0x80) != 0;
        var streamID = header[2] & 0x7F;
        var functionID = header[3];
        return (streamID, functionID, waitBit ? "W" : "");
    }

    private static void ParseMessageBody(byte[] message, ref int index)
    {
        System.Console.WriteLine("111111111111");
        Console.WriteLine(string.Join(" ", message.Select(b => b.ToString("X2"))));
        while (index < message.Length)
        {
            var formatCode = message[index++];
            System.Console.WriteLine("222222222");
            System.Console.WriteLine(formatCode.ToString("X2"));
            var (format, lengthBytes) = GetFormat(formatCode);

            if (format == SECSFormat.UNRECOGNIZE_FORMAT)
            {
                Logger.Print("UNRECOGNIZE_FORMAT");
                return;
            }

            if (format == SECSFormat.List)
            {
                var listLength = message[index++];
                Logger.Print($"<L[{listLength}]");
                Logger.Indent();

                for (var i = 0; i < listLength; i++)
                {
                    ParseMessageBody(message, ref index);
                }

                Logger.Unindent();
                Logger.Print(">");
            }
            else
            {
                var dataLength = message[index++];
                var data = new byte[dataLength];
                Array.Copy(message, index, data, 0, dataLength);
                index += dataLength;

                var value = GetValue(format, data);
                Logger.Print(format == SECSFormat.Ascii ? $"<{format}[{dataLength}] '{value}'>" : $"<{format}[{dataLength}] {value}>");
            }
        }
    }

    private static (SECSFormat format, int lengthBytes) GetFormat(byte formatCode)
    {
        var bits = Convert.ToString(formatCode, 2).PadLeft(8, '0');
        var formatBits = bits[..6];
        var lengthBits = bits[6..];

        var lengthBytes = lengthBits switch
        {
            "01" => 1,
            "10" => 2,
            "11" => 3,
            _ => 1
        };

        return formatBits switch
        {
            "000000" => (SECSFormat.List, lengthBytes),
            "001000" => (SECSFormat.Binary, lengthBytes),
            "001001" => (SECSFormat.Boolean, lengthBytes),
            "010000" => (SECSFormat.Ascii, lengthBytes),
            "010010" => (SECSFormat.Char, lengthBytes),
            "011001" => (SECSFormat.I1, lengthBytes),
            "011010" => (SECSFormat.I2, lengthBytes),
            "011100" => (SECSFormat.I4, lengthBytes),
            "011000" => (SECSFormat.I8, lengthBytes),
            "101001" => (SECSFormat.U1, lengthBytes),
            "101010" => (SECSFormat.U2, lengthBytes),
            "101100" => (SECSFormat.U4, lengthBytes),
            "101000" => (SECSFormat.U8, lengthBytes),
            "100100" => (SECSFormat.F4, lengthBytes),
            "100000" => (SECSFormat.F8, lengthBytes),
            _ => (SECSFormat.UNRECOGNIZE_FORMAT, 0)
        };
    }

    private static string GetValue(SECSFormat format, byte[] data)
    {
        Array.Reverse(data); // 处理字节序

        return format switch
        {
            SECSFormat.Ascii => Encoding.ASCII.GetString(data),
            SECSFormat.Boolean => (data[0] != 0).ToString(),
            SECSFormat.Char => ((char)data[0]).ToString(),
            SECSFormat.F4 => BitConverter.ToSingle(data, 0).ToString(),
            SECSFormat.F8 => BitConverter.ToDouble(data, 0).ToString(),
            SECSFormat.I1 => ((sbyte)data[0]).ToString(),
            SECSFormat.I2 => BitConverter.ToInt16(data, 0).ToString(),
            SECSFormat.I4 => BitConverter.ToInt32(data, 0).ToString(),
            SECSFormat.I8 => BitConverter.ToInt64(data, 0).ToString(),
            SECSFormat.U1 => data[0].ToString(),
            SECSFormat.U2 => BitConverter.ToUInt16(data, 0).ToString(),
            SECSFormat.U4 => BitConverter.ToUInt32(data, 0).ToString(),
            SECSFormat.U8 => BitConverter.ToUInt64(data, 0).ToString(),
            SECSFormat.Binary => BitConverter.ToString(data).Replace("-", " "),
            _ => "UNKNOWN_TYPE"
        };
    }
}

参考原博主的js版本链接:https://www.cnblogs.com/xfweb/p/18144831

posted on 2025-03-04 08:00  超级无敌美少男战士  阅读(70)  评论(0)    收藏  举报