Conversation
There was a problem hiding this comment.
Pull request overview
Adds compile-time-gated Ethernet (RAK13800/W5100S) support to nRF52 example apps to enable TCP-based CLI access and mesh command handling, and extends CI to build the new Ethernet-enabled targets.
Changes:
- Added Ethernet initialization/DHCP + TCP CLI handling to
simple_repeaterandsimple_room_server(behindETH_ENABLED). - Added an nRF52
SerialEthernetInterfaceand wired it intocompanion_radiowhenETH_ENABLEDis set. - Introduced new RAK4631 PlatformIO environments + CI matrix entries for Ethernet-enabled builds.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
variants/rak4631/platformio.ini |
Adds new RAK4631 Ethernet-enabled PlatformIO envs and dependencies. |
variants/rak4631/RAK4631Board.cpp |
Attempts to hook Ethernet init into board bring-up (macro-gated). |
src/helpers/sensors/EnvironmentSensorManager.cpp |
Avoids treating the Ethernet power IO as a GPS-detect pin when Ethernet is enabled on RAK boards. |
src/helpers/nrf52/SerialEthernetInterface.h |
Introduces Ethernet-backed serial interface abstraction for nRF52. |
src/helpers/nrf52/SerialEthernetInterface.cpp |
Implements W5100S init, TCP server/client framing, and DHCP maintenance. |
examples/simple_room_server/main.cpp |
Adds ETH task + TCP CLI parsing/command handling for room server example. |
examples/simple_repeater/main.cpp |
Adds ETH task + TCP CLI parsing/command handling for repeater example. |
examples/companion_radio/main.cpp |
Adds conditional Ethernet serial interface + ETH maintenance in main loop. |
.github/workflows/pr-build-check.yml |
Adds CI builds for the new Ethernet-enabled RAK4631 targets. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
3c57a33 to
12a4f4b
Compare
…mpanion Add W5100S Ethernet adapter support for RAK4631-based firmware, enabling TCP CLI access on port 23 as an alternative to BLE/Serial connections. - New SerialEthernetInterface for nRF52 with DHCP, reconnection handling, and shared WB_IO2 power pin management with GPS module - Ethernet build targets for repeater, room server, and companion firmware - Prevent GPS from toggling WB_IO2 when Ethernet module is active - CI build check for all three ETH firmware targets Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add #pragma once to SerialEthernetInterface.h
- Rename TCP_PORT to ETH_TCP_PORT with #ifndef guard
- Fix typos: "initalizing" → "initializing"
- Fix #elif without condition → #else for STM32 block
- Replace infinite loop on ETH init failure with halt()
- Remove heartbeat Serial.print(".") output
- Remove dead beginETH() call (ETH_ENABLED, not RAK_ETH_ENABLE)
- Comment out MESH_DEBUG and ETH_DEBUG_LOGGING build flags
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Updated to address all the issues in the Copilot feedback. |
liamcottle
left a comment
There was a problem hiding this comment.
Howdy! Thanks for the PR. I've added some comments :)
|
Thanks @liamcottle for the review and the feedback - I've updated the PR to reflect your feedback, I appreciate your time! |
liamcottle
left a comment
There was a problem hiding this comment.
Awesome, thanks for the adjustments. I've gone through again and have some extra comments. Once these are sorted, would be good if you can test it's all working before I ask Scott to do a code review.
docs/cli_commands.md
Outdated
|
|
||
| ### Ethernet (when Ethernet support is compiled in) | ||
|
|
||
| Ethernet support is available on RAK4631 boards with a RAK13800 (W5100S) Ethernet module. Use the `_eth` firmware variants (e.g. `RAK_4631_repeater_eth`) to enable this feature. |
There was a problem hiding this comment.
missed this one ;) _eth -> _ethernet.
There was a problem hiding this comment.
Fixed - also updated the port number in the example output and notes while I was in there.
docs/faq.md
Outdated
|
|
||
| **Firmware:** | ||
| Flash one of the Ethernet-enabled firmware variants: | ||
| - `RAK_4631_repeater_eth` - Repeater with Ethernet CLI access |
There was a problem hiding this comment.
Docs update for new _ethernet suffix
There was a problem hiding this comment.
Fixed - also corrected the port numbers: port 23 for repeater/room server CLI, port 5000 for companion radio.
examples/companion_radio/main.cpp
Outdated
| Serial.println("Initializing Ethernet adapter..."); | ||
| if (!serial_interface.begin()) { | ||
| Serial.println("ETH: Init failed, halting"); | ||
| halt(); |
There was a problem hiding this comment.
I'm wondering if the firmware should still run as normal if ethernet fails to come up? That way remote management over LoRa would still work, and it could be rebooted remotely over the mesh?
Otherwise if firmware was to shutdown due to low voltage, and ethernet failed to come up on reboot, maybe due to still having low power, the unit would be bricked until physically rebooted.
Not sure if this would cause issues reading/writing commands to non initialised ethernet driver...
There was a problem hiding this comment.
Good point - I think we can guard for that issue. I'll see how difficult that would be.
There was a problem hiding this comment.
Good call. Changed to log the failure and continue without the Ethernet interface - the mesh runs normally over LoRa so the unit can be recovered remotely.
examples/simple_repeater/main.cpp
Outdated
|
|
||
| // Format ethernet status into reply buffer. Returns true if command was handled. | ||
| static bool ethernet_handle_command(const char* command, char* reply) { | ||
| if (strcmp(command, "eth") != 0) return false; |
There was a problem hiding this comment.
could we switch the logic, so instead of returning false for a non match for the only command, wrap the status response inside an if block, and return false from ethernet_handle_command by default to indicate it didn't handle it. More so for when you add new commands later, this doesn't need a refactor. e.g:
static bool ethernet_handle_command(const char* command, char* reply) {
if (strcmp(command, "eth.status") == 0) {
if (!ethernet_running) {
strcpy(reply, "not connected");
} else {
IPAddress ip = Ethernet.localIP();
sprintf(reply, "IP: %u.%u.%u.%u:%d", ip[0], ip[1], ip[2], ip[3], ETHERNET_TCP_PORT);
}
return true;
}
// not handled
return false;
}
Maybe we could rename it to eth.status or eth.ip. I'll leave that one up to you.
There was a problem hiding this comment.
Refactored as suggested and went with eth.status.
examples/simple_repeater/main.cpp
Outdated
|
|
||
| // Check for new TCP client connections | ||
| static void ethernet_check_client() { | ||
| if (ethernet_client && ethernet_client.connected()) return; |
There was a problem hiding this comment.
I think this check would prevent new clients from being able to connect until the existing client disconnects. The WiFi firmware allows new connections to kick off old connections. We should allow the same here.
There was a problem hiding this comment.
Fixed - removed the early return guard so server.available() is always called. New connections now replace existing ones.
examples/simple_room_server/main.cpp
Outdated
| } | ||
|
|
||
| static void ethernet_check_client() { | ||
| if (ethernet_client && ethernet_client.connected()) return; |
There was a problem hiding this comment.
same comments as repeater feedback about return preventing new clients connecting
| the_mesh.handleCommand(0, command, reply); // NOTE: there is no sender_timestamp via serial! | ||
| #endif | ||
| if (reply[0]) { | ||
| Serial.print(" -> "); Serial.println(reply); |
There was a problem hiding this comment.
I was originally wondering if the reply is meant to be going back out of the ethernet_interface instead of the Serial, but noted further down the reply is sent out as expected. I guess this just means the reply is sent out on main serial and on ethernet. Not sure if that's an issue.
There was a problem hiding this comment.
The channels are already separate - serial commands reply only to Serial, ethernet commands reply only to ethernet_client. No change needed.
examples/simple_room_server/main.cpp
Outdated
| if (reply[0]) { | ||
| ethernet_client.print(" -> "); ethernet_client.println(reply); | ||
| } | ||
| ethernet_client.print("> "); |
There was a problem hiding this comment.
Same comment as noted on repeater firmware
src/helpers/nrf52/EthernetMac.h
Outdated
|
|
||
| #include <Arduino.h> | ||
|
|
||
| static inline void generateDeviceMac(uint8_t mac[6]) { |
There was a problem hiding this comment.
could maybe rename it so it's clearer? generateEthernetMac? Haven't looked to see what NRF_FICR->DEVICEID does, but I'm assuming we are generating an ethernet mac address, from the existing hardware mac address or device id.
There was a problem hiding this comment.
Renamed to generateEthernetMac. It uses NRF_FICR->DEVICEID (the chip's unique hardware ID) to derive a stable MAC address, with the locally-administered bit set so it's valid for private use without conflicting with real hardware MACs.
| size_t SerialEthernetInterface::checkRecvFrame(uint8_t dest[]) { | ||
| // check if new client connected | ||
| if (client && client.connected()) { | ||
| // Avoid polling for new clients while an active connection exists. |
There was a problem hiding this comment.
we should allow new clients to connect and kick off the old client
There was a problem hiding this comment.
Fixed - removed the guard that skipped server.available() while a connection was active. New connections now replace existing ones.
|
Can this be made to work with W5500-EVB-PICO (Wiznet5500 + RPi Pi Pico RP2040) board because RAK is no the only toy with Ethernet. |
|
This PR comes at the right time! |
Should be possible to extend. I don't have that hardware to test/validate with though. |
- Rename eth command to eth.status for consistency with other commands - Rename generateDeviceMac to generateEthernetMac for clarity - Refactor ethernet_handle_command to return false by default - Allow new TCP clients to replace existing connections (repeater, room server, SerialEthernetInterface) - Boot companion radio without Ethernet on init failure (LoRa-only recovery mode) - Remove > prompt from ethernet CLI for consistency with serial interface - Fix variable redeclaration compile error in SerialEthernetInterface when ETHERNET_STATIC_IP is defined - Fix TCP socket leak when duplicate client detection fires - Remove dead recv_queue and adv_restart_time members from SerialEthernetInterface - Fix port numbers in docs (port 23 for repeater/room server CLI, port 5000 for companion radio) - Clarify eth.status command is only available in repeater and room server firmware Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
I have this board and I am OK to solder/wire LoRA module with board, and do some tests. |
…ate CLI code The Ethernet retry loop in repeater and room server checked hardwareStatus() and linkStatus() before calling Ethernet.begin(), which always returned EthernetNoHardware since hardware detection only happens during begin(). Extract shared Ethernet CLI code into EthernetCLI.h to prevent future divergence. Also fix time_t type mismatch in companion radio Ethernet init. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
All three Ethernet-enabled firmwares have been tested on RAK4631 hardware with the RAK13800 W5100S Ethernet module and are working as expected:
|
Resolve conflicts: keep both Ethernet CLI and SenseCAP power-off button code in repeater, keep both Ethernet docs and power management CLI docs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@liamcottle - let me know if there is anything else, otherwise I think this is ready to merge. |
|
For what reason Ethernet header sit inside nRF52 helper directory? What if Ethernet need to be added to ESP32 and RP2040 microcontrollers. What a crazy platform dependent b**t! If you want Ethernet support, make it platform independent instead or only board laying on your table! |
This follows the existing pattern of SerialBLEInterface which lives in the esp32 and nrf52 folders. Firmware development is often very hardware specific - if it turns out we can reuse the same code, it'll be easy enough to refactor it accordingly when someone with the hardware can verify it works. There's no need to be rude about it. |
Why not to refactor things correctly as soon as they are developed? Is this future of vibe coding or what? |
This pull request adds Ethernet support to the
companion_radio,simple_repeater, andsimple_room_serverexamples for nRF52-based devices, enabling TCP CLI access and mesh command handling over Ethernet. It also updates the build workflow to include new Ethernet-enabled targets. The main changes are grouped below by theme.Everything is compile-time gated by the ETH_ENABLE flag which is only enabled for a new environment profile for RAK firmware + Ethernet support.
Ethernet support for examples
examples/simple_repeater/main.cppandexamples/simple_room_server/main.cpp, including FreeRTOS task for background handling and unique MAC address generation. [1] [2]Integration and initialization
setup()andloop()functions in all examples to start Ethernet tasks, maintain connections, and handle mesh commands from both serial and Ethernet interfaces. [1] [2] [3] [4] [5] [6] [7] [8] [9]examples/companion_radio/main.cppto support conditional inclusion of Ethernet interface and initialization, including debug output and error handling. [1] [2] [3] [4]Build workflow updates
.github/workflows/pr-build-check.ymlto ensure CI coverage for the new features.These changes collectively enable robust Ethernet-based CLI and mesh communication for nRF52 devices, improving flexibility and connectivity options.