The Hub and Hub Plus record .onflight files to a microSD card. Filenames use dataX.onflight, with X increasing from 0 to avoid overwriting existing files. The optional .acrowrx format is separate and is not described here.
The Hub processes data at 50 Hz. Firmware 6 and later support recording rates of 5, 10, 25, or 50 Hz. The Hub holds samples in a buffer before writing them to the card. Switching off power can lose the last buffered samples or leave an incomplete packet at the end of the file.
Reading a log file
A log contains measurement packets and records describing the device and recording. This chapter defines three packet types:
| Header | Contents |
|---|---|
BF |
Sensor measurements, navigation results, and status. |
MD |
Serial number, aircraft tail number, pilot name, and aircraft type. |
AD |
Hub Plus analog-channel assignments and calibration types. |
Search for the packet types above, read the ones your application needs, and ignore other file content. A measurement packet need not start at the beginning of the file.
- Scan for a defined two-byte header:
BFfor a data packet,MDfor aircraft/pilot metadata, orADfor Hub Plus analog metadata. - Read its packet version. Binary data v0 has a fixed 143-byte payload and no length byte. Data v1–v3 and the documented metadata packets have a one-byte
payload_lengthimmediately after the version. - Read the complete payload and the following two checksum bytes. The length excludes the header, version, length byte, and checksum.
- Validate the Fletcher-16 checksum over the header, version, length byte when present, and all payload bytes.
- Decode recognized fields only after validation. Advance past the complete packet. Ignore other file content.
- If the size or checksum is wrong, resume searching one byte after the suspected header. The same two bytes can occur in unrelated data. Ignore any incomplete packet at the end of the file.
What payload length counts
For data versions 1–3 and the MD and AD metadata packets, payload_length counts every byte immediately after the length byte through the last byte before the checksum. It excludes the two-byte header, version byte, length byte itself, and two checksum bytes. The field tables below include these framing fields for completeness; they are not part of the payload count.
Offsets are zero-based from the start of the packet, with N = payload_length:
| Packet bytes | Contents | Counted in payload length? |
|---|---|---|
| 0–1 | Two-byte header | No |
| 2 | Version | No |
| 3 | Payload length (N) |
No |
4 through N + 3 |
Payload | Yes |
N + 4 and N + 5 |
Checksum | No |
The complete packet is N + 6 bytes. For example, a version 3 data packet has N = 198: its payload occupies packet bytes 4–201, and its checksum occupies bytes 202–203.
For BF data packets, the payload begins with the status bytes. For MD, it begins with serial_num; for AD, it begins with analog_channel_enabled. Data version 0 has no length byte: its fixed 143-byte payload occupies bytes 3–145, followed by the checksum at bytes 146–147.
Compatibility with extended packets
Use payload_length to find the checksum and the start of the next packet. A later format may add fields at the end of an existing payload. Your application can continue reading the fields it knows if their positions and meanings are unchanged.
Read the entire payload and check its checksum, including any added bytes. Interpret only fields that are fully present and whose layout you know. If you do not support the layout, skip the complete packet and continue searching.
Always check the version as well as the length. For example, version 1 moves fields compared with version 0, so a version 0 decoder cannot read it simply by ignoring extra bytes.
Encoding and packet sizes
Fields appear in table order, with no padding between them. Multibyte values are little-endian: the least significant byte comes first. Floating-point values use IEEE 754.
| Type notation | Meaning |
|---|---|
U1, U2, U4, U8 |
Unsigned integer occupying 1, 2, 4, or 8 bytes. |
I1, I2, I4 |
Signed integer occupying 1, 2, or 4 bytes. |
C1 |
One character byte. |
F4 |
Four-byte, single-precision floating-point value. |
[N] |
An array of N values of the preceding type. |
Multiply the stored integer by the listed scale to obtain the measurement. For example, a stored value of 1234 with scale 1 / 100 means 12.34 in the listed unit. Where the description gives an offset instead, apply that rule: subtract 10,000 from biased altitude fields, or add 1970 to the year field.
| Data version | Payload bytes | Status bytes | Complete packet bytes |
|---|---|---|---|
| 0 | 143 | 5 | 148 |
| 1 | 152 | 6 | 158 |
| 2 | 184 | 6 | 190 |
| 3 (Hub Plus) | 198 | 6 | 204 |
Fletcher-16 checksum
Compute the checksum over every packet byte preceding the checksum, including the header. Store the result as a little-endian U2, with sum0 first and sum1 second.
uint16_t Checksum(uint8_t * data, size_t len) {
uint16_t sum0 = 0;
uint16_t sum1 = 0;
for (size_t i = 0; i < len; i++) {
sum0 = (sum0 + data[i]) % 255;
sum1 = (sum1 + sum0) % 255;
}
return sum1 << 8 | sum0;
}
Packet and checksum example
This example is an AD packet for four analog channels. Its payload says all four channels are enabled, assigns Elevator, Aileron, Rudder, and Throttle, and selects three-point calibration for the first three channels and two-point calibration for the fourth.
| Packet bytes | Hex values | Meaning |
|---|---|---|
| 0–1 | 41 44 |
ASCII header AD. |
| 2 | 00 |
Metadata version 0. |
| 3 | 09 |
Nine payload bytes follow. |
| 4 | 0F |
Channels 0–3 enabled. |
| 5–8 | 00 01 02 03 |
Control assignments for channels 0–3. |
| 9–12 | 01 01 01 00 |
Calibration types for channels 0–3. |
| 13–14 | A6 90 |
Fletcher-16 checksum, low byte first. |
Pass bytes 0–12 to the checksum function above: start with the A in the header and stop after the final calibration type. Compare the result with the two checksum bytes. The nine-byte payload is bytes 4–12, while the complete packet is 15 bytes.
Packed fields
gnss_fix_num_sv uses the lower three bits for fix type and the upper five bits for satellites used:
fix = gnss_fix_num_sv & 0x07;
num_sv = gnss_fix_num_sv >> 3;
Fix values are 0 = no fix, 2 = 2D, 3 = 3D, and 4 = differential fix.
In version 2, each analog status byte holds two sets of four channel flags. Bits 0–3 contain the first set, and bits 4–7 contain the second. For channel n, test 1 << n in the first set and 1 << (n + 4) in the second. The field table identifies what each set means.
Version 0
The original data packet has five status bytes and no payload-length field. Read 143 payload bytes after the version byte, then the two checksum bytes.
The defined payload is 143 bytes; the complete packet is 148 bytes.
Version 0 data fields
| Type | Name | Scale | Unit | Description |
|---|---|---|---|---|
U1[2] |
header |
- | - | Header {‘B’, ’F’}. |
U1 |
version |
- | - | Data packet version, 0. |
U1[5] |
status |
- | - | Status flags defined below. |
U4 |
sys_time_ms |
- | ms | Elapsed time since power-on. |
U1 |
input_volt |
1 / 25 | V | Input voltage. |
U1 |
filt_input_volt |
1 / 25 | V | Filtered input voltage. |
I1 |
cpu_die_temp_c |
1 | C | CPU die temperature |
I1 |
imu_die_temp_c |
1 | C | IMU die temperature. |
I2 |
imu_accel_x_g |
1 / 1000 | G | X-axis accelerometer. |
I2 |
imu_accel_y_g |
1 / 1000 | G | Y-axis accelerometer. |
I2 |
imu_accel_z_g |
1 / 1000 | G | Z-axis accelerometer. |
I2 |
imu_gyro_x_dps |
1 / 10 | deg/s | X-axis gyro. |
I2 |
imu_gyro_y_dps |
1 / 10 | deg/s | Y-axis gyro. |
I2 |
imu_gyro_z_dps |
1 / 10 | deg/s | Z-axis gyro. |
I1 |
mag_die_temp_c |
1 | C | Magnetometer die temperature. |
I2 |
mag_x_ut |
1 / 80 | uT | X-axis magnetometer. |
I2 |
mag_y_ut |
1 / 80 | uT | Y-axis magnetometer. |
I2 |
mag_z_ut |
1 / 80 | uT | Z-axis magnetometer. |
I1 |
pres_die_temp_c |
1 | C | Static pressure die temperature |
U2 |
pres_pa |
2 | Pa | Static pressure. |
U1 |
gnss_fix_num_sv |
- | - | Lower 3 bits are GNSS fix (0 = no fix, 2 = 2D fix, 3 = 3D fix, 4 = differential fix). Upper 5 bits are the number of satellite vehicles used in the solution. |
U1 |
gnss_utc_year |
- | - | Year from the GNSS receiver; add 1970 to obtain the calendar year. |
U1 |
gnss_utc_month |
- | - | UTC month from GNSS receiver. |
U1 |
gnss_utc_day |
- | - | UTC day from GNSS receiver. |
U1 |
gnss_utc_hour |
- | - | UTC hour from GNSS receiver. |
U1 |
gnss_utc_min |
- | - | UTC minute from GNSS receiver. |
U1 |
gnss_utc_sec |
- | - | UTC second from GNSS receiver. |
U1 |
gnss_horz_pos_acc_ft |
1 / 10 | ft | Estimated GNSS horizontal position accuracy. |
U1 |
gnss_vert_pos_acc_ft |
1 / 10 | ft | Estimated GNSS vertical position accuracy. |
U1 |
gnss_vel_acc_kts |
1 / 10 | kts | Estimated GNSS velocity accuracy. |
I2 |
gnss_ned_vel_x_kts |
1 / 10 | kts | GNSS North velocity. |
I2 |
gnss_ned_vel_y_kts |
1 / 10 | kts | GNSS East velocity. |
I2 |
gnss_ned_vel_z_kts |
1 / 100 | kts | GNSS Down velocity. |
U2 |
gnss_alt_wgs84_ft |
- | ft | GNSS altitude above the WGS84 ellipsoid biased by +10,000 ft (i.e. alt = gnss_alt_wgs84_ft - 10000). |
I2 |
gnss_geoid_height_ft |
1 / 10 | ft | GNSS geoid height, (MSL = WGS84 - geoid). |
I4 |
gnss_lat_deg |
1e-7 | deg | GNSS latitude. |
I4 |
gnss_lon_deg |
1e-7 | deg | GNSS longitude. |
I2 |
ins_pitch_deg |
1 / 100 | deg | Pitch attitude. |
I2 |
ins_roll_deg |
1 / 100 | deg | Roll attitude. |
I2 |
ins_mag_var_deg |
1 / 100 | deg | Magnetic variation, + east. |
U2 |
ins_heading_true_deg |
1 / 100 | deg | Heading angle, true, 0 - 360. |
U2 |
ins_heading_mag_deg |
1 / 100 | deg | Heading angle, magnetic, 0 - 360. |
I2 |
ins_climb_rate_ftpm |
1 | ft/min | Climb rate. |
I2 |
ins_load_factor |
1 / 1000 | G | Load factor. |
I2 |
ins_accel_x_g |
1 / 1000 | G | X-axis acceleration after bias correction and filtering. |
I2 |
ins_accel_y_g |
1 / 1000 | G | Y-axis acceleration after bias correction and filtering. |
I2 |
ins_accel_z_g |
1 / 1000 | G | Z-axis acceleration after bias correction and filtering. |
I2 |
ins_gyro_x_dps |
1 / 10 | deg/s | X-axis angular rate after bias correction and filtering. |
I2 |
ins_gyro_y_dps |
1 / 10 | deg/s | Y-axis angular rate after bias correction and filtering. |
I2 |
ins_gyro_z_dps |
1 / 10 | deg/s | Z-axis angular rate after bias correction and filtering. |
I2 |
ins_mag_x_ut |
1 / 80 | uT | X-axis magnetometer, low pass filtered. |
I2 |
ins_mag_y_ut |
1 / 80 | uT | Y-axis magnetometer, low pass filtered. |
I2 |
ins_mag_z_ut |
1 / 80 | uT | Z-axis magnetometer, low pass filtered. |
I2 |
ins_ned_vel_x_kts |
1 / 10 | kts | INS North velocity. |
I2 |
ins_ned_vel_y_kts |
1 / 10 | kts | INS East velocity. |
I2 |
ins_ned_vel_z_kts |
1 / 100 | kts | INS Down velocity. |
U2 |
ins_gnd_spd_kts |
1 / 100 | kts | INS ground speed. |
U2 |
ins_gnd_track_true_deg |
1 / 100 | deg | INS ground track, true, 0 - 360. |
U2 |
ins_gnd_track_mag_deg |
1 / 100 | deg | INS ground track, mag, 0 - 360. |
I2 |
ins_flt_path_deg |
1 / 100 | deg | INS flight path angle, +/- 90 |
U2 |
ins_alt_wgs84_ft |
- | ft | INS height above the WGS84 ellipsoid, biased by +10,000 ft (i.e. alt = ins_alt_wgs84_ft - 10000). |
I4 |
ins_lat_deg |
1e-7 | deg | INS latitude. |
I4 |
ins_lon_deg |
1e-7 | deg | INS longitude. |
U2 |
adc_pres_pa |
2 | Pa | Air data computer static pressure. |
U2 |
adc_pres_alt_ft |
- | ft | Air data computer pressure altitude, biased by +10,000 ft (i.e. alt = adc_pres_alt_ft - 10000). |
I1 |
airdata_die_temp_c |
1 | C | External airdata board die temperature. |
U2 |
airdata_static_pres_pa |
2 | Pa | External airdata static pressure. |
U2 |
airdata_diff_pres_pa |
1 | Pa | External airdata differential pressure. |
I2 |
airdata_oat_c |
1 / 100 | C | External airdata outside air temperature. |
U2 |
airdata_ias_kts |
1 / 100 | kts | External airdata Indicated Air Speed (IAS). |
U2 |
airdata_tas_kts |
1 / 100 | kts | External airdata True Air Speed (TAS). |
U2 |
airdata_pres_alt_ft |
- | ft | External airdata pressure altitude biased by +10,000 ft (i.e. alt = airdata_pres_alt_ft - 10000). |
U2 |
airdata_density_alt_ft |
- | ft | External airdata density altitude biased by +10,000 ft (i.e. alt = airdata_density_alt_ft - 10000). |
I2 |
airdata_aoa |
1 / 100 | - | External airdata angle of attack, this is either an angle or a pressure ratio as defined by the status bitfield. |
I1 |
agl_alt_die_temp_c |
1 | C | External AGL altimeter board die temperature. |
I2 |
agl_alt_in |
1 | in | External AGL altimeter altitude |
U2 |
checksum |
- | - | Fletcher-16 checksum over all preceding packet bytes. |
Version 0 status flags
Byte 0 is the first byte of status. A flag is set when the byte AND the listed mask is nonzero. Use this version’s table and ignore unlisted bits; UDP status bits have a different layout.
| Byte | Mask | Meaning when set |
|---|---|---|
| 0 | 0x01 |
Filtered input voltage between the configured low and warning voltages. |
| 0 | 0x02 |
Filtered input voltage below the configured low voltage. |
| 0 | 0x04 |
CPU die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 0 | 0x08 |
New IMU data received. |
| 0 | 0x10 |
IMU healthy. |
| 0 | 0x20 |
IMU die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 0 | 0x40 |
New magnetometer data received. |
| 0 | 0x80 |
Magnetometer healthy. |
| 1 | 0x01 |
Magnetometer die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 1 | 0x02 |
New static pressure data received. |
| 1 | 0x04 |
Static pressure healthy. |
| 1 | 0x08 |
Static pressure die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 1 | 0x10 |
New GNSS data received. |
| 1 | 0x20 |
GNSS healthy. |
| 1 | 0x40 |
INS initialized. |
| 1 | 0x80 |
INS healthy. |
| 2 | 0x01 |
New external airdata message received. |
| 2 | 0x02 |
External airdata module connected. |
| 2 | 0x04 |
External airdata battery status warning. |
| 2 | 0x08 |
External airdata battery status critically low. |
| 2 | 0x10 |
External airdata board die temperature ok. |
| 2 | 0x20 |
External airdata OAT measurement available. |
| 2 | 0x40 |
External airdata AOA measurement available. |
| 2 | 0x80 |
External airdata new static pressure data received. |
| 3 | 0x01 |
External airdata static pressure healthy. |
| 3 | 0x02 |
External airdata new differential pressure data received. |
| 3 | 0x04 |
External airdata differential pressure healthy. |
| 3 | 0x08 |
External airdata new OAT data received. |
| 3 | 0x10 |
External airdata OAT healthy. |
| 3 | 0x20 |
External airdata new AOA data received. |
| 3 | 0x40 |
External airdata AOA healthy. |
| 3 | 0x80 |
AOA is in degrees when set; a pressure ratio when clear. |
| 4 | 0x01 |
New external AGL altimeter message received. |
| 4 | 0x02 |
External AGL altimeter module connected. |
| 4 | 0x04 |
External AGL altimeter battery status warning. |
| 4 | 0x08 |
External AGL altimeter battery status critically low. |
| 4 | 0x10 |
External AGL altimeter board die temperature ok. |
| 4 | 0x20 |
External AGL altimeter new sensor data received. |
| 4 | 0x40 |
External AGL altimeter sensor healthy. |
| 4 | 0x80 |
External AGL altimeter sensor in range. |
Version 1
Introduced with firmware 3, this layout adds a payload-length byte, a sixth status byte, calibrated airspeed, and wind estimates.
The defined payload is 152 bytes; the complete packet is 158 bytes.
Version 1 data fields
| Type | Name | Scale | Unit | Description |
|---|---|---|---|---|
U1[2] |
header |
- | - | Header {‘B’, ’F’}. |
U1 |
version |
- | - | Data packet version, 1. |
U1 |
payload_length |
- | - | Payload byte count, 152 for the fields below; excludes framing and checksum. |
U1[6] |
status |
- | - | Status flags defined below. |
U4 |
sys_time_ms |
- | ms | Elapsed time since power-on. |
U1 |
input_volt |
1 / 25 | V | Input voltage. |
U1 |
filt_input_volt |
1 / 25 | V | Filtered input voltage. |
I1 |
cpu_die_temp_c |
1 | C | CPU die temperature |
I1 |
imu_die_temp_c |
1 | C | IMU die temperature. |
I2 |
imu_accel_x_g |
1 / 1000 | G | X-axis accelerometer. |
I2 |
imu_accel_y_g |
1 / 1000 | G | Y-axis accelerometer. |
I2 |
imu_accel_z_g |
1 / 1000 | G | Z-axis accelerometer. |
I2 |
imu_gyro_x_dps |
1 / 10 | deg/s | X-axis gyro. |
I2 |
imu_gyro_y_dps |
1 / 10 | deg/s | Y-axis gyro. |
I2 |
imu_gyro_z_dps |
1 / 10 | deg/s | Z-axis gyro. |
I1 |
mag_die_temp_c |
1 | C | Magnetometer die temperature. |
I2 |
mag_x_ut |
1 / 80 | uT | X-axis magnetometer. |
I2 |
mag_y_ut |
1 / 80 | uT | Y-axis magnetometer. |
I2 |
mag_z_ut |
1 / 80 | uT | Z-axis magnetometer. |
I1 |
pres_die_temp_c |
1 | C | Static pressure die temperature |
U2 |
pres_pa |
2 | Pa | Static pressure. |
U1 |
gnss_fix_num_sv |
- | - | Lower 3 bits are GNSS fix (0 = no fix, 2 = 2D fix, 3 = 3D fix, 4 = differential fix). Upper 5 bits are the number of satellite vehicles used in the solution. |
U1 |
gnss_utc_year |
- | - | Year from the GNSS receiver; add 1970 to obtain the calendar year. |
U1 |
gnss_utc_month |
- | - | UTC month from GNSS receiver. |
U1 |
gnss_utc_day |
- | - | UTC day from GNSS receiver. |
U1 |
gnss_utc_hour |
- | - | UTC hour from GNSS receiver. |
U1 |
gnss_utc_min |
- | - | UTC minute from GNSS receiver. |
U1 |
gnss_utc_sec |
- | - | UTC second from GNSS receiver. |
U1 |
gnss_horz_pos_acc_ft |
1 / 10 | ft | Estimated GNSS horizontal position accuracy. |
U1 |
gnss_vert_pos_acc_ft |
1 / 10 | ft | Estimated GNSS vertical position accuracy. |
U1 |
gnss_vel_acc_kts |
1 / 10 | kts | Estimated GNSS velocity accuracy. |
I2 |
gnss_ned_vel_x_kts |
1 / 10 | kts | GNSS North velocity. |
I2 |
gnss_ned_vel_y_kts |
1 / 10 | kts | GNSS East velocity. |
I2 |
gnss_ned_vel_z_kts |
1 / 100 | kts | GNSS Down velocity. |
U2 |
gnss_alt_wgs84_ft |
- | ft | GNSS altitude above the WGS84 ellipsoid biased by +10,000 ft (i.e. alt = gnss_alt_wgs84_ft - 10000). |
I2 |
gnss_geoid_height_ft |
1 / 10 | ft | GNSS geoid height, (MSL = WGS84 - geoid). |
I4 |
gnss_lat_deg |
1e-7 | deg | GNSS latitude. |
I4 |
gnss_lon_deg |
1e-7 | deg | GNSS longitude. |
I2 |
ins_pitch_deg |
1 / 100 | deg | Pitch attitude. |
I2 |
ins_roll_deg |
1 / 100 | deg | Roll attitude. |
I2 |
ins_mag_var_deg |
1 / 100 | deg | Magnetic variation, + east. |
U2 |
ins_heading_true_deg |
1 / 100 | deg | Heading angle, true, 0 - 360. |
U2 |
ins_heading_mag_deg |
1 / 100 | deg | Heading angle, magnetic, 0 - 360. |
I2 |
ins_climb_rate_ftpm |
1 | ft/min | Climb rate. |
I2 |
ins_load_factor |
1 / 1000 | G | Load factor. |
I2 |
ins_accel_x_g |
1 / 1000 | G | X-axis acceleration after bias correction and filtering. |
I2 |
ins_accel_y_g |
1 / 1000 | G | Y-axis acceleration after bias correction and filtering. |
I2 |
ins_accel_z_g |
1 / 1000 | G | Z-axis acceleration after bias correction and filtering. |
I2 |
ins_gyro_x_dps |
1 / 10 | deg/s | X-axis angular rate after bias correction and filtering. |
I2 |
ins_gyro_y_dps |
1 / 10 | deg/s | Y-axis angular rate after bias correction and filtering. |
I2 |
ins_gyro_z_dps |
1 / 10 | deg/s | Z-axis angular rate after bias correction and filtering. |
I2 |
ins_mag_x_ut |
1 / 80 | uT | X-axis magnetometer, low pass filtered. |
I2 |
ins_mag_y_ut |
1 / 80 | uT | Y-axis magnetometer, low pass filtered. |
I2 |
ins_mag_z_ut |
1 / 80 | uT | Z-axis magnetometer, low pass filtered. |
I2 |
ins_ned_vel_x_kts |
1 / 10 | kts | INS North velocity. |
I2 |
ins_ned_vel_y_kts |
1 / 10 | kts | INS East velocity. |
I2 |
ins_ned_vel_z_kts |
1 / 100 | kts | INS Down velocity. |
U2 |
ins_gnd_spd_kts |
1 / 100 | kts | INS ground speed. |
U2 |
ins_gnd_track_true_deg |
1 / 100 | deg | INS ground track, true, 0 - 360. |
U2 |
ins_gnd_track_mag_deg |
1 / 100 | deg | INS ground track, mag, 0 - 360. |
I2 |
ins_flt_path_deg |
1 / 100 | deg | INS flight path angle, +/- 90 |
U2 |
ins_alt_wgs84_ft |
- | ft | INS height above the WGS84 ellipsoid, biased by +10,000 ft (i.e. alt = ins_alt_wgs84_ft - 10000). |
I4 |
ins_lat_deg |
1e-7 | deg | INS latitude. |
I4 |
ins_lon_deg |
1e-7 | deg | INS longitude. |
U2 |
adc_pres_pa |
2 | Pa | Air data computer static pressure. |
U2 |
adc_pres_alt_ft |
- | ft | Air data computer pressure altitude, biased by +10,000 ft (i.e. alt = adc_pres_alt_ft - 10000). |
I1 |
airdata_die_temp_c |
1 | C | External airdata board die temperature. |
U2 |
airdata_static_pres_pa |
2 | Pa | External airdata static pressure. |
U2 |
airdata_diff_pres_pa |
1 | Pa | External airdata differential pressure. |
I2 |
airdata_oat_c |
1 / 100 | C | External airdata outside air temperature. |
U2 |
airdata_ias_kts |
1 / 100 | kts | External airdata Indicated Air Speed (IAS). |
U2 |
airdata_cas_kts |
1 / 100 | kts | External airdata Calibrated Air Speed (CAS). |
U2 |
airdata_tas_kts |
1 / 100 | kts | External airdata True Air Speed (TAS). |
U2 |
airdata_pres_alt_ft |
- | ft | External airdata pressure altitude biased by +10,000 ft (i.e. alt = airdata_pres_alt_ft - 10000). |
U2 |
airdata_density_alt_ft |
- | ft | External airdata density altitude biased by +10,000 ft (i.e. alt = airdata_density_alt_ft - 10000). |
I2 |
airdata_aoa |
1 / 100 | - | External airdata angle of attack, this is either an angle or a pressure ratio as defined by the status bitfield. |
U2 |
airdata_wind_spd_kts |
1 / 100 | kts | External airdata estimated wind speed, kts. |
U2 |
airdata_wind_dir_true_deg |
1 / 100 | deg | External airdata estimated wind direction, true, 0 - 360. |
U2 |
airdata_wind_dir_mag_deg |
1 / 100 | deg | External airdata estimated wind direction, mag, 0 - 360. |
I1 |
agl_alt_die_temp_c |
1 | C | External AGL altimeter board die temperature. |
I2 |
agl_alt_in |
1 | in | External AGL altimeter altitude |
U2 |
checksum |
- | - | Fletcher-16 checksum over all preceding packet bytes. |
Version 1 status flags
Byte 0 is the first byte of status. A flag is set when the byte AND the listed mask is nonzero. Use this version’s table and ignore unlisted bits; UDP status bits have a different layout.
| Byte | Mask | Meaning when set |
|---|---|---|
| 0 | 0x01 |
Filtered input voltage between the configured low and warning voltages. |
| 0 | 0x02 |
Filtered input voltage below the configured low voltage. |
| 0 | 0x04 |
CPU die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 0 | 0x08 |
New IMU data received. |
| 0 | 0x10 |
IMU healthy. |
| 0 | 0x20 |
IMU die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 0 | 0x40 |
New magnetometer data received. |
| 0 | 0x80 |
Magnetometer healthy. |
| 1 | 0x01 |
Magnetometer die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 1 | 0x02 |
New static pressure data received. |
| 1 | 0x04 |
Static pressure healthy. |
| 1 | 0x08 |
Static pressure die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 1 | 0x10 |
New GNSS data received. |
| 1 | 0x20 |
GNSS healthy. |
| 1 | 0x40 |
INS initialized. |
| 1 | 0x80 |
INS healthy. |
| 2 | 0x01 |
New external airdata message received. |
| 2 | 0x02 |
External airdata module connected. |
| 2 | 0x04 |
External airdata battery status warning. |
| 2 | 0x08 |
External airdata battery status critically low. |
| 2 | 0x10 |
External airdata board die temperature ok. |
| 2 | 0x20 |
External airdata OAT measurement available. |
| 2 | 0x40 |
External airdata AOA measurement available. |
| 2 | 0x80 |
External airdata new static pressure data received. |
| 3 | 0x01 |
External airdata static pressure healthy. |
| 3 | 0x02 |
External airdata new differential pressure data received. |
| 3 | 0x04 |
External airdata differential pressure healthy. |
| 3 | 0x08 |
External airdata new OAT data received. |
| 3 | 0x10 |
External airdata OAT healthy. |
| 3 | 0x20 |
External airdata new AOA data received. |
| 3 | 0x40 |
External airdata AOA healthy. |
| 3 | 0x80 |
AOA is in degrees when set; a pressure ratio when clear. |
| 4 | 0x01 |
New external AGL altimeter message received. |
| 4 | 0x02 |
External AGL altimeter module connected. |
| 4 | 0x04 |
External AGL altimeter battery status warning. |
| 4 | 0x08 |
External AGL altimeter battery status critically low. |
| 4 | 0x10 |
External AGL altimeter board die temperature ok. |
| 4 | 0x20 |
External AGL altimeter new sensor data received. |
| 4 | 0x40 |
External AGL altimeter sensor healthy. |
| 4 | 0x80 |
External AGL altimeter sensor in range. |
| 5 | 0x01 |
External airdata KCAS available. |
| 5 | 0x02 |
External airdata wind speed and direction estimation available. |
Version 2
Introduced with firmware 6, this layout adds heart rate and four analog channels. Firmware 6 and later also write metadata packets.
The defined payload is 184 bytes; the complete packet is 190 bytes.
Version 2 data fields
| Type | Name | Scale | Unit | Description |
|---|---|---|---|---|
U1[2] |
header |
- | - | Header {‘B’, ’F’}. |
U1 |
version |
- | - | Data packet version, 2. |
U1 |
payload_length |
- | - | Payload byte count, 184 for the fields below; excludes framing and checksum. |
U1[6] |
status |
- | - | Status flags defined below. |
U4 |
sys_time_ms |
- | ms | Elapsed time since power-on. |
U1 |
input_volt |
1 / 25 | V | Input voltage. |
U1 |
filt_input_volt |
1 / 25 | V | Filtered input voltage. |
I1 |
cpu_die_temp_c |
1 | C | CPU die temperature |
I1 |
imu_die_temp_c |
1 | C | IMU die temperature. |
I2 |
imu_accel_x_g |
1 / 1000 | G | X-axis accelerometer. |
I2 |
imu_accel_y_g |
1 / 1000 | G | Y-axis accelerometer. |
I2 |
imu_accel_z_g |
1 / 1000 | G | Z-axis accelerometer. |
I2 |
imu_gyro_x_dps |
1 / 10 | deg/s | X-axis gyro. |
I2 |
imu_gyro_y_dps |
1 / 10 | deg/s | Y-axis gyro. |
I2 |
imu_gyro_z_dps |
1 / 10 | deg/s | Z-axis gyro. |
I1 |
mag_die_temp_c |
1 | C | Magnetometer die temperature. |
I2 |
mag_x_ut |
1 / 80 | uT | X-axis magnetometer. |
I2 |
mag_y_ut |
1 / 80 | uT | Y-axis magnetometer. |
I2 |
mag_z_ut |
1 / 80 | uT | Z-axis magnetometer. |
I1 |
pres_die_temp_c |
1 | C | Static pressure die temperature |
U2 |
pres_pa |
2 | Pa | Static pressure. |
U1 |
gnss_fix_num_sv |
- | - | Lower 3 bits are GNSS fix (0 = no fix, 2 = 2D fix, 3 = 3D fix, 4 = differential fix). Upper 5 bits are the number of satellite vehicles used in the solution. |
U1 |
gnss_utc_year |
- | - | Year from the GNSS receiver; add 1970 to obtain the calendar year. |
U1 |
gnss_utc_month |
- | - | UTC month from GNSS receiver. |
U1 |
gnss_utc_day |
- | - | UTC day from GNSS receiver. |
U1 |
gnss_utc_hour |
- | - | UTC hour from GNSS receiver. |
U1 |
gnss_utc_min |
- | - | UTC minute from GNSS receiver. |
U1 |
gnss_utc_sec |
- | - | UTC second from GNSS receiver. |
U1 |
gnss_horz_pos_acc_ft |
1 / 10 | ft | Estimated GNSS horizontal position accuracy. |
U1 |
gnss_vert_pos_acc_ft |
1 / 10 | ft | Estimated GNSS vertical position accuracy. |
U1 |
gnss_vel_acc_kts |
1 / 10 | kts | Estimated GNSS velocity accuracy. |
I2 |
gnss_ned_vel_x_kts |
1 / 10 | kts | GNSS North velocity. |
I2 |
gnss_ned_vel_y_kts |
1 / 10 | kts | GNSS East velocity. |
I2 |
gnss_ned_vel_z_kts |
1 / 100 | kts | GNSS Down velocity. |
U2 |
gnss_alt_wgs84_ft |
- | ft | GNSS altitude above the WGS84 ellipsoid biased by +10,000 ft (i.e. alt = gnss_alt_wgs84_ft - 10000). |
I2 |
gnss_geoid_height_ft |
1 / 10 | ft | GNSS geoid height, (MSL = WGS84 - geoid). |
I4 |
gnss_lat_deg |
1e-7 | deg | GNSS latitude. |
I4 |
gnss_lon_deg |
1e-7 | deg | GNSS longitude. |
I2 |
ins_pitch_deg |
1 / 100 | deg | Pitch attitude. |
I2 |
ins_roll_deg |
1 / 100 | deg | Roll attitude. |
I2 |
ins_mag_var_deg |
1 / 100 | deg | Magnetic variation, + east. |
U2 |
ins_heading_true_deg |
1 / 100 | deg | Heading angle, true, 0 - 360. |
U2 |
ins_heading_mag_deg |
1 / 100 | deg | Heading angle, magnetic, 0 - 360. |
I2 |
ins_climb_rate_ftpm |
1 | ft/min | Climb rate. |
I2 |
ins_load_factor |
1 / 1000 | G | Load factor. |
I2 |
ins_accel_x_g |
1 / 1000 | G | X-axis acceleration after bias correction and filtering. |
I2 |
ins_accel_y_g |
1 / 1000 | G | Y-axis acceleration after bias correction and filtering. |
I2 |
ins_accel_z_g |
1 / 1000 | G | Z-axis acceleration after bias correction and filtering. |
I2 |
ins_gyro_x_dps |
1 / 10 | deg/s | X-axis angular rate after bias correction and filtering. |
I2 |
ins_gyro_y_dps |
1 / 10 | deg/s | Y-axis angular rate after bias correction and filtering. |
I2 |
ins_gyro_z_dps |
1 / 10 | deg/s | Z-axis angular rate after bias correction and filtering. |
I2 |
ins_mag_x_ut |
1 / 80 | uT | X-axis magnetometer, low pass filtered. |
I2 |
ins_mag_y_ut |
1 / 80 | uT | Y-axis magnetometer, low pass filtered. |
I2 |
ins_mag_z_ut |
1 / 80 | uT | Z-axis magnetometer, low pass filtered. |
I2 |
ins_ned_vel_x_kts |
1 / 10 | kts | INS North velocity. |
I2 |
ins_ned_vel_y_kts |
1 / 10 | kts | INS East velocity. |
I2 |
ins_ned_vel_z_kts |
1 / 100 | kts | INS Down velocity. |
U2 |
ins_gnd_spd_kts |
1 / 100 | kts | INS ground speed. |
U2 |
ins_gnd_track_true_deg |
1 / 100 | deg | INS ground track, true, 0 - 360. |
U2 |
ins_gnd_track_mag_deg |
1 / 100 | deg | INS ground track, mag, 0 - 360. |
I2 |
ins_flt_path_deg |
1 / 100 | deg | INS flight path angle, +/- 90 |
U2 |
ins_alt_wgs84_ft |
- | ft | INS height above the WGS84 ellipsoid, biased by +10,000 ft (i.e. alt = ins_alt_wgs84_ft - 10000). |
I4 |
ins_lat_deg |
1e-7 | deg | INS latitude. |
I4 |
ins_lon_deg |
1e-7 | deg | INS longitude. |
U2 |
adc_pres_pa |
2 | Pa | Air data computer static pressure. |
U2 |
adc_pres_alt_ft |
- | ft | Air data computer pressure altitude, biased by +10,000 ft (i.e. alt = adc_pres_alt_ft - 10000). |
I1 |
airdata_die_temp_c |
1 | C | External airdata board die temperature. |
U2 |
airdata_static_pres_pa |
2 | Pa | External airdata static pressure. |
U2 |
airdata_diff_pres_pa |
1 | Pa | External airdata differential pressure. |
I2 |
airdata_oat_c |
1 / 100 | C | External airdata outside air temperature. |
U2 |
airdata_ias_kts |
1 / 100 | kts | External airdata Indicated Air Speed (IAS). |
U2 |
airdata_cas_kts |
1 / 100 | kts | External airdata Calibrated Air Speed (CAS). |
U2 |
airdata_tas_kts |
1 / 100 | kts | External airdata True Air Speed (TAS). |
U2 |
airdata_pres_alt_ft |
- | ft | External airdata pressure altitude biased by +10,000 ft (i.e. alt = airdata_pres_alt_ft - 10000). |
U2 |
airdata_density_alt_ft |
- | ft | External airdata density altitude biased by +10,000 ft (i.e. alt = airdata_density_alt_ft - 10000). |
I2 |
airdata_aoa |
1 / 100 | - | External airdata angle of attack, this is either an angle or a pressure ratio as defined by the status bitfield. |
U2 |
airdata_wind_spd_kts |
1 / 100 | kts | External airdata estimated wind speed, kts. |
U2 |
airdata_wind_dir_true_deg |
1 / 100 | deg | External airdata estimated wind direction, true, 0 - 360. |
U2 |
airdata_wind_dir_mag_deg |
1 / 100 | deg | External airdata estimated wind direction, mag, 0 - 360. |
I1 |
agl_alt_die_temp_c |
1 | C | External AGL altimeter board die temperature. |
I2 |
agl_alt_in |
1 | in | External AGL altimeter altitude |
U1 |
heart_rate_bpm |
1 | bpm | Measured heart rate from connected heart rate sensor. |
U1 |
ain_connected_new_msg |
- | - | Lower 4 bits are status flags for whether each analog input channel is connected, upper 4 bits indicate whether a new message was received. |
U1 |
ain_healthy_die_temp_ok |
- | - | Lower 4 bits are status flags indicating whether each channel is healthy. Upper 4 bits indicate whether the die temperature is ok. |
U1 |
ain_batt_status |
- | - | Lower 4 bits are status flags to indicate a warning battery status for each channel, upper 4 bits indicate a critically low battery status. |
I1[4] |
ain_die_temp_c |
1 | C | Array of die temperatures for each analog channel. |
U2[4] |
ain_volt |
1e-4 | V | Array of measured voltage for each analog channel. |
F4[4] |
ain_val |
- | - | Array of calibrated engineering value for each analog channel, 32-bit floating-point value. |
U2 |
checksum |
- | - | Fletcher-16 checksum over all preceding packet bytes. |
Version 2 status flags
Byte 0 is the first byte of status. A flag is set when the byte AND the listed mask is nonzero. Use this version’s table and ignore unlisted bits; UDP status bits have a different layout.
| Byte | Mask | Meaning when set |
|---|---|---|
| 0 | 0x01 |
Filtered input voltage between the configured low and warning voltages. |
| 0 | 0x02 |
Filtered input voltage below the configured low voltage. |
| 0 | 0x04 |
CPU die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 0 | 0x08 |
New IMU data received. |
| 0 | 0x10 |
IMU healthy. |
| 0 | 0x20 |
IMU die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 0 | 0x40 |
New magnetometer data received. |
| 0 | 0x80 |
Magnetometer healthy. |
| 1 | 0x01 |
Magnetometer die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 1 | 0x02 |
New static pressure data received. |
| 1 | 0x04 |
Static pressure healthy. |
| 1 | 0x08 |
Static pressure die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 1 | 0x10 |
New GNSS data received. |
| 1 | 0x20 |
GNSS healthy. |
| 1 | 0x40 |
INS initialized. |
| 1 | 0x80 |
INS healthy. |
| 2 | 0x01 |
New external airdata message received. |
| 2 | 0x02 |
External airdata module connected. |
| 2 | 0x04 |
External airdata battery status warning. |
| 2 | 0x08 |
External airdata battery status critically low. |
| 2 | 0x10 |
External airdata board die temperature ok. |
| 2 | 0x20 |
External airdata OAT measurement available. |
| 2 | 0x40 |
External airdata AOA measurement available. |
| 2 | 0x80 |
External airdata new static pressure data received. |
| 3 | 0x01 |
External airdata static pressure healthy. |
| 3 | 0x02 |
External airdata new differential pressure data received. |
| 3 | 0x04 |
External airdata differential pressure healthy. |
| 3 | 0x08 |
External airdata new OAT data received. |
| 3 | 0x10 |
External airdata OAT healthy. |
| 3 | 0x20 |
External airdata new AOA data received. |
| 3 | 0x40 |
External airdata AOA healthy. |
| 3 | 0x80 |
AOA is in degrees when set; a pressure ratio when clear. |
| 4 | 0x01 |
New external AGL altimeter message received. |
| 4 | 0x02 |
External AGL altimeter module connected. |
| 4 | 0x04 |
External AGL altimeter battery status warning. |
| 4 | 0x08 |
External AGL altimeter battery status critically low. |
| 4 | 0x10 |
External AGL altimeter board die temperature ok. |
| 4 | 0x20 |
External AGL altimeter new sensor data received. |
| 4 | 0x40 |
External AGL altimeter sensor healthy. |
| 4 | 0x80 |
External AGL altimeter sensor in range. |
| 5 | 0x01 |
External airdata KCAS available. |
| 5 | 0x02 |
External airdata wind speed and direction estimation available. |
| 5 | 0x04 |
External heart rate monitor message received. |
| 5 | 0x08 |
External heart rate monitor connected. |
| 5 | 0x10 |
External AGL altimeter is a Skeeter Enterprises LLC Stadia sensor. |
Version 3 (Hub Plus)
Hub Plus uses data version 3, with a 198-byte payload and a 204-byte complete packet. It retains the version 2 measurement offsets and scales, replaces the external analog-channel measurements with onboard analog inputs, and appends 14 bytes of clock information before the checksum.
The first six payload bytes are stored as status[2] followed by ext_status[4]. Together they occupy the same bytes as status[6] in version 2. UTC fields come from the Hub Plus clock. The renamed cabin-pressure and external-sensor fields retain their version 2 encodings.
Version 3 data fields
Offsets below are from the start of the complete packet, including the two-byte BF header. All arrays are in channel order, 0–3.
| Offset | Type | Name | Scale | Unit | Description |
|---|---|---|---|---|---|
| 0 | U1[2] |
header |
- | - | Header {‘B’, ’F’}. |
| 2 | U1 |
version |
- | - | Data packet version, 3. |
| 3 | U1 |
payload_length |
- | - | 198 payload bytes; excludes framing and checksum. |
| 4 | U1[2] |
status |
- | - | Internal status bytes; see version 3 status flags below (bytes 0–1). |
| 6 | U1[4] |
ext_status |
- | - | External status bytes; see version 3 status flags below (bytes 2–5). |
| 10 | U4 |
sys_time_ms |
- | ms | Elapsed time since power-on. |
| 14 | U1 |
input_volt |
1 / 25 | V | Input voltage. |
| 15 | U1 |
filt_input_volt |
1 / 25 | V | Filtered input voltage. |
| 16 | I1 |
cpu_die_temp_c |
1 | C | CPU die temperature |
| 17 | I1 |
imu_die_temp_c |
1 | C | IMU die temperature. |
| 18 | I2 |
imu_accel_x_g |
1 / 1000 | G | X-axis accelerometer. |
| 20 | I2 |
imu_accel_y_g |
1 / 1000 | G | Y-axis accelerometer. |
| 22 | I2 |
imu_accel_z_g |
1 / 1000 | G | Z-axis accelerometer. |
| 24 | I2 |
imu_gyro_x_dps |
1 / 10 | deg/s | X-axis gyro. |
| 26 | I2 |
imu_gyro_y_dps |
1 / 10 | deg/s | Y-axis gyro. |
| 28 | I2 |
imu_gyro_z_dps |
1 / 10 | deg/s | Z-axis gyro. |
| 30 | I1 |
mag_die_temp_c |
1 | C | Magnetometer die temperature. |
| 31 | I2 |
mag_x_ut |
1 / 80 | uT | X-axis magnetometer. |
| 33 | I2 |
mag_y_ut |
1 / 80 | uT | Y-axis magnetometer. |
| 35 | I2 |
mag_z_ut |
1 / 80 | uT | Z-axis magnetometer. |
| 37 | I1 |
pres_die_temp_c |
1 | C | Static pressure die temperature |
| 38 | U2 |
pres_pa |
2 | Pa | Static pressure. |
| 40 | U1 |
gnss_fix_num_sv |
- | - | Lower 3 bits are GNSS fix (0 = no fix, 2 = 2D fix, 3 = 3D fix, 4 = differential fix). Upper 5 bits are the number of satellite vehicles used in the solution. |
| 41 | U1 |
utc_year |
- | - | UTC year from 1970 from the Hub Plus clock. |
| 42 | U1 |
utc_month |
- | - | UTC month from the Hub Plus clock. |
| 43 | U1 |
utc_day |
- | - | UTC day from the Hub Plus clock. |
| 44 | U1 |
utc_hour |
- | - | UTC hour from the Hub Plus clock. |
| 45 | U1 |
utc_min |
- | - | UTC minute from the Hub Plus clock. |
| 46 | U1 |
utc_sec |
- | - | UTC second from the Hub Plus clock. |
| 47 | U1 |
gnss_horz_pos_acc_ft |
1 / 10 | ft | Estimated GNSS horizontal position accuracy. |
| 48 | U1 |
gnss_vert_pos_acc_ft |
1 / 10 | ft | Estimated GNSS vertical position accuracy. |
| 49 | U1 |
gnss_vel_acc_kts |
1 / 10 | kts | Estimated GNSS velocity accuracy. |
| 50 | I2 |
gnss_ned_vel_x_kts |
1 / 10 | kts | GNSS North velocity. |
| 52 | I2 |
gnss_ned_vel_y_kts |
1 / 10 | kts | GNSS East velocity. |
| 54 | I2 |
gnss_ned_vel_z_kts |
1 / 100 | kts | GNSS Down velocity. |
| 56 | U2 |
gnss_alt_wgs84_ft |
- | ft | GNSS altitude above the WGS84 ellipsoid biased by +10,000 ft (i.e. alt = gnss_alt_wgs84_ft - 10000). |
| 58 | I2 |
gnss_geoid_height_ft |
1 / 10 | ft | GNSS geoid height, (MSL = WGS84 - geoid). |
| 60 | I4 |
gnss_lat_deg |
1e-7 | deg | GNSS latitude. |
| 64 | I4 |
gnss_lon_deg |
1e-7 | deg | GNSS longitude. |
| 68 | I2 |
ins_pitch_deg |
1 / 100 | deg | Pitch attitude. |
| 70 | I2 |
ins_roll_deg |
1 / 100 | deg | Roll attitude. |
| 72 | I2 |
ins_mag_var_deg |
1 / 100 | deg | Magnetic variation, + east. |
| 74 | U2 |
ins_heading_true_deg |
1 / 100 | deg | Heading angle, true, 0 - 360. |
| 76 | U2 |
ins_heading_mag_deg |
1 / 100 | deg | Heading angle, magnetic, 0 - 360. |
| 78 | I2 |
ins_climb_rate_ftpm |
1 | ft/min | Climb rate. |
| 80 | I2 |
ins_load_factor |
1 / 1000 | G | Load factor. |
| 82 | I2 |
ins_accel_x_g |
1 / 1000 | G | X-axis acceleration after bias correction and filtering. |
| 84 | I2 |
ins_accel_y_g |
1 / 1000 | G | Y-axis acceleration after bias correction and filtering. |
| 86 | I2 |
ins_accel_z_g |
1 / 1000 | G | Z-axis acceleration after bias correction and filtering. |
| 88 | I2 |
ins_gyro_x_dps |
1 / 10 | deg/s | X-axis angular rate after bias correction and filtering. |
| 90 | I2 |
ins_gyro_y_dps |
1 / 10 | deg/s | Y-axis angular rate after bias correction and filtering. |
| 92 | I2 |
ins_gyro_z_dps |
1 / 10 | deg/s | Z-axis angular rate after bias correction and filtering. |
| 94 | I2 |
ins_mag_x_ut |
1 / 80 | uT | X-axis magnetometer, low pass filtered. |
| 96 | I2 |
ins_mag_y_ut |
1 / 80 | uT | Y-axis magnetometer, low pass filtered. |
| 98 | I2 |
ins_mag_z_ut |
1 / 80 | uT | Z-axis magnetometer, low pass filtered. |
| 100 | I2 |
ins_ned_vel_x_kts |
1 / 10 | kts | INS North velocity. |
| 102 | I2 |
ins_ned_vel_y_kts |
1 / 10 | kts | INS East velocity. |
| 104 | I2 |
ins_ned_vel_z_kts |
1 / 100 | kts | INS Down velocity. |
| 106 | U2 |
ins_gnd_spd_kts |
1 / 100 | kts | INS ground speed. |
| 108 | U2 |
ins_gnd_track_true_deg |
1 / 100 | deg | INS ground track, true, 0 - 360. |
| 110 | U2 |
ins_gnd_track_mag_deg |
1 / 100 | deg | INS ground track, mag, 0 - 360. |
| 112 | I2 |
ins_flt_path_deg |
1 / 100 | deg | INS flight path angle, +/- 90 |
| 114 | U2 |
ins_alt_wgs84_ft |
- | ft | INS height above the WGS84 ellipsoid, biased by +10,000 ft (i.e. alt = ins_alt_wgs84_ft - 10000). |
| 116 | I4 |
ins_lat_deg |
1e-7 | deg | INS latitude. |
| 120 | I4 |
ins_lon_deg |
1e-7 | deg | INS longitude. |
| 124 | U2 |
filt_pres_pa |
2 | Pa | Air data computer static pressure. |
| 126 | U2 |
air_data_pres_alt_ft |
- | ft | Air data computer pressure altitude, biased by +10,000 ft (i.e. alt = adc_pres_alt_ft - 10000). |
| 128 | I1 |
ext_airdata_die_temp_c |
1 | C | External airdata board die temperature. |
| 129 | U2 |
ext_airdata_static_pres_pa |
2 | Pa | External airdata static pressure. |
| 131 | U2 |
ext_airdata_diff_pres_pa |
1 | Pa | External airdata differential pressure. |
| 133 | I2 |
ext_airdata_oat_c |
1 / 100 | C | External airdata outside air temperature. |
| 135 | U2 |
ext_airdata_ias_kts |
1 / 100 | kts | External airdata Indicated Air Speed (IAS). |
| 137 | U2 |
ext_airdata_cas_kts |
1 / 100 | kts | External airdata Calibrated Air Speed (CAS). |
| 139 | U2 |
ext_airdata_tas_kts |
1 / 100 | kts | External airdata True Air Speed (TAS). |
| 141 | U2 |
ext_airdata_pres_alt_ft |
- | ft | External airdata pressure altitude biased by +10,000 ft (i.e. alt = airdata_pres_alt_ft - 10000). |
| 143 | U2 |
ext_airdata_density_alt_ft |
- | ft | External airdata density altitude biased by +10,000 ft (i.e. alt = airdata_density_alt_ft - 10000). |
| 145 | I2 |
ext_airdata_aoa |
1 / 100 | - | External airdata angle of attack, this is either an angle or a pressure ratio as defined by the status bitfield. |
| 147 | U2 |
ext_airdata_wind_spd_kts |
1 / 100 | kts | External airdata estimated wind speed, kts. |
| 149 | U2 |
ext_airdata_wind_dir_true_deg |
1 / 100 | deg | External airdata estimated wind direction, true, 0 - 360. |
| 151 | U2 |
ext_airdata_wind_dir_mag_deg |
1 / 100 | deg | External airdata estimated wind direction, mag, 0 - 360. |
| 153 | I1 |
ext_agl_alt_die_temp_c |
1 | C | External AGL altimeter board die temperature. |
| 154 | I2 |
ext_agl_alt_in |
1 | in | External AGL altimeter altitude |
| 156 | U1 |
ext_heart_rate_bpm |
1 | bpm | Measured heart rate from connected heart rate sensor. |
| 157 | U1 |
ain_connected_new_msg |
- | - | Fixed value 0xFF; not a measurement of onboard-channel status. |
| 158 | U1 |
ain_healthy_die_temp_ok |
- | - | Fixed value 0xFF; not a measurement of onboard-channel status. |
| 159 | U1 |
ain_batt_status |
- | - | Fixed value 0x00; onboard channels have no separate battery. |
| 160 | I1[4] |
ain_die_temp_c |
1 | C | All four bytes are zero; channel temperatures are not measured. |
| 164 | U2[4] |
ain_volt |
1e-4 | V | Raw onboard input voltages, channels 0–3. |
| 172 | F4[4] |
ain_val |
- | - | Calibrated onboard control values, channels 0–3. Two-point calibration produces 0 to 1; three-point calibration produces -1 to 1. See AD metadata for each channel’s calibration type. |
| 188 | U8 |
gps_time_us |
1 | µs | GPS time since the GPS epoch (1980-01-06). |
| 196 | U4 |
utc_us |
1 | µs | Fraction of the UTC second, 0–999999. |
| 200 | U2 |
sys_time_us |
1 | µs | Remainder beyond sys_time_ms, 0–999. |
| 202 | U2 |
checksum |
- | - | Fletcher-16 checksum over all preceding packet bytes. |
Version 3 status flags
Bytes 0–1 are status[0–1]; bytes 2–5 are ext_status[0–3]. A flag is set when the byte AND the listed mask is nonzero. Ignore unlisted bits; UDP status bits have a different layout.
| Byte | Mask | Meaning when set |
|---|---|---|
| 0 | 0x01 |
Filtered input voltage between the configured low and warning voltages. |
| 0 | 0x02 |
Filtered input voltage below the configured low voltage. |
| 0 | 0x04 |
CPU die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 0 | 0x08 |
New IMU data received. |
| 0 | 0x10 |
IMU healthy. |
| 0 | 0x20 |
IMU die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 0 | 0x40 |
New magnetometer data received. |
| 0 | 0x80 |
Magnetometer healthy. |
| 1 | 0x01 |
Magnetometer die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 1 | 0x02 |
New static pressure data received. |
| 1 | 0x04 |
Static pressure healthy. |
| 1 | 0x08 |
Static pressure die temperature within the allowed range, with a 10°C margin inside the sensor limits. |
| 1 | 0x10 |
New GNSS data received. |
| 1 | 0x20 |
GNSS healthy. |
| 1 | 0x40 |
INS initialized. |
| 1 | 0x80 |
INS healthy. |
| 2 | 0x01 |
New external airdata message received. |
| 2 | 0x02 |
External airdata module connected. |
| 2 | 0x04 |
External airdata battery status warning. |
| 2 | 0x08 |
External airdata battery status critically low. |
| 2 | 0x10 |
External airdata board die temperature ok. |
| 2 | 0x20 |
External airdata OAT measurement available. |
| 2 | 0x40 |
External airdata AOA measurement available. |
| 2 | 0x80 |
External airdata new static pressure data received. |
| 3 | 0x01 |
External airdata static pressure healthy. |
| 3 | 0x02 |
External airdata new differential pressure data received. |
| 3 | 0x04 |
External airdata differential pressure healthy. |
| 3 | 0x08 |
External airdata new OAT data received. |
| 3 | 0x10 |
External airdata OAT healthy. |
| 3 | 0x20 |
External airdata new AOA data received. |
| 3 | 0x40 |
External airdata AOA healthy. |
| 3 | 0x80 |
AOA is in degrees when set; a pressure ratio when clear. |
| 4 | 0x01 |
New external AGL altimeter message received. |
| 4 | 0x02 |
External AGL altimeter module connected. |
| 4 | 0x04 |
External AGL altimeter battery status warning. |
| 4 | 0x08 |
External AGL altimeter battery status critically low. |
| 4 | 0x10 |
External AGL altimeter board die temperature ok. |
| 4 | 0x20 |
External AGL altimeter new sensor data received. |
| 4 | 0x40 |
External AGL altimeter sensor healthy. |
| 4 | 0x80 |
External AGL altimeter sensor in range. |
| 5 | 0x01 |
External airdata KCAS available. |
| 5 | 0x02 |
External airdata wind speed and direction estimation available. |
| 5 | 0x04 |
External heart rate monitor message received. |
| 5 | 0x08 |
External heart rate monitor connected. |
| 5 | 0x10 |
External AGL altimeter is a Skeeter Enterprises LLC Stadia sensor. |
| 5 | 0x20 |
GPS time initialized: the locked signal from the GPS has been received. Hub Plus only currently. |
| 5 | 0x40 |
UTC time initialized: leap seconds have been set. Hub Plus only currently. |
GPS and UTC time initialization
These two initialization features are currently available only on Hub Plus. They indicate separate conditions: GPS time initialization checks for the locked signal from the GPS, while UTC time initialization checks that leap seconds have been set. The leap-second offset is needed to convert GPS time to UTC.
Check byte 5 (ext_status[3]) in each packet before using its absolute time fields. Use gps_time_us when the GPS initialization flag (0x20) is set. Use the UTC calendar fields and utc_us when the UTC initialization flag (0x40) is set. GPS initialization alone does not establish that UTC is initialized; check the UTC flag separately.
While the corresponding flag is clear, do not interpret those fields as an initialized absolute timestamp. Use sys_time_ms and sys_time_us for elapsed time since boot; they do not require GPS or UTC initialization.
Version 3 analog validity
Hub Plus retains the older analog status fields so the following measurements stay at the same byte offsets. It writes fixed values into those fields: 0xFF for connection and health, and zero for battery status and temperature. They are not measurements of onboard-channel status. All four onboard analog channels are included in the output. The AD packet supplies the channel assignments and calibration types; it does not report whether calibration is complete.
Reconstructing time
Hub versions 0–2 record UTC calendar fields directly from the GNSS receiver, with whole-second resolution in the .onflight format. Hub Plus synchronizes its clock to the receiver’s one-pulse-per-second (PPS) signal. Between pulses, it advances time using its internal clock, with a scale correction derived from the PPS intervals. This provides UTC and GPS time of week for samples recorded faster than once per second, both with microsecond resolution. UTC is derived from GPS time using the receiver-provided leap-second offset. Resolution is not a specification of absolute timing accuracy.
The final three payload fields provide the extra timing information:
| Field | Packet offset | Meaning |
|---|---|---|
gps_time_us |
188 | Total microseconds since the GPS epoch, January 6, 1980. |
utc_us |
196 | Microseconds to add to the whole UTC second. |
sys_time_us |
200 | Microseconds to add to the whole system-time millisecond. |
System time: elapsed time since boot
sys_time_ms contains whole milliseconds. sys_time_us contains the remaining 0–999 microseconds. Convert both to seconds and add them:
Elapsed seconds = (sys_time_ms ÷ 1,000) + (sys_time_us ÷ 1,000,000)
For example, sys_time_ms = 1234 and sys_time_us = 567 represent 1.234567 seconds since boot.
UTC: calendar date and time
Use utc_year, utc_month, utc_day, utc_hour, utc_min, and utc_sec for the calendar date and whole-second time. Add 1970 to utc_year to obtain the calendar year.
utc_us supplies the fractional part of the second, from 0–999,999 microseconds:
UTC seconds within the minute = utc_sec + (utc_us ÷ 1,000,000)
For example, utc_sec = 12 and utc_us = 345678 represent 12.345678 seconds within the recorded minute. The configured UTC offset affects microSD file timestamps only; it does not change these UTC fields.
GPS time: week number and time within the week
gps_time_us is a total count from the GPS epoch. To split it into a GPS week number and time of week:
- Divide the count by 604,800,000,000, the number of microseconds in one week. The whole-number quotient is the GPS week number.
- Take the remainder from that division. Divide it by 1,000,000 to obtain seconds within the GPS week.
For example, gps_time_us = 1391040123456789 gives GPS week 2300 and time of week 123.456789 seconds.
Perform the week division and remainder using 64-bit unsigned integers or another exact integer type. Convert the remainder to floating point only when expressing it in seconds; converting the full count first can lose microsecond precision.
GPS time uses a different epoch from Unix time and does not include UTC leap seconds. Use the recorded UTC fields when you need a UTC calendar timestamp.
Metadata packet
Firmware 6 and later include MD metadata packets in the log. Scan for the packet header rather than relying on a fixed file offset. It contains the serial number and null-terminated aircraft/pilot character arrays. Earlier firmware does not write this frame.
| Type | Name | Scale | Unit | Description |
|---|---|---|---|---|
U1[2] |
header |
- | - | Header {‘M’, ’D’}. |
U1 |
version |
- | - | Meta data format version number, 0. |
U1 |
payload_length |
- | - | Length of the payload starting at the next byte and not including the checksum, 54. |
U1[6] |
serial_num |
- | - | OnFlight Hub serial number. |
C1[12] |
tail_num |
- | - | Aircraft tail number, if configured. Text ending with a null byte. |
C1[24] |
pilot_name |
- | - | Pilot name, if configured. Text ending with a null byte. |
C1[12] |
aircraft_type |
- | - | Aircraft type, if configured. Text ending with a null byte. |
U2 |
checksum |
- | - | Fletcher-16 checksum over all preceding packet bytes. |
Analog metadata packet
Hub Plus writes an AD version 0 packet near the beginning of the file. It describes the four onboard analog channels whose measurements appear in version 3 data packets. Search for the AD header and check its checksum; its position in the file is not fixed.
The payload is 9 bytes, and the complete packet is 15 bytes. Offsets are from the start of the AD header.
| Offset | Type | Name | Description |
|---|---|---|---|
| 0 | U1[2] |
header |
ASCII AD, bytes 0x41 0x44. |
| 2 | U1 |
version |
Analog metadata version, 0. |
| 3 | U1 |
payload_length |
9; excludes header, version, length byte, and checksum. |
| 4 | U1 |
analog_channel_enabled |
Bit 1 << n is set when channel n is enabled, for channels 0–3. Ignore the upper four bits. |
| 5 | U1[4] |
analog_control_type |
Control assignment for channels 0–3. |
| 9 | U1[4] |
analog_cal_type |
Calibration type for channels 0–3. |
| 13 | U2 |
checksum |
Fletcher-16 over bytes 0–12, stored little-endian. |
Control assignments
| Value | Control |
|---|---|
| 0 | Elevator |
| 1 | Aileron |
| 2 | Rudder |
| 3 | Throttle |
| 4 | Mixture |
| 5 | Prop |
| 6 | Flaps |
| 7 | Custom |
Calibration types
| Value | Calibration | Calibrated value |
|---|---|---|
| 0 | Two-point | Normalized range 0 to 1. |
| 1 | Three-point | Normalized range -1 to 1, with the calibrated center at 0. |
These values describe normalized control positions, not angles in degrees. The calibration coefficients and completion flags are not carried in AD. The calibrated values themselves are recorded in ain_val in each BF packet.
Match each entry in AD to the same channel number in ain_volt and ain_val. For example, entry 0 in each array describes channel 0. Keep the channel number in your application even if two channels have the same control assignment.
If AD is missing or its checksum is wrong, the control assignments and calibration types are unknown. Leave unknown type codes unidentified. The fixed analog status values in BF do not provide this information.