Skip to content

ZeroTrace AirLeak

Heartbeat Fields

Every diagnostic field in the 2-second heartbeat

The firmware emits a heartbeat every 2 seconds, regardless of capture mode. The heartbeat is a structured status record covering connection state, capture activity, memory, and timing.

The desktop's status bar reads from the heartbeat. If you're scripting against the unit, the heartbeat is what you should poll.


Field reference

Identity

FieldTypeMeaning
firmwarestringVersion string (e.g. airleak-v1.4.2)
buildstringBuild date and tag
macstringThe unit's BLE MAC (also USB device ID)
slotintegerActive OTA slot (0 or 1)
boot_countintegerSuccessful boots since factory reset

Capture state

FieldTypeMeaning
modeenumsetup or monitor
scan_stateenumactive, passive, or off
ble_active_scanningboolWhether SCAN_REQs are being sent
current_channelintegerThe WiFi channel currently being listened to (1–13)
channel_dwell_msintegerPer-channel dwell time
scan_window_msintegerBLE scan window
scan_interval_msintegerBLE scan interval
throttle_msintegerEvent throttle window

When mode=setup, scan_state=off and current_channel=0.

Activity counters

FieldTypeMeaning
devicesintegerUnique aggregated devices since session start
eventsintegerTotal decoded events emitted
events_throttledintegerEvents suppressed from USB stream by throttle
wifi_eventsintegerWiFi-side event count
ble_eventsintegerBLE-side event count
alertsintegerTotal alerts fired since session start
usb_droppedintegerEvents lost on USB transmit (queue full)
drop_pctfloatusb_dropped / events as percent
events_per_secfloatEvents emitted in last 1 s

When events_throttled is much larger than events, the throttle is doing its job — most events are aggregated but not streamed. That's normal in dense environments.

Memory

FieldTypeMeaning
heap_freeintegerFree internal heap in bytes
heap_free_pctintegerFree internal heap as percent of total internal SRAM
heap_min_everintegerLowest free internal heap since boot (high-water-low)
psram_freeintegerFree PSRAM in bytes
psram_free_pctintegerFree PSRAM as percent
largest_blockintegerLargest contiguous internal heap block in bytes

The status bar's Heap NK (X%) is heap_free / 1024 and heap_free_pct. Color coding:

  • >12% — green (healthy)
  • 7–12% — orange (under pressure)
  • <7% — red (safe-mode armed)

largest_block matters under pressure: even with 30 KB free heap, if the largest contiguous block is only 3 KB, the unit can't allocate large queues and may stutter.

Timing

FieldTypeMeaning
uptime_msintegerTime since last boot, in milliseconds
uptime_strstringHuman-readable: 1h 23m 45s, 2d 4h 12m, etc.
time_since_last_event_msintegerMilliseconds since the last event was emitted
time_since_last_alert_msintegerMilliseconds since the last alert was fired

time_since_last_event_ms is useful for diagnosing "is anything happening." If it climbs above 30 s in Monitor mode, either the area is empty or the radio is wedged.

Health flags

FieldTypeMeaning
safe_modeboolTrue if the heap monitor has triggered safe mode
wifi_healthyboolWiFi driver is responding to channel-hop commands
ble_healthyboolBLE host is delivering scan callbacks
usb_attachedboolUSB-CDC reports a host attached
parser_healthyboolParser task hasn't been stuck for >5 s
aggregator_fullboolTrue when device count = 768 (cap)

If any of wifi_healthy / ble_healthy / parser_healthy is false, the desktop displays a red dot and surfaces a diagnostic in the status bar.

Per-task CPU snapshot

A small per-task CPU usage table is included for diagnostic purposes:

FieldMeaning
cpu_parser_pctParser task CPU usage
cpu_usb_pctUSB stream task CPU usage
cpu_nimble_pctNimBLE host task CPU usage
cpu_wifi_pctWiFi capture task CPU usage
cpu_idle_core0_pctIdle time on core 0
cpu_idle_core1_pctIdle time on core 1

These are rolling averages over the last second. Saturation (any task > 90 % consistently) means the throttle should be increased.

Aggregator state

FieldTypeMeaning
aggregator_sizeintegerNumber of devices currently in the aggregator
aggregator_maxintegerMaximum the aggregator can hold (768)
aggregator_evictedintegerTotal devices evicted (LRU) since boot
fingerprint_groupsintegerNumber of fingerprint-merged device groups

A growing aggregator_evicted count in a long capture means devices were rotating fast enough to fill the aggregator. The desktop's library still has them via cross-session matching — eviction only affects the live in-firmware aggregator.

Channel histogram (last minute)

A compact representation of how many frames hit each channel in the last minute:

ch_hist: 1=12 2=8 3=4 4=2 5=3 6=58 7=2 8=4 9=5 10=8 11=124 12=1 13=2

Useful for spotting "channel 6 and 11 are busy, the rest are quiet." The dominant channels are usually the non-overlapping ones (1, 6, 11).


Heartbeat cadence

ModeHeartbeat intervalWhat's reported
Setup2 sIdentity + capture state + memory + uptime + flags
Monitor2 sAll of the above + activity counters + per-task CPU

The cadence is constant — the heartbeat doesn't slow down or speed up under load. A heartbeat skipped is a sign of trouble (parser starved, USB queue saturated).


Reading heartbeats from the desktop

Open AirLeak → Settings → Device log. Filter for HB::

HB: mode=monitor scan=active devices=87 events=4421 ...
HB: mode=monitor scan=active devices=89 events=4533 ...
HB: mode=monitor scan=active devices=89 events=4631 ...

Each line is one heartbeat. The desktop's status bar parses these in real time.


Reading heartbeats from a script

If you connect to the unit's COM port directly (921600 baud, USB-CDC), you'll see lines prefixed:

  • HB: — heartbeats
  • EV: — events (when in Monitor)
  • AL: — alerts (when in Monitor)
  • DEV: — device dumps (on demand via airleak-snapshot)
  • LOG: — diagnostic log

Heartbeats arrive every 2 s on a steady cadence. The format is structured (key=value pairs) — easy to parse without a JSON dependency.


When heartbeats matter most

  • Connection lost — heartbeat freezes; desktop dot turns gray
  • Heap pressureheap_free_pct drops; orange / red threshold
  • Stuck channelcurrent_channel doesn't advance; wifi_healthy=false follows
  • Stream backlogusb_dropped climbs; drop_pct > 5 %
  • Aggregator fullaggregator_full=true; evictions begin

Watch the heartbeat first when something feels wrong. It's the most informative single log line on the unit.


Faster polling

If you need real-time per-second updates instead of per-2-second, send airleak-status from the Command tab on a timer. It returns a single status frame in the heartbeat format, on demand.

Command Palette

Search for a command to run...