Skip to content

OnFlight Hub and Hub Plus / Developer Manual

Log file format

Read measurement and metadata packets from Hub and Hub Plus recordings.

On this page

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.

  1. Scan for a defined two-byte header: BF for a data packet, MD for aircraft/pilot metadata, or AD for Hub Plus analog metadata.
  2. 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_length immediately after the version.
  3. Read the complete payload and the following two checksum bytes. The length excludes the header, version, length byte, and checksum.
  4. Validate the Fletcher-16 checksum over the header, version, length byte when present, and all payload bytes.
  5. Decode recognized fields only after validation. Advance past the complete packet. Ignore other file content.
  6. 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:

  1. Divide the count by 604,800,000,000, the number of microseconds in one week. The whole-number quotient is the GPS week number.
  2. 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.