Skip to content

Fix PWM10+ discovery and sort order in Common.php - #10

Open
mrjacobarussell wants to merge 2 commits into
andrebrait:mainfrom
mrjacobarussell:fix-pwm10-plus-glob-and-sort
Open

mrjacobarussell wants to merge 2 commits into
andrebrait:mainfrom
mrjacobarussell:fix-pwm10-plus-glob-and-sort

Conversation

@mrjacobarussell

@mrjacobarussell mrjacobarussell commented Sep 19, 2026

Copy link
Copy Markdown

What's changed

Two bugs, both hit by any hwmon device with 10+ PWM channels (found via a real ARCTIC Fan Controller, which has 10 channels):

  1. glob("pwm[0-9]") and find -iname 'pwm[0-9]' only match a single digit, so pwm10 and above are silently dropped from both build_pwm_map() and list_pwm(). Fixed by globbing broadly (pwm*) and filtering with a strict ^pwm\d+$ regex — this also avoids accidentally matching auxiliary attributes like pwm1_enable or pwm1_auto_point1_pwm that a looser pwm[0-9]* pattern would pull in.
  2. list_pwm()'s usort() used strcmp(), which sorts alphabetically ("pwm10" < "pwm2" as strings) instead of numerically. Switched to strnatcmp().

Verification

Tested against a live 10-channel ARCTIC Fan Controller on Unraid. Before the fix, channel 10 was missing from the plugin UI entirely, and once naively patched to just match pwm10, it sorted between pwm1 and pwm2 (and a looser glob pattern pulled in every per-channel attribute, not just the base PWM control file). After this fix, all 10 channels appear, in correct numeric order, with nothing extraneous.

Upgrade compatibility

No config/migration impact — this only affects which hwmon files get discovered and how they're ordered for display.

Summary by CodeRabbit

  • Bug Fixes
    • Fan-control channels with multi-digit PWM numbers are now detected and listed correctly.
    • PWM channels are sorted in natural numeric order for clearer presentation.

Two bugs, both hit by any hwmon device with 10+ PWM channels
(e.g. ARCTIC Fan Controller, 10 channels):

1. glob("pwm[0-9]") and find -iname 'pwm[0-9]' match exactly one
   digit, so pwm10 (and above) are silently dropped from both
   build_pwm_map() and list_pwm(). Fixed by globbing broadly
   (pwm*) and filtering with a strict ^pwm\d+$ regex, which also
   avoids matching auxiliary attributes like pwm1_enable,
   pwm1_auto_point1_pwm, etc.

2. list_pwm()'s usort() used strcmp(), which sorts alphabetically
   ("pwm10" < "pwm2" as strings) rather than numerically. Fixed
   by switching to strnatcmp().

Verified against a live 10-channel ARCTIC Fan Controller on Unraid:
before the fix, channel 10 was missing from the plugin UI entirely
and pwm10 sorted between pwm1 and pwm2; after, all 10 channels
appear in correct numeric order.
@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 5583ada5-bd00-4cce-96aa-8966de94d274

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 2bae89e9-cbe1-433f-86f2-37679504edee

📥 Commits

Reviewing files that changed from the base of the PR and between f1b23ac and 669ee0a.

📒 Files selected for processing (1)
  • src/usr/local/emhttp/plugins/fanctrlplus2/include/Common.php

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Changes

PWM channel enumeration

Layer / File(s) Summary
Channel discovery and ordering
src/usr/local/emhttp/plugins/fanctrlplus2/include/Common.php
build_pwm_map() and list_pwm() now detect multi-digit PWM channels. list_pwm() uses natural sorting for channel names such as pwm10.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: andrebrait

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: discovering PWM channels numbered 10 and higher and sorting them correctly in Common.php.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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.

@andrebrait

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

-regextype is incompatible with some supported BusyBox find environments and may hide all PWM channels; regression coverage is also missing.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
What changed in this PR

Fixes PWM discovery for 10+ channels and ensures numeric channel ordering.

Changes:

  • Discovers multi-digit PWM files while excluding auxiliary attributes.
  • Uses natural sorting for PWM channels.
File Summary
src/​usr/​local/​emhttp/​plugins/​fanctrlplus2/​include/​Common.php Updates PWM discovery and sorting; portability and regression-test improvements are needed.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/usr/local/emhttp/plugins/fanctrlplus2/include/Common.php Outdated

@andrebrait andrebrait left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

The change overall is good but I think it could've been simpler.

And I need to improve the testing here

Comment thread src/usr/local/emhttp/plugins/fanctrlplus2/include/Common.php
Comment thread src/usr/local/emhttp/plugins/fanctrlplus2/include/Common.php
Comment thread src/usr/local/emhttp/plugins/fanctrlplus2/include/Common.php
Comment thread src/usr/local/emhttp/plugins/fanctrlplus2/include/Common.php
…ute match

- Replaced the find(1) + GNU-only -regextype chip discovery in list_pwm()
  with the same glob('/sys/class/hwmon/hwmon*') approach build_pwm_map()
  already uses. No more shell exec() for this, and no portability concern
  about -regextype being a GNU find extension.

- Kept the strict ^pwm\d+$ regex filter rather than switching to a bare
  "pwm[0-9]*" glob as suggested in review. Verified directly: a glob char
  class only consumes one character, so "pwm[0-9]*" still matches
  "pwm1_enable", "pwm10_enable", "pwm1_auto_point1_pwm", etc. -- the same
  auxiliary-attribute flooding the regex filter was added to prevent.
  fnmatch() confirms this:

    pwm1_enable vs pwm[0-9]*:            MATCHES
    pwm10_enable vs pwm[0-9]*:           MATCHES
    pwm1_auto_point1_pwm vs pwm[0-9]*:   MATCHES

  Happy to go with a different structure if preferred, but "pwm[0-9]*"
  specifically doesn't fix the bug this PR is for.
@mrjacobarussell

Copy link
Copy Markdown
Author

Pushed an update addressing both review threads:

On pwm[0-9]* vs the regex filter -- verified this directly before changing anything, since it looked like it should work at first glance too:

$patterns = ["pwm1", "pwm1_enable", "pwm1_auto_point1_pwm", "pwm10", "pwm10_enable"];
foreach ($patterns as $p) {
    var_dump(fnmatch("pwm[0-9]*", $p));
}
// pwm1_enable            -> true (matches)
// pwm10_enable           -> true (matches)
// pwm1_auto_point1_pwm   -> true (matches)

A glob character class only ever consumes one character, so [0-9] matches the first digit and the trailing * happily matches everything after it -- _enable, _auto_point1_pwm, whatever. It has the exact same flooding problem as a bare pwm* glob. Kept the strict ^pwm\d+$ regex filter since that's the part that actually excludes those. (This wasn't theoretical -- hit it live testing against a real 10-channel device before opening this PR, where it flooded the UI with every pwm1_auto_point*/pwm1_enable/etc. attribute.)

On the -regextype portability concern (Copilot's comment) -- rather than just swap to a different find/-iname flag, dropped the find() shell-out from list_pwm() entirely and pointed it at glob('/sys/class/hwmon/hwmon*'), the same enumeration build_pwm_map() already uses a few lines up. No more GNU-only flag, no more exec() in this function at all, and it keeps both functions structurally consistent with each other.

Let me know if you'd rather structure it differently -- happy to adjust, just wanted to flag that pwm[0-9]* on its own doesn't fix the bug this PR is for.

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