-
-
Notifications
You must be signed in to change notification settings - Fork 599
Extend BatteryMeter display #1967
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
base: main
Are you sure you want to change the base?
Changes from all commits
c30bbe3
fd4ea92
4b3c71f
7949ad8
cc9d457
8237fe5
f99c78b
00a32ba
825c1a6
df550b5
876564f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,34 +25,142 @@ static const int BatteryMeter_attributes[] = { | |
| }; | ||
|
|
||
| static void BatteryMeter_updateValues(Meter* this) { | ||
| ACPresence isOnAC; | ||
| double percent; | ||
| BatteryInfo info = { | ||
| .ac = AC_ERROR, | ||
| .percent = NAN, | ||
| .powerCurr = NAN, | ||
| .energyCurr = NAN, | ||
| .energyFull = NAN, | ||
| }; | ||
|
|
||
| Platform_getBattery(&percent, &isOnAC); | ||
| Platform_getBattery(&info); | ||
|
|
||
| if (!isNonnegative(percent)) { | ||
| if (!isNonnegative(info.percent)) { | ||
| this->values[0] = NAN; | ||
| xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "N/A"); | ||
| return; | ||
| } | ||
|
|
||
| this->values[0] = percent; | ||
|
|
||
| const char* text; | ||
| switch (isOnAC) { | ||
| case AC_PRESENT: | ||
| text = this->mode == TEXT_METERMODE ? " (Running on A/C)" : "(A/C)"; | ||
| break; | ||
| case AC_ABSENT: | ||
| text = this->mode == TEXT_METERMODE ? " (Running on battery)" : "(bat)"; | ||
| break; | ||
| case AC_ERROR: | ||
| default: | ||
| text = ""; | ||
| break; | ||
| this->values[0] = info.percent; | ||
|
|
||
| bool haveEnergy = isNonnegative(info.energyCurr) && isNonnegative(info.energyFull); | ||
|
|
||
| /* Without energy data there is nothing useful to show beyond the percent. */ | ||
| if (!haveEnergy) { | ||
| xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1f%%", info.percent); | ||
| return; | ||
|
Comment on lines
+49
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Preserve AC source in the percent-only fallback. At Line 49-Line 51, the early return prints only Suggested patch /* Without energy data there is nothing useful to show beyond the percent. */
if (!haveEnergy) {
- xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1f%%", info.percent);
+ const char* src =
+ (info.ac == AC_PRESENT) ? " (AC)" :
+ (info.ac == AC_ABSENT) ? " (bat)" : "";
+ xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1f%%%s", info.percent, src);
return;
}🧰 Tools🪛 ast-grep (0.42.2)[warning] 49-49: Do not use (sizeof-this-c) 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| bool havePower = isfinite(info.powerCurr); | ||
|
Comment on lines
+46
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not discard This fallback reduces the output to percent-only even if rate telemetry is present. Per the supplied stack context, Darwin currently provides 🧰 Tools🪛 ast-grep (0.42.2)[warning] 49-49: Do not use (sizeof-this-c) 🪛 Cppcheck (2.20.0)[style] 53-53: The function 'String_startsWith' is never used. (unusedFunction) |
||
|
|
||
| /* stable: power unknown or |power| < 5 W – time estimate would be unreliable */ | ||
| bool isDischarging = havePower && info.powerCurr <= -5.0; | ||
| bool isCharging = havePower && info.powerCurr >= 5.0; | ||
|
|
||
| /* time estimate in whole minutes; -1 means not available */ | ||
| int timeMinutes = -1; | ||
| if (isDischarging && isPositive(info.energyCurr)) { | ||
| /* floor for discharge; powerCurr is negative, use negative scaling when dividing */ | ||
| timeMinutes = (int)floor(info.energyCurr / info.powerCurr * -60.0); | ||
| } else if (isCharging && 0.95 * info.energyFull > info.energyCurr) { | ||
| /* ceil for charge */ | ||
| timeMinutes = (int)ceil((0.95 * info.energyFull - info.energyCurr) / info.powerCurr * 60.0); | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
|
|
||
| char* buf = this->txtBuffer; | ||
| size_t len = sizeof(this->txtBuffer); | ||
| int ret = 0; | ||
|
|
||
| if (this->mode == TEXT_METERMODE) { | ||
| if (info.ac == AC_PRESENT) { | ||
| ret = xSnprintf(buf, len, "Using %s", isDischarging ? "AC+bat" : "AC"); | ||
| buf += ret; len -= ret; | ||
| } else if (info.ac == AC_ABSENT) { | ||
| ret = xSnprintf(buf, len, "Using bat"); | ||
| buf += ret; len -= ret; | ||
| } | ||
|
|
||
| if (ret && len > 2) { | ||
| *buf++ = ','; | ||
| *buf++ = ' '; | ||
| *buf = 0; | ||
| len -= 2; | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| if (isDischarging) { | ||
| ret = xSnprintf( | ||
| buf, len, "discharging at %.1fW, %.1f/%.1fWh (%.1f%%)", | ||
| -info.powerCurr, info.energyCurr, info.energyFull, info.percent | ||
| ); | ||
| buf += ret; len -= ret; | ||
| if (timeMinutes >= 0) { | ||
| ret = xSnprintf(buf, len, ", time remaining: %dh%02dm", timeMinutes / 60, timeMinutes % 60); | ||
| buf += ret; len -= ret; | ||
| } | ||
| } else if (isCharging) { | ||
| ret = xSnprintf( | ||
| buf, len, "charging at %.1fW, %.1f/%.1fWh (%.1f%%)", | ||
| info.powerCurr, info.energyCurr, info.energyFull, info.percent | ||
| ); | ||
| buf += ret; len -= ret; | ||
|
|
||
| if (timeMinutes >= 0) { | ||
| ret = xSnprintf( | ||
| buf, len, ", time to full: %dh%02dm", | ||
| timeMinutes / 60, timeMinutes % 60 | ||
| ); | ||
| buf += ret; len -= ret; | ||
| } | ||
| } else { | ||
| ret = xSnprintf( | ||
| buf, len, "stable at %.1f/%.1fWh (%.1f%%)", | ||
| info.energyCurr, info.energyFull, info.percent | ||
| ); | ||
| buf += ret; len -= ret; | ||
| } | ||
| } else { | ||
| /* compact label for bar / graph modes */ | ||
| if (info.ac == AC_PRESENT) { | ||
| ret = xSnprintf(buf, len, "%s", isDischarging ? "AC+bat" : "AC"); | ||
| buf += ret; len -= ret; | ||
| } else if (info.ac == AC_ABSENT) { | ||
| ret = xSnprintf(buf, len, "bat"); | ||
| buf += ret; len -= ret; | ||
| } | ||
|
|
||
| if (ret && len > 1) { | ||
| *buf++ = ' '; | ||
| *buf = 0; | ||
| len--; | ||
| } | ||
|
|
||
| if (isCharging || isDischarging) { | ||
| ret = xSnprintf( | ||
| buf, len, "%+.1fW @ %.1f/%.1fWh", | ||
| info.powerCurr, info.energyCurr, info.energyFull | ||
| ); | ||
| buf += ret; len -= ret; | ||
|
|
||
| if (timeMinutes >= 0) { | ||
| ret = xSnprintf( | ||
| buf, len, ", %dh%02dm", | ||
| timeMinutes / 60, timeMinutes % 60 | ||
| ); | ||
| buf += ret; len -= ret; | ||
| } | ||
| } else { | ||
| ret = xSnprintf( | ||
| buf, len, "stable @ %.1f/%.1fWh", | ||
| info.energyCurr, info.energyFull | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| ); | ||
| buf += ret; len -= ret; | ||
| } | ||
| } | ||
|
|
||
| xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%.1f%%%s", percent, text); | ||
| // Simplify the pattern to always use "buf += ret; len -= ret;" for all cases | ||
| (void)ret; | ||
| (void)buf; | ||
| (void)len; | ||
| } | ||
|
|
||
| const MeterClass BatteryMeter_class = { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,15 @@ typedef enum ACPresence_ { | |
| AC_ERROR | ||
| } ACPresence; | ||
|
|
||
| typedef struct BatteryInfo_ { | ||
| ACPresence ac; | ||
|
|
||
| double percent; /* [0..100], NAN if unknown */ | ||
| double powerCurr; /* instantaneous power in W, NAN if unknown */ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win Document the
|
||
| double energyCurr; /* Wh, NAN if unknown */ | ||
| double energyFull; /* Wh, NAN if unknown */ | ||
| } BatteryInfo; | ||
|
|
||
| extern const MeterClass BatteryMeter_class; | ||
|
|
||
| #endif | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enforce the upper bound on
percenthere too.The
BatteryInfocontract sayspercentis[0..100], but this branch only rejects negative/unknown values. Anything above 100 is written straight intothis->values[0]even though the meter total is fixed at 100.🧰 Tools
🪛 ast-grep (0.42.2)
[warning] 39-39: Do not use
sizeof(this)to get the number of bytes of the object in memory. It returns the size of the pointer, not the size of the object.Context: sizeof(this->txtBuffer)
Note: [CWE-467]: Use of sizeof() on a Pointer Type [REFERENCES]
- https://wiki.sei.cmu.edu/confluence/display/c/ARR01-C.+Do+not+apply+the+sizeof+operator+to+a+pointer+when+taking+the+size+of+an+array
(sizeof-this-c)
🪛 Cppcheck (2.20.0)
[style] 39-39: The function 'Vector_quickSort' is never used.
(unusedFunction)