feat(companion): echo injected TX to companion clients as raw RX (0x88)

Push locally-injected TX packets to connected companion frame server
clients as PUSH_CODE_LOG_RX_DATA (0x88) with snr=0/rssi=0, so apps that
decrypt locally from raw RX (e.g. RemoteTerm) see companion-originated
channel traffic. The originating companion is excluded so a node never
hears its own transmission, matching physical firmware behavior.
inject_packet now takes an origin_hash (threaded per-companion via the
packet_injector partial); _on_raw_rx_for_companions gains exclude_hash
to skip that companion's frame server. OTA RX is unaffected.
This commit is contained in:
agessaman
2026-06-01 17:05:38 -07:00
parent ee92f5b1a9
commit e24cdca055
4 changed files with 120 additions and 4 deletions
+9
View File
@@ -143,6 +143,15 @@ async def test_raw_rx_and_duplicate_logging_hooks():
await daemon._on_raw_rx_for_companions(b"abc", rssi=-90, snr=2.0)
fs_ok.push_rx_raw.assert_called_once()
# exclude_hash skips the matching companion's own frame server (no self-echo)
fs_self = SimpleNamespace(companion_hash="0x1a", push_rx_raw=MagicMock())
fs_other = SimpleNamespace(companion_hash="0x2b", push_rx_raw=MagicMock())
daemon.companion_frame_servers = [fs_self, fs_other]
await daemon._on_raw_rx_for_companions(b"xyz", rssi=0, snr=0.0, exclude_hash="0x1a")
fs_self.push_rx_raw.assert_not_called()
fs_other.push_rx_raw.assert_called_once()
daemon.companion_frame_servers = [fs_ok, fs_fail]
engine = SimpleNamespace(
is_duplicate=MagicMock(side_effect=[False, True]),
record_duplicate=MagicMock(),