Extend radio capabilities model with bands, modes, and bandwidths - #6
Merged
Conversation
The capabilities model was three integers (max_channels, max_zones, max_channels_per_zone). That answers 'will this profile fit' but not 'will these channels work on this radio', so a profile could select out-of-band or unsupported-mode channels and validate clean. Concretely: the MateTalk P4 is UHF-only (400-470 MHz), but nothing stopped a profile putting MURS at 151/154 MHz on it. That had to be caught by hand when writing the shared ChiOff profiles; the validator would have emitted a codeplug with unusable channels. Adds three optional capability fields: - bands[]: tunable ranges in MHz, with optional rx_only for receive-only spans. Checked against each selected channel's RX and TX frequency. - modes[]: FM / DMR support. Checked against each chain's mode type. - bandwidths_khz[]: supported analog bandwidths, checked when a chain declares one. Every check is skipped when its field is absent, so an incomplete capabilities file degrades to current behavior rather than emitting false failures. Existing files stay valid. Also adds schemas/capabilities-0.2.schema.json and validates capabilities.json against it at load. Previously a typo in a limits key surfaced as a raw KeyError; it now reports the offending property. Populates both radios. DM-32 band edges and scan-list count are cross-checked against qdmr's DM32UVLimits (lib/dm32uv_limits.cc), which declares 136-174 / 400-480 MHz and a narrow/wide bandwidth enum. Prior art: qdmr models per-radio limits as a RadioLimits tree with RadioLimitFrequencies holding explicit MHz ranges per channel type, and NeonPlug's RadioCapabilities carries bandLimits plus analogOnly and per-object maxima. Both treat band coverage as a first-class radio fact. This change takes the same shape at the scope Codeplugger needs, leaving scan lists, contacts, and DMR identities out of the resolved model as the README already specifies. Verified: both ChiOff shared profiles still validate unchanged; MURS on the P4 now fails with an explicit band error; a DMR channel on an analog-only radio fails with a mode error; an unknown capabilities key fails with a schema error instead of KeyError.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The capabilities model is currently three integers:
{ "id": "...", "name": "...", "limits": { "max_channels": N, "max_zones": N, "max_channels_per_zone": N } }That answers will this profile fit but not will these channels work on this radio. A profile can select out-of-band or unsupported-mode channels and validate clean.
Motivating case
The Retevis MateTalk P4 is UHF-only (400–470 MHz), but nothing stopped a profile from putting MURS at 151/154 MHz on it. That had to be caught by hand while writing the shared ChiOff profiles — the validator would otherwise have emitted a codeplug with ten unusable channels.
A related gap:
capabilities.jsonhad no schema, so a typo in a limits key surfaced as a rawKeyErrorrather than a useful message.Changes
Three optional capability fields:
bands[]— tunable ranges in MHz, with optionalrx_onlyfor receive-only spans. Checked against each selected channel RX and TX frequency.rx_onlybands satisfy receive checks but never transmit checks.modes[]—FM/DMR. Checked against each chain mode type.bandwidths_khz[]— supported analog bandwidths, checked when a chain declares one.Plus
schemas/capabilities-0.2.schema.json, validated at load.Every check is skipped when its field is absent, so an incomplete capabilities file degrades to current behavior instead of producing false failures. Existing capabilities files remain valid — the new fields are additive and optional.
Both radios are populated. DM-32 band edges and scan-list count are cross-checked against qdmr, not guessed.
Prior art
RadioLimitstree.RadioLimitFrequenciesholds explicit MHz ranges per channel type, declared per radio —lib/dm32uv_limits.ccstates 136–174 and 400–480 MHz for RX and TX separately, withRadioLimitTransmitFrequenciesas a distinct subclass. Bandwidth is aRadioLimitEnumover narrow/wide. That RX/TX split is the direct ancestor ofrx_onlyhere.src/types/radioCapabilities.ts) carriesbandLimits(vhfMin/vhfMax, optionaluhfMin/uhfMax— absent on VHF-only radios), ananalogOnlyflag, and per-object maxima. ItsDEFAULT_BAND_LIMITSfallback is a useful counterexample: defaulting to a plausible band silently accepts out-of-band channels on unknown radios, so this PR skips the check instead of assuming.Both mature tools treat band coverage as a first-class radio fact. This takes the same shape at the scope Codeplugger needs, leaving scan lists, contacts, and DMR identities out of the resolved model as the README already specifies.
Verification
chioff_p4_shared1 zone / 6 assignments,chioff_dm32_shared2 zones / 16 assignments).channel 'ChiO MURS 1' RX 151.82 MHz is outside the bands supported by Retevis MateTalk P4 (UHF (400.0-470.0 MHz))channel 'HS W9CRS' uses mode DMR, which Fake Analog-Only does not support (FM)limits: Additional properties are not allowed ('bogus_key' was unexpected)Notes for review
max_zonesallows0to describe radios with no zone concept (NeonPlug models this withsupportsZones: false); nothing enforces that yet, it is just expressible.bandwidths_khzof[12.5, 25.0]reflects the manual Features page stating "Wideband/Narrowband Selectable". The specifications table in that PDF is scanned images with no extractable text, so the exact kHz figures are not machine-readable from the source — worth a second pair of eyes.