-
Notifications
You must be signed in to change notification settings - Fork 4
Data Format
LabRAD is a binary protocol, and every labrad data type has a specific binary representation. Labrad packets are just flattened labrad data, so understanding the binary format is key to understanding the protocol. Every LabRAD data type has an associated type tag. It is impossible to unflatten data without the type tag, you must either use a pre-agreed tag, or transmit the type tag along side the data. All multibyte numbers (including string and array lengths) are formatted with the protocol byte order. Complex numbers are sent as re,im, with each component being a IEEE double precision formated in protocol byte order.
Type Tag | Length (bytes) | Description |
---|---|---|
b | 1 | Boolean value 0x00=False, everything else True |
w | 4 | 32 bit unsigned integer. |
i | 4 | 32 bit signed integer. |
v | 8 | Real number with unspecified units(*) |
c | 16 | Complex number with unspecified units(*) |
v[] | 8 | Double precision dimensionless float (Value) |
c[] | 16 | Dimensionless Complex number as two doubles |
v[m] | 8 | real Value with specified unit (meter) |
c[MHz] | 16 | Complex number with specified unit (MHz) |
(...) | size(...) | Tuple. each item is flattened in turn |
*x | 4 + size(x) | List/array of x. Flattened length followed by data |
*nx | 4*n + size(x) | 3-D list/array of x. Flattened length of each dimension followed by data |
E | 4 | Error. Flattened 32 bit error code |
E? | 4+size(?) | Error. Flattened 32 bit error code followed by data |
(*) v and c types are deprecated. Use v[] and c[] for dimensionless numbers, and use v[unit] and c[unit] if you know the type. Here is how v works: If a server advertizes a setting that takes a quantity with units, for instance v[GHz]
, it expects to receive a number of GHz. However, if the client is lazy and just sends '5.0' that will be encoded with the type tag v
. The labrad manager will see that, assume it is in the correct units, and change the type tag from v
to v[GHz]
. This is very error prone, and is deprecated and will eventually be removed.
There is an incomplete type tag ?
. It is never used for data sent across the wire, as you recipient would not know how to unflatten it. Rather, a server can advertise that a given setting accepts '?'. That means arbitrary labrad data. When the client sends it a message, it will flatten whatever data it has, and send it with the appropriate concrete type tag. The server will need to figure out what to do with it. An important use of this option is the registry. The key get/set methods accept/return ? because you can store any labrad data type in the registry.
The labrad packet format is: '(ww)iws'. The 'records' string is itself flattened data of the list of records with the type tag '*(wss)'. Because the records can have arbitrary type tags, the record structure contains the setting ID, the type tag as a string, and the flattened data. It works like this psuedo-code demonstrates:
context, request_ID, server_ID, request_data = labrad.types.unflatten(packet_stream, '(ww)iws')
records = labrad.types.unflatten(request_data, '*(wss)')
for record in records:
setting_ID, type_tag, record_data = record
setting_args = labrad.types.unflatten(record_data, type_tag)
setting_func = server[setting_ID]
setting_func(*setting_args)