[AZ-396] [AZ-397] Batch 11: C8 source-set switch + QGC telemetry adapter

AZ-396: PymavlinkArdupilotAdapter.request_source_set_switch body sends
MAV_CMD_SET_EKF_SOURCE_SET, awaits COMMAND_ACK with timeout, enforces
Invariant 11 idempotence (1s rate-limit + skip-after-success). Adds
runtime_root.SpoofRecoverySink to bridge C5 spoof-promotion-recovered
signal to the C8 outbound thread via a bounded dispatch queue.
FcConfig gains spoof_recovery_source_set + source_set_switch_timeout_ms.

AZ-397: QgcTelemetryAdapter implements GcsAdapter strategy: MAVLink 2.0
to QGC, emit_summary downsamples 5Hz to configurable summary_rate_hz
[0.5, 5.0] via integer modulo, emit_status_text mirrors to GCS link,
subscribe_operator_commands translates COMMAND_LONG / PARAM_REQUEST_*
/ REQUEST_DATA_STREAM / MISSION_* / SET_MODE into OperatorCommand DTOs
and audits each receipt to FDR. FcKind.GCS_QGC added for PortConfig.

Tests: 25 new (12 AZ-396 + 13 AZ-397); full suite 501 passing, 2 skipped.
Contracts unchanged (additive FcConfig fields, range relaxation on
GcsConfig.summary_rate_hz, additive FcKind enum value).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-11 05:06:56 +03:00
parent 1e0be08e8a
commit 8a9cf88a46
16 changed files with 1608 additions and 12 deletions
+4
View File
@@ -58,6 +58,8 @@ ENV_KEY_MAP: Final[dict[str, tuple[str, str]]] = {
"FC_SIGNING_KEY_SOURCE": ("fc", "signing_key_source"),
"FC_DEV_STATIC_SIGNING_KEY": ("fc", "dev_static_signing_key"),
"FC_SIGNING_FAILURE_THRESHOLD": ("fc", "signing_failure_threshold"),
"FC_SPOOF_RECOVERY_SOURCE_SET": ("fc", "spoof_recovery_source_set"),
"FC_SOURCE_SET_SWITCH_TIMEOUT_MS": ("fc", "source_set_switch_timeout_ms"),
"GCS_ADAPTER": ("gcs", "adapter"),
"GCS_PORT_DEVICE": ("gcs", "port_device"),
"GCS_PORT_BAUD": ("gcs", "port_baud"),
@@ -101,6 +103,8 @@ _FIELD_COERCIONS: Final[dict[str, type]] = {
"signing_key_source": str,
"dev_static_signing_key": str,
"signing_failure_threshold": int,
"spoof_recovery_source_set": int,
"source_set_switch_timeout_ms": int,
"summary_rate_hz": float,
}