I did a simply implementation as a sensor detecting if the mac of the toothbrush is on range. If it is then I know that it’s working.

If anyone did the implementation of the api i’m also interested!


Anything ever happen with this? Recently got one and have been thinking of things I could do if it was up and running yet.


Battery level indicator would be neat for two toothbrush household with one charger!

1 Like

Found some reverse engineering progress here (not by me) to maybe build upon:

Here is a standalone implementation able to display received packets from your toothbrush. By piping into an external program it is easy to make the information available to Home Assistant over MQTT (see example).

Only tested on Linux. Battery level not implemented (yet if available at all).

1 Like

i hacked together a worker for bt-mqtt-gateway that collects the info that this script collects from my oral-b-toothbrushes. i hope to file a pull request there soon. this is the bt-mqtt-gateway-worker that works fine for me so far. needs a bit of polishing …

(@molobrakos implementation got me into dependency hell which i couldn’t solve on raspbian.)

import time
from interruptingcow import timeout
from bluepy.btle import Scanner, DefaultDelegate
from mqtt import MqttMessage
from workers.base import BaseWorker
from logger import _LOGGER

import sys
from datetime import datetime
import codecs

REQUIREMENTS = ['bluepy']

class ScanDelegate(DefaultDelegate):
  def __init__(self):

  def handleDiscovery(self, dev, isNewDev, isNewData):
    if isNewDev:
      _LOGGER.debug("Discovered new device: %s" % dev.addr)

class ToothbrushWorker(BaseWorker):
  def searchmac(self, devices, mac):
    for dev in devices:
      if dev.addr == mac.lower():
         return dev

    return None

  def status_update(self):
    scanner = Scanner().withDelegate(ScanDelegate())
    devices = scanner.scan(5.0)
    ret = []

    for name, mac in self.devices.items():
      device = self.searchmac(devices, mac)
      if device is None:
        ret.append(MqttMessage(topic=self.format_topic(name+'/presence'), payload="0"))
        ret.append(MqttMessage(topic=self.format_topic(name+'/presence/rssi'), payload=device.rssi))
        ret.append(MqttMessage(topic=self.format_topic(name+'/presence'), payload="1"))
        _LOGGER.debug("text: %s" % device.getValueText(255) )
        bytes_ = bytearray(bytes.fromhex(device.getValueText(255)))
        ret.append(MqttMessage(topic=self.format_topic(name+'/running'), payload=bytes_[5] ))
        ret.append(MqttMessage(topic=self.format_topic(name+'/pressure'), payload=bytes_[6] ))
        ret.append(MqttMessage(topic=self.format_topic(name+'/time'), payload=bytes_[7]*60 + bytes_[8] ))
        ret.append(MqttMessage(topic=self.format_topic(name+'/mode'), payload=bytes_[9] ))
        ret.append(MqttMessage(topic=self.format_topic(name+'/quadrant'), payload=bytes_[10] ))

    return ret


      ix: 5c:f8:xx:xx:xx:xx
      ia: 2C:6B:xx:xx:xx:xx
    topic_prefix: toothbrush
  update_interval: 10


(@molobrakos implementation got me into dependency hell which i couldn’t solve on raspbian.)

I’m running this on raspbian myself.

pip3 complained a lot, when i tried installing:

Requested 'dbus-1 >= 1.8' but version of dbus is 1.6.8
Requested 'cairo >= 1.13.1' but version of cairo is 1.12.16

the versions that i could install via apt-get were not new enough. i could compile a newer version of dbus by myself, but failed getting or compiling cairo >= 1.13.1

RE: Battery Level

gatttool -b {$mac} --char-read --uuid=0x2A19 -t public
gatttool -b {$mac} --char-read --uuid=0x2A19 -t random
return a HEX value (replace {$mac} with the MAC Address? Is so that’s reading the bluetooth battery level (I use this for my BLE Bike light, Smart Watch, and other bike sensors)

I have a bit of a convoluted setup of Home Assistant doing the following:-

  • The Bluetooth LE Device Tracker detects the device comes into range
  • This runs a REST command when the BLE device comes into range calling a webpage on my PiHole server
  • This writes a flag file to disk
  • Every 60 seconds a cron task looks for these flag files and if one exists runs the gattool command (public version and if that fails random - it’s a mixed bag as to which works)
  • The output of this command is written to a JSON file
  • This also calls http://hassip:8123/api/states/sensor.{$sensor} to update Home Assistant.
  • Another cron runs every 10 minutes resubmitting the data from the JSON Files to Home Assistant (so you don’t have to wait for the device to be used again when HASS restarts - they appear within 10 minutes)

It’s convoluted as I needed to use a Bluetooth Adapter which isn’t already in use for presence detection so it uses the Bluetooth Adapter on my UniFi Controlled / Pi Hole Machine. All the devices I have keep the BLE Active for 10 minutes so this works fine for me.

Coupled with a few other ways of gathering battery level gives a centralised display of battery levels https://i.imgur.com/GoEdK9n.png

$ gatttool -b 5c:f8:21:xx:xx:xx --char-read --uuid=0x2A19 -t public
Read characteristics by UUID failed: No attribute found within the given range

it made the LED-ring on my toothbrush blink however …
-t random times out:

$ gatttool -b 5c:f8:21:xx:xx:xx --char-read --uuid=0x2A19 -t random
connect error: Connection refused (111)

So the first one shows it connected successfully, however it doesn’t expose the (standard) BLE Battery Service. :frowning:

hi how can i find the ix: 5c:f8:xx:xx:xx:xx and ia: 2C:6B:xx:xx:xx:xx of the my toothbrush?

Did anyone ever make any progress on this? It looks like the Developers programme with Oral-B has long been forgotten about by them.

have a look here, supports Oral-B


Thanks. Will have a look at this.

I tried Cybele, the mqtt gateway and some more but had no luck until now with my 9200w…

Cybele is excellent, but did not read the Battery unfortunately

anyway I’m using noble now and you can grab the script for battery and status here:

did anybody managed to change the color of the led using any of the integrations?
it is possible to change it through the app, but so far I have not seen any integration that would pick up that topic.

btw: GitHub - zewelor/bt-mqtt-gateway: A simple Python script which provides a Bluetooth to MQTT gateway, easily extensible via custom workers. See https://github.com/zewelor/bt-mqtt-gateway/wiki for more information.
took me a while to setup it on docker in a rpi0 - but it working now :wink:

The smart Oral-B toothbrushes use BLE to communicate with their app so you can track your brushing. It would be amazing if someone with the know-how could leverage the power of the new Bluetooth BLE in 2022.8.0 to create an Oral-B integration to track the data without sending it over to Oral-B servers.

1 Like

They are already working with the Passive BLE Monitor custom component. The author of that component has played a big part on the new official integration, so it may be ported at some point in the future.


Yep, I will convert the support in BLE monitor to a core BLE integration in the near future. In the neantime, you can use BLE monitor