Skip to content

feat: BrandMeister network lookup for DMR channels, talk groups, and RX lists #167

Description

@pskillen

Problem / outcome

Let operators pull authoritative DMR data from the BrandMeister network instead of hand-typing it, mirroring the ukrepeater.net feature (#92) but for the DMR side. BrandMeister exposes an unauthenticated, CORS-enabled public API, so it is callable directly from the browser SPA — no proxy/server required.

Three flows, delivered in phases (below):

  • Flow A — Channel datasource: when adding/editing a DMR channel, look up a repeater on BrandMeister (by ID / callsign) and pre-fill channel information (frequencies, colour code, etc.).
  • Flow B — Auto-generate talk groups + RX group list: query the talk-group APIs for a repeater to auto-generate the talk groups it carries (if not already present) and build an RX group list tailored to that repeater.
  • Flow C — Validate against an authoritative source: check existing local talk groups / channels against BrandMeister and surface a diff.

Data source

Halligan API v2 — the API behind the BrandMeister Dashboard. It authenticates dashboard users and routes queries to the correct backend servers in the decentralised BrandMeister network.

  • Base URL: https://api.brandmeister.network/v2/
  • Docs: https://api.brandmeister.network/docs/
  • Public read endpoints are unauthenticated and CORS-compatible for the queries we need (repeater / talk-group lookups).
  • Treat as third-party / potentially unstable: degrade gracefully on failure, cache responses, attribute the source in the UI, and keep the "not authoritative for emergency operations" disclaimer.

TODO during implementation: confirm exact v2 endpoint paths and response shapes against the live docs, plus which endpoints are genuinely unauthenticated + CORS-open vs. requiring a token.

Architecture / vendor boundaries

  • Add a network-backed "remote DMR directory" source — a sibling to existing import adapters under src/lib/import/, not a CSV file adapter. Mirror the generic "remote repeater directory" pattern introduced for ukrepeater.net (feat: import by callsign or qth from ukrepeater.net #92) so multiple directories can plug in.
  • This is an import-boundary concern only: field mapping (BrandMeister → internal Channel / talk group / RX group list) lives in the new source/adapter. The internal models stay vendor- and radio-neutral — no BrandMeister constants, no caps, no profile assumptions in mutations/validation/CRUD.
  • Snapshot fetched data into the codeplug at add-time. Live shared-library references only matter once feat: shared reference library of channels/TGs/contacts (outside any one codeplug) #30 lands.
  • Internal relationships use UUID id FKs; do not introduce name-based FKs from BrandMeister payloads.

Field mapping (import boundary only) — to be finalised against live API

BrandMeister concept internal target notes
Repeater RX/TX frequencies Channel.rxFrequency / Channel.txFrequency watch repeater-side vs radio-side inversion (see #92)
Colour code Channel.colourCode
Talk groups carried by repeater TalkGroup entities auto-create if missing; dedupe by id
Timeslot per talk group RX group list / channel timeslot mapping
Generated repeater RX list RxGroupList tailored to the looked-up repeater
Repeater metadata (location, keeper, status) display / vendorExtras

Scope / phasing

  1. Channel datasource — look up a repeater and pre-fill a DMR channel (Flow A).
  2. Auto-generate talk groups + repeater RX group list (Flow B).
  3. Validate existing entities against BrandMeister (diff + confirm) (Flow C).
  4. Library target — depends on feat: shared reference library of channels/TGs/contacts (outside any one codeplug) #30.

Open questions

  • Exact v2 endpoints + auth/CORS guarantees for the queries we need (repeaters, talk groups).
  • Identity / dedupe: how to match a BrandMeister repeater & its talk groups to existing local entities (talk-group ids vs names).
  • How much remote metadata to retain (vendorExtras) vs discard.
  • Talk-group catalogue size: do we fetch on demand per repeater, or cache a wider list?
  • Failure / rate-limit UX if the API or its CORS policy changes (no offline fallback in scope).

Relates to

Workflow note

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    data-sourceenhancementNew feature or requestquality-of-lifefeature to improve the QOL of the person making a codeplug

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions