python-sonicare
python-sonicare copied to clipboard
Feature Request: Integrate with Home Assistant
I would love to see this make its way into a Home Assistant integration.
Same here Alternatively or in addition an app for iphone to implement apple health data localy rather than the data greedy sonicare app by Philips
would be very nice if somebody could make this happen :D
With the new BLE support in Home Assistant and the ability to use esphome devices as bluetooth proxies, this would be a great time this integration. You can see support for many other devices being added (i.e. oral-b, swtichbot, etc)
https://github.com/Bluetooth-Devices
The predecessor to this repo was a custom integration called Passive BLE Monitor and it had a process to request new sensors - https://custom-components.github.io/ble_monitor/sensor_request I do not have a BLE enabled sonicare at this point but perhaps someone else does and could work on this.
The sonicare toothbrushes were not compatible with the 'old' passive BLE Monitor, because it has an active communication protocoll... Nevertheless, I think it should work with the new BLE support in HomeAssistant, because the bluetooth proxis now also can handle active communication. I have not the knowhow to make an custom component for this, but I could help an developer with testing and generating logs in order to make it working... :) Maybe somebody has the knowhow and has time to develop it (Y)
I agree that getting this into Home Assistant would be awesome. Even though we don't know what all the BLE services translate to, just getting the basic on/off state into Home Assistant would be helpful for many automations. @bdraco I have seen you pop up a few times in your work with Home Assistant/BLE stuff, and I think you recently worked on the Oral-B integration. Do you think basic Sonicare integration is a possibility, given this project? How big of a lift would that be, in your opinion? This might be something we could all work on together, if necessary (and with your guidance!)
Even though we don't know what all the BLE services translate to, just getting the basic on/off state into Home Assistant would be helpful for many automations.
The page from the repo owner has a lot of info about what is available - https://blog.johannes-mittendorfer.com/artikel/2020/10/my-toothbrush-streams-gyroscope-data
From the docs it doesn’t look like the device has data in the advertisements so it requires an active connection which makes it much more difficult to integrate.
It’s possible it actually does but someone with the device would have to do that investigation
Thanks for taking a look! I have the device and I think a few others here do as well. What should I look for? And what's the best way to collect and analyze that data?
And what's the best way to collect and analyze that data?
https://community.home-assistant.io/t/oral-b-support-toothbrush-model-3764/483732/2?u=bdraco
Thanks for taking a look! I have the device and I think a few others here do as well. What should I look for? And what's the best way to collect and analyze that data?
I was going to say if you don't have a BT-attached HA close enough to the toothbrush, I like the nRF connect app on my phone to see what is advertised as a quick test. But then I realized its a toothbrush and pictured you standing by your HA instance in somewhere like the basement brushing your teeth trying to capture data.
Also, the kids Sonicare seems to have BT abilities and is only ~30 USD if someone was looking for one.
And what's the best way to collect and analyze that data?
https://community.home-assistant.io/t/oral-b-support-toothbrush-model-3764/483732/2?u=bdraco
Hi, i activated the debug log for bluetooth in HomeAssistant and started my toothbrush... ;) in the logs I found the following:
2022-11-03 21:26:15.983 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] kuehlung-lowboard: 61:A7:80:AC:98:0C AdvertisementData(manufacturer_data={76: b'\x10\x07\x14\x1f\xa6\xa6\x05\xa9H'}, tx_power=-127, rssi=-75) connectable: True match: set() rssi: -75
2022-11-03 21:26:28.470 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] kuehlung-lowboard: 45:E0:E5:16:24:A6 AdvertisementData(manufacturer_data={76: b'\x10\x05%\x18\xdc\xb2\xef'}, tx_power=-127, rssi=-71) connectable: True match: set() rssi: -71
2022-11-03 21:30:57.249 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] F0:9E:4A:85:6A:0A: D8:CB:3C:A4:C5:3F AdvertisementData(manufacturer_data={89: b'\xd8\xcb<\xa4\xc5?'}, rssi=-101) connectable: True match: set() rssi: -101
2022-11-03 21:31:59.213 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] kuehlung-lowboard: 18:57:98:5D:F1:FD AdvertisementData(manufacturer_data={6: b'\x01\t \x02+>a\xa2Fy\xc8@\xd7\xa5n\xd1\xb8\x85\xba\x96\x96\x1b_\xe7\xfd\xc6\x07'}, tx_power=-127, rssi=-65) connectable: True match: set() rssi: -65
Is this information useful?
2022-11-03 21:26:15.983 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] kuehlung-lowboard: 61:A7:80:AC:98:0C AdvertisementData(manufacturer_data={76: b'\x10\x07\x14\x1f\xa6\xa6\x05\xa9H'}, tx_power=-127, rssi=-75) connectable: True match: set() rssi: -75
This is likely an apple device
2022-11-03 21:26:28.470 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] kuehlung-lowboard: 45:E0:E5:16:24:A6 AdvertisementData(manufacturer_data={76: b'\x10\x05%\x18\xdc\xb2\xef'}, tx_power=-127, rssi=-71) connectable: True match: set() rssi: -71
This is likely an apple device
2022-11-03 21:31:59.213 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] kuehlung-lowboard: 18:57:98:5D:F1:FD AdvertisementData(manufacturer_data={6: b'\x01\t \x02+>a\xa2Fy\xc8@\xd7\xa5n\xd1\xb8\x85\xba\x96\x96\x1b_\xe7\xfd\xc6\x07'}, tx_power=-127, rssi=-65) connectable: True match: set() rssi: -65
This is likely a microsoft device
Is this information useful?
None of them are likely tooth brushes
All the oralB ones will be {220:
aka https://github.com/hbldh/bleak/blob/aa24332a39952880005705155629df423fbad1aa/bleak/backends/_manufacturers.py#L226
now i found the right log entries:
2022-11-03 21:10:13.431 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] F0:9E:4A:85:6A:0A: 24:E5:AA:06:A2:BD AdvertisementData(local_name='Philips Sonicare', rssi=-97) connectable: True match: set() rssi: -97
2022-11-03 21:10:14.014 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] F0:9E:4A:85:6A:0A: 24:E5:AA:06:A2:BD AdvertisementData(local_name='Philips Sonicare', service_uuids=['477ea600-a260-11e4-ae37-0002a5d50001'], rssi=-93) connectable: True match: set() rssi: -93
2022-11-03 21:24:12.960 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] F0:9E:4A:85:6A:0A: 24:E5:AA:06:A2:BD AdvertisementData(local_name='Philips Sonicare', service_uuids=['477ea600-a260-11e4-ae37-0002a5d50001'], rssi=-92) connectable: True match: set() rssi: -92
2022-11-03 21:24:20.461 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] Philips Sonicare (24:E5:AA:06:A2:BD): Switching from F0:9E:4A:85:6A:0A[True] to kuehlung-lowboard[True] (new rssi:-79 - threshold:5 > old rssi:-92)
@bdraco , does this help?
now i found the right log entries:
2022-11-03 21:10:13.431 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] F0:9E:4A:85:6A:0A: 24:E5:AA:06:A2:BD AdvertisementData(local_name='Philips Sonicare', rssi=-97) connectable: True match: set() rssi: -97 2022-11-03 21:10:14.014 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] F0:9E:4A:85:6A:0A: 24:E5:AA:06:A2:BD AdvertisementData(local_name='Philips Sonicare', service_uuids=['477ea600-a260-11e4-ae37-0002a5d50001'], rssi=-93) connectable: True match: set() rssi: -93 2022-11-03 21:24:12.960 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] F0:9E:4A:85:6A:0A: 24:E5:AA:06:A2:BD AdvertisementData(local_name='Philips Sonicare', service_uuids=['477ea600-a260-11e4-ae37-0002a5d50001'], rssi=-92) connectable: True match: set() rssi: -92 2022-11-03 21:24:20.461 DEBUG (MainThread) [homeassistant.components.bluetooth.manager] Philips Sonicare (24:E5:AA:06:A2:BD): Switching from F0:9E:4A:85:6A:0A[True] to kuehlung-lowboard[True] (new rssi:-79 - threshold:5 > old rssi:-92)
@bdraco , does this help?
That's the one. Looks like there isn't anything useful in the advertisement so the device would require an active connection. That makes it a poor candidate to integrate as an active connection would drain the battery.
hmm, you mean that the toothbrush would need a permanent active connetion to HA? or only when you are brushing the teeth? in the second case I think that the battery shouldn't be the huge problem, because (at least for me) I put the toothbrush on the charger evertime I finished with the brushing... But I understand that the integration will not be that easy due to the fact, that an active connection is needed. Wouldn't it be possible to use the python code from this repo as a starting point for the custom component? (sorry for the (maybe) stupid question, but I am not a python programmer nor I am into developing custom components... ;) )
hmm, you mean that the toothbrush would need a permanent active connetion to HA?
Yes, otherwise you wouldn't know when it turns on and off
or only when you are brushing the teeth? in the second case I think that the battery shouldn't be the huge problem, because (at least for me) I put the toothbrush on the charger evertime I finished with the brushing...
But I understand that the integration will not be that easy due to the fact, that an active connection is needed.
BLE adapters have limits to how many connections they can handle at the same time. Some can only handle 1, some will only handle 3, and some of the better ones will handle up to 9. As such holding an active connection comes at a premium since the majority of devices only need an active connection for a few seconds when you are interacting with them.
Wouldn't it be possible to use the python code from this repo as a starting point for the custom component? (sorry for the (maybe) stupid question, but I am not a python programmer nor I am into developing custom components... ;) )
This code doesn't use bleak
so it would be quite difficult to integration into HA as you'd have to rewrite the bulk of it
Hmm. Yeah I think only initiating the active connection when HA hears an advertisement (which I think would only happen when the toothbrush is picked up/turned on? I'd need to test.), or even manually activating the "listening" via another automation is a reasonable compromise. I would also be willing to deploy a dedicated ESP BLE Proxy for something like this, so I'm not worried about the number of connections. I also don't think an active connection is needed all the time. The way the app works, is that you have to open the app and connect it to the toothbrush while you are using it. There is no passive data collection into the app. Do you have any example integrations for other devices that use an active connection? If so, I could maybe look at adapting that.
Hmm. Yeah I think only initiating the active connection when HA hears an advertisement (which I think would only happen when the toothbrush is picked up/turned on? I'd need to test.), or even manually activating the "listening" via another automation is a reasonable compromise.
You may find its sending advertisements regardless if its on or not.
I would also be willing to deploy a dedicated ESP BLE Proxy for something like this, so I'm not worried about the number of connections. I also don't think an active connection is needed all the time. The way the app works, is that you have to open the app and connect it to the toothbrush while you are using it. There is no passive data collection into the app. Do you have any example integrations for other devices that use an active connection? If so, I could maybe look at adapting that.
You could look at led-ble
as its an always connected integration
Thanks! If I can find some time, I'll play around with this. If anyone else wants to work on this as well, feel free!
Quick update! Did some testing this evening with the Sonicare DiamondClean Smart (HX993X) BLE brush. If the brush has been laying motionless for a period of time, all BLE activity stops. I tested this while it was in the charger, and laying on a table. As soon as the brush is "woken up" (either by removing from the charger, or just moving it [gyroscope]) it starts advertising a timestamp. Once the brush is awake, I'm able to interrogate it for services. So it looks like triggering a manual "listen" wouldn't be necessary. A library could theoretically scan for a particular device ID's timestamp advertisement, or filter by Serial Number which is exposed over the Device Information Service. So it seems like once an advertisement is detected, an active BLE connection could be established? I'll come back to this as I have time. This is currently a very low priority project but I'd love to see it working :)
nice learnings 👍 hope to hear from you soon again ;)
Hi all, repo owner here. Sorry for not replying earlier, but unfortunately the Bluetooth part of my toothbrush broke and I can't help with your project.
This code doesn't use bleak so it would be quite difficult to integration into HA as you'd have to rewrite the bulk of it
I should have used bleak from the beginning but was not aware of it's existence.
If the brush has been laying motionless for a period of time, all BLE activity stops
Yes, very annoying during development.
Happy to help if you need some additional information!
Hi @joushx! No worries. I mean yeah I really haven't done much BLE development so this will be new for me. If you have time to help migrate to bleak
that would be awesome but I'll eventually find some time to play with this. Any tips are welcome!
It's really just going to be a matter of listening for the passive advertisement, initiating an active connection, and then continually poll state (or watch for push updates? Not sure what options are available for BLE dev) until the device disconnects. Disconnect can be an assumed state of "off". Polling might drain the battery but as long as it is charged right after I think it's probably fine.
Also, if anyone else is interested in working on this, please feel free to jump in!
@villasenor
I also have not much experience with bleak but would be willing to help code a lib for it. If we build a lib based on bleak, is it easier to integrate in HA?
What would be a good approach to start porting, so that integrating into HA is as flexible and easy as it can get? I have a device and would like to at least figure out when it's on or off.
@peteh I feel much the same way just state would be great. I haven't done any major BLE dev, so I'm not sure what the best practices are. Based on what @bdraco said, it sounds like bleak
is the way to go for Home Assistant integration? I'm not sure why...maybe there is already a hook for it with the BLE proxies and stuff? My current knowledge of the HA Bluetooth stack turns to magic pretty quick haha but I'm willing to learn.
If you use bleak the proxies will just work with no additional code
So porting this stuff to bleak should be a good starting point.
Hi, I started a project and got the very basics and made an example to read the battery soc via bleak. However, I have never really used it before so I don't know how to properly design a lib with bleak and asyncio.
https://github.com/peteh/python-bleaksonicare
If somebody wants to join the work, feel free to join.
Awesome! I'll take a look at this when I can. Thanks so much for jumping in, @peteh!
@bdraco - I know you probably have a million things on your plate, but if you get a second to glance at the repo that @peteh has started on (https://github.com/peteh/python-bleaksonicare), I think that would be helpful to make sure we are headed in the right direction. Thanks so much, everyone!
My plan is to make a bleak based lib similar to this and then use it to create another repo integrating it into HA. As I'm pretty busy and can only work on it every now and then, help is really appreciated.