# Logitech Battery Widget An open-source Windows tray widget that displays battery information for connected Logitech mice, keyboards, and headsets. It discovers devices locally through HID and attempts a read-only Logitech HID++ battery query. Multiple devices are shown together. If Windows or a device does not expose a battery value, the widget says so instead of guessing. > **Screenshot placeholder:** A project screenshot will be added under `docs/screenshot.png` after > the first signed release build is visually verified on Windows 11. ## Trust and privacy - No network access, telemetry, analytics, updater, advertising, or runtime downloads. - No administrator rights or UAC prompt. - No hidden startup entry. "Start with Windows" changes only the current user's registry after an explicit click, and can be disabled from the same menu. - The complete source and reproducible GitLab CI recipe are public so the behavior can be audited. - Settings and logs stay in the documented per-user Windows folders. See [SECURITY.md](SECURITY.md) for the full security model. ## End-user installation 1. Download `LogitechBatteryWidget.exe` from a GitLab release or build artifact. 2. Optionally verify its SHA-256 value against `LogitechBatteryWidget.exe.sha256`. 3. Run the EXE. It is portable and does not install a service or driver. 4. Use the tray menu to refresh, hide the widget, change settings, or explicitly enable startup. The executable is produced by PyInstaller. Some antivirus products heuristically flag unsigned PyInstaller one-file programs. This can be a false positive; verify the checksum, inspect the CI job and source, or submit the file to VirusTotal. A detection should still be investigated rather than automatically ignored. ## Local development Requires Python 3.12+. ```powershell py -3.12 -m venv .venv .venv\Scripts\Activate.ps1 python -m pip install -r requirements.txt python -m logitech_battery_widget.main pytest ruff check . ``` On Linux and macOS the UI starts with clearly named demo devices. This makes UI development possible without pretending that real Logitech hardware was detected. ## Build On Windows: ```powershell python -m pip install -r requirements.txt pytest ruff check . pyinstaller --clean --noconfirm packaging/pyinstaller.spec Get-FileHash dist/LogitechBatteryWidget.exe -Algorithm SHA256 ``` The result is `dist/LogitechBatteryWidget.exe`, a console-free, UPX-disabled one-file executable. GitLab CI executes the same dependency installation, tests, lint, and PyInstaller command on a Windows runner and publishes the EXE plus checksum. Builds fail when tests fail. ## Reproducible builds 1. Check out the same commit on a clean Windows machine or isolated Windows runner. 2. Install Python 3.12 and the exact packages from `requirements.txt`. 3. Run the commands in **Build**. 4. Compare the SHA-256 result. Exact bytes also depend on the same Python patch version, Windows SDK/runtime, and PyInstaller version; the GitLab job log records that environment. No file is downloaded by the application itself. Dependency retrieval happens only while preparing the build environment. ## Configuration `%APPDATA%\LogitechBatteryWidget\config.json` contains: | Key | Type | Meaning | | --- | --- | --- | | `theme` | string | `system`, `light`, or `dark` | | `always_on_top` | boolean | Keep the widget above normal windows | | `window_x`, `window_y` | integer/null | Last widget position | | `refresh_interval_seconds` | integer | Refresh period, clamped to 15-3600 | | `log_level` | string | `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL` | Logs rotate at `%LOCALAPPDATA%\LogitechBatteryWidget\logs\app.log` (1 MB, three backups). ## Device compatibility Logitech exposes different protocols across receivers, Bluetooth devices, and product generations. The widget supports HID++ battery features `0x1000` and `0x1004`. A detected device can therefore appear with `N/A` when its interface, firmware, Bluetooth stack, or receiver does not expose either feature. Contributions with tested protocol captures are welcome; do not include serial numbers. ## License MIT. This project is independent and is not affiliated with or endorsed by Logitech. Logitech is a trademark of its respective owner.