Skip to content

New channel management#5

Open
peterus wants to merge 3 commits intomainfrom
new_channel_management
Open

New channel management#5
peterus wants to merge 3 commits intomainfrom
new_channel_management

Conversation

@peterus
Copy link
Owner

@peterus peterus commented Mar 11, 2026

This pull request introduces a new, platform-agnostic channel scanning and discovery system for OpenDriveHub, refactoring how WiFi channel selection and device discovery are handled. It removes the manual WiFi channel setting from the transmitter UI, adds a new odh-channel library with channel scanning logic, and updates the protocol to support a multi-stage discovery process using new packet types. Several legacy protocol elements and compatibility aliases are removed, and related code is modernized.

The most important changes are:

Channel Scanning and Discovery System:

  • Added a new odh-channel library (Channel.h, ChannelScanner.h, ChannelScanner.cpp, library.json) that provides shared constants, candidate channel definitions (1, 6, 11), timing parameters, and a platform-agnostic ChannelScanner class for transmitter/receiver discovery and channel selection. ([[1]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-4d044102101f7bcae9988c7926f5e383c8df230b15c09b54a9cf25953c0e579aR1-R83), [[2]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-87e89b5d7e9a172318336e06695a6455dfb6fef47ad9ab934034f06117ea86d1R1-R81), [[3]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-bd318187cc43f37ed6cb6e826df2222b7b86ab04dddc3bbbf7de1da113c28b94R1-R97), [[4]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-d7e22310954fae837fdf86fbf5dec4f1e87f34a2d9c1a625b506232acb751e2bR1-R8))
  • Introduced new packet types and structures in the protocol (Protocol.h) for multi-stage discovery: DiscoveryRequestPacket, DiscoveryResponsePacket, ReceiverPresencePacket, and ChannelMigrationPacket, along with the DeviceRole enum and DiscoveredVehicle struct. ([[1]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-dbfff5ce784513a67041f5bdafe276424efe6c57d85b486335d72644bda6f7aaL71-R82), [[2]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-dbfff5ce784513a67041f5bdafe276424efe6c57d85b486335d72644bda6f7aaL161-R225), [[3]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-dbfff5ce784513a67041f5bdafe276424efe6c57d85b486335d72644bda6f7aaL225-R282))

UI and Config Changes:

  • Removed the manual WiFi channel selection UI and related logic from the transmitter web interface (index.html), reflecting the move to automatic channel scanning. ([[1]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-7c3f8d0303a54bf02cabad27c470dabf8c88a3b94936e764c1ca220fea90dccaL186-L189), [[2]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-7c3f8d0303a54bf02cabad27c470dabf8c88a3b94936e764c1ca220fea90dccaL269), [[3]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-7c3f8d0303a54bf02cabad27c470dabf8c88a3b94936e764c1ca220fea90dccaL348))
  • Removed the now-obsolete kRadioWifiChannel constant from Config.h. ([firmware/lib/odh-config/Config.hL41-L43](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-cd8a6e33d63cb9695e45ebe20ed0d4a3bd286414b7e42c59fc7f114c781463d0L41-L43))

Protocol and Legacy Cleanup:

  • Removed deprecated packet types (Announce, Ack) and legacy compatibility aliases from the protocol header, as well as the corresponding AnnouncePacket structure. ([[1]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-dbfff5ce784513a67041f5bdafe276424efe6c57d85b486335d72644bda6f7aaL71-R82), [[2]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-dbfff5ce784513a67041f5bdafe276424efe6c57d85b486335d72644bda6f7aaL161-R225), [[3]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-dbfff5ce784513a67041f5bdafe276424efe6c57d85b486335d72644bda6f7aaL225-R282))
  • Updated function map utilities to use the new FunctionMapEntry type and modernized return values. ([[1]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-a4305670a786cc8b4ae5d3049e79cafe85d80e17ca7326b26b905c19e7593babL262-R268), [[2]](https://github.com/peterus/OpenDriveHub/pull/5/files#diff-a4305670a786cc8b4ae5d3049e79cafe85d80e17ca7326b26b905c19e7593babL277-R283))

These changes lay the groundwork for robust, automatic channel selection and device discovery, simplifying the user experience and improving system reliability.

peterus added 3 commits March 11, 2026 21:07
…ation

- Added WiFi channel management to the WiFi class, allowing retrieval of the current channel.
- Updated esp_now.h to define functions for setting and getting the WiFi channel.
- Modified sim_espnow.cpp to bind UDP sockets to channels dynamically based on the current WiFi channel.
- Enhanced ReceiverApp and TransmitterApp to support channel discovery and migration, including callbacks for channel changes.
- Implemented channel scanning logic to find active transmitters and manage channel acquisition.
- Added unit tests for channel validation, discovery packet construction, and ChannelScanner functionality.
- Updated API endpoints to reflect changes in channel management.
… and clarity

- Updated NVS store initialization in ReceiverApi to use a more generic namespace.
- Modified TransmitterShellCommands to enhance command help descriptions and add new commands for input and rescan functionalities.
- Changed command syntax from "list" to "get" for channel and trim commands to align with new command structure.
- Added new tests for config help, config reset, and model setting to ensure proper command functionality.
- Implemented additional tests for mapping and failsafe commands to verify expected behavior.
- Enhanced help command tests to include new commands and ensure comprehensive coverage.
Copilot AI review requested due to automatic review settings March 11, 2026 22:14
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Die PR erweitert OpenDriveHub um eine kanalbasierte Discovery-/Presence-Logik (WiFi 1/6/11) inkl. neuer Protokollpakete und Scanner-Abstraktion, integriert das in TX/RX Apps & Shell, und passt Simulator sowie Tests auf das neue Modell an.

Changes:

  • Neues Channel-Modul (odh-channel) mit gemeinsamen Konstanten und ChannelScanner für TX/RX.
  • Protokoll-Erweiterung um Discovery/Presence/Migration-Pakete sowie Umstellung von “Announce” → “ReceiverPresence”.
  • Simulator- und Console-/Native-Tests auf neue Kommandos/Discovery-Mechanik umgestellt.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
firmware/test/test_native/test_protocol.cpp Aktualisiert Packet-Tests (ReceiverPresence) und registriert neue Channel/Discovery-Tests im Test-Runner.
firmware/test/test_native/test_channel.cpp Neue Native-Unit-Tests für Channel-Konstanten, Packetgrößen/Checksums und ChannelScanner.
firmware/test/test_console/test_help.py Erweitert Help-Assertions um neue/umbenannte Commands (mapping/failsafe/input/rescan/reboot).
firmware/test/test_console/test_commands_tx.py Passt TX-Console-Tests an neue Subcommands an (trim get, module list, input, rescan, bind help).
firmware/test/test_console/test_commands_rx.py Ergänzt RX-Console-Tests für mapping/failsafe sowie config set vehicle.
firmware/test/test_console/test_commands_common.py Stellt channel listchannel get um und ergänzt Tests für config help/reset und Validierung.
firmware/src/transmitter/web/TransmitterApi.cpp Entfernt radio_channel aus der TX-Web-Config API.
firmware/src/transmitter/TransmitterApp.h Fügt Channel-Discovery State/Methoden und rescan() API hinzu.
firmware/src/transmitter/TransmitterApp.cpp Implementiert Channel-Acquisition, NVS-Persistenz für radio_ch und Rescan-Flow.
firmware/src/transmitter/shell/TransmitterShellCommands.cpp Shell: neue Commands/Help/Reset; Umstellung auf get/list-Semantik; config help/reset/model; rescan/reboot.
firmware/src/receiver/web/ReceiverApi.cpp Umstellung auf Presence-Status (isPresencing) und NVS-Namespace odh.
firmware/src/receiver/shell/ReceiverShellCommands.cpp RX Shell erweitert: config help/reset/model/vehicle, mapping, failsafe, reboot; channel get.
firmware/src/receiver/ReceiverApp.h Ergänzt Channel-Discovery State + Migration/Loss-Handling Methoden.
firmware/src/receiver/ReceiverApp.cpp Implementiert Channel-Discovery, Presence-Tick, Transmitter-Loss-Redisccovery und ChannelMigration Handling.
firmware/sim/src/sim_espnow.cpp Simulator: Mapping Channel → UDP Port, Self-Packet Filter, Channel-Switching via Socket-Rebind.
firmware/sim/sim_build.py Fügt Include-Pfad für neue Shared-Lib odh-channel für Shim-Quellen hinzu.
firmware/sim/include/WiFi.h Ergänzt WiFi.channel() via sim_get_wifi_channel().
firmware/sim/include/esp_now.h Entfernt TX/RX-Portmodell; deklariert sim_get/set_wifi_channel().
firmware/lib/odh-radio/TransmitterRadioLink.h RadioLink API erweitert: setChannel, DiscoveryRequest/Response, Migration, Callbacks.
firmware/lib/odh-radio/TransmitterRadioLink.cpp Implementiert Channel-Switching (sim/esp_wifi), Discovery- und Migration-Pakete sowie Presence-Handling.
firmware/lib/odh-radio/ReceiverRadioLink.h ReceiverLink API: setChannel, Presence-Modus, Discovery/Response/Migration Callbacks.
firmware/lib/odh-radio/ReceiverRadioLink.cpp Implementiert Presence, DiscoveryRequest, DiscoveryResponse-/Migration-Handling und Channel-Switching.
firmware/lib/odh-radio/IRadioLink.h Neue Callback-Typen für DiscoveryResponse/Request und ChannelMigration.
firmware/lib/odh-protocol/Protocol.h Neue PacketTypes + Packet-Structs (Discovery*, ReceiverPresence, ChannelMigration) und neue DiscoveredVehicle-Definition.
firmware/lib/odh-protocol/FunctionMap.h Passt Legacy-Wrapper-Signaturen an neuen FunctionMapEntry Typ an.
firmware/lib/odh-config/Config.h Entfernt fest verdrahteten Default-WLAN-Kanal und Announce-Intervall zugunsten Channel-Modul.
firmware/lib/odh-channel/library.json Neues PIO-Lib-Metadatenfile für odh-channel.
firmware/lib/odh-channel/ChannelScanner.h Neuer plattformagnostischer Scanner (Callbacks für setChannel/sendDiscovery/delay).
firmware/lib/odh-channel/ChannelScanner.cpp Implementierung Scan/BestChannel/Response-Latching.
firmware/lib/odh-channel/Channel.h Zentrale Channel-Konstanten, Timing und Sim-Port-Mapping.
firmware/data/transmitter/index.html Entfernt Radio-Channel UI und zugehörige Config-POST/GET Felder.

Comment on lines +231 to +237
void ReceiverApp::runChannelDiscovery() {
// Wire up the ChannelScanner callbacks to our radio layer
ChannelScanner scanner([this](uint8_t ch) -> bool { return _radio.setChannel(ch); }, [this](uint8_t /*ch*/) -> bool { return _radio.sendDiscoveryRequest(); }, [](uint32_t ms) { delay(ms); });

// Forward DiscoveryResponse to the scanner
_radio.onDiscoveryResponse([&scanner](uint8_t ch, int8_t rssi, uint8_t devCount) { scanner.onDiscoveryResponse(ch, rssi, devCount); });

Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In runChannelDiscovery() wird ein onDiscoveryResponse-Callback registriert, das eine Referenz auf den Stack-ChannelScanner scanner capturt. Diese Registrierung bleibt nach Rückkehr aus der Funktion bestehen (z.B. wenn checkTransmitterLoss() später erneut runChannelDiscovery() aufruft), wodurch eingehende DiscoveryResponse später einen Dangling-Reference/UAF auslösen können. Lösung: nach dem Scan den Callback wieder auf einen langlebigen Handler zurücksetzen (z.B. wieder auf den "activity tracking"-Lambda), oder den Scanner als Member halten bzw. einen RAII-Guard nutzen, der den alten Callback am Ende wiederherstellt.

Copilot uses AI. Check for mistakes.
Comment on lines +66 to 90
static void rebindSocket() {
if (s_sock >= 0) {
close(s_sock);
s_sock = -1;
}
return nullptr;
}

/* ── ESP-NOW API ────────────────────────────────────────────────────────── */

int esp_now_init() {
/* Create a UDP socket bound to the listen port. */
s_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (s_sock < 0) {
perror("[SIM] socket");
return ESP_FAIL;
return;
}

int opt = 1;
setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
setsockopt(s_sock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));

uint16_t port = odh::channel::channelToSimPort(s_currentChannel);

struct sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(SIM_LISTEN_PORT);
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

if (bind(s_sock, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) < 0) {
perror("[SIM] bind");
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Die Simulation bindet alle Geräte eines Kanals auf denselben UDP-Port (SO_REUSEPORT) und sendet unicast an 127.0.0.1:port. Bei mehreren Prozessen/Sockets auf demselben Port werden UDP-Datagramme typischerweise nur an EINEN Empfänger verteilt (hash/load-balancing), nicht an alle – damit können Pakete beim falschen Prozess landen und dann durch den Self-MAC-Filter verworfen werden (flaky/defekte Sim-Kommunikation). Zudem wird in sim_set_wifi_channel() während recvLoop läuft der Socket geschlossen/neu gebunden, ohne Synchronisation. Bitte auf ein echtes Broadcast/Multicast pro Kanal umstellen (z.B. UDP multicast group je Kanal) oder ein explizites Fan-out/Relay implementieren; und Channel-Switching so gestalten, dass der recv-Thread sauber gestoppt/neu gestartet oder der FD thread-safe getauscht wird.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants