# Receiver JSONL records

URL: /reference/receiver-jsonl

Read any ground receive record field by field, from the MAVLink message that arrived to the system that sent it and the moment it reached range control. A receipt trails its send time, and this page shows by how much.



Receiver JSONL is the ground receive log. The MAVLink receiver at range control writes one JSON object per line, one line per message it heard, stamped on arrival by its own clock. The [`telemetry_gap`](/rules/telemetry-gap) rule reads these records, and the timeline draws them as a receipt rug.

## Record fields [#record-fields]

| Field      | Type and unit                           | Meaning                                                                                                               |
| ---------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `recv_utc` | String, UTC, ISO 8601 with milliseconds | Time the message reached the receiver, on the receiver's NTP-disciplined clock. The console shows this time.          |
| `mono_ns`  | Integer, nanoseconds                    | Monotonic time on the receiver at arrival.                                                                            |
| `link`     | String                                  | The link the message arrived on: `mesh0` in the example dataset.                                                      |
| `sysid`    | Integer                                 | MAVLink system ID of the sender, which identifies the vehicle. In the example dataset, UAS-04 is 4 and UGV-02 is 22.  |
| `compid`   | Integer                                 | MAVLink component ID of the sender within its system. Every example record carries 1.                                 |
| `msgid`    | Integer                                 | MAVLink message ID. `0` is `HEARTBEAT`.                                                                               |
| `msg`      | String                                  | Message name, such as `HEARTBEAT`.                                                                                    |
| `seq`      | Integer, 0 to 255                       | MAVLink packet sequence. It counts every message the system sends on the link, not only heartbeats, and wraps at 256. |
| `len`      | Integer, bytes                          | Payload length. A `HEARTBEAT` payload is 9 bytes.                                                                     |

Every record in the example dataset is a `HEARTBEAT`, which the vehicles send at 1 Hz. `telemetry_gap` reads only `HEARTBEAT` records and measures the time between consecutive ones from the same `sysid`.

## Example record [#example-record]

This is the last heartbeat from UAS-04 before the gap in INC-0142, line 1,118 of `rc1-receive.jsonl`:

```json title="rc1-receive.jsonl" caption="Example dataset, INC-0142, line 1,118, one line in the file"
{
  "recv_utc": "2026-09-24T14:32:03.912Z",
  "mono_ns": 12805145901122,
  "link": "mesh0",
  "sysid": 4,
  "compid": 1,
  "msgid": 0,
  "msg": "HEARTBEAT",
  "seq": 204,
  "len": 9
}
```

The next record from system 4, on line 1,119, arrived at 14:32:10.874. The 6.96 s between the two is the gap `telemetry_gap` reports as **Heartbeat due and not received. Nothing for 6.96 s**.

That record's `seq` is 5, not 205, because the counter moves on with every message the vehicle sends on the link and wraps at 256.

The evidence inspector shows the pair, indented, under **Original record**, with **Lines 1,118 and 1,119** under **Location**.

## How Foxborne recognizes the format [#how-foxborne-recognizes-the-format]

**Import files** reads the first 4,096 bytes of each file. A file with `"recv_utc"` in those bytes is detected as **Receiver JSONL**, with the detail **Receive records found**.

This check runs after the ULog magic bytes and `__REALTIME_TIMESTAMP`, and before the collector check for `"boot_id"` or `"rss_kib"`. [Collector JSONL records](/reference/collector-jsonl#how-foxborne-recognizes-the-format) gives the full order.

## Clock and bound [#clock-and-bound]

**Source files** on the run page lists the receive log with these values, here from run R-0931 in the example dataset:

| Column               | Value                                                                               | What it means                                                      |
| -------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| **Clock and anchor** | **Range control receiver clock**, anchored by **NTP, synchronised, offset +0.4 ms** | The receiver's own clock, kept on UTC by NTP.                      |
| **Bound**            | **±15 ms + latency**                                                                | The clock's error bound, plus link latency on the early side only. |
| **Parser**           | `receive 0.4.1`                                                                     | The parser and version that read the file.                         |

On the timeline, the **Ground receive** lane, subtitled **sysid 4, 1 Hz**, draws a receipt rug with one tick per record. A stretch with no receipts is hatched and labeled, such as **No telemetry received for 6.96 s**.

## Receive time is not send time [#receive-time-is-not-send-time]

A receipt always comes after the transmission, later by the link latency. Foxborne gives each receipt an interval that reaches back by the clock error plus the latency, and forward by the clock error alone.

```text title="Send window of the example record" caption="Example dataset, INC-0142"
earliest send = recv_utc - error - latency = 14:32:03.912 - 15 ms - 412 ms = 14:32:03.485
latest send   = recv_utc + error           = 14:32:03.912 + 15 ms          = 14:32:03.927
```

The last heartbeat before the gap left the vehicle between 14:32:03.485 and 14:32:03.927. Reports quote that window, not the arrival time alone.

## Link latency [#link-latency]

Foxborne measures link latency per run and carries the 95th percentile as the one-sided term. Since Foxborne 1.4.1, latency estimates for receive logs come from `SYSTEM_TIME`.

| Run              | Median | 95th percentile |
| ---------------- | ------ | --------------- |
| R-0931, INC-0142 | 96 ms  | 412 ms          |
| R-0934, INC-0143 | 88 ms  | 380 ms          |

The console shows the latency wherever it shows a receipt's time:

| Where                               | What it reads                                                  |
| ----------------------------------- | -------------------------------------------------------------- |
| Run page, **Bound**                 | **±15 ms + latency**                                           |
| Timeline                            | A dashed extension to the left of each receipt's error bracket |
| Evidence inspector, **When**        | The bound, then **+ 412 ms latency**                           |
| Timeline hover                      | **plus up to 412 ms latency**                                  |
| **Ordering bounds between sources** | A second line, such as **plus 412 ms latency**                 |
| Event page, **Context**, **Clock**  | **Receive latency: Up to 412 ms, 95th percentile**             |

Latency also decides how a receipt orders against other sources. In INC-0142, `mavlink-router.service` stopped at 14:32:04.152 on the journal, with a bound of ±6 ms. The next heartbeat was due at range control at 14:32:04.912, with ±15 ms and up to 412 ms of latency.

The two are 760 ms apart against a bound of 6 + 15 + 412 = 433 ms, so their order holds. The report files the pair as correlated, with the note &#x2A;*Due 0.76 s after mavlink-router.service stopped. Bound ±0.43 s including link latency.**

## Related [#related]

* [telemetry\_gap](/rules/telemetry-gap) reads these records and explains what a receive gap does not mean.
* [MAVLink ground receiver](/collect/receiver) covers the receiver itself.
* [Clocks, anchors and error bounds](/concepts/clocks) and [Alignment and event order](/concepts/alignment) explain how a receipt's bound combines with other sources.
* [Collector JSONL records](/reference/collector-jsonl) documents process samples from the companion computer.
