Small, dependency-free macOS monitoring tools that publish to Home Assistant over MQTT (using MQTT discovery, so entities just appear — no manual HA config).
macOS only warns about a low Bluetooth keyboard/mouse battery once it's nearly dead (~2%), and only while you're at the machine to see it. These tools publish battery (and, over time, other) state to MQTT on a schedule, so you can build a Home Assistant automation that warns you early — and even when you're away from the machine.
Each tool is a separate Swift executable target under Sources/, so the project can
grow without the tools depending on each other.
Reads Bluetooth accessory battery levels (keyboard, mouse, trackpad) via ioreg and
publishes each as an MQTT-discovered sensor entity. Meant to run periodically via
launchd, not as a long-running daemon.
Device battery data comes from
ioreg -c AppleDeviceManagementHIDEventService -r -a (parsed as a property list).
system_profiler SPBluetoothDataType does not expose battery info, despite
looking like the obvious place to check.
MQTT publishing is a small hand-rolled MQTT 3.1.1 client (Sources/bluetooth-battery/MQTTClient.swift)
rather than shelling out to mosquitto_pub — the whole project only needs Foundation
and the Swift toolchain that ships with Xcode Command Line Tools, no Homebrew or other
package manager required.
- macOS with the Swift toolchain (Xcode or Xcode Command Line Tools —
xcode-select --install) - An MQTT broker reachable from the Mac (e.g. the one your Home Assistant MQTT integration already uses)
mkdir -p ~/.config/macos_monitor
cp deploy/bluetooth-battery/config.example.env ~/.config/macos_monitor/config.env
chmod 600 ~/.config/macos_monitor/config.env
# edit ~/.config/macos_monitor/config.env with your MQTT broker's host/port/username/password
./deploy/bluetooth-battery/install.shinstall.sh builds the release binary, installs the launchd agent (runs every 15
minutes, plus once immediately), and loads it — skipping the load step with a reminder
if config.env isn't in place yet.
To run it once by hand instead (useful for testing):
swift build -c release
.build/release/bluetooth-batterylaunchctl bootout "gui/$(id -u)/com.macos-monitor.bluetooth-battery"
rm ~/Library/LaunchAgents/com.macos-monitor.bluetooth-battery.plist- Add an executable target to
Package.swiftand its sources underSources/<tool-name>/. - Add
deploy/<tool-name>/with its ownlaunchdplist template +install.sh, following thebluetooth-batterylayout. - Reuse
~/.config/macos_monitor/config.envfor shared settings (e.g. MQTT credentials) where it makes sense.
MIT, see LICENSE.