Skip to content

add support for up to 10 ESPNow remotes #4654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

DedeHai
Copy link
Collaborator

@DedeHai DedeHai commented Apr 22, 2025

  • upgraded ESPNow remotes to a vector array
  • changed config to support arrays
  • updated wifi settings page to:
    • display the list of linked remotes
    • add last seen remote to the list
    • limit to 10 remotes max
    • send out the list of remots as "RM0" to "RM9"

Since I have very little knowledge on HTML and java script I did the UI update with a lot of help from AI's.
Please check the code for any mistakes or possible improvements. I tested it and it does work but I really do not know if there is better ways to do the java part.

image

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added support for managing multiple ESP-NOW remote MAC addresses in the WiFi settings, replacing the previous single-remote limitation.
    • Introduced a new user interface for adding, removing, and listing up to 10 ESP-NOW remotes directly from the settings page.
  • Bug Fixes

    • Improved handling and validation of remote MAC addresses to prevent duplicates and enforce limits.
    • Enhanced message processing to accept ESP-NOW data only from authorized linked remotes.
  • Refactor

    • Updated internal logic to store and process multiple remote devices, enhancing flexibility for advanced users.
    • Removed legacy single-remote filtering to support multiple remotes seamlessly.

@DedeHai DedeHai requested a review from blazoncek April 22, 2025 19:06
Copy link

coderabbitai bot commented Apr 22, 2025

Walkthrough

This change updates the handling of ESP-NOW remote MAC addresses throughout the codebase, transitioning from support for a single linked remote to supporting multiple linked remotes. The update modifies the data structure for storing MAC addresses, changes serialization and deserialization logic, and updates the web interface to allow users to manage multiple remotes. The ESP-NOW message processing logic is also updated to check against a list of authorized remotes. JavaScript and HTML in the WiFi settings page are revised to provide a user interface for adding, removing, and displaying multiple linked MAC addresses.

Changes

Files/Paths Change Summary
wled00/wled.h Changed the global variable for ESP-NOW remote MAC addresses from a single fixed-size array to a vector of fixed-size arrays, enabling storage of multiple remotes.
wled00/cfg.cpp Updated serialization and deserialization logic to handle a JSON array of remote MAC addresses instead of a single string, supporting multiple remotes.
wled00/set.cpp Modified the settings handler to read and store up to 10 remote MAC addresses from request arguments, replacing the previous single-remote logic.
wled00/udp.cpp Changed ESP-NOW receive callback to check incoming messages against all linked remotes instead of just one, ignoring messages from unlinked senders.
wled00/remote.cpp Removed the filter that ignored messages from unlinked remotes, allowing all messages to be processed regardless of sender.
wled00/xml.cpp Replaced single remote MAC JavaScript initialization with commands to populate the client with all linked remotes in the settings page.
wled00/data/settings_wifi.htm Replaced single remote MAC input with a dynamic UI for managing multiple remotes, including JavaScript functions for adding, removing, and syncing remotes.

Suggested reviewers

  • blazoncek

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e97d84b and 37416aa.

📒 Files selected for processing (1)
  • wled00/data/settings_wifi.htm (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • wled00/data/settings_wifi.htm
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: wled_build / Build Environments (esp32s3_4M_qspi)
  • GitHub Check: wled_build / Build Environments (usermods)
  • GitHub Check: wled_build / Build Environments (esp32s3dev_8MB_opi)
  • GitHub Check: wled_build / Build Environments (esp32dev)
  • GitHub Check: wled_build / Build Environments (esp32dev_V4)
  • GitHub Check: wled_build / Build Environments (esp32c3dev)
  • GitHub Check: wled_build / Build Environments (esp32_eth)
  • GitHub Check: wled_build / Build Environments (lolin_s2_mini)

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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/data/settings_wifi.htm (1)

264-269: Well-designed UI for managing remote MACs

The UI shows the last seen device MAC address and provides an easy way to add it to the list. The implementation is clean and user-friendly.

Consider adding confirmation when removing a remote to prevent accidental deletions:

btn.onclick = function() {
-  removeRemote(row);
+  if(confirm('Are you sure you want to remove this remote?')) {
+    removeRemote(row);
+  }
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3538684 and de2c052.

📒 Files selected for processing (7)
  • wled00/cfg.cpp (2 hunks)
  • wled00/data/settings_wifi.htm (2 hunks)
  • wled00/remote.cpp (1 hunks)
  • wled00/set.cpp (1 hunks)
  • wled00/udp.cpp (1 hunks)
  • wled00/wled.h (1 hunks)
  • wled00/xml.cpp (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (19)
  • GitHub Check: wled_build / Build Environments (esp32s3_4M_qspi)
  • GitHub Check: wled_build / Build Environments (esp32_wrover)
  • GitHub Check: wled_build / Build Environments (esp32dev)
  • GitHub Check: wled_build / Build Environments (usermods)
  • GitHub Check: wled_build / Build Environments (esp32s3dev_8MB_opi)
  • GitHub Check: wled_build / Build Environments (esp32c3dev)
  • GitHub Check: wled_build / Build Environments (esp32dev_V4)
  • GitHub Check: wled_build / Build Environments (esp01_1m_full_compat)
  • GitHub Check: wled_build / Build Environments (esp8266_2m_160)
  • GitHub Check: wled_build / Build Environments (lolin_s2_mini)
  • GitHub Check: wled_build / Build Environments (nodemcuv2_compat)
  • GitHub Check: wled_build / Build Environments (esp32s3dev_16MB_opi)
  • GitHub Check: wled_build / Build Environments (esp32_eth)
  • GitHub Check: wled_build / Build Environments (nodemcuv2_160)
  • GitHub Check: wled_build / Build Environments (esp8266_2m_compat)
  • GitHub Check: wled_build / Build Environments (nodemcuv2)
  • GitHub Check: wled_build / Build Environments (esp8266_2m)
  • GitHub Check: wled_build / Build Environments (esp01_1m_full_160)
  • GitHub Check: wled_build / Build Environments (esp01_1m_full)
🔇 Additional comments (7)
wled00/wled.h (1)

541-542: Implementation of multiple ESP-NOW remotes vector looks good

The change from a single fixed-size array to a vector of fixed-size arrays is a clean way to support multiple remote devices. I see the original declaration is kept as a comment, which might help with understanding the change or potential backwards compatibility.

wled00/remote.cpp (1)

184-207: Removed sender validation from handleWiZdata

The sender validation logic that was previously in this function has been properly moved to the ESP-NOW receive callback in udp.cpp. This is a good architectural change, as it centralizes the MAC address validation in a single place.

wled00/xml.cpp (1)

219-222: Client-side remotes initialization implementation is correct

The code now correctly initializes the client-side list of remotes by:

  1. First calling resetRemotes() to clear any existing entries
  2. Then iterating through the vector to add each remote with a unique identifier ("RM0" through "RM9")

This approach properly supports the new multi-remote functionality.

wled00/udp.cpp (2)

962-973: Correctly implemented multi-remote validation

This is a key change that enables support for multiple ESP-NOW remotes. The code now:

  1. Iterates through all stored MAC addresses in the linked_remotes vector
  2. Checks if the sender's MAC matches any of the authorized remotes
  3. Rejects messages from unauthorized senders with appropriate debug logging

This validation logic is more robust than the previous single-remote check.


975-979: WiZ remote data handling is unchanged

The core functionality for handling WiZ remote data is preserved after the validation check, maintaining compatibility with existing remotes while enabling support for multiple devices.

wled00/cfg.cpp (1)

742-745: Correctly serializes the remote MACs to JSON array

The implementation properly serializes the vector of linked remotes to a JSON array, which matches the deserialization logic.

wled00/data/settings_wifi.htm (1)

200-200: Good form submission handling

Adding the onsubmit event handler ensures the MAC array is updated before form submission, which is essential for proper data serialization.

Copy link
Collaborator

@blazoncek blazoncek left a comment

Choose a reason for hiding this comment

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

I would like to not change existing config token name.

Paired Remote MAC: <input type="text" name="RMAC" minlength="12" maxlength="12"><br>
Last device seen: <span class="rlid" onclick="d.Sf.RMAC.value=this.textContent;" style="cursor:pointer;">None</span> <br>
Last device seen: <span class="rlid">None</span>
<button type="button" class="btn btn-xs" onclick="addRemote('RM'+remoteCount,this.parentElement.querySelector('.rlid').textContent)">Add</button><br>
Copy link
Collaborator

Choose a reason for hiding this comment

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

You could use id property in last device seen <span> and then use shorter form gId("rlid").

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I tried this, since xml.cpp modifies it, it must be a class no? I cann add an id on top.

Copy link
Collaborator

Choose a reason for hiding this comment

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

class is used for formatting purposes, id for identification. Each element must have unique id if it is used.
You can assign multiple classes to an element (and they are inherited) but id is specific to the element (tag).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

if I remove the class and replace it with id, the xml.cpp update does not work.
this does work:

Last device seen: <span class="rlid" id="ld">None</span>
<button type="button" onclick="aR('RM'+rC,gId('ld').textContent)">+</button><br>

- reverting name to `linked_remote`
- ESPNow remote list is now hidden if unchecked
- shortened java script function names and variables to save flash
- removed now obsolete settings in xml.cpp
- correct checking of valid hex string for remote list in java script
Copy link

@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: 0

🧹 Nitpick comments (2)
wled00/data/settings_wifi.htm (2)

156-185: Consider more descriptive function and variable names.

While the function effectively adds a remote MAC to the list with proper validation, the variable and function names (aR, rC) are very terse and not self-descriptive. Using more meaningful names would improve code readability and maintainability.

-var rC = 0; // remote count
+var remoteCount = 0; // remote count

-function aR(id, mac) {
+function addRemote(id, mac) {
  if (!/^[0-9A-F]{12}$/i.test(mac)) return; // check for valid hex string
-  if (rC >= 10) return;
+  if (remoteCount >= 10) return;
  
  // Rest of the function remains the same

-  rC++;
+  remoteCount++;
-  uR();
+  updateRemoteList();
}

Also, update references to this function elsewhere in the code (like line 273).


186-190: Consider adding user feedback when removing a remote.

The removal function works correctly, but there's no feedback to the user when a remote is removed. Consider adding a brief notification or visual feedback.

-function rR(e) {
+function removeRemote(e) {
  e.remove();
-  uR();
+  updateRemoteList();
+  // Optional: Show brief feedback
+  let notification = cE('div');
+  notification.className = 'notification';
+  notification.innerText = 'Remote removed';
+  document.body.appendChild(notification);
+  setTimeout(() => notification.remove(), 2000);
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05000c8 and 28c716f.

📒 Files selected for processing (3)
  • wled00/cfg.cpp (2 hunks)
  • wled00/data/settings_wifi.htm (2 hunks)
  • wled00/xml.cpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • wled00/cfg.cpp
  • wled00/xml.cpp
⏰ Context from checks skipped due to timeout of 90000ms (19)
  • GitHub Check: wled_build / Build Environments (esp32_wrover)
  • GitHub Check: wled_build / Build Environments (esp01_1m_full_compat)
  • GitHub Check: wled_build / Build Environments (esp32s3dev_16MB_opi)
  • GitHub Check: wled_build / Build Environments (esp32s3dev_8MB_opi)
  • GitHub Check: wled_build / Build Environments (esp8266_2m_compat)
  • GitHub Check: wled_build / Build Environments (esp32c3dev)
  • GitHub Check: wled_build / Build Environments (usermods)
  • GitHub Check: wled_build / Build Environments (esp32dev)
  • GitHub Check: wled_build / Build Environments (esp32dev_V4)
  • GitHub Check: wled_build / Build Environments (esp01_1m_full_160)
  • GitHub Check: wled_build / Build Environments (esp32s3_4M_qspi)
  • GitHub Check: wled_build / Build Environments (lolin_s2_mini)
  • GitHub Check: wled_build / Build Environments (esp32_eth)
  • GitHub Check: wled_build / Build Environments (esp8266_2m_160)
  • GitHub Check: wled_build / Build Environments (esp01_1m_full)
  • GitHub Check: wled_build / Build Environments (nodemcuv2)
  • GitHub Check: wled_build / Build Environments (esp8266_2m)
  • GitHub Check: wled_build / Build Environments (nodemcuv2_compat)
  • GitHub Check: wled_build / Build Environments (nodemcuv2_160)
🔇 Additional comments (6)
wled00/data/settings_wifi.htm (6)

139-139: Using setTimeout for DOM initialization is appropriate here.

The use of setTimeout to delay calling tE() ensures the DOM has loaded before attempting to access elements, which is a good practice in this context.


142-149: Good implementation of ESP-NOW UI toggle functionality.

The tE() function effectively toggles the visibility of the remote list UI based on the checkbox state. The function has clear comments and handles the DOM manipulation appropriately.


150-155: Well-implemented reset function for remotes list.

This function correctly clears the remote list and updates the internal state, with proper comments explaining its purpose and origin.


191-202: Well-implemented function for updating the remote list.

This function correctly collects all MAC addresses, validates them, and updates the hidden form field with a JSON string. The return value ensures the form submission continues.


207-207: Good use of form onsubmit handler.

Adding the onsubmit handler ensures the hidden input is updated with the current list of remotes before form submission, which is essential for proper data handling.


268-279: Well-structured UI for managing ESP-NOW remotes.

The UI implementation effectively displays the last seen device and provides a clean interface for managing linked MAC addresses. The organization of elements with appropriate containers and the hidden input for form submission is well done.

I notice you've addressed the previous feedback about using an ID for the last device span by adding id="ld" to the span element.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Apr 25, 2025

in the html files, indentation seems to be messed up here on git, but it displays right in vscode. Do I need to change a setting or is this a github thing?

@blazoncek
Copy link
Collaborator

indentation seems to be messed up

It is not. HTML/CSS/JS files use tabs, C/C++ files use spaces. Fix that in your VSC configuration and you are good.

@blazoncek
Copy link
Collaborator

One more thing that sprung into mind: Instead of "Add" and "Remove" buttons you could use familiar "+" and "-" buttons.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Apr 25, 2025

I think I have it all fixed and ready now.
image

if ESPNow is disabled, the list is hidden (but still kept in config if it exists)
image

Copy link
Collaborator

@blazoncek blazoncek left a comment

Choose a reason for hiding this comment

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

A minor tweak here and there might do it good but it looks great already. Will need to test still.

@@ -136,12 +136,75 @@
getLoc();
loadJS(getURL('/settings/s.js?p=1'), false); // If we set async false, file is loaded and executed, then next statement is processed
if (loc) d.Sf.action = getURL('/settings/wifi');
setTimeout(tE, 500); // wait for DOM to load before calling tE()
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should not be needed here. You can add call to tE() in xml.cpp if it is necessary to be invoked when all fields are set.

Copy link
Collaborator Author

@DedeHai DedeHai Apr 26, 2025

Choose a reason for hiding this comment

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

I tried many variations, including calling tE() from xml.cpp. this variant, although a bit of a hack, is the only one that consistently worked. tE() was always evaluated too early, not properly showing/hiding the section.
maybe I did it wrong, you can try if you can get it working right with an xml.cpp call.

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