You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The internal Codeplug model is (and must remain) vendor-agnostic — one canonical representation of channels, zones, contacts, and talk groups regardless of which CPS formats we export to.
In practice, operators design a codeplug with specific radios in mind (Baofeng DM-1701, DM-32, UV-5R, …). Each radio/profile imposes different constraints: LCD name length, max channels, zone member slots, feature availability, and how logical channels denormalise into CPS rows (#46 multi-mode shipped; #36 multi-talkgroup imminent).
Today:
Profile limits are enforced (or silently violated) only at export time — see #106 (standardised export validation report).
#86 sketches target-radio hint validation in CRUD but does not cover per-profile display names or the denormalised naming problem.
Operators discover length/capacity issues late, and cannot pre-configure shorter names for radios with tight LCD limits without polluting the canonical channel name.
Intended outcome
Introduce export profiles on the codeplug project wrapper (CodeplugProject) — a structured, machine-readable set of target radios the operator selects when setting up a project. Export profiles drive compatibility hints during editing and profile-aware behaviour at export — without adding vendor fields to Channel, Zone, or other Codeplug entities.
Vendor neutrality is non-negotiable. Export profiles and their overrides live on CodeplugProject (or project-scoped adjunct types). The Codeplug payload stays format-agnostic.
What an export profile enables
For each selected export profile (e.g. opengd77:baofeng-1701, dm32:dm-32uv, chirp:uv-5r):
Capability
Example
Compatibility warnings
Channel name exceeds 16-char LCD limit; project has >1023 channels; zone has >80 members
Per-profile display names
Canonical MB7IDQ Alexandria → MB7IDQ Alex'ria on 1701 only
validateExport(codeplug, { profileIds }) runs against project profiles before download
Hints are warnings by default (non-blocking save) unless a rule is explicitly elevated to error at export boundary — consistent with vendor boundaries.
Up to m×n DMR rows; analogue/FM is always a single row → m×n + 1 at worst when both features enabled
Export profiles must support per-variant overrides keyed by variantKey (design during implementation — e.g. mode:fm, mode:dmr+tgid:235, or a stable denormalisation id from the export layer).
Compatibility warnings for name length must evaluate the effective export name (override if set, else generated denormalised name, else canonical name) per profile.
Export adapters own denormalisation; the profile layer consumes a stable variant enumeration API rather than re-implementing expansion logic in CRUD.
Problem
The internal
Codeplugmodel is (and must remain) vendor-agnostic — one canonical representation of channels, zones, contacts, and talk groups regardless of which CPS formats we export to.In practice, operators design a codeplug with specific radios in mind (Baofeng DM-1701, DM-32, UV-5R, …). Each radio/profile imposes different constraints: LCD name length, max channels, zone member slots, feature availability, and how logical channels denormalise into CPS rows (#46 multi-mode shipped; #36 multi-talkgroup imminent).
Today:
CodeplugProject.targetRadiosis a free-text operator note — explicitly not used for import, export, or validation (codeplug-project docs).Operators discover length/capacity issues late, and cannot pre-configure shorter names for radios with tight LCD limits without polluting the canonical channel name.
Intended outcome
Introduce export profiles on the codeplug project wrapper (
CodeplugProject) — a structured, machine-readable set of target radios the operator selects when setting up a project. Export profiles drive compatibility hints during editing and profile-aware behaviour at export — without adding vendor fields toChannel,Zone, or otherCodeplugentities.What an export profile enables
For each selected export profile (e.g.
opengd77:baofeng-1701,dm32:dm-32uv,chirp:uv-5r):MB7IDQ Alexandria→MB7IDQ Alex'riaon 1701 onlyvalidateExport(codeplug, { profileIds })runs against project profiles before downloadHints are warnings by default (non-blocking save) unless a rule is explicitly elevated to error at export boundary — consistent with vendor boundaries.
Distinction from
targetRadiostargetRadios(existing)string[]free textexportProfiles(new)string[]registry idsDo not overload
targetRadios. Consider UI that links them (suggest profile when operator types a known radio) but keep data separate.Data model — illustrative (
CodeplugProject)Final shape TBD during design; must stay on the project wrapper:
exportProfiles: [],exportNameOverrides: []— current behaviour.Channel.nameremains the project source of truth.Denormalised naming — the m×n problem
Logical channels can expand to multiple CPS rows at export:
Export profiles must support per-variant overrides keyed by
variantKey(design during implementation — e.g.mode:fm,mode:dmr+tgid:235, or a stable denormalisation id from the export layer).Compatibility warnings for name length must evaluate the effective export name (override if set, else generated denormalised name, else canonical name) per profile.
Export adapters own denormalisation; the profile layer consumes a stable variant enumeration API rather than re-implementing expansion logic in CRUD.
Profile registry
Machine-readable constraints mirror reference docs (
docs/reference/opengd77/radios/, CHIRP radios, future DM32):src/lib/exportProfiles/(or extendsrc/lib/radioProfiles/from feat: optional target-radio validation hints in CRUD UI #86) —registry.ts+ per-profile modules{ id, label, formatId, constraints, nameLimits, cardinalityCaps, featureFlags }codeids correlating with #106 export reports and CRUD hintsMVP profiles: Baofeng 1701 (OpenGD77), at least one CHIRP radio; DM32 when #67 ships.
Validation engine
Build on #86 sketch; extend for overrides and denormalised variants:
validateChannelProfileHints(channel, profiles, overrides)validateZoneProfileHints(zone, codeplug, profiles)validateCodeplugProfileHints(codeplug, project)resolveExportDisplayName(channel, profileId, variantKey, overrides)enumerateChannelVariants(channel, profileId)Reuse
ValidationIssue(severity: 'warning') fromsrc/lib/validation/channel.tsfor CRUD hints.UI surfaces
exportProfiles; run #106 validation per profile; allow session overrideStyle: amber compatibility warnings — distinct from save-blocking CRUD errors (#81).
Relationship to other tickets
ExportReportIssue/ pre-export UI; profiles feedvalidateExport({ profileIds })Suggested slice order: profile registry →
exportProfileson project → hint engine (no overrides) → #106 integration → name overrides → multi-mode/TG variant UI.Affected
src/models/codeplugProject.ts+ storage migrationsrc/state/codeplugStore.tsx—updateProject, hint cache invalidationsrc/lib/exportProfiles/(new registry) — or rename/consolidate with feat: optional target-radio validation hints in CRUD UI #86'sradioProfilessrc/lib/validation/profileHints.ts(new)src/lib/export/— denormalisation variant enumeration; apply overrides in serialisersTargetRadiosEditorwith structured profile pickerdocs/features/codeplug-project/,docs/features/import-export/, per-format radio reference docsOut of scope
Channel/Zone/ContactentitiesManual verify
MB7IDQ Alex'ria→ warning clears for 1701; canonical name unchanged.targetRadiosfree-text notes still work independently ofexportProfiles.Workflow note
Large multi-commit epic: branch from
origin/main, atomic conventional commits per slice (registry → project fields → hints → export integration → overrides → variant UI → docs/tests). PR(s) linkingCloses #. Consider progress log underdocs/features/codeplug-project/.