Table of Contents
Habpack Binary Protocol
This page details the msgpack based binary protocol. Habpack uses msgpack to encode the binary data, and defines how msgpack is used to encode telemetry, and defines IDs for telemetry fields.
Encoders should pick the smallest type within the correct family. eg. '112' can be encoded as an unsigned int using the 'positive fixnum' type, for an encoded size of 1 byte. Unsigned integers are always assumed to be positive.
This means that using integers can scale the storage required to the value being transmitted, while floats maintain a constant size (5 bytes for 32b float). See the msgpack spec for more details: msgpack spec -> type system
Basic Structure
A single telemetry string is a msgpack map. Each telemetry field then consists of a key which defines what that field is, and a value field. For efficiency reasons, each key is usually a 7bit unsigned int, and the list of keys is defined in the section below. An example packet is as follows:
{ 0:”CALLSIGN”, 2:12:56:14, 3:[52.33, -0.3543, 12320], 20:8, … }
- { …. } means msgpack map array
- 0:123 means a map entry with key 0 and data 123
- […, …, …] means an array
It should be noted that the datatype (eg string, integer etc) is handled by msgpack. As a result, the decoder should see what datatype has been sent, and handle the data accordingly.
Telemetry field IDs
A list of reserved Map IDs is suggested below to standardise parsing of commonly used telemetry fields without requirement of a payload-doc, eg. for embedded & offline receivers. This list is intended to be expanded over time as new requirements develop.
Core:
- 0: callsign (string or unsigned integer) (integer converted to string representation for habitat upload)
- 1: sentence id (unsigned integer)
- 2: time (unsigned integer seconds past midnight UTC, or unsigned integer unix epoch seconds)
- 3: position (2 or 3 element array of signed integers: [lat, long, <alt>]. 1e-7 of a degree; meters)
- 4: number of gnss satellites (unsigned integer)
- 5: gnss lock [0: none, 1: time, 2: 2D, 3: 3D, 4: 3D+SBAS] (unsigned integer)
- 6: voltage (float as Volts or signed integer as milli-volts)
Environmental:
- 10: Internal temperature (float as degrees C or signed integer as milli-degrees C)
- 11: External temperature (float as degrees C or signed integer as milli-degrees C)
- 12: pressure (float as bar, or unsigned integer as milli-bar)
- 13: relative humidity (float or unsigned integer as relative humidity percentage)
- 14: absolute humidity (float as g/m^3, or unsigned integer as milligrams/m^3)
Calling Beacon:
- 20: downlink frequency, for use in calling channel (unsigned integer as Hz)
- 21: ID of common downlink LoRa Mode (unsigned integer)
- 22: custom downlink LoRa: Implicit (unsigned integer)
- 23: custom downlink LoRa: Error Coding (unsigned integer)
- 24: custom downlink LoRa: Bandwidth (unsigned integer)
- 25: custom downlink LoRa: Spreading Factor (unsigned integer)
- 26: custom downlink LoRa: Low Datarate Optimise (unsigned integer)
Uplink:
- 30: total uplinked messages (unsigned integer)
Landing/Flight Predictions:
- 40: predicted time (unsigned integer seconds past midnight UTC, or unsigned integer unix epoch seconds)
- 41: predicted position (2 or 3 element array of signed integers: [lat, long, <alt>]. 1e-7 degree; meters)
Multi-position:
- 60: Multi-position position-diff scaling factor (unsigned integer)
- 61: Multi-position altitude-diff scaling factor (unsigned integer)
- 62: Multi-position array of positions (each: 2 or 3 element array of signed integers: [lat, long, <alt>]. 1e-7 degree; meters)
As msgpack handles datatypes, arrays can be used to send multiple entries for one field. For example, if there are two external temperature sensors, this can be sent as 11:[-40.5,-39,1] Types 6,10,11,12,13,14 can be an array of legal values to represent more than one field.
Current RPi Decoder Implementation
For bodging habitat upload compatibility, values are re-encoded into a UKHAS-compatible RTTY string ($$…*<crc>), with fields ordered by map ID ascending, and array index ascending when multiple values exist.
eg. “$$<callsign>,<count>,<time>,<lat>,<lon>,<alt>,<satellites>,<temp 1>,<temp 2>,<battery voltage>*<crc>”
LoRa Calling Beacon Modes (Field 21)
- 0: Explicit, FEC: 4/8, BW: 20.8KHz, SF: 11, LDO: On
- Used for telemetry
- Approx baudrate: 60
- 1: Implicit, FEC: 4/5, BW: 20.8KHz, SF: 6, LDO: Off
- Used for SSDV
- Approx baudrate: 1400
- 2: Explicit, FEC: 4/8, BW: 62.5KHz, SF: 8, LDO: Off
- Used for repeater network
- Approx baudrate: 2000
- 3: Explicit, FEC: 4/6, BW: 250KHz, SF: 7, LDO: Off
- Used for high speed images in 868MHz band
- Approx baudrate: 8000
- 4: Implicit, FEC: 4/5, BW: 250KHz, SF: 6, LDO: Off
- Fastest mode within IR2030 in 868MHz band
- Approx baudrate: 16828
- 5: Explicit, FEC: 4/8, BW: 41.7KHz, SF: 11, LDO: Off
- Used for Calling mode
- Approx baudrate: 200
- 6: Implicit, FEC: 4/5, BW: 41.7KHz, SF: 6, LDO: Off
- Used for Uplink on 868
- Approx baudrate: 2800
- 7: Explicit, FEC: 4/5, BW: 20.8KHz, SF: 7, LDO: Off
- Used for Telnet-style comms with HAB on 434
- Approx baudrate: 2800
- 8: Implicit, FEC: 4/5, BW: 62.5KHz, SF: 6, LDO: Off
- Used for Fast (SSDV) repeater network
- Approx baudrate: 4500
LoRa Calling Beacon Custom Fields (Fields 22-26)
- 22: custom downlink LoRa: Implicit (unsigned integer)
- 0: Explicit Mode
- 1: Implicit Mode
- 23: custom downlink LoRa: Error Coding (unsigned integer)
- 5: 4/5
- 6: 4/6
- 7: 4/7
- 8: 4/8
- 24: custom downlink LoRa: Bandwidth (unsigned integer)
- 0: 7.8KHz
- 1: 10.4Khz
- 2: 15.6KHz
- 3: 20.8KHz
- 4: 31.25KHz
- 5: 41.7Khz
- 6: 62.5KHz
- 7: 125KHz
- 8: 250KHz
- 9: 500KHz
- 25: custom downlink LoRa: Spreading Factor (unsigned integer)
- 6: SF6
- 7: SF7
- 8: SF8
- 9: SF9
- 10: SF10
- 11: SF11
- 12: SF12
- 26: custom downlink LoRa: Low Datarate Optimise (unsigned integer)
- 0: LDO Off
- 1: LDO On