Support for RAK ethernet module#1983
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.
|
|
||
| // 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.
|
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? |
|
Thanks for the review @oltaco! I've updated the PR based on your feedback. |
|
@rgregg Would you consider adding support for redirecting |
| size_t SerialEthernetInterface::checkRecvFrame(uint8_t dest[]) { | ||
| // check if new client connected; new connections replace existing ones | ||
| auto newClient = server.available(); | ||
| if (newClient) { | ||
| IPAddress new_ip = newClient.remoteIP(); | ||
| uint16_t new_port = newClient.remotePort(); | ||
| ETHERNET_DEBUG_PRINTLN( | ||
| "New client available %u.%u.%u.%u:%u", | ||
| new_ip[0], | ||
| new_ip[1], | ||
| new_ip[2], | ||
| new_ip[3], | ||
| new_port); | ||
| if (client && client.connected()) { | ||
| IPAddress cur_ip = client.remoteIP(); | ||
| uint16_t cur_port = client.remotePort(); | ||
| ETHERNET_DEBUG_PRINTLN( | ||
| "Current client %u.%u.%u.%u:%u", | ||
| cur_ip[0], | ||
| cur_ip[1], | ||
| cur_ip[2], | ||
| cur_ip[3], | ||
| cur_port); | ||
| if (cur_ip == new_ip && cur_port == new_port) { | ||
| ETHERNET_DEBUG_PRINTLN("Ignoring duplicate client"); | ||
| newClient.stop(); | ||
| return 0; | ||
| } | ||
| } | ||
|
|
||
| deviceConnected = false; | ||
| if (client) { | ||
| ETHERNET_DEBUG_PRINTLN("Closing previous client"); | ||
| client.stop(); | ||
| } | ||
| _state = RECV_STATE_IDLE; | ||
| _frame_len = 0; | ||
| _rx_len = 0; | ||
| client = newClient; | ||
| ETHERNET_DEBUG_PRINTLN("Switched to new client"); | ||
| } |
There was a problem hiding this comment.
Has this actually been tested with Android/Iphone/Meshcore-CLI for companion?
As a compile and test results in an immediate disconnect after first packet of data sent to the companion and it seems to be because of the code here. This doesn't seem consistant with the RAK examples. As any packet is received newClient will be created, and will point to same exact same socket# as the previous client object already in memory that was created from previous packet, so you hit the code that called newClient.stop(0 which actually wiill close newClient AND client sockets. Which disconnects the companion.
I think I have been able to rework the logic to make it work, as at least my the changes I have made to the logic flow seem to have fixed it. Will try to put a pull request in over on rgregg:rak-ethernet
|
@rgregg As an alternative to MESH_PACKET_LOGGING, add support for the Ethernet module to the KISS firmware? Then we could run pyMC_repeater in a container/VM and have it connect remotely over Ethernet to the LoRa modem. Also, do you have builds of this in its current state available online anywhere? If so, I'd be happy to try testing it on my RAK Ethernet MQTT Gateway kit. Thanks. |
# Conflicts: # examples/companion_radio/main.cpp
EthernetServer::available() returns any socket with data, including the already-connected client's socket. The companion path then called stop() on what it thought was a duplicate client, closing the shared socket and disconnecting the companion after the first packet. Switch both SerialEthernetInterface and EthernetCLI to server.accept(), which only returns newly-accepted sockets. Removes the IP/port duplicate detection in the companion path (no longer reachable) and the same-socket early-return in the CLI path. Reported by mcode6726 on PR meshcore-dev#1983.
|
@mcode6726 — Thanks for catching the companion disconnect, I've mostly tested the repeater firmware which didn't have the same bug. I've adjusted both paths to use @liamcottle — all of your round-2 feedback plus oltaco's nits have been addressed in earlier commits, and this latest fix resolves the companion bug. Ready for another look when you have time. |
|
Whats needed for this to be implemented? I want to use something similar to this but with an esp32-Olimex-POE board so using this as a base would be great, but if it will not be merged than I will continue on looking at a Raspberry Pi + normal MC device combination to put up on the roof. If programming help is needed I am available as well, I however do not own any RAK modules right now. If needed I can acquire some. |
# Conflicts: # docs/faq.md # examples/companion_radio/main.cpp
|
@AcidWizard - I'm not really sure tbh. I've been running this firmware on my own repeater and companion nodes for a while, everything has been working great for me. I'd love to get this merged, it seems like there is sufficient interest in supporting it, but I haven't from the maintainers in several months. |
|
So I've tested a bit with the repeater firmware, on a RAK4631microcontroller paired with a RAK 13800 Ethernet module. Everything seems to be working fine for now using DHCP, commands work the same way the CLI does. It might be useful to later store network configuration in node memory instead of relying on values set at compile time when using a static IP, to avoid having to reflash everything if that config has to change afterwards. |
|
@liamcottle — another nudge on this when you have time. Since your last review, all of your round-2 feedback is in (the I've also merged up to current Your CHANGES_REQUESTED is the only thing holding up the review decision at this point. Happy to fix anything else you spot, but I think it's ready for another look. |
|
@ripplebiz I am hoping to get your read on this one when you have a moment -- or any other maintainer. Quick status: all of @liamcottle's review feedback from the earlier rounds is in (the The main reason I'm tagging you: there are now two overlapping Ethernet PRs on the bench and I'd like a steer on which one you'd prefer to take forward so we're not duplicating effort:
I'm happy to go whichever direction makes the most sense to you, either get this merged as the foundation and coordinate #2679 on top, consolidate into one, or adjust scope. Just let me know your preference and I'll run with it. Thanks! |
|
@rgregg thanks for teeing this up so clearly. From my side I'm fully on board with your suggested direction: land #1983 as the Ethernet foundation, and I'll rebase the PoE-specific parts of #2679 on top of it. The PoE handling (W5100S power/reset sequencing, no-sleep, boot-voltage bypass, deferred bring-up) is largely transport-independent, so it should port cleanly onto your base — and it would apply to the repeater/room-server variants too, not just the companion. Happy to coordinate whenever #1983 merges. @ripplebiz — a steer here would be much appreciated. |
ripplebiz
left a comment
There was a problem hiding this comment.
Happy to merge, if you can attend to merge conflicts.
# Conflicts: # examples/companion_radio/main.cpp
|
Thanks @ripplebiz - I've pushed a fix for the merge conflict and validated the PR functions as expected. |
…sport - New WITH_ESP32_ETHERNET transport option for companion_radio (ESP32 / arduino core 3.x): brings up ETH.h W5500-over-SPI and reuses SerialWifiInterface, since WiFiServer/WiFiClient are NetworkServer/ NetworkClient aliases there. DHCP by default, optional ETH_STATIC_* build flags. Distinct from the nRF52 ETHERNET_ENABLED flag (PR #1983), which selects the RAK13800 SerialEthernetInterface implementation. - New variant waveshare_esp32s3_eth: Waveshare ESP32-S3-ETH board (W5500 on GPIO 9-14, PoE power option) + external Core1262 SX1262 module, RXEN-style RF switch per waveshare_rp2040_lora (SX126X_DIO2_AS_RF_SWITCH + SX126X_RXEN). Uses pioarduino platform like esp32c6_base. Envs: companion_radio_eth, repeater, room_server. Hardware-tested: DHCP + companion protocol over TCP.
meshcore-dev#1983 landed a generic RAK4631 Ethernet base (repeater/room_server/companion envs, single-client SerialEthernetInterface, EthernetCLI telnet CLI) and independently added the same WB_IO2 rail-power fix we found for PoE boot. Layer the remaining PoE-specific delta on top of it instead of duplicating: - W5100SPoE: drop the now-redundant WB_IO2 early-ctor code (covered by meshcore-dev#1983's own constructor), keep only the early W5100S RST release and the bit-bang activation/VERSIONR check. - SerialEthernetInterface: add PoE-safe deferred bring-up (Ethernet.init/ begin() moved out of begin() into loop(), gated by an _hwReady flag, so the disruptive PHY soft-reset + DHCP can't collapse the marginal PoE supply at cold start) and bounded DHCP with a static-IP fallback. - EthernetCLI: same deferral (vTaskDelay before hardware bring-up) and bounded DHCP + static fallback for the repeater/room_server telnet path. - platformio.ini: add RAK_4631_{repeater,room_server,companion_radio} _ethernet_poe envs extending meshcore-dev#1983's _ethernet envs with WITH_W5100S_POE. Verified: all three new _poe envs build, plus the plain _ethernet envs and non-Ethernet variants (no cross-variant breakage). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The commented-out debug flag still referenced meshcore-dev#1983's original macro name (ETHERNET_DEBUG_LOGGING). SerialEthernetInterface.h now checks ETH_DEBUG_LOGGING after the merge with our multi-client/PoE-deferred implementation, so the comment was stale and enabling it would have done nothing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.