Skip to content

Update and improve INA226 usermod#5411

Closed
daggerrz wants to merge 9 commits intowled:mainfrom
magwled:feature/configurable-ina226-params
Closed

Update and improve INA226 usermod#5411
daggerrz wants to merge 9 commits intowled:mainfrom
magwled:feature/configurable-ina226-params

Conversation

@daggerrz
Copy link

@daggerrz daggerrz commented Mar 8, 2026

Improves the INA226 usermod to work correctly out of the box and be easier to configure. Previously, the usermod was silently disabled by default, had no serial debug output, couldn't represent common low-value shunt resistors, and showed no units in the config UI.

  • Add compile-time -D flags for hardware-specific defaults (INA226_SHUNT_MICRO_OHMS, INA226_DEFAULT_CURRENT_RANGE, INA226_CURRENT_OFFSET_MA, INA226_ADDRESS)
    so board profiles can ship with correct values without requiring runtime configuration
  • Initialize all bit fields in constructor — _settingEnabled was uninitialized and defaulted to false for static objects, silently disabling the usermod
  • Add serial debug output on init (config params, operating mode) and on each reading
  • Show shunt voltage drop in mV instead of V, renamed to "Shunt Voltage Drop"
  • Add unit labels (mΩ, mA, μs, seconds) to config UI via appendConfigData()
  • Store ShuntResistor as float milliohms, allowing decimal values like 4.8 for 4.8mΩ
  • Reduce default check interval from 60s to 1s

Breaking changes

ShuntResistor config value: Previously stored as integer milliohms, now stored as float milliohms. Old integer values (e.g. 1000 for 1Ω) will still parse
correctly. However, sub-milliohm shunt values that were previously truncated to 0 will need to be re-entered. This is an acceptable tradeoff because:

  • The old integer format couldn't represent common low-value shunts (e.g. 4.8mΩ, 0.5mΩ) — it silently truncated them
  • Anyone using sub-milliohm shunts was getting wrong readings anyway, so there's no valid config to break

Shunt voltage MQTT topic: Changed from shunt_voltage to shunt_voltage_drop, unit changed from V to mV. This breaks existing HA dashboards or automations referencing the old topic. I think it's worth it because:

  • "Shunt Voltage Drop" is the correct term for what was actually measured
  • mV is the appropriate unit for typical shunt drops (sub-1mV to tens of mV)

Summary by CodeRabbit

  • New Features

    • Added Current Offset setting for INA226 measurements
    • New UI/config display for INA226 parameters and compile-time defaults
  • Improvements

    • Interval handling now uses milliseconds for finer scheduling
    • Shunt reading renamed to "Shunt Voltage Drop" (reported in mV); current offset applied to readings
    • MQTT topic and sensor names updated for clarity
    • Clearer init error message and enhanced debug output
  • Documentation

    • Added compile-time defaults guide with examples

daggerrz added 6 commits March 8, 2026 17:35
_settingEnabled was uninitialized, defaulting to false for static
objects, which silently disabled the usermod. Default it to true
and explicitly initialize all other bit fields.
Log configuration parameters and operating mode on init, and
print each measurement reading to serial when WLED_DEBUG is enabled.
With low-value shunt resistors the voltage drop rounds to 0.00V.
Read in mV, rename label to "Shunt Voltage Drop", and update the
MQTT topic and HA discovery accordingly.
Add appendConfigData() to show units (seconds, mΩ, mA, μs, etc.)
next to each config field. Store ShuntResistor as float milliohms
so values like 4.8 mΩ can be entered directly. Old integer configs
remain backward compatible.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 8, 2026

Walkthrough

Added compile-time defaults and unit changes for INA226 (μΩ, mA); replaced interval tracking with _checkIntervalMs; introduced current offset handling and adjusted measurements to mV; renamed MQTT/topic keys to shunt_voltage_drop; added config parsing and appendConfigData(); updated README.

Changes

Cohort / File(s) Summary
Core usermod
usermods/INA226_v2/INA226_v2.cpp
Added compile-time defaults and #ifndef INA226_ADDRESS guard; replaced _checkInterval with _checkIntervalMs (ms); migrated _shuntResistor_shuntResistorUOhm, _currentRange_currentRangeMa, added _currentOffsetMa; updated init/log messages and DEBUG output; changed trigger logic to use _checkIntervalMs; shunt voltage now in mV and current subtracts _currentOffsetMa; MQTT/topic and JSON keys renamed to shunt_voltage_drop; added appendConfigData() and updated readFromConfig.
Documentation
usermods/INA226_v2/README.md
Added CurrentOffset setting and Compile-time Defaults section documenting build flags (INA226_ADDRESS, INA226_SHUNT_MICRO_OHMS, INA226_DEFAULT_CURRENT_RANGE, INA226_CURRENT_OFFSET_MA); included example INI and note that compile-time defaults can be overridden at runtime.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Update and improve INA226 usermod' is generic and vague, describing the general nature of changes without conveying the specific modifications made to the usermod. Consider a more specific title that highlights the main change, such as 'Add compile-time defaults and improve INA226 usermod configuration' or 'Refactor INA226 usermod with configurable parameters and debug output'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

❤️ Share

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

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@usermods/INA226_v2/INA226_v2.cpp`:
- Line 100: The _checkIntervalMs field must be widened to 32-bit to avoid
overflow when the user-configured seconds are multiplied by 1000; change the
declaration of _checkIntervalMs from uint16_t to uint32_t and update any
assignments/calculations that set it (the code that multiplies the seconds value
by 1000) to use the new type, ensuring any callers, setters, and comparisons
(including the logic that selects mode based on _checkIntervalMs) handle
uint32_t and that any format specifiers or explicit casts are adjusted
accordingly.
- Around line 561-569: The code must reject non-positive shunt and range values
before they get used by setResistorRange; after reading ShuntResistor with
getJsonValue into shuntMilliOhms, verify shuntMilliOhms > 0 before assigning
_shuntResistorUOhm and otherwise set configComplete = false; similarly, when
reading CurrentRange into _currentRangeMa treat a missing or non-positive value
as invalid (set configComplete = false) instead of accepting 0; keep the
existing fallback for CurrentOffset using INA226_CURRENT_OFFSET_MA. Reference
symbols: getJsonValue, shuntMilliOhms, _shuntResistorUOhm, _currentRangeMa,
setResistorRange, INA226_CURRENT_OFFSET_MA.

In `@usermods/INA226_v2/README.md`:
- Around line 69-93: Update the Compile-time Defaults (or a newly added
"MQTT/topic migration" subsection) to document that the MQTT field/topic
formerly named "shunt_voltage" has been renamed to "shunt_voltage_drop" and its
unit changed from V to mV; explicitly call out that existing dashboards,
automations, and integrations must be updated to use the new name and unit, show
the old → new mapping (shunt_voltage → shunt_voltage_drop) and unit conversion
(V → mV) so users can adjust thresholds/graphs, and mention any retained
backward-compatibility behavior (if none, state that topics/payloads are
breaking changes).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c4297ef6-36c3-4aa6-8917-cd201bd3f615

📥 Commits

Reviewing files that changed from the base of the PR and between 53d6c4b and 85c6da8.

📒 Files selected for processing (2)
  • usermods/INA226_v2/INA226_v2.cpp
  • usermods/INA226_v2/README.md

Comment on lines +69 to +93
### Compile-time Defaults

Several parameters can be overridden at compile time via `-D` build flags. This is useful for setting board-specific defaults so the device works correctly on first boot without manual configuration.

| Build Flag | Default | Unit | Description |
|---|---|---|---|
| `INA226_ADDRESS` | `0x40` | — | I2C address of the INA226 |
| `INA226_SHUNT_MICRO_OHMS` | `1000000` | μΩ | Shunt resistor value (1 000 000 μΩ = 1 Ω) |
| `INA226_DEFAULT_CURRENT_RANGE` | `1000` | mA | Expected maximum current (1000 mA = 1 A) |
| `INA226_CURRENT_OFFSET_MA` | `0` | mA | Current offset subtracted from readings |

Example for a board with a 4.8 mΩ shunt, 10 A range, and 53 mA offset:

```ini
[env:my_board]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} INA226
build_flags = ${env:esp32dev.build_flags}
-D USERMOD_INA226
-D INA226_SHUNT_MICRO_OHMS=4800
-D INA226_DEFAULT_CURRENT_RANGE=10000
-D INA226_CURRENT_OFFSET_MA=53
```

All compile-time defaults can still be changed at runtime through the Usermod settings page. No newline at end of file
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 8, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Document the MQTT/topic migration in this section.

This PR intentionally renames shunt_voltage to shunt_voltage_drop and changes the unit from V to mV, but the README still does not call out that existing dashboards and automations need to be updated.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@usermods/INA226_v2/README.md` around lines 69 - 93, Update the Compile-time
Defaults (or a newly added "MQTT/topic migration" subsection) to document that
the MQTT field/topic formerly named "shunt_voltage" has been renamed to
"shunt_voltage_drop" and its unit changed from V to mV; explicitly call out that
existing dashboards, automations, and integrations must be updated to use the
new name and unit, show the old → new mapping (shunt_voltage →
shunt_voltage_drop) and unit conversion (V → mV) so users can adjust
thresholds/graphs, and mention any retained backward-compatibility behavior (if
none, state that topics/payloads are breaking changes).

Copy link
Author

Choose a reason for hiding this comment

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

I don't think this belongs in the README.md, but rather in the release notes. Anyone have an opinion?

Copy link
Contributor

Choose a reason for hiding this comment

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

@daggerrz, that's a fair point — release notes are the natural place to call out breaking changes for a specific version. However, there's a case for a small note in the README as well: release notes tend to get buried over time, while the README is what a user sees when they first look at the module or when they're troubleshooting a broken dashboard months after upgrading. Many projects (e.g., Home Assistant integrations, Mosquitto-based tools) keep a short "Upgrading / Breaking Changes" section in the README alongside the main changelog entry, so the information stays discoverable long-term.

A lightweight middle ground could be:

  • Release notes – the primary call-out, with the full old → new mapping.
  • README – a brief, permanent note (one or two lines) in the configuration section under ShuntResistor / MQTT settings, e.g.:

⚠️ Breaking change (v<X>): The MQTT topic shunt_voltage (V) has been renamed to shunt_voltage_drop (mV). Existing dashboards and automations must be updated.

That way users who land on the README without reading the release notes are still warned. But if the project's convention is to keep only release notes for such notices, that's perfectly reasonable too — ultimately it's your call as the maintainer.


🧠 Learnings used
Learnt from: netmindz
Repo: wled/WLED PR: 5311
File: platformio.ini:395-395
Timestamp: 2026-01-31T18:19:33.055Z
Learning: In WLED, usermods can be referenced as out-of-tree library dependencies (e.g., via lib_deps pointing to external repositories) while the `custom_usermods` setting in platformio.ini controls which in-tree usermods are enabled. Setting `custom_usermods = ` (empty) only disables in-tree usermods; out-of-tree usermods pulled via library dependencies remain active.

Learnt from: KrX3D
Repo: wled/WLED PR: 4237
File: usermods/ina2xx_v2/ina2xx_v2.cpp:178-185
Timestamp: 2025-05-06T20:31:05.208Z
Learning: KrX3D plans to add INA226 support to the INA2xx usermod in a future update. Currently, the code only instantiates INA219_WE objects despite the more generic naming.

Learnt from: KrX3D
Repo: wled/WLED PR: 4585
File: usermods/seven_segment_display_reloaded_v2/seven_segment_display_reloaded_v2.cpp:612-617
Timestamp: 2026-02-18T00:41:15.185Z
Learning: In the seven_segment_display_reloaded_v2 usermod (PR `#4585`), the `addToConfig()` method intentionally calls `_updateMQTT()` to publish MQTT state on every config save. This behavior is by design and should not be flagged as an issue.

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/INA226_v2/INA226_v2.cpp (1)

561-568: ⚠️ Potential issue | 🟠 Major

Reject non-positive calibration inputs here.

ShuntResistor <= 0 and CurrentRange == 0 are still accepted, so one bad cfg entry can leave the module calibrated with nonsensical values until the setting is fixed. Please fall back to the compile-time defaults and mark the config incomplete when either field is missing or non-positive.

Proposed fix
         float shuntMilliOhms;
-        if (getJsonValue(top[F("ShuntResistor")], shuntMilliOhms))
+        if (getJsonValue(top[F("ShuntResistor")], shuntMilliOhms) && shuntMilliOhms > 0.0f)
             _shuntResistorUOhm = static_cast<uint32_t>(shuntMilliOhms * 1000.0f + 0.5f);
-        else
+        else {
+            _shuntResistorUOhm = INA226_SHUNT_MICRO_OHMS;
             configComplete = false;
+        }
 
-        configComplete &= getJsonValue(top[F("CurrentRange")], _currentRangeMa);
+        if (!getJsonValue(top[F("CurrentRange")], _currentRangeMa) || _currentRangeMa == 0) {
+            _currentRangeMa = INA226_DEFAULT_CURRENT_RANGE;
+            configComplete = false;
+        }
         if (!getJsonValue(top[F("CurrentOffset")], _currentOffsetMa))
             _currentOffsetMa = INA226_CURRENT_OFFSET_MA;  // Use compile-time default if missing from config
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@usermods/INA226_v2/INA226_v2.cpp` around lines 561 - 568, The code currently
accepts non-positive ShuntResistor and CurrentRange values; modify the logic
around getJsonValue for top[F("ShuntResistor")] and top[F("CurrentRange")] so
that if the parsed shuntMilliOhms <= 0 or _currentRangeMa == 0 you restore the
compile-time defaults (reset _shuntResistorUOhm to the constant default and
_currentRangeMa to its default), set configComplete = false, and do not apply
the invalid value; keep using getJsonValue and update the configComplete boolean
accordingly (also ensure the branch that sets _currentOffsetMa remains unchanged
except for relying on the validated range).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@usermods/INA226_v2/INA226_v2.cpp`:
- Around line 344-350: The default conversion time is being stored in raw
microseconds but the code expects the shifted representation (µs >> 2); update
the initialization so _settingInaConversionTimeUs is assigned the shifted value
(use DEFAULT_INACONVERSIONTIME >> 2 or equivalent) to match the rest of the code
and avoid initializeINA226() clamping from altering the intended 1100µs default.

---

Duplicate comments:
In `@usermods/INA226_v2/INA226_v2.cpp`:
- Around line 561-568: The code currently accepts non-positive ShuntResistor and
CurrentRange values; modify the logic around getJsonValue for
top[F("ShuntResistor")] and top[F("CurrentRange")] so that if the parsed
shuntMilliOhms <= 0 or _currentRangeMa == 0 you restore the compile-time
defaults (reset _shuntResistorUOhm to the constant default and _currentRangeMa
to its default), set configComplete = false, and do not apply the invalid value;
keep using getJsonValue and update the configComplete boolean accordingly (also
ensure the branch that sets _currentOffsetMa remains unchanged except for
relying on the validated range).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ec90716c-4d12-40ec-b2f7-730c57dccb56

📥 Commits

Reviewing files that changed from the base of the PR and between 85c6da8 and 7bf8617.

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

@DedeHai
Copy link
Collaborator

DedeHai commented Mar 9, 2026

also see #4237

@LordMike I will leave the judgement on these changes to you

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@usermods/INA226_v2/INA226_v2.cpp`:
- Around line 164-166: The debug printf uses the wrong format specifier for a
uint32_t: in the DEBUG_PRINTF_P call that prints _checkIntervalMs (and related
fields) replace the `%u` used for _checkIntervalMs with `%lu` (or cast
_checkIntervalMs to unsigned long and use `%lu`) so the format matches the
uint32_t type; update the format string in the DEBUG_PRINTF_P invocation that
references _isTriggeredOperationMode, _checkIntervalMs, _settingInaSamples, and
_settingInaConversionTimeUs accordingly to avoid undefined behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9eee7385-d83a-4cb6-9106-0b67b35fac23

📥 Commits

Reviewing files that changed from the base of the PR and between 34466cc and 97c6171.

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

Comment on lines +164 to +166
DEBUG_PRINTF_P(PSTR("INA226: mode=%s interval=%ums samples=%u convTime=%uμs\n"),
_isTriggeredOperationMode ? "triggered" : "continuous",
_checkIntervalMs, _settingInaSamples, _settingInaConversionTimeUs << 2);
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 | 🟡 Minor

Use %lu format specifier for uint32_t.

_checkIntervalMs is uint32_t, but %u is for unsigned int. While this works on ESP32/ESP8266 where both are 32-bit, %lu is the correct portable specifier for uint32_t.

Proposed fix
-        DEBUG_PRINTF_P(PSTR("INA226: mode=%s interval=%ums samples=%u convTime=%uμs\n"),
+        DEBUG_PRINTF_P(PSTR("INA226: mode=%s interval=%lums samples=%u convTime=%uμs\n"),
                        _isTriggeredOperationMode ? "triggered" : "continuous",
                        _checkIntervalMs, _settingInaSamples, _settingInaConversionTimeUs << 2);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@usermods/INA226_v2/INA226_v2.cpp` around lines 164 - 166, The debug printf
uses the wrong format specifier for a uint32_t: in the DEBUG_PRINTF_P call that
prints _checkIntervalMs (and related fields) replace the `%u` used for
_checkIntervalMs with `%lu` (or cast _checkIntervalMs to unsigned long and use
`%lu`) so the format matches the uint32_t type; update the format string in the
DEBUG_PRINTF_P invocation that references _isTriggeredOperationMode,
_checkIntervalMs, _settingInaSamples, and _settingInaConversionTimeUs
accordingly to avoid undefined behavior.

@LordMike
Copy link
Contributor

LordMike commented Mar 9, 2026

also see #4237

@LordMike I will leave the judgement on these changes to you

I have not reviewed any code - is there a specific area you want feedback on?

Contributions to the INA226 mod for WLED to make it better, easier to approach, all around improvements are a win in my book any day. :) I'm not a C/C++/MCU expert by any measure, so what I've made might also reflect that.

@DedeHai
Copy link
Collaborator

DedeHai commented Mar 9, 2026

@LordMike no worries, I can take care of the review but since this is your usermod, you get a veto in any changes. Usually we try to keep things backwards compatible as much as possible so existing setups do still work even when using latest code (please take that into accountt @daggerrz). I do not use this sensor nor any other sensors or MQTT - changing the MQTT topic seems like a bad idea, also units of measurements etc.
Also enabling the usermod by default is not the best idea, I think most UMs are disabled by default to avoid causing issues if multiple are used and they cause a conflict.

@LordMike
Copy link
Contributor

LordMike commented Mar 9, 2026

I would definitely not enable it by default. It needs I2C set up, it acts on a specific address (which could be used elsewhere), it takes up space (both ROM, and compute time), .. don't do that. But that's more of a general thing imo.

Dunno about changing mqtt topics.. that seems risky. Although I can understand wanting to move from a decimal to an integer (V v. mV). To be honest though, I don't recall adding MQTT output - I only recall adding to the info output (shown in wled UI under info for the server). :O

EDIT: Just checked, I did add MQTT stuff. Hot damn. I forgot all about it :D

@softhack007 softhack007 added this to the 17.0 milestone Mar 9, 2026
@daggerrz
Copy link
Author

daggerrz commented Mar 9, 2026

@LordMike no worries, I can take care of the review but since this is your usermod, you get a veto in any changes. Usually we try to keep things backwards compatible as much as possible so existing setups do still work even when using latest code (please take that into accountt @daggerrz). I do not use this sensor nor any other sensors or MQTT - changing the MQTT topic seems like a bad idea, also units of measurements etc. Also enabling the usermod by default is not the best idea, I think most UMs are disabled by default to avoid causing issues if multiple are used and they cause a conflict.

Of course, I don't mind at all to revert the renaming of shunt_voltage to shunt_voltage_drop, but since it's also changing the unit from V to mV, I thought clarifying the metric would be a good idea. Happy to revert both if that's preferred, @LordMike?

@LordMike
Copy link
Contributor

I'm fine with either name. Don't worry about me there.

@daggerrz
Copy link
Author

@DedeHai, anything else your want me to take care of here?

@DedeHai
Copy link
Collaborator

DedeHai commented Mar 12, 2026

@coderabbitai please check the changes for backwards compatibility. list potential issues.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 12, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

Let me examine the code changes in detail.


🏁 Script executed:

#!/bin/bash
# Read the current INA226 usermod file
fd -e cpp "INA226" --exec cat {}

Length of output: 21503


Let me also look at the git history to compare with the original version.


🏁 Script executed:

#!/bin/bash
# Get the base branch version of the file (compare before/after)
git log --oneline -5
git show HEAD:usermods/INA226_v2/INA226_v2.cpp 2>/dev/null || echo "File not found in HEAD"
git diff HEAD~1 HEAD -- usermods/INA226_v2/INA226_v2.cpp 2>/dev/null | head -300

Length of output: 22450


Let me get the original version from the upstream main branch for a proper comparison.


🏁 Script executed:

#!/bin/bash
# Try to find the original file on upstream main
git remote -v
git fetch origin main 2>/dev/null || true
git show origin/main:usermods/INA226_v2/INA226_v2.cpp 2>/dev/null || echo "Not found on origin/main"

Length of output: 18669


@DedeHai: Here is a full backwards compatibility analysis comparing the PR branch against origin/main:


Backwards Compatibility Analysis — INA226 v2 (PR #5411)

🔴 Breaking Changes

1. MQTT topic rename + unit change: shunt_voltage (V) → shunt_voltage_drop (mV)

  • The topic name changes, and the unit changes from Volts to millivolts — so even a subscriber that just renames its topic will receive values that are 1000× larger than before.
  • Existing Home Assistant automations, dashboards, Node-RED flows, or any external MQTT subscriber listening to <deviceTopic>/shunt_voltage will silently stop receiving data.
  • The Home Assistant discovery config for "Shunt Voltage" is published as a retained message. After upgrading, the old retained discovery record remains in the MQTT broker and will create a stale sensor in HA (no longer updated) alongside the new "Shunt Voltage Drop" sensor. Users must manually delete the old retained topic homeassistant/sensor/<clientID>/Shunt Voltage/config.

2. JSON Info API key rename + unit change: "Shunt Voltage" (V) → "Shunt Voltage Drop" (mV)

  • Any external tooling or scripts that parse the WLED /json/info (or /json user section) for the key "Shunt Voltage" will break.
  • The numeric value also scales by 1000× (V → mV).

🟡 Behavioral Changes (non-config-breaking, but notable)

3. Default CheckInterval changed: 60 s → 1 s

  • Old: DEFAULT_CHECKINTERVAL = 60000 ms. New: DEFAULT_CHECKINTERVAL = 1000 ms.
  • Saved configs that have "CheckInterval": 60 will still be read and applied correctly (no issue).
  • But on first boot or missing config, the sensor will now poll 60× more frequently, increasing I2C and CPU overhead.
  • Additionally, the old 60 s default exceeded the 20 000 ms threshold for triggered mode (_checkInterval >= 20000). The new 1 s default falls below it, so the operating mode silently changes from triggered to continuous for any installation that never explicitly saved a config.

4. _settingEnabled = true by default (was uninitialized)

  • The old constructor did not initialize _settingEnabled, which is a bug (undefined behavior for a bit-field). The PR fixes it by setting it to true.
  • However, this means on first boot with no saved config, the usermod will now actively attempt to initialize and probe the INA226 on the I2C bus. As noted by @LordMike and @DedeHai, this is undesirable: it consumes ROM/RAM and may conflict with other I2C devices at 0x40. Most usermods default to disabled.
  • Suggested fix: Change _settingEnabled = true_settingEnabled = false in the constructor. Users who want it enabled can enable it in the config UI.

✅ Backwards Compatible Changes

Item Details
ShuntResistor config key Still named "ShuntResistor". Old saved integer mΩ values (e.g. 100) parse correctly as float 100.0 mΩ → 100 000 μΩ. ✅
CurrentRange config key Still named "CurrentRange", still in mA. ✅
CheckInterval config key Still named "CheckInterval", still in seconds, same valid range (1–600). ✅
New CurrentOffset field Gracefully defaults to 0 when absent from old config. ✅
INA226_ADDRESS guard Wrapped in #ifndef — boards already defining this won't conflict. ✅
_checkInterval_checkIntervalMs Internal rename only; config key and unit are unchanged. ✅
Triggered mode threshold Logic >= 20000 ms is unchanged; purely internal variable rename. ✅

Summary

# Severity Issue
1 🔴 Breaking MQTT topic shunt_voltageshunt_voltage_drop breaks all subscribers
2 🔴 Breaking Shunt value unit V → mV (1000× scale change) in MQTT and JSON info
3 🔴 Breaking HA discovery: stale retained sensor not cleaned up automatically
4 🟡 Behavioral Default poll interval 60 s → 1 s; changes operating mode default (triggered → continuous)
5 🟡 Behavioral Usermod now enabled by default (_settingEnabled = true) — should be false

🧠 Learnings used
Learnt from: KrX3D
Repo: wled/WLED PR: 4585
File: usermods/seven_segment_display_reloaded_v2/seven_segment_display_reloaded_v2.cpp:3-5
Timestamp: 2026-02-18T00:11:02.403Z
Learning: In PR `#4585`, the seven_segment_display_reloaded_v2 usermod intentionally uses `#error` to require MQTT (`#ifdef WLED_DISABLE_MQTT `#error` "This user mod requires MQTT to be enabled." `#endif``) because the integration flow has not been tested or validated without MQTT, and failing fast at compile time is preferred over allowing potentially broken builds until a full MQTT-optional refactor is completed.

Learnt from: DedeHai
Repo: wled/WLED PR: 4798
File: wled00/FX.cpp:7531-7533
Timestamp: 2025-08-26T11:51:21.817Z
Learning: In WLED PR `#4798`, DedeHai confirmed that certain gamma-related calls in FX.cpp/FX_fcn.cpp/particle systems are intentional for effect-level shaping (e.g., brightness curves, TV sim, Pride 2015 pre-mix), distinct from final output gamma. Do not flag or remove these in future reviews; add comments when feasible to clarify intent.

Learnt from: KrX3D
Repo: wled/WLED PR: 4585
File: usermods/seven_segment_display_reloaded_v2/seven_segment_display_reloaded_v2.cpp:612-617
Timestamp: 2026-02-18T00:41:15.185Z
Learning: In the seven_segment_display_reloaded_v2 usermod (PR `#4585`), the `addToConfig()` method intentionally calls `_updateMQTT()` to publish MQTT state on every config save. This behavior is by design and should not be flagged as an issue.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:11.994Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with appropriate defined constants when those constants are meaningful in the context of the PR. For example, the hardcoded value 32 should be replaced with WLED_MAX_SEGNAME_LEN when it represents a segment name length limit. This improves code maintainability and reduces the risk of inconsistencies.

Learnt from: softhack007
Repo: wled/WLED PR: 0
File: :0-0
Timestamp: 2025-11-14T13:37:30.955Z
Learning: In WLED code reviews, when code is modified or added, look for "magic numbers" (hardcoded numeric literals) and suggest replacing them with defined constants when meaningful constants exist in the codebase. For example, suggest replacing hardcoded "32" with WLED_MAX_SEGNAME_LEN if the context relates to segment name length limits.

Learnt from: KrX3D
Repo: wled/WLED PR: 4237
File: usermods/ina2xx_v2/ina2xx_v2.cpp:178-185
Timestamp: 2025-05-06T20:31:05.208Z
Learning: KrX3D plans to add INA226 support to the INA2xx usermod in a future update. Currently, the code only instantiates INA219_WE objects despite the more generic naming.

@DedeHai
Copy link
Collaborator

DedeHai commented Mar 12, 2026

there are still breaking changes, this may annoy a lot of people using this usermod (it is unknonw to us how many that are, especially if this UM is used in products, this is a problem)

@DedeHai
Copy link
Collaborator

DedeHai commented Mar 12, 2026

If reverting breaking changes is not an option for you, try to get your changes into the other usermod I linked which is still unreleased and more flexible.

@softhack007 softhack007 added discussion waiting for feedback addition information needed to better understand the issue usermod usermod related labels Mar 14, 2026
@softhack007 softhack007 mentioned this pull request Mar 14, 2026
@daggerrz
Copy link
Author

If reverting breaking changes is not an option for you, try to get your changes into the other usermod I linked which is still unreleased and more flexible.

Sorry about the delay. The other PR looks interesting. I'll close this PR for now, check out the other one and add my changes to the other one if applicable.

@daggerrz daggerrz closed this Mar 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

discussion usermod usermod related waiting for feedback addition information needed to better understand the issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants