Project Supporting Reasoning Notes
This section explains the key design decisions embedded in this architecture. These notes provide the "why" behind the scope boundaries, tier separation, and responsibility assignments.
1. Why Source Selection Comes Before Decode and Binding
1.1 Problem statement
Telemetry arrives as binary frames at the node. The central server and frontend both need decoded parameter values. The question is: where should source selection happen, where should decoding happen, and where should UI binding (mapping parameters to dashboard widgets) happen?
1.2 Design decision
Source selection happens first. The central server chooses the preferred source stream before any expensive decode work. Nodes do not know which stream the central server will prefer; they simply publish the outputs they are configured to emit. The preferred stream can then be decoded centrally, or the node can emit typed telemetry when a deployment explicitly opts into edge decoding.
UI binding happens on the central server and frontend. The central server maintains a registry of which node payload types map to which UI parameters. The frontend subscribes to decoded telemetry and renders it using that binding map.
1.3 Reasoning
-
Node as transport appliance: The node is RF hardware + acquisition code. It should not know about mission context or UI. Keeping the node responsible for bitwise decoding (knowing field offsets, types, scales) is reasonable; asking it to know UI binding rules violates this principle.
-
Central owns mission context: The central server knows which rocket is flying, which targets are active, and what UI representation is expected. It's the right place to maintain binding rules and to choose which source stream is preferred for operator display.
-
Multiple targets: In multi-target or multi-emitter scenarios, the same telemetry frame type might decode to multiple mission contexts. The central server can apply different binding rules per target. The node has no visibility into that.
-
Transport and compute efficiency: The node is already demodulating and inspecting the stream locally. The cheapest path is to keep candidate streams lightweight until central picks the best source, then decode only the winning stream. That avoids wasting decode work on discarded candidates and avoids pushing typed telemetry across every antenna when only one source will be displayed.
-
Flexibility: If binding rules change (e.g., a new dashboard layout), the central server can update them without redeploying node code or restarting DSP processes.
1.4 Consequence
- Node API includes optional
predecode_enabledflag andfield_schema[]array - Central server maintains binding registry:
(target_id, payload_type_id, parameter_path) → UI_parameter_id - Frontend receives decoded telemetry with
target_idfrom the stream selected by the central server and applies binding rules from central
Practical note: best-source selection happens at the stream-routing layer. Candidate streams stay raw or lightly annotated until central promotes one. Edge pre-decode is only used when a deployment wants the node to emit typed telemetry for its configured payloads.
2. Why Per-Target Parameter Binding
2.1 Problem statement
A single payload type (e.g., flight computer telemetry) can be received from multiple targets or emitters. The central server and frontend both need to display decoded parameters per target independently.
2.2 Design decision
Binding keys include target_id: (target_id, payload_type_id, parameter_path).
The binding resolution follows a fallback hierarchy:
- Exact target binding: If a binding exists for this specific target and payload, use it
- Payload-type default binding: If not, use the default binding for the payload type (applies to all targets)
- Global mission default binding: If not, use a global binding rule
2.3 Reasoning
-
Homogeneous payload types, diverse targets: A rocket telemetry frame type is standardized. But on a given launch, multiple vehicles (e.g., rocket + chase plane) might downlink the same format. Each target deserves independent display.
-
Fallback robustness: If a specific target binding is not defined, the system gracefully falls back to a default. Telemetry is never dropped just because a binding is missing.
-
Operational flexibility: Mission planners can stage per-target overrides without redefining the entire binding map.
2.4 Consequence
- Frontend renders each parameter value in a target-aware context (e.g., "Target Alpha: altitude 5000 m", "Target Beta: altitude 3500 m")
- Central server can stage target-specific overrides before launch
- If a binding is not found, frontend displays raw telemetry in an unbound inspector
3. Why Control-Plane and Data-Plane Separation
3.1 Problem statement
The antenna node sends multiple types of information to central: commands that need routing and acknowledgment, and a high-rate telemetry stream that can tolerate some loss. Mixing these on one transport is inefficient and couples latency requirements.
3.2 Design decision
- Control plane: Low-rate, reliable, point-to-point command and status (HTTPS, gRPC)
- Data plane: High-rate, continuous, fan-out telemetry and metrics (WebSocket, UDP multicast, ZeroMQ)
3.3 Reasoning
-
Different latency budgets: Commands need acknowledgment but don't need to be real-time (100 ms acceptable). Telemetry needs to stream continuously but can tolerate packet loss because frames repeat.
-
Scalability: Many clients can subscribe to multicast telemetry without overloading the node. Control commands remain point-to-point (one command at a time, routed to the right handler).
-
Implementation simplicity: Real-time demands of high-rate telemetry don't constrain command-path design. Command handlers can do validation, logging, auditing without blocking the data stream.
-
Resilience: If central loses telemetry for a few seconds (network hiccup), operators see a gap but can replay. If central loses a command, it retries. The two concerns are decoupled.
3.4 Consequence
- Node API (
/radio/config, etc.) is HTTP(S) based - Node telemetry output (port 9002, WebSocket) is separate
- Central server runs at least two service boundaries: API and stream gateway
Next: See Project Gaps & Deferred Decisions for unresolved architecture decisions that need formal ADRs.
Project Deployment, Risks, and Next Steps
MVP scope, deployment risks, and recommended mitigations for the project.
Project Architecture Gaps and Deferred Decisions
This section identifies architectural decisions that are currently **proposed** but not yet formally decided. Each item requires a formal ADR to move from "proposed" to "accepted" status.