This is a custom component for Home Assistant to integrate Philips Sonicare BLE toothbrushes.
The integration connects to your toothbrush via Bluetooth Low Energy (BLE) to provide battery status, brushing session data, brush head wear tracking, and more. All communication is fully local -- no cloud, no app required.
Three connection methods are supported:
- Direct Bluetooth -- connects from the HA host's Bluetooth adapter (built-in or USB). Uses a persistent live connection with a poll fallback.
- ESP32 BLE Bridge ★ -- an ESP32 running a custom ESPHome component acts as a wireless BLE relay. Recommended for out-of-range setups; supports multiple devices and notification throttling.
- Bluetooth Proxy -- uses an existing ESPHome
bluetooth_proxy. Works for a single Sonicare per proxy; not recommended due to stability issues.
See Configuration for setup instructions.
- Tested Models
- Dashboard Card
- Features
- Prerequisites
- Installation
- Configuration
- How It Works
- Troubleshooting & Caveats
- BLE Protocol
- Screenshots
| Model | Direct BLE | ESP32 Bridge | Tested by |
|---|---|---|---|
| Sonicare For Kids | |||
| HX6340 | ✅ | ✅ | Maintainer |
| HX6322, HX6352 | ✅ | — | Community (GrumpyMeow#14) |
| FlexCare Platinum Connected | |||
| HX9120 | not yet tested | not yet tested | — |
| ExpertClean | |||
| HX962V | — | ✅ | Community (#1) |
| DiamondClean Smart | |||
| HX992X | ✅ | ✅ | Maintainer |
| DiamondClean 9000 | |||
| HX991M | ✅ | ✅ | Community (forum, #7) |
| DiamondClean Prestige | |||
| HX999X | ✅ | ✅ | Maintainer, Community (forum) |
Any BLE-enabled Philips Sonicare toothbrush using the standard protocol should work (Sonicare For Kids, ExpertClean, DiamondClean Smart, DiamondClean 9000, DiamondClean Prestige, and more). The Series 5300–7400 (HX74xx) use a newer BLE protocol that is not yet supported. The integration auto-discovers compatible devices via BLE. If you have a different model — happy to hear your test results!
Note
Some models (ExpertClean, HX991M, DiamondClean Prestige) require BLE bonding. The integration detects this automatically and pairs the device during setup. Models like DiamondClean Smart and Sonicare For Kids use open GATT and connect without pairing.
For a visual brushing dashboard, use the Toothbrush Card -- a custom Lovelace card with live sector tracking, pressure display, and brush head wear indicator. Works with both Philips Sonicare and Oral-B toothbrushes.
This integration creates a new device for your toothbrush and provides the following entities based on your device's hardware:
| Entity | Type | Description |
|---|---|---|
| Handle State | Sensor | Current state (Off, Standby, Running, Charging, Shutdown). |
| Activity | Sensor | Composite state derived from handle + brushing state (Off, Standby, Brushing, Paused, Charging). |
| Brushing State | Sensor | Detailed brushing status (Off, On, Pause, Session Complete, Session Aborted). |
| Brushing Mode | Sensor | Active cleaning mode (Clean, White+, Gum Health, Deep Clean+, Sensitive, Tongue Care). |
| Intensity | Sensor | Current intensity level (Low, Medium, High). |
| Battery Level | Sensor | Battery charge level (%). |
| Brushing | Binary Sensor | Indicates if actively brushing. |
| Charging | Binary Sensor | Indicates if currently charging. |
| Pressure Alert | Binary Sensor | Indicates if too much pressure is applied (during brushing). |
| Entity | Type | Description |
|---|---|---|
| Brushing Mode | Select | Set the brushing mode for the next session. Only created on models that support BLE mode writes (DiamondClean Prestige HX999X, HX9996, and HX74xx series). BrushSync-enabled models like DiamondClean Smart HX992X use brush-head-based mode selection and do not get this entity. |
These sensors are only available while actively brushing and stream live data from the toothbrush IMU.
| Entity | Type | Description |
|---|---|---|
| Pressure | Sensor | Brushing pressure force (g). |
| Pressure State | Sensor | Pressure classification (No Contact, Optimal, Too High). |
| Temperature | Sensor | Handle temperature (°C). |
| Entity | Type | Description |
|---|---|---|
| Brushing Time | Sensor | Current session brushing time (seconds). |
| Routine Length | Sensor | Target brushing duration (typically 120s). |
| Session ID | Sensor | Current brushing session identifier. |
| Latest Session ID | Sensor | Most recently completed session identifier. |
| Session Count | Sensor | Total number of stored sessions. |
| Entity | Type | Description |
|---|---|---|
| Brush Head Wear | Sensor | Brush head wear level (%, computed from usage/lifetime limit). |
| Brush Head Usage | Sensor | Accumulated brush head usage counter. |
| Brush Head Limit | Sensor | Maximum brush head lifetime. |
| Brush Head Type | Sensor | Brush head type (Adaptive Clean, Adaptive White, Tongue Care, Adaptive Gums, Sensitive). |
| Brush Head Serial | Sensor | Brush head serial number (from NFC tag). |
| Brush Head Date | Sensor | Brush head manufacturing date. |
| Brush Head Ring ID | Sensor | Color ring identifier (for family brush head tracking). |
| Brush Head NFC Version | Sensor | NFC chip version on the brush head. |
| Brush Head Payload | Sensor | Raw NFC payload data (hex). |
| Entity | Type | Description |
|---|---|---|
| Motor Runtime | Sensor | Cumulative motor runtime (seconds). |
| Handle Time | Sensor | Total handle operating time since manufacture (seconds). |
| Model Number | Sensor | Device model number (e.g., HX992B). |
| Firmware | Sensor | Installed firmware version. |
| Last Seen | Sensor | Timestamp of last successful data read. |
| RSSI | Sensor | BLE signal strength in dBm (Direct BLE only). |
| Bridge Version | Sensor | ESP bridge firmware version (ESP Bridge only). |
- A compatible Philips Sonicare toothbrush (see Tested Models above).
- Either a Home Assistant instance with the Bluetooth integration enabled and a working Bluetooth adapter, or an ESP32 running the BLE Bridge component.
- Pairing depends on the model -- DiamondClean Smart (HX992X) uses open GATT without bonding. ExpertClean (HX962X), DiamondClean Prestige (HX999X), and HX991M require BLE pairing. The integration handles both cases automatically. Simply close any Sonicare phone app to free the BLE connection.
Note
The toothbrush only advertises via BLE for a short time after being picked up from the charger or turned on/off. It enters deep sleep after approximately 20 seconds of inactivity. While on the charging stand, it is not reachable via BLE.
Don't have HACS yet? Follow the HACS installation guide first.
- Go to HACS > Integrations in your Home Assistant UI.
- Click the three-dot menu in the top right and select Custom repositories.
- Add
https://github.com/mtheli/philips_sonicare_bleand select the category Integration. - Find the "Philips Sonicare" integration and click Install.
- Restart Home Assistant.
- Copy the
custom_components/philips_sonicare_bledirectory from this repository into your Home Assistantconfig/custom_components/folder. - Restart Home Assistant.
The integration supports three connection methods:
| Method | Best for | |
|---|---|---|
| Option A | Direct Bluetooth | HA host within Bluetooth range of the toothbrush (typically 5–10 m / 15–30 ft) |
| Option B | ESP32 BLE Bridge ★ | Recommended for out-of-range setups. Multiple devices, live data streaming, full notification throttling |
| Option C | Bluetooth Proxy | Single Sonicare, existing bluetooth_proxy — not recommended, see warning below |
Important
Both proxy/bridge paths on ESP32 are affected by an ESP-IDF bug that crashes GATT service discovery. A compile-time workaround is available and required until ESP-IDF v5.5.5 ships (expected mid-May 2026).
- Wake up your toothbrush (pick it up from the charger or briefly turn it on).
- Navigate to Settings > Devices & Services.
- The toothbrush should appear under Discovered -- click Configure.
- If not discovered automatically, click + Add Integration, search for "Philips Sonicare", and enter the MAC address manually.
- The confirmation dialog shows the current brush status and detected services. Make sure the toothbrush is turned on (status shows "Active") before clicking Submit.
Tip
Some models (ExpertClean, HX991M) require BLE bonding -- the integration detects this automatically and pairs the device during setup via D-Bus. If auto-pairing is not available (e.g. HAOS without D-Bus), manual pairing instructions are shown. Simply close the Sonicare phone app to free the BLE connection.
If your Home Assistant host is too far from the toothbrush for a direct Bluetooth connection, you can use an ESP32 as a wireless BLE bridge. The ESP32 connects to the toothbrush and relays data to HA over WiFi.
This is not a standard ESPHome Bluetooth Proxy -- it is a dedicated component that manages the BLE connection directly on the ESP32 and provides full read/write/subscribe access to all GATT characteristics.
Note
This option requires basic ESPHome knowledge (flashing firmware, editing YAML configs). If you're new to ESPHome, check out Getting Started with ESPHome first.
For the complete setup guide, see ESP32 Bridge Setup Guide.
Warning
Due to stability issues, it is strongly recommended to use Option B: ESP32 BLE Bridge instead of a Bluetooth Proxy. Proxy setups have shown silent-connection issues — after a brushing session a device can stop delivering notifications while the proxy itself stays reachable, requiring a Home Assistant integration reload to recover. The proxy also has no notification throttling, which overloads the WiFi socket queue when more than one Sonicare is connected to the same proxy.
This option is documented for users who already operate a proxy for other devices and only have a single Sonicare.
If you already operate an ESPHome Bluetooth Proxy, the integration can use it as a relay — no dedicated bridge firmware needed. Confirmed working on ESPHome 2026.2+ with io_capability: none.
Known caveats:
- Proxy firmware needs the Bluedroid workaround until ESP-IDF v5.5.5 is released.
- First connect after reboot takes ~5 s longer than Direct BLE. Bond keys live on the proxy's NVS, so service discovery and re-encryption race briefly; the integration retries reads automatically during this window.
- Notify Throttle option has no effect on Proxy — throttling is only implemented in the ESP32 BLE Bridge firmware.
- RSSI shown in the Connection device reflects the scanner actually carrying the link (since v0.9.x), not the strongest advertisement.
Setup is the same as Option A — Home Assistant's Bluetooth stack picks the proxy automatically when it has a better or equal connection score to the host adapter.
| Option | Default | Description |
|---|---|---|
| Pressure Sensor | Enabled | Stream live pressure data during brushing. |
| Temperature Sensor | Enabled | Stream live temperature data during brushing. |
| Gyroscope Sensor | Disabled | Stream live 6-axis IMU data during brushing (experimental). |
| Notify Throttle | 500ms | Minimum interval between BLE notification updates (ESP Bridge only, 100-5000ms). |
The Sonicare toothbrush has unique BLE behavior compared to other Philips devices:
- Slow advertising -- the toothbrush sends BLE advertisements only every 10-30 seconds (most BLE devices: every 100-500ms).
- Short wake window -- after turning off, the toothbrush stays connectable for only ~20 seconds before entering deep sleep.
- Pairing varies by model -- DiamondClean Smart (HX992X) uses open GATT without bonding. ExpertClean (HX962X), DiamondClean Prestige (HX999X), and HX991M require BLE pairing. The integration handles both cases automatically.
The integration handles this with:
- Advertisement-triggered reconnect -- a BLE advertisement callback immediately wakes the connection thread, eliminating unnecessary backoff delays.
- Subscribe-first pattern -- after connecting, BLE notification subscriptions are established immediately (before reading data). This keeps the connection alive because the toothbrush stays awake as long as active subscriptions exist.
- Smart lock management -- the polling fallback yields to the live monitoring thread when an advertisement is detected, preventing connection contention.
Toothbrush wakes up
--> BLE Advertisement detected by HA
--> Integration connects (~6s BLE stack overhead)
--> Subscribe to 13 notification characteristics (~1s)
--> Read all characteristics (~3s)
--> Live updates flow until toothbrush sleeps
--> Disconnect detected --> wait for next advertisement
- Toothbrush not discovered: Wake it up by picking it up from the charger or briefly turning it on. The toothbrush is not reachable via BLE while on the charging stand.
- Slow connection: The toothbrush advertises every 10-30 seconds. The integration connects as soon as the first advertisement is received, but the BLE stack adds ~6 seconds overhead.
- Connection drops quickly: This is normal when the toothbrush is idle. It sleeps after ~20 seconds. The integration will reconnect automatically on the next wake.
- Phone app conflict: The toothbrush supports only one BLE connection. Close or uninstall the Sonicare phone app if you experience connection issues.
- Pairing issues: If a model that requires bonding won't connect, remove the toothbrush from your phone's Bluetooth settings first (Settings → Bluetooth → Philips Sonicare → Forget/Unpair). The integration handles stale bonds automatically, but the phone's bond may block the connection.
- ESPHome Bluetooth Proxy: Works with the Bluedroid NULL-check patch until ESP-IDF v5.5.5 ships. See Option C for scope and the dedicated ESP32 BLE Bridge as the recommended alternative for multi-device setups.
- Unsure if your model is compatible? Run the GATT scan script to check which BLE protocol your toothbrush uses. It only needs Python 3 and
bleak(pip install bleak).
- Direct BLE reconnect may be delayed: Home Assistant's Bluetooth stack filters duplicate advertisements. Since the Sonicare sends identical advertisement data on every broadcast, wake-ups can be missed. The integration uses a D-Bus RSSI listener as a workaround, but reconnects may still take longer than expected. See habluetooth#397 for the upstream discussion.
The integration communicates directly via BLE -- no cloud, no app required. All communication is fully local.
The toothbrush exposes multiple GATT services with individual characteristics for each data point (battery, brushing state, pressure, brush head, etc.). Data is read directly from these characteristics and live updates are received via GATT notifications.
For a detailed technical description of the BLE protocol including service UUIDs, characteristic reference, data formats, and enum values, see PROTOCOL.md.
| Sensors & Controls | Diagnostics | Dashboard Card |
|---|---|---|
![]() |
![]() |
![]() |
| Device Overview | Brush Head |
|---|---|
![]() |
![]() |
This is an independent community project and is not affiliated with, endorsed by, or sponsored by Philips. All product names, trademarks, and registered trademarks are property of their respective owners.




