juniper25
juniper25

Reputation: 91

Writing a binary multi-byte array message (big endian) (.Net C#)

I'm trying to communicate with a server running locally on my machine. I just don't know how to write the message the sever expects. I'm trying to do this on a .Net application (C#). This server expects an at least 10 byte message arranged by the following structure, from the manual:

[Full manual] http://jkca.ca/help/pages/telemetry.html#messageformat

Each message has the same basic binary format. All multi-byte values are in network-byte-order (big-endian)!! The minimum message size is 10 bytes. Clients are allowed to send Client Request messages (see Message Type Table). The server will respond with corresponding Server Reply messages. The Request ID can be freely assigned by the client and has no special meaning. The server's reply message will use the same Request ID in the corresponding answer.

(I seem to be unable to format a table in this question so I'm omitting the table that can be found in the manual)

I would like to understand how to form these messages. If anyone could explain to a non CS student how to form, for example, the message to send a "pause command" (http://jkca.ca/help/pages/telemetry.html#msg27) that would be super useful.

I've tried all sorts of variations of:

string message = N + "27" + "1000" + "01" + "1" + L;
Byte[] data = System.Text.Encoding.BigEndianUnicode.GetBytes(message);

and (which I realize is not binary)

 //                           N  |Type ID(2) |     ID (4)            |Datasize(2)|Data |  L    |  
 //Byte[] data = new Byte[] { 0x4E, 0x32, 0x37, 0x31, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x4C };
 //                           N  |  2  |  7  |  1  |  0  |  0  |  0  |  0  |  1  |  1  |  L    |

and sending the data with

stream.Write(data, 0, data.Length);

Alternatively, an explanation of how to request "software version" and how to read the reply (http://jkca.ca/help/pages/telemetry.html#msg3) might be all I need to start understanding how to do this.

Many thanks in advance.

PD: I found this (https://github.com/bestdani/py_nl2telemetry) repo in python that manages to comunicate and retreive data from this server, but I cant follow it to the point to understand how to do it using .Net. Maybe its useful for someone crafting an answer.

Upvotes: 2

Views: 624

Answers (1)

Andrew Williamson
Andrew Williamson

Reputation: 8696

To expand on Hans' comment, each letter in a string literal usually equates to one byte. E.g. A is stored as 0x41, B is stored as 0x42, 0 is stored as 0x30. Search for ASCII and UTF8 character encodings for more info. When you write a string like '1000', then get the underlying bytes, you end up with the sequence 0x31 0x30 0x30 0x30. The number of bytes here is equal to the number of digits in your string. This is a variable-length number, and it's not a very compact way to store the information, because instead of using the full range of each byte (00 to FF) for a total of 256 possibilities per byte, it only uses 10 of the possibilities (30 to 39). This inefficiency becomes more obvious when you use larger numbers, e.g. 1000000 takes up 7 bytes.

The server is expecting the request id in a different format, int32, which always takes up 4 bytes. You can get the data into this format by calling BinaryPrimitives.WriteInt32BigEndian(buffer, 1000). The same applies for the message type id and the data size fields, they should be provided as Int16.

After reading the documentation you posted, it looks like the expected data for a 'Set Pause' request would be like this:

0x4E 'N'
------------------------
0x00 Set Pause (27)
0x1B
------------------------
0x00 Request id (1000)
0x00
0x03
0xE8
------------------------
0x00 Data size (1)
0x01
------------------------
0x01 Data (Enable pause)
------------------------
0x4C 'L'

Upvotes: 3

Related Questions