Developer Reference

SPOT Tools JSON File Spec

Published format reference for developers integrating tooling, converters, or automated pipelines with SPOT Tools JSON files.

SPOT Tools JSON File Spec

This document defines the JSON format used by SPOT Tools to load/save radio and channel state.
Audience: developers integrating tooling, converters, or automated pipelines.

Format Overview

SPOT Tools stores two types of information: radio-wide settings and an array of channel objects. It will accept a file that has only a channels array. In that case defaults will be used for the radio-wide settings. Lists are stored in the radio-wide settings, so a more practical minimal file is a radio object with list names and a channel array.

On import/read, compatibility mapping is applied first so deprecated JSON forms and receiver-specific encodings are converted into the current field set. The resulting radio and channel data are then normalized once into SPOT Tools' canonical in-memory model before downstream code uses them.

Current exported schema:

  • schema_version: 10
  • radio_model: "uv-k5-telemetry"

Canonical Top-Level Shape

{
  "schema_version": 10,
  "radio_model": "uv-k5-telemetry",
  "radio": { "...": "see Radio section" },
  "channel_count": 200,
  "channels": [ { "...": "see Channel section" } ]
}

Notes:

  • channel_count is informational on import (not authoritative).
  • schema_version and radio_model are currently not enforced by the parser.

Radio Object

The radio has one canonical sub-object, active_options, which carries the radio-wide settings.

Older files may also carry deprecated compatibility data such as legacy_values. Those forms are still accepted on import for now and are documented in Appendix B, but they are no longer emitted when a file is saved.

radio.active_options (canonical)

{
  "beep_control": true,
  "bpm_control": true,
  "battery_type": 0,
  "scan": {
    "active_list_mask": 1,
    "list_names": ["L1", "...", "L16"],
    "resume_mode": "stop",
    "dwell_time_seconds": 5
  },
  "telemetry": {
    "peak_time": 22
  },
  "receiver": {
    "rf_gain": 12,
    "tag_mode": "channel"
  },
  "display": {
    "power_on_display_mode": "logo",
    "backlight_time": 4
  },
  "boot": {
    "line1": "SPOT",
    "line2": "Telemetry RX"
  },
  "keys": {
    "flashlight_enabled": true,
    "arrow_orientation": "up_down"
  },
  "developer": {
    "squelch_level": 0,
    "pulse_threshold_dbm": -95,
    "full_scale_dbm": -31,
    "battery_calibration": 2300
  }
}

radio.active_options Field Definitions

Field Type Description
beep_control boolean Flag that enables or disables button/key beep feedback in the receiver UI.
bpm_control boolean Flag that enables or disables BPM display/processing behavior in telemetry operation.
battery_type integer Selector for the battery profile used by the firmware’s battery meter logic.
scan.
active_list_mask
integer Mask, effective visible range 0..65535 (& 0xffff on read/write; each bit enables one visible scan list. The low-order bit (0x0001) is list 1, and the high-order visible bit (0x8000) is list 16. A zero mask means the built-in ALL channels list.
scan.
list_names
array Up to the first 16 entries are used. Each entry should be a string of at most 10 printable ASCII characters. Names will be normalized to normalized to L<n> if missing or empty.
scan.
resume_mode
"stop" | "dwell" Controls whether scanning stays on a hit or continues after a dwell interval.
scan.
dwell_time_seconds
integer Sanitized to the nearest of 1, 2, 3, 5, 10, 15, 20, 25, 30; used when scan.resume_mode is "dwell".
telemetry.
peak_time
integer Sanitized to the nearest of 5, 10, 20, 22, 24, 29, 39 (encoded values for 0.5, 1, 2, 3, 5, 10, 20 seconds); controls how long the peak meter indicator is held.
receiver.
rf_gain
integer Clamped to 0..24; selects the manual telemetry RF gain setting.
receiver.
tag_mode
"channel" | "tag" Controls whether navigation/search prefers channel order or tag-style naming.
display.
power_on_display_mode
"message" | "sound" | "voltage" | "logo" | "none" Selects what the receiver shows at power-on. Import also accepts "full_screen" and normalizes it to "logo".
display.
backlight_time
integer SPOT UI backlight-time index, clamped to 0..7: 0=OFF, 1=5 sec, 2=10 sec, 3=20 sec, 4=1 min, 5=2 min, 6=4 min, 7=ON. SPOT Tools maps this UI index to the firmware’s stored timing value internally.
boot.
line1, line2
string Used as the first and second lines of the boot message when power-on display mode is set to "message". Truncated to 15 characters.
keys.
flashlight_enabled
boolean Determines whether the flashlight key is enabled.
keys.
arrow_orientation
"up_down" | "left_right" Specifies the orientation of the arrow keys on the physical receiver. Standard units use up_down.

Channel Object

Each element of the channels array has this canonical shape:

channels[] (canonical)

{
  "index": 0,
  "active": true,
  "name": "664 R L",
  "rx_frequency": 16840830,
  "step_setting": 9,
  "attributes": {
    "band": 2,
    "scanlists": [1, 2, 3]
  }
}

channels[] Field Definitions

Field Type Description
index integer Zero-based channel slot index within the 200-channel receiver memory.
active boolean Indicates whether this channel should be treated as an enabled, usable telemetry channel.
name string Operator-visible channel label, usually used for tag number and/or descriptive text. Up to 10 printable ASCII characters.
rx_frequency number Given in 10's of Hz. For example, 15536720 is 155.36720 MHz. This is the same resolution as is displayed by the firmware.
step_setting
optional
integer Numeric code to select the frequency step. If omitted or invalid, the default telemetry step, 0.5 kHz (code 11), will be used. Available values are:
Step Size Numeric code
0.01 kHz 07
0.05 kHz 08
0.10 kHz 09
0.25 kHz 10
0.50 kHz 11
1.00 kHz 12
1.25 kHz 13
2.50 kHz 00
5.00 kHz 01
attributes.
band
integer Internal band classification used by the firmware for frequency validation and channel normalization.
attributes.
scanlists

optional
array Indicates which lists this channel is a member of, expressed as list numbers 1..16.

Deprecated legacy channel compatibility fields and import aliases are collected in Appendix B. These will be removed in a future release.

Normalization (Sanitization) Rules

Radio Object Normalization (Sanitization) Rules

After compatibility mapping and parsing/import, SPOT Tools sanitizes radio-wide settings once into its canonical in-memory radio model:

  • radio.active_options.battery_type: rounded and clamped to 0..4
  • radio.active_options.scan.active_list_mask: normalized to the visible 16-bit range (& 0xffff)
  • radio.active_options.scan.list_names: only the first 16 entries are used; each entry is reduced to printable ASCII, trimmed, truncated to 10 characters, and normalized to L<n> if the internalized result is empty
  • radio.active_options.scan.resume_mode: normalized to "stop" or "dwell"
  • radio.active_options.scan.dwell_time_seconds: sanitized to the nearest of 1, 2, 3, 5, 10, 15, 20, 25, 30
  • radio.active_options.telemetry.peak_time: sanitized to the nearest of 5, 10, 20, 22, 24, 29, 39 (encoded values for 0.5, 1, 2, 3, 5, 10, 20 seconds)
  • radio.active_options.receiver.squelch_level: rounded and clamped to 0..9
  • radio.active_options.receiver.rf_gain: rounded and clamped to 0..24
  • radio.active_options.receiver.tag_mode: normalized to "channel" or "tag"
  • radio.active_options.display.power_on_display_mode: legacy import value "full_screen" is normalized to "logo"
  • radio.active_options.display.backlight_time: rounded and clamped to the SPOT UI range 0..7
  • radio.active_options.boot.line1 and line2: truncated to 15 characters
  • radio.active_options.keys.arrow_orientation: normalized to "up_down" or "left_right"
  • radio.active_options.developer.pulse_threshold_dbm: rounded and clamped to -125..-60
  • radio.active_options.developer.full_scale_dbm: rounded and clamped to -100..-20
  • radio.active_options.developer.force_bandwidth: normalized to "dont_force", "wide", "narrow", or "narrower"
  • radio.active_options.developer.battery_calibration: rounded and clamped to 1500..3500

Important:

  • Save and receiver-write paths emit this canonical radio state using JSON or receiver-specific encoding rules. Receiver writes still perform transport-specific encoding such as timing conversion and bit packing.

Channel Object Normalization (Sanitization) Rules

After compatibility mapping and parsing/import, SPOT Tools sanitizes channels once into its canonical in-memory channel model:

  • channels[].name: trim, printable ASCII only, max 10 chars
  • channels[].attributes.scanlists: normalized to the currently visible 16-bit range (& 0xffff) internally before being re-emitted as list numbers
  • channels[].step_setting: if omitted or unsupported, replaced with default telemetry step (0.5 kHz)
  • channels[].legacy.bandwidth: forced to "narrow" internally
  • channels[].active = true entries are validated against telemetry constraints:
    • channels[].attributes.band must be 0..6
    • channels[].rx_frequency range must be:
      • min 14400000 (144 MHz)
      • max exclusive 17400000 (174 MHz)
  • invalid channels[].active = true entries are coerced/inactivated per sanitizer logic

Important:

  • Save and write paths emit this canonical channel state. JSON export re-emits visible scan-list memberships as scanlists, while receiver writes still perform receiver-specific encoding.

Export Behavior (Canonicalization)

When SPOT Tools saves JSON, it emits:

  • schema_version: 10
  • canonical radio.active_options only
  • channels with:
    • index, active, name, rx_frequency, step_setting
    • attributes.band
    • attributes.scanlists
  • radio.active_options.developer only when one or more optional developer-backed values are actually present. It will not provide defaults for these values. They are either set explicitly or not at all.

Strictness and Unknown Fields

  • Known fields are type-checked strictly.
  • Missing optional fields fall back to defaults.
  • Unknown fields are generally ignored by parser.
  • Deprecated compatibility fields in older files are still accepted on import. See Appendix B.

Minimal Valid Input Example

{
  "channels": [
    {
      "index": 0,
      "active": true,
      "name": "CH001",
      "rx_frequency": 16840000,
      "attributes": {
        "band": 2,
        "scanlists": [1]
      }
    }
  ]
}

Omitted radio fields are filled from defaults, and omitted step_setting is normalized to the default telemetry step.

Appendix A: Developer Radio Fields

This appendix documents the optional developer-facing fields nested within radio.active_options.developer.

radio.active_options.developer (canonical)

{
  "squelch_level": 0,
  "pulse_threshold_dbm": -95,
  "full_scale_dbm": -31,
  "force_bandwidth": "narrower",
  "battery_calibration": 2300
}

radio.active_options.developer Field Definitions

Field Type Description
squelch_level integer For telemetry purposes, squelch should always be 0. It is hear only for developer experimentation.
pulse_threshold_dbm integer Developer-facing threshold used by telemetry pulse qualification logic.
full_scale_dbm integer Developer-facing full-scale reference for telemetry power/meter display.
force_bandwidth "dont_force" | "wide" | "narrow" | "narrower" Forces the bandwidth setting for all channels to the selected value. Using "dont_force" respects the channel setting.
battery_calibration integer Developer-facing calibration value for battery reporting.

Appendix B: Deprecated Import-Only Compatibility

These fields are still accepted on import for near-term compatibility, but current exports do not emit them. They are deprecated and will be removed.

Radio Legacy Fields

radio.legacy_values (deprecated import-only)

{
  "tx_timeout_timer": 1,
  "mic_sensitivity": 4,
  "roger_mode": "off",
  "repeater_tail_tone_elimination": 0,
  "tx_vfo_index": 0,
  "auto_keypad_lock": false,
  "cross_band_rx_tx": "off",
  "dual_watch": "off",
  "vfo_open": true,
  "raw": {}
}

radio.legacy_values Field Definitions

Field Type Description
tx_timeout_timer integer Legacy transmit timeout setting retained only for compatibility and round-tripping.
mic_sensitivity integer Legacy microphone gain setting retained for compatibility with inherited layouts.
roger_mode "off" | "roger" | "mdc" Legacy roger-beep/MDC transmit behavior setting.
repeater_tail_tone_elimination integer Legacy repeater-tail suppression field preserved for compatibility.
tx_vfo_index integer Legacy selected transmit VFO index from the source radio model.
auto_keypad_lock boolean Legacy keypad auto-lock preference.
cross_band_rx_tx "off" | "chan_a" | "chan_b" Legacy cross-band receive/transmit mode selector.
dual_watch "off" | "chan_a" | "chan_b" Legacy dual-watch mode selector.
vfo_open boolean Legacy flag indicating whether VFO mode was enabled/open.
raw object Opaque compatibility bucket for legacy or vendor-specific values not explicitly modeled elsewhere.

Legacy radio import aliases

  • radio.active_options.scan.target_mode: accepted on import for compatibility and collapsed into the mask-only scan model.
  • radio.active_options.scan.default_list: legacy alias accepted on import and mapped into scan.active_list_mask.
  • radio.active_options.keys.flashlight_key: legacy alias accepted on import and normalized into keys.flashlight_enabled.
  • radio.active_options.display.power_on_display_mode with value "full_screen": accepted on import and normalized to "logo".
  • radio.legacy_values.beep_control, radio.legacy_values.bpm_control, and radio.legacy_values.battery_type: accepted as fallback sources when the canonical active_options fields are absent.
  • radio.active_options.receiver.squelch_level: deprecated import-only alias for canonical radio.active_options.developer.squelch_level.
  • radio.active_options.meter_calibration: deprecated import-only compatibility object.

Channel Legacy Fields

channels[].legacy (deprecated import-only)

channels[].legacy Field Definitions

Field Type Description
legacy.
bandwidth
"wide" | "narrow" Legacy compatibility field accepted on import, but normalized to SPOT’s telemetry-safe bandwidth behavior.
legacy.
step_setting
integer Legacy fallback source for step_setting on import.

channels[].attributes legacy scan-list import fields (deprecated import-only)

channels[].attributes Field Definitions

Field Type Description
attributes.
scanlist_mask
0..65535 Legacy mask-based form accepted on import.
attributes.
scanlist1

attributes.
scanlist2
boolean Legacy boolean scan-list membership fields accepted on import.