Various data on characteristic 4130
I was experimenting a bit, especially the gyro characteristics. I own a sonicare HX991W which should be identical to the HX992B. I could not get any gyro data out of it, but I was able to find some other useful values:
You have to write a value to 4120 to enable output on 4130. Depending on what you write to 4210, you get different outputs:
0: no output on 4130 1: pressure data 2: unknown values. They change sometimes, but I cannot find when or how, or any meaning 8: grip strength Combinations are possible (so, write '9' to 4120 to get pressure and grip data).
The first byte of the received value on 4130 indicates the kind of data in the rest of the string:
1: pressure data: 5th and 6th byte output a signed integer, positive if you press on the brush (the normal force when you brush your teeth), negative it you pull the brush up. 7th byte has a value of '2' if you exceed the recommended pressure. Only streams this when the brushing is active.
8: grip strength: 5th byte indicated how strong you hold the body. Around 100 if you don't touch it, around 160 is you squeeze it. Other bytes seem to be some kind of moving average, and other related values I cannot identify. These values regardless of brushing active of inactive.
Do you know how to enable streaming of the accelerometer/gyroscope data?
You have to write a value to 4120 to enable output on 4130. Depending on what you write to 4210, you get different outputs:
I also looked into this one and implemented it into the GUI (that I did not document very good): https://github.com/joushx/python-sonicare/blob/main/examples/gui/sensor/sensor.py#L46. Now I added instructions to the README.

2: unknown values. They change sometimes, but I cannot find when or how, or any meaning
This one looks like a temperature value in degrees Celsius for me.
1: pressure data: 5th and 6th byte output a signed integer, positive if you press on the brush (the normal force when you brush your teeth), negative it you pull the brush up. 7th byte has a value of '2' if you exceed the recommended pressure. Only streams this when the brushing is active.
I know that there is the pressure and some kind of alarm, but I think I somehow broke it in the code...
8: grip strength: 5th byte indicated how strong you hold the body. Around 100 if you don't touch it, around 160 is you squeeze it. Other bytes seem to be some kind of moving average, and other related values I cannot identify. These values regardless of brushing active of inactive.
That is very interesting! I think my brush cannot measure that. Feel free to integrate it into the GUI if you want.