C#-解码服务器响应MSN,LSN

问题描述

我正在尝试解码服务器(TCP客户端)响应。

在服务器手册中,以下是规则:

    Octet 001 : Command code
    Octet 002-005 : Serial number
    Octet 006 : MSB block number
    Octet 007 : LSB block number

    Octet 008 : 8 least significant bits of the first visible channel counter,nth interval (binary).

    Octet 009 : MSN: 4 most significant bits of the first visible channel counter,nth interval (binary).
                LSN: 4 most significant bits of the second visible channel counter,nth interval (binary).
                
    Octet 010 : 8 least significant bits of the second visible channel counter,nth interval.
    Octet 011 : 8 least significant bits of the third visible channel counter,nth interval.

    Octet 012 : MSN: 4 most significant bits of the third visible channel counter,nth interval (binary).
                LSN: 4 most significant bits of the first visible channel counter,nth + 1 interval (binary).

    Octet 013 : 8 least significant bits of the first visible channel counter,nth + 1 interval (binary),follow the rest of intervals.

    Octet 254 : 8 least significant bits of the third visible channel counter,nth + 54 interval (binary).

    Octet 255 : MSN: 4 most significant bits of the third visible channel counter,nth + 54 interval (binary).
                LSN: 4 most significant bits of the first visible channel counter,nth + 55 interval (binary).
                
    Octet 256 : 8 least significant bits of the first visible channel counter,nth + 55 interval (binary).

    Octet 257 : CRC LSB
    Octet 258 : CRC MSB

服务器响应示例:

524009232300020700001c000700001d0600001c000600001c0700001c000700001c0700001d000800001c0700001c000700001c0600001d000800001c0700001c000800001c0800001c000600001c0600001d000600001c0600001c000500001c0800001d000900001c0b00001c000d00001c0b00001d000e00001c0e00001c000d00001c0e00001c000d00001d0e00001c000e00001c0d00001d000d00001c0e00001c000e0000220e000024000e0000230e000024000d0000230d000024000c0000230f000024000e0000230a000024000a0000230900002400090000230c000024000e0000230e000024000d0000230c000024000c0000230e000026000e7f3b

第一个八位位组检查是命令52。八位位组2-5检查序列号是40092323。但是服务器响应的其余部分,我都不知道如何解码。

解决方法

尝试以下。字节(7 + [41 * 6] + 2)= 255或(7 + [82 * 3] + 2)= 255:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Runtime.InteropServices;


namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input = "524009232300020700001c000700001d0600001c000600001c0700001c000700001c0700001d000800001c0700001c000700001c0600001d000800001c0700001c000800001c0800001c000600001c0600001d000600001c0600001c000500001c0800001d000900001c0b00001c000d00001c0b00001d000e00001c0e00001c000d00001c0e00001c000d00001d0e00001c000e00001c0d00001d000d00001c0e00001c000e0000220e000024000e0000230e000024000d0000230d000024000c0000230f000024000e0000230a000024000a0000230900002400090000230c000024000e0000230e000024000d0000230c000024000c0000230e000026000e7f3b";
            byte[] bytes = input.Select((x,i) => new { nibble = x,index = i }).GroupBy(x => x.index / 2).Select(x => byte.Parse(x.First().nibble.ToString() + x.Last().nibble.ToString(),NumberStyles.HexNumber)).ToArray();

            Test test = new Test(bytes);
            test.Print();
            Console.ReadLine();
        }

    }
    public class Test
    {
        public byte commandCode { get; set; }
        public int serialNumber { get; set; }
        public Int16 blockNumber { get; set; }
        public List<List<int>> intervals { get; set; }
        public Int16 crc { get; set; }

        public Test(byte[] input)
        {
            intervals = new List<List<int>>();
            commandCode = input[0];
            serialNumber = BitConverter.ToInt32(input,1);
            blockNumber = BitConverter.ToInt16(input,5);
            crc = BitConverter.ToInt16(input,256);
            int channel1 = 0;
            int channel2 = 0;

            for (int i = 0; i < 41; i++)
            {
                //even
                channel1 = ((input[(6 * i) + 8] << 4) & 0xF0) + input[(6 * i) + 7];
                channel2 = ((input[(6 * i) + 8] << 8) & 0x0F) + input[(6 * i) + 9];

                List<int> interval = new List<int>();
                interval.AddRange(new List<int> { channel1,channel2 });
                intervals.Add(interval);

                //odd
                channel1 = ((input[(6 * i) + 11] << 4) & 0xF0) + input[(6 * i) + 10];
                channel2 = ((input[(6 * i) + 11] << 8) & 0x0F) + input[(6 * i) + 12];

                interval = new List<int>();
                interval.AddRange(new List<int> { channel1,channel2});
                intervals.Add(interval);
            }
        }
        public void Print()
        {
            Console.WriteLine("Command Code : {0}",commandCode);
            Console.WriteLine("Serial Number : {0}",serialNumber);
            Console.WriteLine("Block Number : {0}",blockNumber);
            Console.WriteLine("CRC : {0}",crc.ToString("X4"));

            for (int i = 0; i < 82; i++)
            {
                Console.WriteLine("Interval : {0},Channel 1 : {1},Channel 2 : {2}",i + 1,intervals[i][0],intervals[i][1]);
            }
        }

    }
}

由于每个间隔为3个字节,因此可以这样编写for循环

           for (int i = 0; i < 82; i++)
            {
                //even
                channel1 = ((input[(3 * i) + 8] << 4) & 0xF0) + input[(3 * i) + 7];
                channel2 = ((input[(3 * i) + 8] << 8) & 0x0F) + input[(3 * i) + 9];

                List<int> interval = new List<int>();
                interval.AddRange(new List<int> { channel1,channel2 });
                intervals.Add(interval);

            }
,

我读取服务器的方法:

public string read()
        {
            // CREATE TCP CLIENT
            TcpClient client = new TcpClient("SERVER_IP",2180);
            NetworkStream ns = client.GetStream();

            // SEND COMMAND
            var command = StringToByteArray("COMMAND_TO_SEND");
            ns.Write(command,command.Length);

            // GET SERVER RESPONSE
            byte[] bytesToRead = new byte[client.ReceiveBufferSize];
            int bytesRead = ns.Read(bytesToRead,client.ReceiveBufferSize);

            // DECODE ANSWER
            string returndata = BitConverter.ToString(bytesToRead,bytesRead).Replace("-","");

            // Close connection
            client.Close();

            return returndata;
        }

        public byte[] StringToByteArray(string hex)
        {
            return Enumerable.Range(0,hex.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(hex.Substring(x,2),16)).ToArray();
        }

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...