Search code examples
c#typesmodbus

C# i use Modbus/TCP to get Data, Data type is 「LReal」. i want turn to double


i use Modbus/TCP to get data, data type is LReal.

but i want LReal to int.

this is my data.

enter image description here

enter image description here

enter image description here

staic_13 data is 「4.232」

but i get [80] 16400 [81]-2098 [82] -9962 [83] -30933.

i don't know how turn to double


Solution

  • Based on this experimental Python code,

    >>> x = [16400, -2098, -9962, -30933]
    >>> struct.unpack(">d", struct.pack(">4h", *x))
    (4.242,)
    

    it looks like you'd need to concatenate those 4 16-byte integers in big-endian format, then interpret those 8 bytes as a single big-endian double.

    In .NET 6 (see this fiddle):

    using System.Buffers.Binary;
    using System;
    
    short[] values = {16400, -2098, -9962, -30933};
    byte[] buf = new byte[values.Length * sizeof(short)];
    for (int i = 0; i < values.Length; i++)
    {
        BinaryPrimitives.WriteInt16BigEndian(buf.AsSpan(i * sizeof(short)), values[i]);
    }
    double result = BinaryPrimitives.ReadDoubleBigEndian(buf);
    Console.WriteLine(result);
    

    In .NET 4 (see this fiddle):

    using System;
    
    public class Program
    {
        public static void Main()
        {
            short[] values = {16400, -2098, -9962, -30933};
            byte[] buf = new byte[8];
            for (int i = 0; i < 4; i++)
            {
                byte[] sh_buf = BitConverter.GetBytes(values[i]);
                if(BitConverter.IsLittleEndian) {
                    // Flip the bytes around if we're little-endian
                    buf[(3 - i) * 2] = sh_buf[0];
                    buf[(3 - i) * 2 + 1] = sh_buf[1];
                } else {
                    buf[i * 2] = sh_buf[0];
                    buf[i * 2 + 1] = sh_buf[1];
                }
            }
            double result = BitConverter.ToDouble(buf, 0);
            Console.WriteLine(result);
        }
    }