Skip to content

feat: show the controller battery level - #160

Merged
lippdev merged 2 commits into
mainfrom
feat/controller-battery
Oct 19, 2026
Merged

lippdev merged 2 commits into
mainfrom
feat/controller-battery

Conversation

@lippdev

@lippdev lippdev commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

What

Shows the battery of the connected controller(s) (issue #70):

  • Session menu header (Select + Y): battery glyph + percentage after "Xbox controller detected".
  • Console interface top bar: same indicator next to the clock.
  • Low-battery notice during a session: reuses the corner toast of the session hint (SessionHintWindow, never takes focus). Warns once at <= 15 %, once more at <= 5 %, and re-arms only after charging (or a reading above 25 %, e.g. new batteries).

With several pads it shows the emptiest one. Wired pads with no battery show nothing. "~" marks XInput's rough four-step level.

How

  • Services/ControllerBattery.cs (pure, unit-tested): XInput level mapping (5/30/65/100, approximate), WGI BatteryReport to percent, DS4/DualSense status byte parsing (offsets as in Linux hid-playstation: DS4 USB 30 / BT 0x11 32; DualSense USB 53 / BT 0x31 54; the short Bluetooth 0x01 report is ignored), combining sources (Sony HID wins for PlayStation pads, WGI RawGameController.TryGetBatteryReport for the rest, XInput only when WGI reported no non-Sony pad), glyph choice (Segoe Fluent battery / charging glyphs) and the LowBatteryAlarm hysteresis.
  • Services/ControllerBatteryMonitor.cs: reads the three sources; ControllerBatteryMonitor.Snapshot (IReadOnlyList<BatteryReading>) is the last result, for other screens (e.g. diagnostics).
  • SonyHidReader parses the battery byte at most every 5 s per pad (not on every report) and exposes ReadBatteries().
  • MainViewModel.Battery.cs polls every 30 s off the UI thread, plus on controller connect/disconnect and when the session menu opens.
  • The diagnostics report (Settings) lists each controller with battery 80% / battery ~65%, charging in its detail.
  • Strings in all six catalogs; manual checks in docs/TESTING.md (1f).

Testing

  • dotnet test tests/ConsoleMode.Tests/ConsoleMode.Tests.csproj: 473 passed (new ControllerBatteryTests).
  • The app build is left to the Windows CI (written on Linux). Hardware behaviour (Xbox wireless, DualSense USB/BT, DS4, wired pad, charging) is in the manual checklist.

Closes #70

🤖 Generated with Claude Code

@lippdev
lippdev force-pushed the feat/controller-battery branch from e737249 to 32b91ba Compare October 19, 2026 19:06

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes This review covers the controller battery feature from source polling through UI presentation, low-battery notices, localization, tests, and manual verification guidance.

  • Battery sources and parsing Converts XInput, Windows.Gaming.Input, and Sony HID battery reports, combines readings, and chooses the emptiest reported controller.
  • Indicators and warnings Adds battery indicators to the session menu and Console UI, plus threshold-based notices during active sessions.
  • Tests and localization Adds pure-logic tests, translations in all six catalogs, and a manual hardware checklist.

Pullfrog  | View workflow run | Using gpt-6-luna | 𝕏

lippdev and others added 2 commits October 19, 2026 21:10
Reads the battery from Windows.Gaming.Input, XInput (approximate) and the DS4/DualSense HID reports, and shows the emptiest pad in the session menu header and the Console interface top bar, with a low-battery notice during a session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lippdev
lippdev force-pushed the feat/controller-battery branch from 32b91ba to 07a11fc Compare October 19, 2026 19:11

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues — one minor diagnostics accuracy issue inline.

Reviewed changes This review covers the diagnostics report change since the prior Pullfrog review.

  • Added controller battery details — Included each controller's last known battery reading in the diagnostics report.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6-luna | 𝕏

Comment on lines +121 to +123
?? batteries.FirstOrDefault(b => b.Source == (raw.HardwareVendorId == ControllerMapping.SonyVendorId
? ControllerBattery.SourceSony
: ControllerBattery.SourceXInput));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When the ID match fails, this fallback can attach one controller's battery to a different row: Sony HID readings are keyed by HID path, while XInput readings are eligible for every non-Sony controller. In multi-pad setups the copied diagnostics report can therefore misidentify which controller has a low battery.

Technical details
# Avoid associating battery readings by source alone

## Affected sites
- `src/ConsoleMode/ViewModels/MainViewModel.Diagnostics.cs:120-124` — Source-only fallback removes the first reading of that source without proving it belongs to the current `RawGameController`.
- `src/ConsoleMode/Services/SonyHidReader.cs:144` — Sony battery IDs are HID device paths, not necessarily `RawGameController.NonRoamableId`.
- `src/ConsoleMode/Services/ControllerBatteryMonitor.cs:44-51` — XInput readings carry slot IDs, which are not tied to arbitrary non-Sony raw controllers.

## Required outcome
- Only include a battery detail when its reading can be associated with the specific controller row; leave the detail empty rather than report a potentially wrong controller battery.

@lippdev
lippdev merged commit 611eb46 into main Oct 19, 2026
5 checks passed
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.

Show controller battery in the session menu

1 participant