Skip to content

Replace QuickESPNow with local library#5624

Open
DedeHai wants to merge 6 commits into
wled:mainfrom
DedeHai:ESPNow_nolib
Open

Replace QuickESPNow with local library#5624
DedeHai wants to merge 6 commits into
wled:mainfrom
DedeHai:ESPNow_nolib

Conversation

@DedeHai
Copy link
Copy Markdown
Collaborator

@DedeHai DedeHai commented May 16, 2026

QuickESPNow is not well suited as it is focused on compatibility rather than speed and resources.

This PR replaces it with local functions directly based on esp API calls.
From my tests it is faster and more light weight:

  • ESP32 shows a saving of ~10k of heap
  • ESP8266 shows a saving of ~1.5k of heap

I tested this with a send and receive function both with large packets and bursts of small packets. While large packets work quite well, small (5 bytes) packets tend to get lost on ESP8266 when sent in bursts longer than 6 packets.
The changes need testing in real applications but bench-top tests are very promising.

Summary by CodeRabbit

  • Refactor

    • Refactored ESP-NOW communication to use an internal implementation instead of an external library dependency.
    • Updated ESP-NOW initialization and packet transmission handling.
  • Chores

    • Removed external ESP-NOW library dependency from project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

Review Change Stack

Walkthrough

This PR migrates WLED from the external QuickESPNow library to an internal WledEspNow abstraction. It adds a new lightweight ESP-NOW driver library with platform-agnostic callbacks and lifecycle management, replaces all QuickESPNow calls, and removes the external dependency from the build configuration.

Changes

ESP-NOW Abstraction Migration

Layer / File(s) Summary
WledEspNow implementation and API
lib/wled_espnow/wled_espnow.h, lib/wled_espnow/wled_espnow.cpp, lib/wled_espnow/library.json
New wled::EspNow class with callback registration, begin(channel, iface) and stop() lifecycle, broadcast-only send() with in-flight throttling, platform-specific send/receive callbacks with RSSI extraction on ESP32/IDF < 5.0, and broadcast detection. Includes library manifest and commented-out alternative abstraction block.
Unified ESPNOW include in wled.h
wled00/wled.h
Remove platform-specific ESPNOW/QuickEspNow includes from ESP8266 and ESP32 conditional blocks; add single unified <wled_espnow.h> include guarded by WLED_DISABLE_ESPNOW. Removes WiFi mode macro mappings from ESP8266 path.
Integration: initialization and notify send paths
wled00/wled.cpp, wled00/udp.cpp
Replace quickEspNow.stop() with espNow.stop() in shutdown sequence; register espNow data callbacks and call espNow.begin() for AP/STA initialization with bandwidth configuration. Replace quickEspNow.send() calls with wled::espNow.send() in UDP notify multi-segment chunking loop.
Remove QuickESPNow from platformio.ini
platformio.ini
Delete blazoncek/QuickESPNow.git#optional-debug entries from both ESP8266 lib_deps sections.

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • willmmiles
  • blazoncek
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.16% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main change: replacing the QuickESPNow external dependency with a local library implementation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Infer (1.2.0)
lib/wled_espnow/wled_espnow.cpp

lib/wled_espnow/wled_espnow.cpp:1:10: fatal error: 'wled.h' file not found
1 | #include "wled.h" // includes wled_espnow.h
| ^~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/20eb5fb6bd5cc171b57c965306857c3a52f5997a-b8fe42dca2d38442/tmp/clang_command_.tmp.a9e47f.txt
++Contents of '/tmp/coderabbit-infer/20eb5fb6bd5cc171b57c965306857c3a52f5997a-b8fe42dca2d38442/tmp/clang_command_.tmp.a9e47f.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRING_SIZE=65535" "-cc1" "-triple"
"x86_64-unknown-linux-gnu" "-emit-obj" "-mrelax-all" "-di

... [truncated 1083 characters] ...

all/lib/clang/18/include"
"-internal-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-fdeprecated-macro" "-ferror-limit" "19" "-fgnuc-version=4.2.1"
"-fskip-odr-check-in-gmf" "-fcxx-exceptions" "-fexceptions"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/b8fe42dca2d38442/file.o" "-x" "c++"
"lib/wled_espnow/wled_espnow.cpp" "-O0" "-fno-builtin" "-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"

wled00/udp.cpp

In file included from wled00/udp.cpp:1:
wled00/wled.h:77:10: fatal error: 'Arduino.h' file not found
77 | #include <Arduino.h>
| ^~~~~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/20eb5fb6bd5cc171b57c965306857c3a52f5997a-c60badf90f24d60b/tmp/clang_command_.tmp.097f90.txt
++Contents of '/tmp/coderabbit-infer/20eb5fb6bd5cc171b57c965306857c3a52f5997a-c60badf90f24d60b/tmp/clang_command_.tmp.097f90.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRING_SIZE=65535" "-cc1" "-triple"
"x86_64-unknown-linux-gnu" "-emit-obj" "-mrelax-all

... [truncated 1060 characters] ...

lugins/clang/install/lib/clang/18/include"
"-internal-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-fdeprecated-macro" "-ferror-limit" "19" "-fgnuc-version=4.2.1"
"-fskip-odr-check-in-gmf" "-fcxx-exceptions" "-fexceptions"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/c60badf90f24d60b/file.o" "-x" "c++"
"wled00/udp.cpp" "-O0" "-fno-builtin" "-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"

wled00/wled.cpp

In file included from wled00/wled.cpp:2:
wled00/wled.h:77:10: fatal error: 'Arduino.h' file not found
77 | #include <Arduino.h>
| ^~~~~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/20eb5fb6bd5cc171b57c965306857c3a52f5997a-81fb86539a4966e6/tmp/clang_command_.tmp.93630a.txt
++Contents of '/tmp/coderabbit-infer/20eb5fb6bd5cc171b57c965306857c3a52f5997a-81fb86539a4966e6/tmp/clang_command_.tmp.93630a.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRING_SIZE=65535" "-cc1" "-triple"
"x86_64-unknown-linux-gnu" "-emit-obj" "-mrelax-al

... [truncated 1063 characters] ...

ugins/clang/install/lib/clang/18/include"
"-internal-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-fdeprecated-macro" "-ferror-limit" "19" "-fgnuc-version=4.2.1"
"-fskip-odr-check-in-gmf" "-fcxx-exceptions" "-fexceptions"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/81fb86539a4966e6/file.o" "-x" "c++"
"wled00/wled.cpp" "-O0" "-fno-builtin" "-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the connectivity Issue regarding protocols, WiFi connection or availability of interfaces label May 16, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
wled00/src/dependencies/espnow_wled/espnow_wled.cpp (1)

230-230: ⚡ Quick win

Use debug macros instead of unconditional Serial.printf.

Line 230 bypasses WLED_DEBUG gating and adds serial I/O in normal builds.

Suggested fix
-  if (err != 0 && isretransmit) Serial.printf("ESP-NOW send failed with error %d, inflight=%d\n", err, (int)espNow._inFlight);
+  if (err != 0 && isretransmit) DEBUG_PRINTF_P(PSTR("ESP-NOW send failed with error %d, inflight=%d\n"), err, (int)espNow._inFlight);
As per coding guidelines: "Use `DEBUG_PRINTF()` / `DEBUG_PRINTLN()` for debug output (compiled out unless `-D WLED_DEBUG`)."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wled00/src/dependencies/espnow_wled/espnow_wled.cpp` at line 230, Replace the
unconditional Serial.printf in espnow_wled.cpp (the ESP-NOW send failure log in
the send callback/handler around the if (err != 0 && isretransmit) check) with
the project debug macro so it is compiled out unless WLED_DEBUG is defined; use
DEBUG_PRINTF (or DEBUG_PRINTLN if preferred) to emit the same formatted message
("ESP-NOW send failed with error %d, inflight=%d\n") and preserve the
(int)espNow._inFlight cast and err variable so the debug output remains
identical but gated by WLED_DEBUG.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wled00/src/dependencies/espnow_wled/espnow_wled.cpp`:
- Around line 221-228: The retry branch that calls esp_now_send(...) when
isretransmit is set does not increment the in-flight counter, causing _inFlight
to go out of sync; update the block that contains the
esp_now_send(const_cast<uint8_t*>(BCAST), const_cast<uint8_t*>(data), len) call
so that after a successful send (check err == ESP_OK) you increment _inFlight,
e.g., modify the retry path around variables _inFlight and isretransmit to
++_inFlight when the send returns success to keep the in-flight counter
accurate.
- Around line 186-190: The ESP8266 branch currently ignores return values from
esp_now_register_recv_cb(_espnowRecvCB),
esp_now_register_send_cb(_espnowSentCB), and
esp_now_add_peer(const_cast<uint8_t*>(BCAST), ESP_NOW_ROLE_COMBO, channel,
nullptr, 0) and sets _running = true unconditionally; change this to check each
call's return code (like the ESP32 path), log or handle failures, avoid setting
_running when any registration/peer-add fails, and return/clean up appropriately
(e.g., deinit or unregister) on error so subsequent send/stop operations behave
consistently.

In `@wled00/src/dependencies/espnow_wled/espnow_wled.h`:
- Around line 7-11: The conditional include for ESP-NOW uses a generic `#else`
which can incorrectly include <esp_now.h> on non-target platforms; update the
guard to explicitly check for the ESP32 architecture by replacing the `#else` with
`#elif` defined(ARDUINO_ARCH_ESP32) so the block reads `#ifdef` ESP8266 / `#elif`
defined(ARDUINO_ARCH_ESP32) / `#endif` and include <espnow.h> for ESP8266 and
<esp_now.h> for ESP32 (references: macros ESP8266, ARDUINO_ARCH_ESP32 and the
include directives <espnow.h> and <esp_now.h>).

---

Nitpick comments:
In `@wled00/src/dependencies/espnow_wled/espnow_wled.cpp`:
- Line 230: Replace the unconditional Serial.printf in espnow_wled.cpp (the
ESP-NOW send failure log in the send callback/handler around the if (err != 0 &&
isretransmit) check) with the project debug macro so it is compiled out unless
WLED_DEBUG is defined; use DEBUG_PRINTF (or DEBUG_PRINTLN if preferred) to emit
the same formatted message ("ESP-NOW send failed with error %d, inflight=%d\n")
and preserve the (int)espNow._inFlight cast and err variable so the debug output
remains identical but gated by WLED_DEBUG.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 09fa15a1-2b61-4741-a209-3454a4ae2277

📥 Commits

Reviewing files that changed from the base of the PR and between d337c8a and 32901fb.

📒 Files selected for processing (6)
  • platformio.ini
  • wled00/src/dependencies/espnow_wled/espnow_wled.cpp
  • wled00/src/dependencies/espnow_wled/espnow_wled.h
  • wled00/udp.cpp
  • wled00/wled.cpp
  • wled00/wled.h
💤 Files with no reviewable changes (1)
  • platformio.ini

Comment thread wled00/src/dependencies/espnow_wled/espnow_wled.cpp Outdated
Comment thread lib/wled_espnow/wled_espnow.cpp
Comment thread lib/wled_espnow/wled_espnow.h
@DedeHai
Copy link
Copy Markdown
Collaborator Author

DedeHai commented Jun 3, 2026

I have some pending changes, the actual bug the rabbit did not even mention...

@DedeHai
Copy link
Copy Markdown
Collaborator Author

DedeHai commented Jun 3, 2026

@willmmiles question about folder and file structure: I put this in src/dependencies but it feels kind of out of place since it is not an external dependency. I could put it in the main code folder but it is cluttered as it is. Any suggestion on a better folder structure to put such "local library" files?

@willmmiles
Copy link
Copy Markdown
Member

@willmmiles question about folder and file structure: I put this in src/dependencies but it feels kind of out of place since it is not an external dependency. I could put it in the main code folder but it is cluttered as it is. Any suggestion on a better folder structure to put such "local library" files?

I absolutely agree that src/dependencies should be reorganized. PlatformIO suggests that local or vendored libraries should be subfolders in lib/. That's probably a good place if you want to make sure it's treated as quasi-independent library, written with a presumption that it could (in theory) be used outside of WLED (even if that never actually happens).

If it was really up to me, though ... I'd pull ESP-NOW support out of the core entirely and move it to usermods/esp_now. ;) The library back-end could naturally live there. It'd be a good test case for finding the places where the module APIs need extension. (Blockers that I know about offhand: settings UI integration, reading cfg root, notify integration -- I think most other call sites already have hooks available.)

@willmmiles
Copy link
Copy Markdown
Member

If you do go with lib/ , I suggest inverting the name (wled-EspNow) and using a namespace of wled::EspNow for the functions and objects. A couple of things have been pointing in favor of a common wled root namespace (doesn't conflict with current class WLED), and I've got wled::Log and wled::Net kicking about in prototype code.

@DedeHai
Copy link
Copy Markdown
Collaborator Author

DedeHai commented Jun 3, 2026

I think making core libraries a usermod puts too much strain on the concept, at least for now.

@willmmiles
Copy link
Copy Markdown
Member

willmmiles commented Jun 3, 2026

I think making core libraries a usermod puts too much strain on the concept, at least for now.

Oh for sure - there are still some key APIs missing. I do think that moving things in to modules instead of #ifdefs and expanding our set of default modules is the best path for the long run, though. I'm really quite excited to see integrations like Hue V2, Matter, and FPP all available through the module API instead of adding to our tangled core.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/wled_espnow/wled_espnow.cpp (2)

47-50: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Synchronize _inFlight updates between EspNow::send() and the ESP-NOW sent callbacks.

_inFlight is declared as volatile int8_t in lib/wled_espnow/wled_espnow.h:60, decremented in _espnowSentCB (lib/wled_espnow/wled_espnow.cpp:48 and :130) and incremented/read in EspNow::send() (lib/wled_espnow/wled_espnow.cpp:219-232). volatile doesn’t make ++/-- atomic, so callback/send interleaving can corrupt the in-flight counter and break the send throttling used by burst ESP-NOW calls in wled00/udp.cpp:168, :178, :185. Use atomic operations or an appropriate synchronization mechanism that is safe with callback context.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/wled_espnow/wled_espnow.cpp` around lines 47 - 50, The _inFlight counter
is updated non-atomically in _espnowSentCB and in EspNow::send(), risking races;
change espNow._inFlight from volatile int8_t to an atomic type (e.g.,
std::atomic<int8_t> or std::atomic<int>) and replace ++/-- and reads with atomic
operations (fetch_add/fetch_sub/load) using an appropriate memory_order (relaxed
is fine for a simple counter) so updates from the ESP-NOW callback
(_espnowSentCB) and EspNow::send() are synchronized and safe in the callback
context; ensure all sites that increment, decrement or check _inFlight
(including _espnowSentCB, EspNow::send(), and any other reads) use the new
atomic API.

183-193: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix ESP8266 ESP-NOW init to fail cleanly when peer/callback setup fails
In lib/wled_espnow/wled_espnow.cpp’s ESP8266 EspNow::begin() branch, return values from esp_now_set_self_role, esp_now_register_recv_cb, esp_now_register_send_cb, and esp_now_add_peer are ignored, but _running is set to true and the function returns true unconditionally. That lets wled00/wled.cpp set statusESPNow = ESP_NOW_STATE_ON, and wled00/udp.cpp begin sending ESPNOW sync packets via wled::espNow.send() even if the peer/callbacks were never installed.
Mirror the ESP32 path: check each step’s return code, unwind (esp_now_unregister_* / esp_now_deinit / peer removal as appropriate), leave _running unset, and return false on any failure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/wled_espnow/wled_espnow.cpp` around lines 183 - 193, In EspNow::begin()
for the ESP8266 branch, check the return values of esp_now_set_self_role,
esp_now_register_recv_cb, esp_now_register_send_cb and esp_now_add_peer (the
calls that currently ignore errors) and if any fail, undo any previously
successful setup (call esp_now_del_peer for the broadcast peer if added,
esp_now_unregister_recv_cb and esp_now_unregister_send_cb if registered, and
esp_now_deinit) leave _running false and return false; only set _running = true
and return true after all steps succeed. Use the existing callback symbols
(_espnowRecvCB, _espnowSentCB) and mirror the error/unwind pattern used in the
ESP32 path to ensure partial initialization is rolled back cleanly.
🧹 Nitpick comments (1)
lib/wled_espnow/wled_espnow.h (1)

66-123: ⚡ Quick win

Delete the commented-out EspNowBroadcast API until it's real.

This block is disabled, duplicated again in lib/wled_espnow/wled_espnow.cpp, and explicitly labeled unreviewed/untested. Keeping a dormant public API in the header adds noise to the migration and makes it easier to accidentally revive code that has never been validated. Please either remove it from this PR or move the porting notes to an issue/ADR. As per coding guidelines, "Remove dead/unused code — justify or delete it" and "Mark AI-generated code blocks with // AI: below section was generated by an AI and // AI: end comments."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/wled_espnow/wled_espnow.h` around lines 66 - 123, Remove the entire
commented-out EspNowBroadcast API block (the multi-line comment that defines
class EspNowBroadcast and its methods) and the commented extern for
espnowBroadcast so no dormant, duplicate, AI-generated API remains; if you need
to preserve the migration notes, move them to an issue/ADR or add explicit AI
markers (// AI: ... // AI: end) in a non-compiling doc instead of leaving the
code commented in the header.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@lib/wled_espnow/wled_espnow.cpp`:
- Around line 47-50: The _inFlight counter is updated non-atomically in
_espnowSentCB and in EspNow::send(), risking races; change espNow._inFlight from
volatile int8_t to an atomic type (e.g., std::atomic<int8_t> or
std::atomic<int>) and replace ++/-- and reads with atomic operations
(fetch_add/fetch_sub/load) using an appropriate memory_order (relaxed is fine
for a simple counter) so updates from the ESP-NOW callback (_espnowSentCB) and
EspNow::send() are synchronized and safe in the callback context; ensure all
sites that increment, decrement or check _inFlight (including _espnowSentCB,
EspNow::send(), and any other reads) use the new atomic API.
- Around line 183-193: In EspNow::begin() for the ESP8266 branch, check the
return values of esp_now_set_self_role, esp_now_register_recv_cb,
esp_now_register_send_cb and esp_now_add_peer (the calls that currently ignore
errors) and if any fail, undo any previously successful setup (call
esp_now_del_peer for the broadcast peer if added, esp_now_unregister_recv_cb and
esp_now_unregister_send_cb if registered, and esp_now_deinit) leave _running
false and return false; only set _running = true and return true after all steps
succeed. Use the existing callback symbols (_espnowRecvCB, _espnowSentCB) and
mirror the error/unwind pattern used in the ESP32 path to ensure partial
initialization is rolled back cleanly.

---

Nitpick comments:
In `@lib/wled_espnow/wled_espnow.h`:
- Around line 66-123: Remove the entire commented-out EspNowBroadcast API block
(the multi-line comment that defines class EspNowBroadcast and its methods) and
the commented extern for espnowBroadcast so no dormant, duplicate, AI-generated
API remains; if you need to preserve the migration notes, move them to an
issue/ADR or add explicit AI markers (// AI: ... // AI: end) in a non-compiling
doc instead of leaving the code commented in the header.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 502c10e9-3cf6-4d1b-808e-cb1be401b667

📥 Commits

Reviewing files that changed from the base of the PR and between 51ce7cc and 20eb5fb.

📒 Files selected for processing (6)
  • lib/wled_espnow/library.json
  • lib/wled_espnow/wled_espnow.cpp
  • lib/wled_espnow/wled_espnow.h
  • wled00/udp.cpp
  • wled00/wled.cpp
  • wled00/wled.h
✅ Files skipped from review due to trivial changes (1)
  • lib/wled_espnow/library.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • wled00/wled.cpp
  • wled00/wled.h
  • wled00/udp.cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Awaiting testing connectivity Issue regarding protocols, WiFi connection or availability of interfaces enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants