Skip to content

added new usermod adc_sensor_mqtt_v2 with hass integration #4635

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 12 commits into
base: main
Choose a base branch
from

Conversation

rommo911
Copy link

@rommo911 rommo911 commented Apr 8, 2025

added new usermod for ldr with hass mqtt integration :

  • photoresistor_sensor_mqtt_v2 :
    features : it will publish auto discovery message to hass mqtt and attach the light sensor to the wled integration automatically with good options
    pir switch usermod : added support for discovery message to integrate mqtt entity into wled integration ( check photo )
    hass_ldr_mqtt
    othert changes : fixed signed/unsigned comparasion compiler warning , added to gitignore local buildcache folder ( when desired )

Summary by CodeRabbit

  • New Features

    • Introduced a new usermod for reading analog sensor values (e.g., photoresistor) and publishing them via MQTT, with optional Home Assistant auto-discovery support.
    • Supports multiple ADC pins depending on hardware, configurable update intervals, value inversion, change thresholds, and raw value publishing.
    • Sensor readings and status are accessible through the WLED JSON info endpoint.
  • Documentation

    • Added comprehensive README with setup instructions, configuration options, and usage details for the new usermod.
  • Chores

    • Added metadata file for the new usermod.
    • Added new usermod identifier and pin owner enumeration for integration with the pin manager.

Copy link
Contributor

coderabbitai bot commented Apr 8, 2025

Walkthrough

This change introduces a new usermod called adc_sensor_mqtt for the WLED project, enabling analog sensor readings (such as from a photoresistor) to be published via MQTT and integrated with Home Assistant using MQTT discovery. The update includes the implementation of the usermod, documentation, and configuration files. To support this usermod, a new usermod identifier macro and a corresponding pin manager enumerator are added to the core WLED headers. The changes involve updates to constants, pin management, and the addition of new usermod source, documentation, and metadata files.

Changes

Files/Paths Change Summary
wled00/const.h Added macro USERMOD_ID_ADC_MQTT 58 for the new usermod identifier.
wled00/pin_manager.h Added UM_ADC_MQTT enumerator to the PinOwner enum with value USERMOD_ID_ADC_MQTT and comment about default pin usage; added a trailing comma to UM_PIXELS_DICE_TRAY enumerator.
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp Added new usermod implementation for reading ADC values and publishing them via MQTT, with support for Home Assistant discovery, configurable pins, update intervals, thresholds, inversion, and raw value publishing. Includes pin validation, dynamic pin allocation, MQTT payload formatting, and JSON config integration.
usermods/adc_sensor_mqtt/README.md Added documentation describing the purpose, setup, configuration options, and Home Assistant integration of the adc_sensor_mqtt usermod, with author attribution and usage instructions.
usermods/adc_sensor_mqtt/library.json Added metadata file specifying the name of the usermod as "adc_sensor_mqtt".
✨ Finishing Touches
  • 📝 Generate Docstrings

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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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
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: 2

🧹 Nitpick comments (9)
usermods/photoresistor_sensor_mqtt_v2/README.md (7)

1-1: Fix spelling of “Photoresister” heading.
To maintain consistent terminology:

- # Photoresister sensor with MQTT ##
+ # Photoresistor sensor with MQTT ##

2-2: Add the article "an" before 'auto discovery message'.

- it will publish auto discovery message to hass mqtt 
+ it will publish an auto-discovery message to Hass MQTT
🧰 Tools
🪛 LanguageTool

[uncategorized] ~2-~2: You might be missing the article “an” here.
Context: ... more hass application. it will publish auto discovery message to hass mqtt and atta...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


8-8: Specify a language for the fenced code block.
Adding a language identifier (e.g., bash, ini, or plaintext) to fenced code blocks improves readability and adheres to markdownlint guidelines.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

8-8: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


16-16: Surround the table with blank lines.
Markdown guidelines recommend blank lines before and after tables. Adding these will clear the markdownlint warning.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

16-16: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)


28-28: Convert bare URL to a proper link.

- [@jeffwdh](https://github.com/jeffwdh)  
- [email protected]
+ [@jeffwdh](https://github.com/jeffwdh)  
+ [mailto:[email protected]]([email protected])

Or simply enclose the email in angled brackets: <[email protected]>.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

28-28: Bare URL used
null

(MD034, no-bare-urls)


31-31: Add a comma before “so” to fix run-on sentence.

- A threshold value can be set so significant changes...
+ A threshold value can be set, so significant changes...
🧰 Tools
🪛 LanguageTool

[uncategorized] ~31-~31: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ... definable. A threshold value can be set so significant changes in the readings are...

(COMMA_COMPOUND_SENTENCE_2)


35-35: Add a missing comma after 'sensor'.

- This usermod has only been tested with the KY-018 sensor though...
+ This usermod has only been tested with the KY-018 sensor, though...
🧰 Tools
🪛 LanguageTool

[uncategorized] ~35-~35: Possible missing comma found.
Context: ...od has only been tested with the KY-018 sensor though it should work for any other ana...

(AI_HYDRA_LEO_MISSING_COMMA)

usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (2)

7-7: Correct the spelling of “threshould”.

- float change_threshould = 1;
+ float change_threshold = 1;

57-57: Fix variable name “force_upadate”.

- bool force_upadate = ...
+ bool force_update = ...
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e979c58 and d86a86f.

📒 Files selected for processing (13)
  • .gitignore (1 hunks)
  • usermods/PIR_sensor_switch/PIR_sensor_switch.cpp (1 hunks)
  • usermods/photoresistor_sensor_mqtt_v2/README.md (1 hunks)
  • usermods/photoresistor_sensor_mqtt_v2/library.json (1 hunks)
  • usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (1 hunks)
  • wled00/FX_fcn.cpp (1 hunks)
  • wled00/FXparticleSystem.cpp (0 hunks)
  • wled00/const.h (1 hunks)
  • wled00/network.cpp (1 hunks)
  • wled00/pin_manager.h (1 hunks)
  • wled00/wled.cpp (1 hunks)
  • wled00/wled.h (1 hunks)
  • wled00/xml.cpp (1 hunks)
💤 Files with no reviewable changes (1)
  • wled00/FXparticleSystem.cpp
🧰 Additional context used
🧬 Code Graph Analysis (4)
wled00/const.h (1)
usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (1)
  • USERMOD_PHOTORESISTOR_MQTT_V2 (144-147)
wled00/pin_manager.h (2)
usermods/pixels_dice_tray/pixels_dice_tray.cpp (1)
  • USERMOD_ID_PIXELS_DICE_TRAY (528-528)
usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (1)
  • USERMOD_PHOTORESISTOR_MQTT_V2 (144-147)
wled00/network.cpp (1)
wled00/FX.h (1)
  • selected (591-591)
usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (2)
wled00/pin_manager.h (4)
  • allocatePin (89-89)
  • allocatePin (97-97)
  • deallocatePin (83-83)
  • deallocatePin (99-99)
usermods/SN_Photoresistor/SN_Photoresistor.cpp (1)
  • REGISTER_USERMOD (214-214)
🪛 LanguageTool
usermods/photoresistor_sensor_mqtt_v2/README.md

[uncategorized] ~2-~2: You might be missing the article “an” here.
Context: ... more hass application. it will publish auto discovery message to hass mqtt and atta...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~31-~31: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ... definable. A threshold value can be set so significant changes in the readings are...

(COMMA_COMPOUND_SENTENCE_2)


[uncategorized] ~35-~35: Possible missing comma found.
Context: ...od has only been tested with the KY-018 sensor though it should work for any other ana...

(AI_HYDRA_LEO_MISSING_COMMA)

🪛 markdownlint-cli2 (0.17.2)
usermods/photoresistor_sensor_mqtt_v2/README.md

8-8: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


16-16: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)


28-28: Bare URL used
null

(MD034, no-bare-urls)

🔇 Additional comments (10)
.gitignore (1)

26-26: LGTM! Added build cache to gitignore.

Adding .buildcache to .gitignore is good practice to prevent local build artifacts from being committed to the repository.

wled00/FX_fcn.cpp (1)

1498-1498: Good type safety improvement

Changing the loop iterator from int to size_t improves type safety by ensuring the variable used for indexing is an unsigned type, which aligns better with the return type of BusManager::getNumBusses().

wled00/const.h (1)

213-213: LGTM! Added new usermod identifier

The new usermod identifier USERMOD_PHOTORESISTOR_MQTT_V2 follows the correct naming convention and is assigned the next available ID (58).

wled00/wled.h (1)

370-370: Improved type safety with size_t for array index

Changed variable type from int8_t to size_t which is more appropriate for indexing into the WiFi networks vector. This is a good practice as it:

  1. Provides better type safety for array indices
  2. Allows for more than 127 WiFi networks (the limit of int8_t)
  3. Matches the standard C++ container indexing type
wled00/wled.cpp (1)

753-753: Suppressed compiler warning for potentially unused variable

Added __attribute__((unused)) to the nowS variable to prevent compiler warnings when the variable is not used in certain code paths. This is a clean approach to maintain the variable for debugging or future use while eliminating unwanted warnings.

usermods/PIR_sensor_switch/PIR_sensor_switch.cpp (1)

320-322: Enhanced Home Assistant integration with device identification

Added device connection information to the Home Assistant MQTT auto-discovery message. This improves device identification in the Home Assistant ecosystem by providing the MAC address as a unique identifier.

This change follows the Home Assistant discovery protocol standards and will make device management more reliable in Home Assistant.

wled00/xml.cpp (1)

298-298: Improved type safety with size_t for bus iteration

Changed loop counter from int to size_t for better type safety when iterating over buses. This is consistent with the C++ standard practice of using size_t for container indices and counters, reducing the risk of negative values or overflow.

wled00/network.cpp (1)

299-299: Correct use of size_t for indexing.
This change from int to size_t is appropriate for indexing and helps avoid potential out-of-range issues.

wled00/pin_manager.h (1)

76-77: Addition of new usermod enumerator looks good.
The new UM_PHOTO_RESISTOR_MQTT enumerator aligns well with the newly introduced usermod.

usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (1)

57-57: Verify large multiplier for forced update frequency.
The expression (update_interval * 100) introduces a 100× factor, possibly causing forced updates at a much slower rate than expected. Confirm that a 5-minute interval (3000ms × 100) is intended.

Copy link
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: 0

🧹 Nitpick comments (4)
usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (4)

6-6: Consider using unsigned long for timing calculations
In Arduino, millis() returns an unsigned long. Using a signed type like long for lastTime and update_interval can lead to sign-comparison issues or overflow problems over extended run times.

- long update_interval = 3000;
- long lastTime = 0;
+ unsigned long update_interval = 3000UL;
+ unsigned long lastTime = 0UL;

Also applies to: 10-10, 55-58


7-7: Fix spelling of “threshold”
Your code uses the variable and key "change_threshould" in multiple places. Renaming them to "change_threshold" improves clarity and avoids confusion.

- float change_threshould = 1;
+ float change_threshold = 1;

- top["change threshould"] = change_threshould;
+ top["change threshold"] = change_threshold;

- configComplete &= getJsonValue(top["change threshould"], change_threshould);
+ configComplete &= getJsonValue(top["change threshold"], change_threshold);

- JsonArray LDR_change_threshould = user.createNestedArray("change threshould");
+ JsonArray LDR_change_threshold = user.createNestedArray("change threshold");

Also applies to: 100-100, 112-112, 140-140


16-16: Simplify inverted logic for readability
The current arithmetic with * -1 works but can be confusing. Splitting out the expression clarifies the behavior, especially when inverted is true.

- if (inverted)
- {
-   lightPercentage = 100.0 - ((float)lightValue * -1 + mapping) / (float)mapping * 100;
- }
- else
- {
-   lightPercentage = ((float)lightValue * -1 + mapping) / (float)mapping * 100;
- }
+ float normalized = (mapping - (float)lightValue) / mapping * 100.0;
+ if (inverted) {
+   lightPercentage = 100.0 - normalized;
+ } else {
+   lightPercentage = normalized;
+ }

Also applies to: 69-73


57-57: Rename “force_upadate” to “force_update”
There is a minor spelling issue in the variable name. Renaming it makes the code clearer.

- bool force_upadate = (millis() - lastTime) > (update_interval * 100);
+ bool force_update = (millis() - lastTime) > (update_interval * 100);

Also applies to: 76-76

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d86a86f and 58b51e3.

📒 Files selected for processing (1)
  • usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (1 hunks)
🔇 Additional comments (1)
usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (1)

187-187: Confirm hardware version labeling for ESP8266
Here, device[F("hw_version")] = F("esp32"); suggests the hardware is always ESP32, but there is partial ESP8266 support. Verify if this is intentional.

Please confirm your intended platforms; if you also support ESP8266, consider setting this dynamically or via a compile-time macro.

Copy link
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: 1

🧹 Nitpick comments (4)
usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (4)

24-43: Consider logging warnings for invalid pin scenarios.
At present, the usermod is silently disabled when an invalid or busy pin is detected. Logging a warning or error message would help with debugging and user feedback.

     if (!PinManager::allocatePin(ldrPin, false, PinOwner::UM_PHOTO_RESISTOR_MQTT))
     {
       ldrEnabled = false; // pin already in use -> disable usermod
+      DEBUG_PRINTLN(F("photoresistor_sensor_mqtt_v2: Pin already in use, disabling usermod."));
     }
     else
     {
       pinMode(ldrPin, INPUT); // alloc success -> configure pin for input
     }
   }
   else
   {
     ldrEnabled = false; // invalid pin -> disable usermod
+    DEBUG_PRINTLN(F("photoresistor_sensor_mqtt_v2: Invalid pin, disabling usermod."));
   }

45-51: Avoid triggering Home Assistant discovery multiple times.
Since discovery is also published in the publishMqtt() method when hassDiscoverySent is false, calling publishDiscovery() again in connected() may result in redundant messages if the function is called more than once.

 void connected()
 {
   if (WLED_MQTT_CONNECTED && HomeAssistantDiscovery
+       && !hassDiscoverySent
   )
   {
     publishDiscovery();
   }
 }

53-91: Use dedicated floating-point absolute function.
abs() is overloaded in C++, but it's clearer to use std::fabs() or fabs() for floating-point arguments to avoid any ambiguity.

- if (abs(lightPercentage - lastPercentage) > change_threshold || force_update)
+ if (fabs(lightPercentage - lastPercentage) > change_threshold || force_update)

93-102: Fix the repeated typo "threshould" → "threshold".

--- a/usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp
+++ b/usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp
@@ -100 +100 @@
-  top["change threshould"] = change_threshold;
+  top["change threshold"] = change_threshold;

@@ -112 +112 @@
-  configComplete &= getJsonValue(top["change threshould"], change_threshold);
+  configComplete &= getJsonValue(top["change threshold"], change_threshold);

@@ -140 +140 @@
-  JsonArray LDR_change_threshold = user.createNestedArray("change threshould");
+  JsonArray LDR_change_threshold = user.createNestedArray("change threshold");

Also applies to: 103-120, 122-142

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 58b51e3 and c1c89fb.

📒 Files selected for processing (1)
  • usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (1)
wled00/pin_manager.h (4)
  • allocatePin (89-89)
  • allocatePin (97-97)
  • deallocatePin (83-83)
  • deallocatePin (99-99)
🔇 Additional comments (2)
usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (2)

1-3: No concerns with this initial class definition.


203-206: Looks good.

Comment on lines 149 to 162
void publishMqtt(float state)
{
if (WLED_MQTT_CONNECTED)
{
if (!hassDiscoverySent && HomeAssistantDiscovery)
{
publishDiscovery();
}
char subuf[38];
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, MQTT_TOPIC);
mqtt->publish(subuf, 0, true, String(state).c_str());
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify maximum lengths to prevent buffer overflow.
subuf, uid, and buf have fixed sizes, but they rely on mqttDeviceTopic and MQTT_TOPIC (or uid for the discovery path) not exceeding certain lengths. If these strings are longer than expected, a buffer overflow could occur.

Also applies to: 164-201


🏁 Script executed:

#!/bin/bash
# Description: Validate the maximum length constraints for mqttDeviceTopic, escapedMac, and other strings.

# 1. Search for definitions or references of mqttDeviceTopic and escapedMac to check any enforced size.
rg -A 5 "mqttDeviceTopic|escapedMac" 

# 2. Inspect how these variables are assigned or constrained in the codebase.
#    If there's no size limit, consider using safer functions like strlcpy or strncat.

Length of output: 51656


Potential Buffer Overflow in MQTT Publish Function – Use Safe String Functions

The use of strcpy and strcat in the publishMqtt() function (lines 149–162 in usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp) is risky if the lengths of mqttDeviceTopic and MQTT_TOPIC exceed the expected limits. Our grep output shows that many parts of the codebase already enforce size limits using safe functions like strlcpy, strlcat, or snprintf_P. To mitigate a potential buffer overflow:

  • Replace strcpy/strcat with safe variants (e.g., strlcpy/strlcat or equivalent) using the correct size (e.g., MQTT_MAX_TOPIC_LEN + 1 for the topic buffer).
  • Verify that the fixed buffer (subuf[38]) is sufficiently sized to hold mqttDeviceTopic plus MQTT_TOPIC. If not, adjust its size accordingly.
  • Consider checking the lengths of these strings prior to concatenation.

Please update the function to use safer string operations to avoid overflow risks.

@DedeHai
Copy link
Collaborator

DedeHai commented Apr 9, 2025

thank you for contributing.
the UM looks ok, please revert changes to other files, make them seperate PRs.

… improved hass intgeration for PIR_sensor_switch
@rommo911
Copy link
Author

rommo911 commented Apr 9, 2025

@DedeHai thanks for the review ,i rebased it to have the UM as a single commit. tested on esp32 & esp8266 nodmcu & esp_01

Copy link
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: 1

🧹 Nitpick comments (5)
usermods/photoresistor_sensor_mqtt_v2/README.md (5)

8-13: Specify Language for Fenced Code Block
The fenced code block in the installation example does not specify a language, which is flagged by markdownlint (MD040). Adding a language specifier such as ini can improve readability and tooling support. For example, change the opening fence from:

-```
+```ini

This small change helps keep the documentation aligned with best practices.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

8-8: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


15-23: Improve Table Formatting for Better Markdown Readability
The table under the "Usermod Settings" header would benefit from having blank lines both before and after it to conform with markdown formatting guidelines (MD058). For instance, insert a blank line immediately before line 16 and after line 23.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

16-16: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)


24-29: Enhance Author Section Formatting
Consider revising the "Author" section for consistent formatting. For example:

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

28-28: Bare URL used
null

(MD034, no-bare-urls)


31-33: Refine Messaging and Punctuation for Clarity
The sentence on line 31 would be clearer with improved punctuation and phrasing. For example, change:

"A threshold value can be set so significant changes in the readings are published immediately vice waiting for the next update."

to

"A threshold value can be set, so that significant changes in the readings are published immediately rather than waiting for the next update."

Additionally, consider revising the sentence on line 33 to improve its flow; for instance, "I also found it useful to limit the frequency of analog pin reads; otherwise, the board hangs."

🧰 Tools
🪛 LanguageTool

[uncategorized] ~31-~31: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ... definable. A threshold value can be set so significant changes in the readings are...

(COMMA_COMPOUND_SENTENCE_2)


[uncategorized] ~31-~31: Possible missing comma found.
Context: ...t changes in the readings are published immediately vice waiting for the next update. This ...

(AI_HYDRA_LEO_MISSING_COMMA)


35-36: Minor Punctuation and Clarity Improvements in Usermod Testing Note
On line 35, adding a comma after "KY-018 sensor" can improve readability:

"This usermod has only been tested with the KY-018 sensor, though it should work for any other analog pin sensor."

Similarly, on line 36, consider rephrasing to enhance clarity—for example:

"Note: This usermod does not directly control the LED strip; it only publishes MQTT readings for use with integrations like Home Assistant."

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c1c89fb and 546839c.

📒 Files selected for processing (8)
  • .gitignore (1 hunks)
  • usermods/PIR_sensor_switch/PIR_sensor_switch.cpp (1 hunks)
  • usermods/photoresistor_sensor_mqtt_v2/README.md (1 hunks)
  • usermods/photoresistor_sensor_mqtt_v2/library.json (1 hunks)
  • usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp (1 hunks)
  • wled00/FXparticleSystem.cpp (0 hunks)
  • wled00/const.h (1 hunks)
  • wled00/pin_manager.h (1 hunks)
💤 Files with no reviewable changes (1)
  • wled00/FXparticleSystem.cpp
🚧 Files skipped from review as they are similar to previous changes (6)
  • usermods/photoresistor_sensor_mqtt_v2/library.json
  • .gitignore
  • wled00/const.h
  • usermods/PIR_sensor_switch/PIR_sensor_switch.cpp
  • wled00/pin_manager.h
  • usermods/photoresistor_sensor_mqtt_v2/photoresistor_sensor_mqtt_v2.cpp
🧰 Additional context used
🪛 LanguageTool
usermods/photoresistor_sensor_mqtt_v2/README.md

[uncategorized] ~2-~2: You might be missing the article “an” here.
Context: ... more hass application. it will publish auto discovery message to hass mqtt and atta...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


[uncategorized] ~31-~31: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ... definable. A threshold value can be set so significant changes in the readings are...

(COMMA_COMPOUND_SENTENCE_2)


[uncategorized] ~31-~31: Possible missing comma found.
Context: ...t changes in the readings are published immediately vice waiting for the next update. This ...

(AI_HYDRA_LEO_MISSING_COMMA)

🪛 markdownlint-cli2 (0.17.2)
usermods/photoresistor_sensor_mqtt_v2/README.md

8-8: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


16-16: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)


28-28: Bare URL used
null

(MD034, no-bare-urls)

Comment on lines 1 to 2
# Photoresister sensor with MQTT ## based on LDR_Dusk_Dawn_v2 usermod from [@jeffwdh](https://github.com/jeffwdh)
This usermod will obtain readings from a Light Dependent Resistor (LDR). This is useful for exterior lighting situations where you want the lights to only be on when it is dark out. but this mod is designed for more hass application. it will publish auto discovery message to hass mqtt and attach the light sensor to the wled integration automatically
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Clarify and Correct the Introduction
The header and opening paragraph contain a few typographical and grammatical issues. For example, "Photoresister" should be corrected to "Photoresistor" to match the file name, and the wording—especially around "more hass application" and "auto discovery message"—can be improved for clarity and formality. Consider revising the text as follows:

"Photoresistor sensor with MQTT – based on the LDR_Dusk_Dawn_v2 usermod from @jeffwdh"

This usermod obtains readings from a Light Dependent Resistor (LDR), which is useful for exterior lighting conditions where the lights should only be on when it is dark. However, this mod is designed primarily for Home Assistant integration: it publishes auto-discovery messages via MQTT to automatically attach the light sensor to the WLED integration.

This will address the issues flagged by LanguageTool and improve overall clarity.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~2-~2: You might be missing the article “an” here.
Context: ... more hass application. it will publish auto discovery message to hass mqtt and atta...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)

@DedeHai
Copy link
Collaborator

DedeHai commented Apr 9, 2025

please dont force push. there are still changed files not part of the UM

@rommo911
Copy link
Author

rommo911 commented Apr 9, 2025

alright.
yes all UM are good here.

@DedeHai
Copy link
Collaborator

DedeHai commented Apr 9, 2025

no, you still mixed two PRs and changed unrelated files.

@rommo911
Copy link
Author

no, you still mixed two PRs and changed unrelated files.

sorry , my bad. now should be good

@DedeHai
Copy link
Collaborator

DedeHai commented Apr 13, 2025

I took a closer look at the UM. If the purpose of it is to read an analog value and send it to MQTT why not just name it that? It is not limited to a photoresistor even if that is what you use it for. It would be much better suited as a general "read analog input, publish the value", it could even be extended to multiple pins. I did not check if any usermod already does something like this.

@rommo911
Copy link
Author

I took a closer look at the UM. If the purpose of it is to read an analog value and send it to MQTT why not just name it that? It is not limited to a photoresistor even if that is what you use it for. It would be much better suited as a general "read analog input, publish the value", it could even be extended to multiple pins. I did not check if any usermod already does something like this.

it can be adapted as general purpose analog read, but the UM aims to support hass wled integration via mqqt as light sensor with auto discovery. so if its not used as light sensor, hass discovery needs adjustement.
1- multiple pins can be supported yes
2- usage as general purpose can be also supported but needs to add more customization options for hass discovery .
but the main goal is to use it with LDR as sensor for hass users so i think this could be very useful to many peopole and it can be adjusted or improved next.

@DedeHai
Copy link
Collaborator

DedeHai commented Apr 13, 2025

I am unfamiliar with how HA works. If you made this into a more generally useable UM, there could be any analog sensor attached. If HA uses a particular structure: adding a dropdown to the UM config to select what type HA should be detecting would be a good option.
The multiple pin options is something I see optional and also you could add that later.

@DedeHai DedeHai changed the title added new usermod photoresistor_sensor_mqtt_v2 with hass integration, improved hass intgeration for PIR_sensor_switch, fixed compile warnings added new usermod photoresistor_sensor_mqtt_v2 with hass integration Apr 14, 2025
@DedeHai
Copy link
Collaborator

DedeHai commented Apr 15, 2025

I read the code some more.

  • formating could be streamlined to rest of WLED code (similar to google format)
  • you forgot to add a pin selection
  • this would be the third usermod for photoresistors, to get my vote to add it, it needs to bring configurability, otherwise it does almost exactly the same as existing "V1" apart from added HA specific things.

@blazoncek since you are more familiar with UMs capabilities, would you care to take a look?

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 do not like duplicates and would have preferred older usermods be updated. This will allow existing users to benefit from the updated code without modifying their environments.

change threshould | the minimum limit to detect change and publish the value (in % ; float ; ex 0.8 ) . | 1.0

## Author
[@jeffrommo911wdh](https://github.com/rommo911)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Username needs fixing.

Copy link
Author

Choose a reason for hiding this comment

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

i'll put it in a seperate PR . its very useful for hass integration

JsonObject top = root[FPSTR(_name)];
bool configComplete = !top.isNull();
configComplete &= getJsonValue(top["Enabled"], ldrEnabled);
configComplete &= getJsonValue(top["LDR Pin"], ldrPin);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Even though it is (currently) supported, I would avoid spaces in JSON key names.

bool configComplete = !top.isNull();
configComplete &= getJsonValue(top["Enabled"], ldrEnabled);
configComplete &= getJsonValue(top["LDR Pin"], ldrPin);
configComplete &= getJsonValue(top["LDR update interval"], update_interval);
Copy link
Collaborator

Choose a reason for hiding this comment

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

These are cfg.json configuration item key names. They need not be descriptive. Use addInfo() to add description.

configComplete &= getJsonValue(top["change threshould"], change_threshold);
// pin changed - un-register previous pin, register new pin
PinManager::deallocatePin(oldLdrPin, PinOwner::UM_PHOTO_RESISTOR_MQTT);
if (ldrEnabled && ldrPin > 0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is a 0 invalid entry?

static const char MQTT_TOPIC[];
static const char _name[];
const bool HomeAssistantDiscovery = true; // is HA discovery turned on by default
int ldrPin = A0;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use actual GPIO number and not Arduino pin monikers.

@rommo911
Copy link
Author

I do not like duplicates and would have preferred older usermods be updated. This will allow existing users to benefit from the updated code without modifying their environments.

alrighty , i am still new to WLED PR. i use it very much around my house with several UM & hass integration ( i have almost all versions running in my house , ESP01 / ESP8266 / ESP32 / ESP32-S2 ESP32-S3 .

I am unfamiliar with how HA works. If you made this into a more generally useable UM, there could be any analog sensor attached. If HA uses a particular structure: adding a dropdown to the UM config to select what type HA should be detecting would be a good option. The multiple pin options is something I see optional and also you could add that later.

i am working on modifying it to be as @DedeHai , analog sensor with multiple pins support & hass general WLED integration to be most correct, current mqtt hass dicovery add a seperate mqtt device that is identified outside the WLED device in hass. this integration would put the mqtt entity inside the WLED device menu in hass.

TODO :
1- add support for multiple pins
2- rename to generic ADC mqtt sensor
3- streamline json & config .
4- add hass discovery option to UM settings.
5- fix pins issues

@rommo911
Copy link
Author

rommo911 commented Apr 15, 2025

@blazoncek i have issue with choosing pin A0 in esp8266 via pinManager , actually A0 is pin number 17 . and pin manager refuses to allocate pin 17 as its ONLY ADC pin and in the code its explicitly specified to return false if pin >=17 for ESP8266 ...
should we consider also adding support for pin manager to allocate pin 17 for esp8266 in input only mode ? or should i do a workaround only in the UM ?

@DedeHai
Copy link
Collaborator

DedeHai commented Apr 15, 2025

I think a more or less generic analog sensor UM with MQTT and proper HA support would be greatly appreciated by other users. There have been several requests in this direction.

@blazoncek
Copy link
Collaborator

ESP8266 only has one (un-modifiable) ADC pin and is so pointless to allow selection of it.
I would recommend you ignore any input in such case.
For ESP32 (and variants) that does not apply.

@rommo911
Copy link
Author

I think a more or less generic analog sensor UM with MQTT and proper HA support would be greatly appreciated by other users. There have been several requests in this direction.

on it .

@rommo911
Copy link
Author

its looking like this at this moment

image

for ESP8266 , removed pin choice and forced A0=17 , ignore changes on pin.

HASS detect the sensor class & its unit.
added option to disable hass discovery, added option to publish either % of ADC ( mapping to 100 ) or publish raw value.
tested on ESP32 & ESP8266 ...
for ESP32 only ADC 1 channels are allowed ( as wifi uses ADC 2 )

TODO : gotta check with pin for ESP32-C3 / S2 / S3 to ensure appropriate ADC pins are allowed,

would appreciate your feedback or advices while working on it to consider other aspects.

spoiler alert : the UM setup / config / discovery is rather heavy complicated code but since its for ESP series , it can be handled quit good i guess.

Copy link
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: 4

🔭 Outside diff range comments (1)
usermods/adc_sensor_mqtt/README.md (1)

16-23: 🛠️ Refactor suggestion

Update and expand the settings table.

The settings table is missing several configuration options and should have blank lines around it for proper markdown formatting.

Apply these improvements to the settings table:

 # Usermod Settings
+
 Setting | Description | Default
 --- | --- | ---
 Enabled | Enable/Disable the LDR functionality. | Disabled
- Pin | The analog capable pin your LDR is connected to. | A0
- update interval | update interval to read the analog pin ( in ms ) | 3000
- inverted | invert readings based on your own hardware setup ( invert mapping analog to digital value to  0V = 100%  or 3.3V = 100% ) | false
-change threshould | the minimum limit to detect change and publish the value (in % ; float ; ex 0.8 ) . | 1.0
+ AdcPin_0 | The analog capable pin your sensor is connected to. (ESP32: 32-39, ESP8266: A0) | -1 (ESP32), A0 (ESP8266)
+ DeviceClass_0 | Home Assistant device class for the sensor. | illuminance
+ UnitOfMeas_0 | Home Assistant unit of measurement for the sensor. | lx
+ AdcUpdateInterval | Update interval to read the analog pin (in ms). | 2000
+ AdcInverted | Invert readings based on your hardware setup (0V = 100% or 3.3V = 100%). | false
+ ChangeThreshold | The minimum change required to publish a new value (in %, float). | 1.0
+ HomeAssistantDiscovery | Enable Home Assistant MQTT auto-discovery. | true
+ PublishRawValue | Publish raw ADC values instead of percentages. | false
+
+## Hardware Notes
+
+- For ESP8266, only the A0 pin (GPIO17) is available for analog input.
+- For ESP32, pins 32-39 can be used for analog input.
+- Connect your sensor (LDR, thermistor, etc.) with appropriate pull-up/pull-down resistors.
+
+## Home Assistant Integration
+
+This usermod will automatically create sensors in Home Assistant when Discovery is enabled.
+The sensors will be grouped under your WLED device.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

16-16: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)

🧹 Nitpick comments (10)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (7)

134-135: Improve debug message for ADC readings.

The debug message is printing the percentage value as an 8-bit integer (0-255), which will truncate values and could cause confusion.

Apply this diff to fix the debug message:

-            sprintf_P(buf, PSTR("adc %d: %d (%d)"), i, static_cast<uint8_t>(adc_Percentage[i]), adc_value[i]);
+            sprintf_P(buf, PSTR("adc %d: %.2f (%d)"), i, adc_Percentage[i], adc_value[i]);

174-174: Fix spelling error in configuration key.

There's a spelling error in the configuration key "ChangeThreshould".

Apply this diff to fix the typo:

-    top["ChangeThreshould"] = change_threshold;
+    top["ChangeThreshold"] = change_threshold;

Make sure to update this in the readFromConfig method as well.


238-238: Fix spelling error in configuration key when reading.

The spelling error in the configuration key "ChangeThreshould" is also present in the readFromConfig method.

Apply this diff to fix the typo:

-    configComplete &= getJsonValue(top["ChangeThreshould"], change_threshold);
+    configComplete &= getJsonValue(top["ChangeThreshold"], change_threshold);

342-391: Consider adding MQTT entity categories for Home Assistant.

Home Assistant discovery can be improved by adding entity categories to help organize the sensors in the UI.

Add entity category to the discovery message:

     doc[F("dev_cla")] = device_class[pin_number].c_str();
     doc[F("unit_of_meas")] = unit_of_meas[pin_number].c_str();
     doc[F("val_tpl")] = F("{{ value }}");
+    doc[F("ent_cat")] = F("diagnostic");

103-103: Reconsider the force update interval multiplier.

Using a multiplier of 100 for the force update interval could lead to very long delays between forced updates.

Consider using a smaller multiplier or a fixed interval:

-      bool force_update = (millis() - lastTime) > (update_interval * 100); // to keep the mqtt alive if the light is not changing
+      bool force_update = (millis() - lastTime) > (update_interval * 10); // to keep the mqtt alive if the light is not changing

46-47: Enhance default device class and unit settings.

For a usermod that's primarily used with LDR sensors, consider using more appropriate defaults.

-      device_class[i] = "voltage"; // default device class
-      unit_of_meas[i] = "V"; // default unit of measurement
+      device_class[i] = "illuminance"; // default device class for LDR
+      unit_of_meas[i] = "lx"; // default unit of measurement for light sensors

1-4: Consider adjusting the maximum number of pins.

The default maximum of 1 ADC pin is quite limiting, especially for ESP32 which supports multiple ADC pins.

 #include "wled.h"
 #ifndef UM_ADC_MQTT_PIN_MAX_NUMBER
-#define UM_ADC_MQTT_PIN_MAX_NUMBER 1
+#define UM_ADC_MQTT_PIN_MAX_NUMBER 4
 #endif
usermods/adc_sensor_mqtt/README.md (3)

1-2: Improve README clarity and formatting.

The introduction paragraph has grammar and punctuation issues that should be fixed for better readability.

Apply these improvements to the introduction:

-# ADC sensor with MQTT ## based on LDR_Dusk_Dawn_v2 usermod from  [@jeffwdh](https://github.com/jeffwdh)  
-This usermod will obtain readings from adc pin. This is useful for ldr for example for exterior lighting situations where you want the lights to only be on when it is dark out. but this mod is designed for more hass application. it will publish auto discovery message to hass mqtt and attach the sensor to the wled integration automatically
+# ADC Sensor with MQTT
+## Based on LDR_Dusk_Dawn_v2 usermod from [@jeffwdh](https://github.com/jeffwdh)
+
+This usermod obtains readings from ADC pins. This is useful for LDR sensors, for example, for exterior lighting situations where you want the lights to only be on when it is dark out. The mod is designed for Home Assistant integration. It will publish an auto-discovery message to Home Assistant MQTT and attach the sensor to the WLED integration automatically.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~2-~2: A comma might be missing here.
Context: ...adings from adc pin. This is useful for ldr for example for exterior lighting situa...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~2-~2: A comma might be missing here.
Context: ...rom adc pin. This is useful for ldr for example for exterior lighting situations where ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~2-~2: You might be missing the article “an” here.
Context: ... more hass application. it will publish auto discovery message to hass mqtt and atta...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)


8-14: Add language identifier to code block.

The code block should specify a language for better syntax highlighting.

-```
+```ini
 [env:adc_sensor_mqtt_esp32dev]
 extends = env:esp32dev
 custom_usermods = ${env:esp32dev.custom_usermods} 
-  adc_sensor_mqtt   # Enable LDR Dusk Dawn Usermod
+  adc_sensor_mqtt   # Enable ADC Sensor MQTT Usermod

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

8-8: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

---

`12-13`: **Update comment in installation example.**

The comment in the installation example refers to "LDR Dusk Dawn Usermod" instead of the current usermod name.


```diff
 custom_usermods = ${env:esp32dev.custom_usermods} 
-  adc_sensor_mqtt   # Enable LDR Dusk Dawn Usermod
+  adc_sensor_mqtt   # Enable ADC Sensor MQTT Usermod
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 546839c and 5760d4d.

📒 Files selected for processing (6)
  • usermods/PIR_sensor_switch/PIR_sensor_switch.cpp (0 hunks)
  • usermods/adc_sensor_mqtt/README.md (1 hunks)
  • usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (1 hunks)
  • usermods/adc_sensor_mqtt/library.json (1 hunks)
  • wled00/const.h (1 hunks)
  • wled00/pin_manager.h (1 hunks)
💤 Files with no reviewable changes (1)
  • usermods/PIR_sensor_switch/PIR_sensor_switch.cpp
✅ Files skipped from review due to trivial changes (1)
  • usermods/adc_sensor_mqtt/library.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • wled00/const.h
  • wled00/pin_manager.h
🧰 Additional context used
🪛 LanguageTool
usermods/adc_sensor_mqtt/README.md

[uncategorized] ~2-~2: A comma might be missing here.
Context: ...adings from adc pin. This is useful for ldr for example for exterior lighting situa...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~2-~2: A comma might be missing here.
Context: ...rom adc pin. This is useful for ldr for example for exterior lighting situations where ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~2-~2: You might be missing the article “an” here.
Context: ... more hass application. it will publish auto discovery message to hass mqtt and atta...

(AI_EN_LECTOR_MISSING_DETERMINER_AN)

🪛 markdownlint-cli2 (0.17.2)
usermods/adc_sensor_mqtt/README.md

8-8: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


16-16: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)

Comment on lines 33 to 50
public:
adc_sensor_mqtt()
{
for (uint8_t i = 0; i < UM_ADC_MQTT_PIN_MAX_NUMBER; i++)
{
#ifdef ESP8266 // static assert
adc_pin[0] = 17; // A0
#else
adc_pin[i] = -1;
#endif
adc_value[i] = 0;
adc_Percentage[i] = 0;
adc_last_value[i] = 0;
device_class[i] = "voltage"; // default device class
unit_of_meas[i] = "V"; // default unit of measurement
}
// customize here your hass adc device class and unit of measurement
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add configuration options for device class settings in the constructor.

Provide common device class presets to make configuration easier for specific sensor types.

Add a configuration enum and extend the constructor to support common sensor types:

 public:
+  enum SensorType {
+    VOLTAGE,
+    ILLUMINANCE,
+    TEMPERATURE,
+    HUMIDITY
+  };
+  
+  void setSensorType(uint8_t index, SensorType type) {
+    if (index >= UM_ADC_MQTT_PIN_MAX_NUMBER) return;
+    
+    switch(type) {
+      case ILLUMINANCE:
+        device_class[index] = "illuminance";
+        unit_of_meas[index] = "lx";
+        break;
+      case TEMPERATURE:
+        device_class[index] = "temperature";
+        unit_of_meas[index] = "°C";
+        break;
+      case HUMIDITY:
+        device_class[index] = "humidity";
+        unit_of_meas[index] = "%";
+        break;
+      case VOLTAGE:
+      default:
+        device_class[index] = "voltage";
+        unit_of_meas[index] = "V";
+        break;
+    }
+  }

   adc_sensor_mqtt()
   {
     for (uint8_t i = 0; i < UM_ADC_MQTT_PIN_MAX_NUMBER; i++)
     {
 #ifdef ESP8266         // static assert
       adc_pin[0] = 17; // A0
 #else
       adc_pin[i] = -1;
 #endif
       adc_value[i] = 0;
       adc_Percentage[i] = 0;
       adc_last_value[i] = 0; 
-      device_class[i] = "voltage"; // default device class
-      unit_of_meas[i] = "V"; // default unit of measurement
+      setSensorType(i, ILLUMINANCE); // Default to illuminance for LDR sensors
     }
-    // customize here your hass adc device class and unit of measurement
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public:
adc_sensor_mqtt()
{
for (uint8_t i = 0; i < UM_ADC_MQTT_PIN_MAX_NUMBER; i++)
{
#ifdef ESP8266 // static assert
adc_pin[0] = 17; // A0
#else
adc_pin[i] = -1;
#endif
adc_value[i] = 0;
adc_Percentage[i] = 0;
adc_last_value[i] = 0;
device_class[i] = "voltage"; // default device class
unit_of_meas[i] = "V"; // default unit of measurement
}
// customize here your hass adc device class and unit of measurement
}
public:
enum SensorType {
VOLTAGE,
ILLUMINANCE,
TEMPERATURE,
HUMIDITY
};
void setSensorType(uint8_t index, SensorType type) {
if (index >= UM_ADC_MQTT_PIN_MAX_NUMBER) return;
switch(type) {
case ILLUMINANCE:
device_class[index] = "illuminance";
unit_of_meas[index] = "lx";
break;
case TEMPERATURE:
device_class[index] = "temperature";
unit_of_meas[index] = "°C";
break;
case HUMIDITY:
device_class[index] = "humidity";
unit_of_meas[index] = "%";
break;
case VOLTAGE:
default:
device_class[index] = "voltage";
unit_of_meas[index] = "V";
break;
}
}
adc_sensor_mqtt()
{
for (uint8_t i = 0; i < UM_ADC_MQTT_PIN_MAX_NUMBER; i++)
{
#ifdef ESP8266 // static assert
adc_pin[0] = 17; // A0
#else
adc_pin[i] = -1;
#endif
adc_value[i] = 0;
adc_Percentage[i] = 0;
adc_last_value[i] = 0;
setSensorType(i, ILLUMINANCE); // Default to illuminance for LDR sensors
}
}

Copy link
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: 0

♻️ Duplicate comments (3)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (3)

173-205: 🛠️ Refactor suggestion

Add a dropdown menu for sensor type selection in the configuration UI.

To improve user experience, add a dropdown menu for selecting common sensor types instead of requiring manual entry of device class and unit of measurement.

     JsonObject top = root.createNestedObject(FPSTR(_name));
     top["Enabled"] = adc_enabled;
+    // Add dropdown for sensor type selection
+    JsonArray sensorTypes = top.createNestedArray("SensorTypes");
+    sensorTypes.add("Voltage");
+    sensorTypes.add("Illuminance");
+    sensorTypes.add("Temperature");
+    sensorTypes.add("Humidity");
+    
     for (uint8_t i = 0; i < UM_ADC_MQTT_PIN_MAX_NUMBER; i++)
     {
       // debug
       DEBUG_PRINT(F("configuring adc_sensor_mqtt: Pin "));
       DEBUG_PRINT(i);
 #ifndef ESP8266 // esp8266 always use A0 no use of pin choice
       String adc_pin_name = F("AdcPin_");
       adc_pin_name += String(i);
       top[adc_pin_name] = adc_pin[i];
 #endif
+      String sensor_type_name = F("SensorType_");
+      sensor_type_name += String(i);
+      // Add dropdown for each sensor
+      JsonObject dropDown = top.createNestedObject(sensor_type_name);
+      dropDown["type"] = "select";
+      dropDown["value"] = getSensorTypeIndex(device_class[i]);
+      dropDown["options"] = sensorTypes;
+      
       // debug print new pin
       String device_class_name = F("DeviceClass_");
       device_class_name += String(i);
       top[device_class_name] = device_class[i].c_str();

Add a helper method to get the sensor type index:

private:
  uint8_t getSensorTypeIndex(const String& deviceClass) {
    if (deviceClass == "illuminance") return 1;
    if (deviceClass == "temperature") return 2;
    if (deviceClass == "humidity") return 3;
    return 0; // default to voltage
  }

142-147: ⚠️ Potential issue

Fix incorrect ADC percentage calculation formulas.

The current formulas for calculating percentage values (both inverted and non-inverted) are unnecessarily complex and might produce unexpected results.

Apply this diff to simplify and fix the percentage calculations:

-            adc_Percentage[i] = 100.0 - ((float)adc_value[i] * -1 + mapping) / mapping * 100.0f;
+            adc_Percentage[i] = 100.0 - ((float)adc_value[i] / mapping * 100.0f);
-            adc_Percentage[i] = ((float)adc_value[i] * -1 + mapping) / mapping * 100.0f;
+            adc_Percentage[i] = ((float)adc_value[i] / mapping * 100.0f);

51-67: 🛠️ Refactor suggestion

Add sensor type presets to improve usability.

Instead of requiring users to manually configure device_class and unit_of_measurement, adding preset configurations for common sensor types would improve the user experience.

 public:
+  enum SensorType {
+    VOLTAGE,
+    ILLUMINANCE,
+    TEMPERATURE,
+    HUMIDITY
+  };
+  
+  void setSensorType(uint8_t index, SensorType type) {
+    if (index >= UM_ADC_MQTT_PIN_MAX_NUMBER) return;
+    
+    switch(type) {
+      case ILLUMINANCE:
+        device_class[index] = "illuminance";
+        unit_of_meas[index] = "lx";
+        break;
+      case TEMPERATURE:
+        device_class[index] = "temperature";
+        unit_of_meas[index] = "°C";
+        break;
+      case HUMIDITY:
+        device_class[index] = "humidity";
+        unit_of_meas[index] = "%";
+        break;
+      case VOLTAGE:
+      default:
+        device_class[index] = "voltage";
+        unit_of_meas[index] = "V";
+        break;
+    }
+  }

   adc_sensor_mqtt()
   {
     for (uint8_t i = 0; i < UM_ADC_MQTT_PIN_MAX_NUMBER; i++)
     {
 #ifdef ESP8266         // static assert
       adc_pin[0] = 17; // A0
 #else
       adc_pin[i] = -1;
 #endif
       adc_value[i] = 0;
       adc_Percentage[i] = 0;
       adc_last_value[i] = 0;
-      device_class[i] = "voltage"; // default device class
-      unit_of_meas[i] = "V";       // default unit of measurement
+      setSensorType(i, ILLUMINANCE); // Default to illuminance for LDR sensors
     }
-    // customize here your hass adc device class and unit of measurement
   }
🧹 Nitpick comments (4)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (4)

121-126: Improve the force update logic for better clarity.

The current force update logic is complex and could be made more readable with clearer variable names and comments.

-      bool force_update = (millis() - lastTime) > (update_interval * 100); // to keep the mqtt alive if the light is not changing
-      bool regular_update = (millis() - lastTime) > update_interval;
-      if (regular_update || force_update ) // force update if the time is up or if the light is not changing to retain mqtt hass activity in case
+      // Update on regular interval or periodically to keep MQTT connection alive
+      const unsigned long currentTime = millis();
+      const unsigned long timeSinceLastUpdate = currentTime - lastTime;
+      const bool isRegularUpdateDue = timeSinceLastUpdate > update_interval;
+      const bool isLongTermUpdateDue = timeSinceLastUpdate > (update_interval * 100);
+      
+      if (isRegularUpdateDue || isLongTermUpdateDue)
       {
-        bool force_first_update = ((published_initial_value == false) && WLED_MQTT_CONNECTED);
-        lastTime = millis(); // reset lastTime to current time
+        // Force first update if MQTT is connected but no values were published yet
+        const bool isFirstUpdateNeeded = !published_initial_value && WLED_MQTT_CONNECTED;
+        lastTime = currentTime; // reset lastTime to current time

365-412: Add error handling for MQTT operations and optimize JSON memory usage.

The publishDiscovery method could benefit from additional error handling and more efficient memory management.

   void publishDiscovery(uint8_t pin_number)
   {
-    StaticJsonDocument<700> doc;
+    // Calculate buffer size based on the maximum possible content
+    const size_t capacity = JSON_OBJECT_SIZE(11) + JSON_OBJECT_SIZE(7) + JSON_ARRAY_SIZE(2) + 256;
+    StaticJsonDocument<capacity> doc;
     String uid = escapedMac.c_str();
     uid += F("_adc_");
     uid += String(pin_number);
@@ -410,7 +410,15 @@
     discovery_topic += F("/config");
     char json_str[700];
     size_t payload_size = serializeJson(doc, json_str);
-    hassDiscoverySent = mqtt->publish(discovery_topic.c_str(), 1, true, json_str, payload_size) > 0; // publish discovery message
+    
+    // Publish discovery message and handle errors
+    bool publishSuccess = mqtt->publish(discovery_topic.c_str(), 1, true, json_str, payload_size) > 0;
+    if (publishSuccess) {
+      hassDiscoverySent = true;
+      DEBUG_PRINTLN(F("Discovery message sent successfully"));
+    } else {
+      DEBUG_PRINTLN(F("Failed to send discovery message!"));
+    }
   }

340-363: Add retry mechanism for MQTT publishing.

The publishMqtt method could be enhanced with a retry mechanism for more reliable communication.

   void publishMqtt(int index, float state)
   {
     if (WLED_MQTT_CONNECTED)
     {
       DEBUG_PRINTLN(F("Publishing MQTT message..."));
+      const uint8_t maxRetries = 3;
+      uint8_t retryCount = 0;
+      bool publishSuccess = false;
+      
       if (!hassDiscoverySent && HomeAssistantDiscovery)
       {
         // publish all discovery message if not already done
@@ -354,7 +362,19 @@
       String mqtt_stat_topic = mqttDeviceTopic;
       mqtt_stat_topic += MQTT_TOPIC;
       mqtt_stat_topic += String(index);
-      mqtt->publish(mqtt_stat_topic.c_str(), 0, true, String(state, 2).c_str());
+      
+      // Attempt publishing with retries
+      String stateStr = String(state, 2);
+      while (!publishSuccess && retryCount < maxRetries) {
+        publishSuccess = mqtt->publish(mqtt_stat_topic.c_str(), 0, true, stateStr.c_str());
+        if (!publishSuccess) {
+          retryCount++;
+          DEBUG_PRINT(F("MQTT publish failed, retry "));
+          DEBUG_PRINT(retryCount);
+          DEBUG_PRINTLN(F(" of 3"));
+          delay(100); // Short delay before retry
+        }
+      }
       published_initial_value = true;
       DEBUG_PRINT(F("MQTT message sent: "));
       DEBUG_PRINT(mqtt_stat_topic.c_str());

149-166: Improve change threshold handling to avoid repetitive calculations.

The current implementation recalculates whether there's a meaningful change without considering the percentage value, which might lead to unnecessary MQTT updates.

-          if (abs(adc_value[i] - adc_last_value[i]) > change_threshold || force_update || force_first_update)
+          // Calculate the percentage change relative to the full range
+          float percentageChange = abs(adc_value[i] - adc_last_value[i]) / mapping * 100.0f;
+          
+          if (percentageChange > change_threshold || force_update || force_first_update)
           {
             adc_last_value[i] = adc_value[i];
             char buf[64];
-            sprintf_P(buf, PSTR("adc %d: %d (%d)"), i, static_cast<uint8_t>(adc_Percentage[i]), adc_value[i]);
+            sprintf_P(buf, PSTR("adc %d: %.1f%% (%d) - change: %.1f%%"), 
+                    i, adc_Percentage[i], adc_value[i], percentageChange);
             DEBUG_PRINTLN(buf);
             if (WLED_MQTT_CONNECTED)
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5dececb and 5fd149f.

📒 Files selected for processing (1)
  • usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (1 hunks)

@rommo911
Copy link
Author

I think a more or less generic analog sensor UM with MQTT and proper HA support would be greatly appreciated by other users. There have been several requests in this direction.

it is ready now, i tested it well on multiple targets :) . let me know you opinion

@DedeHai
Copy link
Collaborator

DedeHai commented Apr 23, 2025

generally looks really good, I have no means to test any of it though.

@rommo911
Copy link
Author

generally looks really good, I have no means to test any of it though.

i tested it on 5 targets normal ESP32 and C3/S2/S3 and esp8266. no monkey business found since couple of days in my setup.

@DedeHai DedeHai changed the title added new usermod photoresistor_sensor_mqtt_v2 with hass integration added new usermod adc_sensor_mqtt_v2 with hass integration Apr 24, 2025
Copy link
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: 0

🧹 Nitpick comments (5)
usermods/adc_sensor_mqtt/README.md (5)

1-3: Fix markdown heading style and improve initial description clarity.

The top-level heading has an extra trailing ##, and the description line contains grammar and punctuation issues. Consider:

  • Removing the stray ## or using a matching closing # (e.g., # ADC sensor with MQTT & HASS support #).
  • Rewriting the description for clarity, capitalizing acronyms (ADC, HASS) and fixing sentence structure.

Proposed diff:

-# ADC sensor with MQTT & HASS support ## 
-This usermod will obtain readings from adc pin. This is useful for ldr for example for exterior lighting situations where you want the lights to only be on when it is dark out. but this mod is designed for more hass application. it will publish auto discovery message to hass mqtt and attach the sensor to the wled integration automatically
+# ADC sensor with MQTT & HASS support #
+
+This usermod reads analog values from an ADC pin (e.g., using an LDR for exterior lighting). It publishes Home Assistant MQTT auto-discovery messages, automatically attaching the sensor to the WLED integration.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~2-~2: A comma might be missing here.
Context: ...adings from adc pin. This is useful for ldr for example for exterior lighting situa...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~2-~2: A comma might be missing here.
Context: ...rom adc pin. This is useful for ldr for example for exterior lighting situations where ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


4-12: Specify fenced code block language and use inline code formatting.

The installation example fence is missing a language identifier, and the usermod name should be formatted as inline code. Update the snippet as follows:

-```
+```ini
 [env:adc_sensor_mqtt_esp32dev]
 extends = env:esp32dev
 custom_usermods = ${env:esp32dev.custom_usermods}
-  adc_sensor_mqtt   # Enable  ADC sensor with MQTT
+  `adc_sensor_mqtt`   # Enable ADC sensor with MQTT
-```
+```
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

4-4: Heading style
Expected: atx_closed; Actual: atx

(MD003, heading-style)


7-7: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


14-16: Surround tables with blank lines and close headings.

Markdown tables should be preceded and followed by blank lines, and headings should have matching closing hashes:

-# Usermod Settings
-Setting | Description | Default
--- | --- | ---
+# Usermod Settings #
+
+Setting | Description | Default
+--- | --- | ---
+
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

14-14: Heading style
Expected: atx_closed; Actual: atx

(MD003, heading-style)


15-15: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)


17-26: Standardize table entries and improve wording.

Ensure each setting:

  • Uses inline code formatting for the setting name (e.g., `Pin`).
  • Capitalizes acronyms (ESP8266, ESP32, HASS).
  • Has clear and consistent descriptions.

Example adjustments:

-Enabled | Enable/Disable the LDR functionality. | Disabled
+`Enabled` | Enable or disable the analog sensor functionality. | false
-Pin | The analog capable pin your LDR is connected to. | A0 is forced in esp8266 and its not optional
+`Pin` | The analog-capable pin the sensor is connected to (ESP8266 only supports A0). | platform default
-AdcUpdateInterval | update interval to read the analog pin ( in ms ) | 3000
+`AdcUpdateInterval` | Interval in milliseconds between readings. | 3000
-Inverted | invert readings based on your own hardware setup ( invert mapping analog to digital value to  0V = 100%  or 3.3V = 100% ) | false
+`Inverted` | Invert the mapping (0 V = 100 % or 3.3 V = 100 %). | false
-ChangeThreshold | the minimum limit to detect change and publish the value ; checks the raw value ( int ;  5 ) . | 1
+`ChangeThreshold` | Minimum delta in raw value to trigger an MQTT update. | 1
-HASS | Enable home assistant mqtt discovery message with wled integration | true 
+`HASS` | Enable Home Assistant MQTT auto-discovery. | true
-Raw | publish the ADC value as raw measurement (0-4096 for ESP32 / 0-1024 for ESP8266) | false
+`Raw` | Publish the raw ADC value (0 – 4095 on ESP32, 0 – 1023 on ESP8266). | false
-DeviceClass | HASS sensor discovery device class | voltage 
+`DeviceClass` | Home Assistant sensor device class. | voltage
-UnitOfMeas | HASS sensor discovery device unit of measurements | V  
+`UnitOfMeas` | Home Assistant sensor unit of measurement. | V

27-28: Correct author link formatting and close heading.

There's an unintended space breaking the link syntax, and the heading should close with matching hashes:

-## Author
-[@rommo911] (https://github.com/rommo911)  
+## Author ##
+[@rommo911](https://github.com/rommo911)
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

27-27: Heading style
Expected: atx_closed; Actual: atx

(MD003, heading-style)


28-28: Bare URL used
null

(MD034, no-bare-urls)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5fd149f and 243ceb7.

📒 Files selected for processing (2)
  • usermods/adc_sensor_mqtt/README.md (1 hunks)
  • usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp
🧰 Additional context used
🪛 LanguageTool
usermods/adc_sensor_mqtt/README.md

[uncategorized] ~2-~2: A comma might be missing here.
Context: ...adings from adc pin. This is useful for ldr for example for exterior lighting situa...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~2-~2: A comma might be missing here.
Context: ...rom adc pin. This is useful for ldr for example for exterior lighting situations where ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

🪛 markdownlint-cli2 (0.17.2)
usermods/adc_sensor_mqtt/README.md

4-4: Heading style
Expected: atx_closed; Actual: atx

(MD003, heading-style)


7-7: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)


14-14: Heading style
Expected: atx_closed; Actual: atx

(MD003, heading-style)


15-15: Tables should be surrounded by blank lines
null

(MD058, blanks-around-tables)


27-27: Heading style
Expected: atx_closed; Actual: atx

(MD003, heading-style)


28-28: Bare URL used
null

(MD034, no-bare-urls)

@rommo911
Copy link
Author

it looks pretty decent now

image

in HASS
image

and added simple section to customize number of available sensor class/unit and their values properties
and added simplified customizable mapping ADC value mapping (by default maps 0..3.3V to 0..100 in addition to optional publish raw adc value without a unit )

@DedeHai
Copy link
Collaborator

DedeHai commented Apr 25, 2025

is the change threshold in ADC bits? would that be better to do in % of full scale or something more accessible to the "unknowing" user?

@rommo911
Copy link
Author

is the change threshold in ADC bits? would that be better to do in % of full scale or something more accessible to the "unknowing" user?

Yeah i though about it but it can be set to percentage but in this case i want it to be float value, example , getting change threshold to 0.5% or 2.5% , or in this case the default mapped value.
Let me change it to float and test it ans specify in the ui also how this behave.
Any other things to consider ?

Refines ADC value mapping and change detection logic.
@rommo911
Copy link
Author

rommo911 commented May 2, 2025

is the change threshold in ADC bits? would that be better to do in % of full scale or something more accessible to the "unknowing" user?

yeah i added logic to detect change either in raw value if activated or in mapped ( % ) value if raw value is disabled .

Copy link
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 (8)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (8)

38-39: Home Assistant Discovery enabled by default - consider potential impact.

The usermod enables HomeAssistantDiscovery by default, which will automatically send MQTT discovery messages when a device connects. While convenient for Home Assistant users, this could cause unnecessary network traffic for users who don't use Home Assistant.

Consider making this opt-in rather than opt-out for new installations:

- bool HomeAssistantDiscovery = true; // is HA discovery turned on by default
+ bool HomeAssistantDiscovery = false; // is HA discovery turned on by default

89-106: Improve error handling for pin allocation.

The current implementation doesn't clearly distinguish between different types of pin allocation failures or provide enough debugging information.

Improve the error handling with more specific messages:

 if ((adc_pin[i] != -1) && adc_enabled)
 {
#ifdef ESP8266
   if (adc_pin[i] == 17) // only one Pin supported : A0 for esp8266 //
#else
-  if ((_valid_adc_pin(adc_pin[i])) && PinManager::allocatePin(adc_pin[i], false, PinOwner::UM_ADC_MQTT)) // ESP32 only pins 32-39 are available for ADC
+  if (!_valid_adc_pin(adc_pin[i])) {
+    DEBUG_PRINT(F("adc_sensor_mqtt: Pin "));
+    DEBUG_PRINT(adc_pin[i]);
+    DEBUG_PRINTLN(F(" is not in valid ADC range!"));
+    adc_pin[i] = -1; // invalid pin -> disable this pin
+  } 
+  else if (!PinManager::allocatePin(adc_pin[i], false, PinOwner::UM_ADC_MQTT)) {
+    DEBUG_PRINT(F("adc_sensor_mqtt: Pin "));
+    DEBUG_PRINT(adc_pin[i]);
+    DEBUG_PRINTLN(F(" allocation failed, pin may be in use!"));
+    adc_pin[i] = -1; // allocation failed -> disable this pin
+  }
+  else // valid pin and allocation successful
#endif
   {
     pinMode(adc_pin[i], INPUT); // alloc success -> configure pin for input
     valid_pins++;
   }
   else
   {
-    DEBUG_PRINTLN(F("adc_sensor_mqtt: Pin allocation failed!"));
     adc_pin[i] = -1; // invalid pin -> disable this pin
   }

136-137: Improve logic for force update timing.

The current implementation uses update_interval * 100 for force updates, which might be excessive for longer update intervals. For example, with a 2000ms interval, this would be 200,000ms (over 3 minutes).

Consider using a more reasonable interval for force updates:

- bool force_update = (millis() - lastTime) > (update_interval * 100); // to keep the mqtt alive if the light is not changing
+ bool force_update = (millis() - lastTime) > min(update_interval * 10, 60000); // Force update at least every minute

154-158: Improve debug print format and efficiency.

The current debug message formatting could be improved, and there's a type conversion that might lose precision.

Refine the debug output:

- adc_last_mapped_value[i] = adc_mapped_value[i];
- char buf[64];
- sprintf_P(buf, PSTR("adc %d: %d (%d)"), i, static_cast<uint8_t>(adc_mapped_value[i]), adc_value[i]);
- DEBUG_PRINTLN(buf);
+ adc_last_mapped_value[i] = this->publishRawValue ? adc_value[i] : adc_mapped_value[i];
+ DEBUG_PRINTF("adc %d: %.2f (%d)\n", i, adc_mapped_value[i], adc_value[i]);

378-378: MQTT payload format could cause precision issues.

The current code publishes MQTT messages with 2 decimal places regardless of the data type or range, which might cause issues with some sensors requiring higher precision.

Consider adapting the precision based on the device class:

- mqtt->publish(mqtt_stat_topic.c_str(), 0, true, String(state, 2).c_str());
+ // Adjust precision based on device class
+ int precision = 2; // Default precision
+ if (device_class[index] == "temperature") precision = 1;
+ else if (device_class[index] == "illuminance") precision = 0;
+ mqtt->publish(mqtt_stat_topic.c_str(), 0, true, String(state, precision).c_str());

385-385: Potential memory issue with MQTT topics.

The code creates multiple String objects for MQTT topics, which could lead to memory fragmentation over time, especially on ESP8266 with limited RAM.

Consider using static buffers instead of String objects:

void publishMqtt(int index, float state)
{
  if (WLED_MQTT_CONNECTED)
  {
    DEBUG_PRINTLN(F("Publishing MQTT message..."));
    if (!hassDiscoverySent && HomeAssistantDiscovery)
    {
      // publish all discovery message if not already done
      for (uint8_t i = 0; i < UM_ADC_MQTT_PIN_MAX_NUMBER; i++)
      {
        publishDiscovery(i);
      }
    }
-   String mqtt_stat_topic = mqttDeviceTopic;
-   mqtt_stat_topic += MQTT_TOPIC;
-   mqtt_stat_topic += String(index);
+   char mqtt_stat_topic[128];
+   snprintf_P(mqtt_stat_topic, sizeof(mqtt_stat_topic), PSTR("%s%s%d"), 
+              mqttDeviceTopic.c_str(), MQTT_TOPIC, index);
+   
+   char value_str[16];
+   dtostrf(state, 0, 2, value_str);
-   mqtt->publish(mqtt_stat_topic.c_str(), 0, true, String(state, 2).c_str());
+   mqtt->publish(mqtt_stat_topic, 0, true, value_str);

400-405: Consider additional Home Assistant metadata for better integration.

The Home Assistant discovery message could benefit from additional metadata to improve integration.

Add more metadata to the Home Assistant discovery message:

doc[F("stat_t")] = mqtt_stat_topic;
doc[F("dev_cla")] = device_class[pin_number].c_str();
if (publishRawValue == false)
{
  doc[F("unit_of_meas")] = unit_of_meas[pin_number].c_str();
}
+ // Add state class for better graphing in Home Assistant
+ doc[F("stat_cla")] = F("measurement");
+ // Add entity category
+ doc[F("ent_cat")] = F("diagnostic");

447-448: Add battery as a device class option as discussed in PR feedback.

In the PR feedback, you discussed adding battery as one of the device class options, but it's not included in the final implementation.

Add battery as a device class option:

- const String adc_sensor_mqtt::device_classes[NUMBER_OF_DEFAULT_SENSOR_CLASSES] PROGMEM = {"illuminance", "current", "power", "temperature", "voltage"}; // default device class
- const String adc_sensor_mqtt::device_unit_of_measurement[NUMBER_OF_DEFAULT_SENSOR_CLASSES] PROGMEM = {"lx", "A", "W", "°C", "V"};                       // default unit of measurement
+ // Update NUMBER_OF_DEFAULT_SENSOR_CLASSES to 6 in the class definition
+ const String adc_sensor_mqtt::device_classes[NUMBER_OF_DEFAULT_SENSOR_CLASSES] PROGMEM = {"illuminance", "current", "power", "temperature", "voltage", "battery"}; // default device class
+ const String adc_sensor_mqtt::device_unit_of_measurement[NUMBER_OF_DEFAULT_SENSOR_CLASSES] PROGMEM = {"lx", "A", "W", "°C", "V", "%"};                       // default unit of measurement
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ee8743c and 21d4340.

📒 Files selected for processing (1)
  • usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (1 hunks)
🔇 Additional comments (2)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (2)

64-64: LGTM! The mapFloat function implementation is correct.

The function properly handles mapping values from one range to another using floating-point arithmetic.


267-305: Great work implementing the dropdown selections for device class and unit of measurement!

The UI configuration code provides an excellent user experience with dropdown options for device classes and units of measurement. This implementation addresses the previous feedback about providing user-friendly selection options.

Comment on lines 150 to 151
adc_mapped_value[i] = read_adc_mapping(adc_value[i]); // read adc value and map it to percentage
bool changed = this->publishRawValue ? (adc_value[i] != adc_last_mapped_value[i]) : (adc_mapped_value[i] != adc_last_mapped_value[i]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix comparison logic in change detection.

The current implementation compares the current mapped value with the last mapped value, but stores the mapped value in adc_last_mapped_value even when using raw values.

Update the comparison logic to properly track changes based on publishing mode:

- adc_mapped_value[i] = read_adc_mapping(adc_value[i]); // read adc value and map it to percentage
- bool changed = this->publishRawValue ? (adc_value[i] != adc_last_mapped_value[i]) : (adc_mapped_value[i] != adc_last_mapped_value[i]);
+ adc_mapped_value[i] = read_adc_mapping(adc_value[i]); // read adc value and map it to percentage
+ bool changed;
+ if (this->publishRawValue) {
+   changed = abs(adc_value[i] - adc_last_mapped_value[i]) > change_threshold;
+ } else {
+   changed = abs(adc_mapped_value[i] - adc_last_mapped_value[i]) > change_threshold;
+ }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +458 to +472
{
#ifdef ESP32
const uint16_t mapping = 4096; // ESP32 ADC resolution is 12 bit, so 4096 values
#else
const uint16_t mapping = 1024; // ESP8266 ADC resolution is 10 bit, so 1024 values
#endif
if (adc_sensor_mqtt::inverted) // default mapping value to 0-100 -- replace here your own mapping for your own unit of measurement
{
return mapFloat(rawValue, 0, mapping, 100, 0); // map raw value to percentage
}
else
{
return mapFloat(rawValue, 0, mapping, 0, 100); // map raw value to percentage
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance ADC mapping flexibility.

The current mapping function only supports percentage values. To be more generic, it would be useful to support custom scaling based on the selected device class.

Enhance the ADC mapping function to support different device classes:

float adc_sensor_mqtt::read_adc_mapping(uint16_t rawValue)
{
#ifdef ESP32
  const uint16_t mapping = 4096; // ESP32 ADC resolution is 12 bit, so 4096 values
#else
  const uint16_t mapping = 1024; // ESP8266 ADC resolution is 10 bit, so 1024 values
#endif
+ 
+ // Default percentage mapping (0-100%)
  if (adc_sensor_mqtt::inverted) // default mapping value to 0-100  -- replace here your own mapping for your own unit of measurement
  {
    return mapFloat(rawValue, 0, mapping, 100, 0); // map raw value to percentage
  }
  else
  {
    return mapFloat(rawValue, 0, mapping, 0, 100); // map raw value to percentage
  }
+ 
+ // Add custom mappings for specific device classes as needed
+ // Example for a voltage sensor (assuming 0V-3.3V range):
+ // if (device_class == "voltage") {
+ //   return mapFloat(rawValue, 0, mapping, 0, 3.3);
+ // }
}

Comment on lines +229 to +239
configComplete &= getJsonValue(top[str][F("Pin")], adc_pin[i]);
const bool valid_adc_pin = _valid_adc_pin(adc_pin[i]); // only ADC1 available on ESP32 with wifi
if (!valid_adc_pin || !PinManager::isPinOk(adc_pin[i], false)) // // ESP32 only pins 32-39 are available for ADC
{
DEBUG_PRINT(F("adc_sensor_mqtt: Pin "));
DEBUG_PRINT(i);
DEBUG_PRINTLN(F(" is not valid!"));
configComplete = false; // pin not valid -> disable usermod
adc_pin[i] = -1; // invalid pin -> disable usermod
}
else
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix logical error in pin validation.

The code has a logical error where configComplete is incorrectly set to false and the usermod is disabled when a pin is invalid, but the loop continues and might process valid pins later.

Correct the validation logic:

configComplete &= getJsonValue(top[str][F("Pin")], adc_pin[i]);
const bool valid_adc_pin = _valid_adc_pin(adc_pin[i]);         // only ADC1 available on ESP32 with wifi
if (!valid_adc_pin || !PinManager::isPinOk(adc_pin[i], false)) // // ESP32 only pins 32-39 are available for ADC
{
  DEBUG_PRINT(F("adc_sensor_mqtt: Pin "));
  DEBUG_PRINT(i);
  DEBUG_PRINTLN(F(" is not valid!"));
- configComplete = false; // pin not valid -> disable usermod
  adc_pin[i] = -1;        // invalid pin -> disable usermod
}

Copy link
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: 0

♻️ Duplicate comments (2)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (2)

148-149: ⚠️ Potential issue

Fix comparison logic in change detection.

The current implementation compares the current mapped value with the last mapped value, but stores the mapped value in adc_last_mapped_value even when using raw values.

adc_mapped_value[i] = read_adc_mapping(adc_value[i]); // read adc value and map it to percentage
-bool changed = this->publishRawValue ? (adc_value[i] != adc_last_mapped_value[i]) : (adc_mapped_value[i] != adc_last_mapped_value[i]);
+bool changed;
+if (this->publishRawValue) {
+  changed = abs(adc_value[i] - adc_last_mapped_value[i]) > change_threshold;
+} else {
+  changed = abs(adc_mapped_value[i] - adc_last_mapped_value[i]) > change_threshold;
+}

227-237: ⚠️ Potential issue

Fix logical error in pin validation.

The code has a logical error where configComplete is incorrectly set to false and the usermod is disabled when a pin is invalid, but the loop continues and might process valid pins later.

configComplete &= getJsonValue(top[str][F("Pin")], adc_pin[i]);
const bool valid_adc_pin = _valid_adc_pin(adc_pin[i]);         // only ADC1 available on ESP32 with wifi
if (!valid_adc_pin || !PinManager::isPinOk(adc_pin[i], false)) // // ESP32 only pins 32-39 are available for ADC
{
  DEBUG_PRINT(F("adc_sensor_mqtt: Pin "));
  DEBUG_PRINT(i);
  DEBUG_PRINTLN(F(" is not valid!"));
- configComplete = false; // pin not valid -> disable usermod
  adc_pin[i] = -1;        // invalid pin -> disable usermod
}
🧹 Nitpick comments (3)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (3)

33-55: Member variables are well organized but consider naming convention consistency.

The class variables are well-structured, but there's inconsistency in naming conventions. WLED typically uses camelCase for variable names (like lastTime), but many variables use snake_case (like adc_pin, adc_value). Consider standardizing on camelCase for better consistency with the rest of the WLED codebase.


58-61: Add parameter validation to mapFloat function.

The mapFloat function could encounter a division by zero error if in_max equals in_min.

static inline float mapFloat(int x, int in_min, int in_max, float out_min, float out_max)
{
+  if (in_max == in_min) return out_min; // Prevent division by zero
  return ((float)(x - in_min) * (out_max - out_min)) / (float)(in_max - in_min) + out_min;
}

453-468: Enhance ADC mapping flexibility.

The current mapping function only supports percentage values. To be more generic, it would be useful to support custom scaling based on the selected device class.

float adc_sensor_mqtt::read_adc_mapping(uint16_t rawValue)
{
#ifdef ESP32
  const uint16_t mapping = 4096; // ESP32 ADC resolution is 12 bit, so 4096 values
#else
  const uint16_t mapping = 1024; // ESP8266 ADC resolution is 10 bit, so 1024 values
#endif
+ 
+ // Default percentage mapping (0-100%)
  if (adc_sensor_mqtt::inverted) // default mapping value to 0-100  -- replace here your own mapping for your own unit of measurement
  {
    return mapFloat(rawValue, 0, mapping, 100, 0); // map raw value to percentage
  }
  else
  {
    return mapFloat(rawValue, 0, mapping, 0, 100); // map raw value to percentage
  }
+ 
+ // Add custom mappings for specific device classes as needed
+ // Example for a voltage sensor (assuming 0V-3.3V range):
+ // if (device_class == "voltage") {
+ //   return mapFloat(rawValue, 0, mapping, 0, 3.3);
+ // }
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 21d4340 and 9dae91a.

📒 Files selected for processing (1)
  • usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (1 hunks)
🔇 Additional comments (4)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (4)

1-29: Platform-specific configuration looks good.

The preprocessor directives handle different ESP variants correctly, defining appropriate pin ranges for each target platform. The static assert for ESP8266 ensures that only one ADC pin is defined, which matches hardware capabilities.


266-302: Good UI implementation with dropdown selections.

The dropdown implementation for device class and unit selection enhances user experience, making it easier to configure the sensor. This is an excellent improvement over text fields.


359-382: MQTT publishing implementation looks good.

The method to publish sensor values to MQTT handles all necessary aspects - checking connection status, handling discovery messages, and formatting the payload correctly.


384-434: Comprehensive Home Assistant discovery implementation.

The discovery message includes all necessary information for Home Assistant to properly integrate the sensor, including device metadata, availability topics, and sensor-specific configuration. Good attention to detail with hardware version detection and connection information.

Copy link
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: 1

♻️ Duplicate comments (1)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (1)

225-235: ⚠️ Potential issue

Fix logical error in pin validation

The pin validation logic incorrectly disables the entire usermod if any pin is invalid by setting configComplete = false. This prevents the usermod from working even when other pins are valid.

      configComplete &= getJsonValue(top[str][F("Pin")], adc_pin[i]);
      const bool valid_adc_pin = _valid_adc_pin(adc_pin[i]);         // only ADC1 available on ESP32 with wifi
      if (!valid_adc_pin || !PinManager::isPinOk(adc_pin[i], false)) // // ESP32 only pins 32-39 are available for ADC
      {
        DEBUG_PRINT(F("adc_sensor_mqtt: Pin "));
        DEBUG_PRINT(i);
        DEBUG_PRINTLN(F(" is not valid!"));
-        configComplete = false; // pin not valid -> disable usermod
        adc_pin[i] = -1;        // invalid pin -> disable usermod
      }
🧹 Nitpick comments (2)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (2)

63-79: Remove outdated comment about customizing HASS settings

The comment on line 78 about customizing HASS device class and unit of measurement is now outdated since these settings are handled through the configuration UI.

    }
-    // customize here your hass adc device class and unit of measurement
  }

451-466: Consider enhancing the ADC mapping to support different sensor types

The current mapping function only supports percentage conversion. For greater flexibility, consider extending it to support different mappings based on the selected device class.

float adc_sensor_mqtt::read_adc_mapping(uint16_t rawValue)
{
#ifdef ESP32
  const uint16_t mapping = 4096; // ESP32 ADC resolution is 12 bit, so 4096 values
#else
  const uint16_t mapping = 1024; // ESP8266 ADC resolution is 10 bit, so 1024 values
#endif
+ 
+ // This function could be extended to support different mappings based on the device class
+ // For example, for voltage sensors, map to 0-3.3V depending on the ESP platform
+ 
  if (adc_sensor_mqtt::inverted) // default mapping value to 0-100  -- replace here your own mapping for your own unit of measurement
  {
    return mapFloat(rawValue, 0, mapping, 100, 0); // map raw value to percentage
  }
  else
  {
    return mapFloat(rawValue, 0, mapping, 0, 100); // map raw value to percentage
  }
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9dae91a and 7882dcf.

📒 Files selected for processing (1)
  • usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (1 hunks)
🔇 Additional comments (3)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (3)

16-29: Good platform-specific handling for ESP32 variants

The code properly defines valid ADC pin ranges for different ESP32 variants using preprocessor conditionals. This ensures the usermod works correctly across the ESP32 family.


264-300: Good UI implementation with dropdowns for device class and unit

The UI configuration is well-implemented with dropdown menus for device class and unit of measurement, which greatly improves user experience as requested in the PR feedback.


382-432: Good Home Assistant discovery implementation

The Home Assistant discovery implementation is comprehensive and includes all necessary fields for proper integration, including unique ID, name, state topic, device class, unit of measurement, and device metadata.

// DEBUG_PRINTLN(F("adc_sensor_mqtt:loop Pin not valid!"));
continue; // skip if pin is not valid
}
bool changed = this->publishRawValue ? (abs(adc_value[i] - analogRead(adc_pin[i])) > change_threshold) : (abs(adc_mapped_value[i] - read_adc_mapping(analogRead(adc_pin[i]))) > change_threshold);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize ADC reading to avoid redundant analogRead() calls

The current change detection logic reads the analog pin twice - once for comparison and again for storage. This is inefficient and may lead to inconsistent values if the analog reading changes between calls.

-          bool changed = this->publishRawValue ? (abs(adc_value[i] - analogRead(adc_pin[i])) > change_threshold) : (abs(adc_mapped_value[i] - read_adc_mapping(analogRead(adc_pin[i]))) > change_threshold);
+          uint16_t current_reading = analogRead(adc_pin[i]);
+          float current_mapped = read_adc_mapping(current_reading);
+          bool changed = this->publishRawValue ? 
+                        (abs(adc_value[i] - current_reading) > change_threshold) : 
+                        (abs(adc_mapped_value[i] - current_mapped) > change_threshold);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bool changed = this->publishRawValue ? (abs(adc_value[i] - analogRead(adc_pin[i])) > change_threshold) : (abs(adc_mapped_value[i] - read_adc_mapping(analogRead(adc_pin[i]))) > change_threshold);
// Cache the ADC reading and its mapped value to avoid double reads
uint16_t current_reading = analogRead(adc_pin[i]);
float current_mapped = read_adc_mapping(current_reading);
bool changed = this->publishRawValue
? (abs(adc_value[i] - current_reading) > change_threshold)
: (abs(adc_mapped_value[i] - current_mapped) > change_threshold);

Copy link
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: 0

♻️ Duplicate comments (4)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (4)

452-466: Enhance ADC mapping flexibility.

The current mapping function only supports percentage values. To be more generic, it would be useful to support custom scaling based on the selected device class.

float adc_sensor_mqtt::read_adc_mapping(uint16_t rawValue)
{
#ifdef ESP32
  const uint16_t mapping = 4096; // ESP32 ADC resolution is 12 bit, so 4096 values
#else
  const uint16_t mapping = 1024; // ESP8266 ADC resolution is 10 bit, so 1024 values
#endif
+ 
+ // Default percentage mapping (0-100%)
  if (adc_sensor_mqtt::inverted) // default mapping value to 0-100  -- replace here your own mapping for your own unit of measurement
  {
    return mapFloat(rawValue, 0, mapping, 100, 0); // map raw value to percentage
  }
  else
  {
    return mapFloat(rawValue, 0, mapping, 0, 100); // map raw value to percentage
  }
+ 
+ // Add custom mappings for specific device classes as needed
+ // Example for a voltage sensor (assuming 0V-3.3V range):
+ // if (device_class == "voltage") {
+ //   return mapFloat(rawValue, 0, mapping, 0, 3.3);
+ // }
}

78-78: Please add more device class options to the dropdown.

As discussed in previous reviews, adding a selection of the most relevant device classes for WLED applications would improve usability.

Based on the previous discussion between DedeHai and rommo911, please verify that you've implemented the dropdown with the agreed-upon device classes:

  • battery (%)
  • illuminance (lx)
  • temperature (°C)
  • voltage (V)
  • current (mA)
  • None (N/A)
#!/bin/bash
# Check if the device classes in the code match the agreed list
grep -A5 "const char \\*adc_sensor_mqtt::device_classes" usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp

146-146: 🛠️ Refactor suggestion

Optimize ADC reading to avoid redundant analogRead() calls.

The current change detection logic reads the analog pin twice - once for comparison and again for storage. This is inefficient and may lead to inconsistent values if the analog reading changes between calls.

-          bool changed = this->publishRawValue ? (abs(adc_value[i] - analogRead(adc_pin[i])) > change_threshold) : (abs(adc_mapped_value[i] - read_adc_mapping(analogRead(adc_pin[i]))) > change_threshold);
+          uint16_t current_reading = analogRead(adc_pin[i]);
+          float current_mapped = read_adc_mapping(current_reading);
+          bool changed = this->publishRawValue ? 
+                        (abs(adc_value[i] - current_reading) > change_threshold) : 
+                        (abs(adc_mapped_value[i] - current_mapped) > change_threshold);

225-235: ⚠️ Potential issue

Fix logical error in pin validation.

The code has a logical error where configComplete is incorrectly set to false and the usermod is disabled when a pin is invalid, but the loop continues and might process valid pins later.

configComplete &= getJsonValue(top[str][F("Pin")], adc_pin[i]);
const bool valid_adc_pin = _valid_adc_pin(adc_pin[i]);         // only ADC1 available on ESP32 with wifi
if (!valid_adc_pin || !PinManager::isPinOk(adc_pin[i], false)) // // ESP32 only pins 32-39 are available for ADC
{
  DEBUG_PRINT(F("adc_sensor_mqtt: Pin "));
  DEBUG_PRINT(i);
  DEBUG_PRINTLN(F(" is not valid!"));
- configComplete = false; // pin not valid -> disable usermod
  adc_pin[i] = -1;        // invalid pin -> disable usermod
}
🧹 Nitpick comments (2)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (2)

156-164: Simplify redundant MQTT publishing logic.

The conditional statement is unnecessary since both branches call the same function with the same parameters.

-          if (publishRawValue)
-          {
-            publishMqtt(i);
-          }
-          else
-          {
-            publishMqtt(i);
-          }
+          publishMqtt(i);

145-151: Add validation for extreme ADC values.

Consider adding validation for the ADC readings to handle potential outliers or invalid readings.

          uint16_t current_reading = analogRead(adc_pin[i]);
+          // Filter out invalid or extreme readings
+          #ifdef ESP32
+          if (current_reading > 4095) current_reading = 4095; // ESP32 max ADC value
+          #else
+          if (current_reading > 1023) current_reading = 1023; // ESP8266 max ADC value
+          #endif
          adc_mapped_value[i] = read_adc_mapping(current_reading);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7882dcf and e1ae636.

📒 Files selected for processing (1)
  • usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (3)
wled00/pin_manager.h (5)
  • allocatePin (89-89)
  • allocatePin (97-97)
  • isPinOk (104-104)
  • deallocatePin (83-83)
  • deallocatePin (99-99)
usermods/PIR_sensor_switch/PIR_sensor_switch.cpp (4)
  • publishMqtt (274-294)
  • publishMqtt (274-274)
  • setup (370-390)
  • setup (370-370)
usermods/SN_Photoresistor/SN_Photoresistor.cpp (1)
  • REGISTER_USERMOD (214-214)
🔇 Additional comments (5)
usermods/adc_sensor_mqtt/adc_sensor_mqtt.cpp (5)

16-29: Excellent platform-specific pin validation approach.

The code correctly handles different pin configurations for various ESP32 variants (ESP32, ESP32-S2/S3, ESP32-C3), ensuring only ADC1 pins are used since ADC2 can't be used with WiFi active. This is a robust approach to cross-platform compatibility.


34-54: Well-organized member variables with clear initialization.

The class member variables are logically organized with good naming conventions and sensible default values. The use of static const variables for device classes and units of measurement provides flexibility while maintaining memory efficiency.


272-300: Great configuration UI with dropdown menus for sensor types.

The implementation of dropdown menus for device classes and units of measurement enhances usability, making it easy for users to configure the sensor without needing to look up valid Home Assistant device classes.


382-432: Comprehensive Home Assistant MQTT discovery implementation.

The MQTT discovery implementation is thorough, providing all necessary information for Home Assistant to automatically discover and configure the sensor, including unique IDs, device metadata, and availability tracking.


468-470: Good implementation of usermod registration.

The code correctly registers the usermod instance with the WLED framework using the standard REGISTER_USERMOD macro.

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.

3 participants