Skip to content

feat: import/export qDMR YAML codeplugs #37

Description

@pskillen

Problem

qDMR (and its CLI dmrconf) is the most prominent open-source, cross-vendor codeplug tool, and it stores codeplugs in a human-readable, device-independent YAML format. A meaningful share of OpenGD77 (and wider DMR) operators already keep their codeplugs as qDMR YAML, and qDMR can encode that YAML straight to the device binary.

Supporting qDMR YAML as an interchange format would let those users bring their existing codeplugs into this tool (to visualise / manage / report) and take them back out into a toolchain that can already write the radio — without going through a lossy vendor CSV round-trip.

Distinction from #10 (our native YAML)

This is not the same as #10. #10 defines our own native YAML that losslessly represents our internal models. This ticket treats qDMR YAML as a third-party (foreign) format — like a vendor CSV, but YAML — handled at the import/export adapter boundary and mapped to/from our internal models. It is lossy at the edges (qDMR models concepts we don't, and vice versa).

Intended outcome

Add qDMR YAML as a first-class import and export format alongside OpenGD77 CSV:

  • Import: parse a qDMR YAML codeplug and map it into the internal data models (feat: genericise CPS import via internal data models #7) — radios/general settings (as far as we model them), channels (analogue + digital), zones, contacts, group lists (RX group lists / TG lists), and talk groups.
  • Export: serialise the internal models back out to a valid qDMR YAML document that qDMR / dmrconf will accept and can encode to a device.
  • Round-trip friendly: import-then-export should reproduce an equivalent qDMR YAML codeplug (modulo documented lossy fields).
  • Adapter, not core: keep qDMR specifics behind the import/export adapter layer (mirroring src/lib/import/), so feature code only ever sees internal models.

qDMR YAML specifics to handle

  • The format uses anchors/explicit id: references to link objects (channels → contacts/group lists, zones → channels, group lists → contacts). Our internal models already use stable ids (feat: genericise CPS import via internal data models #7), so map qDMR ids ↔ our internal ids at the boundary; do not leak qDMR ids into the models.
  • Distinguish analogue (FM) vs digital (DMR) channel nodes and their differing fields (CTCSS/DCS, bandwidth vs colour code, timeslot, group list, TX contact).
  • Map qDMR group lists ↔ our TG lists, and qDMR contacts (group vs private call) ↔ our contacts / talk groups.
  • Frequencies in qDMR YAML are human-readable strings (e.g. 145.500 MHz) — normalise to our internal representation on import and re-emit in qDMR's expected form on export.
  • Capture/round-trip fields we don't model yet (best-effort) rather than silently dropping them where practical; document what is lossy.

Affected

  • Import: new adapter under src/lib/import/ + registration in the import registry (src/lib/import/index.ts).
  • Export: the export layer (feat: CPS export support (internal models → vendor format) #8) gains a qDMR YAML target alongside OpenGD77 CSV.
  • Internal models (src/models/): no new vendor coupling — mapping stays at the edges. May surface gaps where qDMR carries data we don't yet model (e.g. talk groups / contacts / group lists, currently stubs).
  • A YAML parse/serialise dependency (e.g. yaml/js-yaml).

Notes / dependencies

Out of scope

  • Writing the device binary or talking to the radio directly (qDMR/dmrconf already do this; native binary/Web Serial is a separate concern).
  • Bundling or shelling out to dmrconf (this is a native, in-browser YAML mapping only).
  • Full fidelity for qDMR features we don't model — best-effort + documented lossiness.

Workflow note (for whoever picks this up)

Likely multi-commit work: branch from origin/main, use atomic conventional commits per logical change (do not batch into one big end-of-plan commit), and open a PR linking Closes #. Pair with the docs/features / progress-tracking skills for the build log.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestradio-format-supportsupport for 3rd party radio formats - import/export, etc

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions