Closed Misiu closed 3 months ago
Hi all, I have a couple of the H5126 buttons (dual buttons).
I see there was an attempt a year ago, to perhaps start adding the button for support, ie, the branch here: https://github.com/Bluetooth-Devices/govee-ble/tree/button
Looks like @bdraco started it, but doesn't appear to be moving.
I am starting to try to figure out their packing of their bytes based on mucking around with my 2 buttons.
The payload appears to always be 24 bytes.
The first 2 bytes are the specific ID of the unit. I can tell this, based on pressing the buttons on each of my devices, and those 2 bytes are the same on each respective sensor)
The next 4 bytes is the uptime of the device, on a running clock based on milliseconds. You can tell this, by pulling your battery, putting it back in. the 4 bytes start at 0x00 0x00 0x00 0x00, and keep climbing. If you press the button, jot down the number, then press the button again 30 minutes later, if you do the subtraction between those 2 4 byte values, it is dead-on uptime when based on milliseconds.
I do not know what the remaining bytes are yet.
Also, the ID that is reported by the unit is NOT the same as the SN value you see inside your button. At least, I can't see any reasonable way to make one match the other. So it may be that they aren't meant to match.
As far as I can tell, the sensor does NOT send any data ever, unless you press a button. (Although, I would hope it would send a battery warning. But I do not know what it may be)
The only piece of data I am missing is which button is being pressed. I have 2 buttons on my device, and presumably, one of the remaining bytes in the packet probably indicates which button on the device is being pressed.
Once I figure this out, I think I could add support for the buttons, assuming there is still interest in it.
Thanks!
If you figure it out, please update this issue. I'm all for adding support for them if we can get a handle on the format
If you figure it out, please update this issue. I'm all for adding support for them if we can get a handle on the format
I was just thinking about this one a couple days ago! (I actually switched over to some Ikea buttons over Zigbee awhile ago, so my need for this button support isn't there anymore)
However, I wouldn't mind completing this one, or at least, pushing it along, since I do still have the buttons on my desk!
I do have a question for you, if you don't mind... Modifying the Govee driver code locally was easy enough, and starting up a local Home Assistant was easy as well, following the docs that Home Assistant has.
However, I ran into some difficulty trying to figure out how to get the Button support down into the Govee driver layer, since the Govee layer uses the sensor-state-data library above it to help support it.
It didn't make much sense to make the Govee Button a sensor, so I decided to put it on hold until I thought of some way to get the Button support down into the Govee driver.
Since I think you write both sensor-state-data and the Govee driver, I was thinking you might have a suggestion of the best way to do this?
Thanks!
Take a look at the bthome-ble and xiaomi-ble events. Those repos are also on this org.
Take a look at the bthome-ble and xiaomi-ble events. Those repos are also on this org.
Ah. xiamoi-ble definitely points me in the right direction on how to do it. Thank you for the pointer!
@bdraco : Thanks again for the pointer to the bthome-ble/xiaomi-ble code. I was able to add in the button events based on seeing what they do there. That works fine, so now I just need to circle back to the remaining issue that I have...
Which is to figure out which button was pressed. (I have the 2 button version, the H5126)
Unfortunately, I don't see any obvious patterns in the payloads to indicate the button (ie, 0/1 or 1/2 or odd/evens, etc).
So I figured I would post a few of the payload dumps here, just in case you, or others might see something I don't.
The data payloads are 24 bytes long. The first 2 bytes are the ID of the button itself. The next 4 bytes is a running uptime of the button.
The remaining bytes really seem to be random, and nothing really sticks out to me for either the button being pressed, or the battery level, which I would expect to see in each payload.
Below is a 10 dumps for each button, in hex of those 24 bytes, after I yanked the battery, (so we can see the uptime starting at 0):
1st button pressed:
48 89 00 00 0c 26 78 83 76 43 3b d6 cf a3 5d aa 29 e4 29 b5 34 f1 bc a6
48 89 00 00 13 7e 73 50 e4 0f 51 32 e9 44 79 1e 1c 3b 99 55 26 51 79 e2
48 89 00 00 1a 18 c6 85 44 8a 1e 1c 07 a1 9a 93 f4 a1 0b 58 5c e0 b1 7b
48 89 00 00 27 2e 2a a8 e3 6a 2b 86 62 53 ab 0d d6 04 85 56 23 c4 c7 df
48 89 00 00 2e 5e b8 bd a8 3d e8 78 b3 63 2d 3e 84 ad c9 8e 66 2c 70 dc
48 89 00 00 35 3e 52 e4 fb fd 8f 77 d0 b5 70 c7 62 33 3c 2b 38 ef 65 d5
48 89 00 00 3c 82 49 e5 d5 64 05 f5 dc f2 84 a6 ad 6b 57 ae 62 92 ea 6d
48 89 00 00 43 58 04 d6 eb 38 34 41 b6 83 96 8a 14 ae 83 c4 bc 2c 17 60
48 89 00 00 4a 92 9e e6 46 bb d9 f4 20 38 14 a2 ec 6b 4e 5f c2 d5 88 28
48 89 00 00 52 6c b3 38 da e6 83 82 83 50 87 97 d4 ac eb 9c 2b d3 0b ef
2nd button pressed:
48 89 00 00 60 40 53 50 53 22 4c 01 b2 11 b9 b3 d7 9d 82 12 b5 9c 80 b6
48 89 00 00 69 28 0b f2 43 1a 7b f3 34 34 01 3a 90 b7 f2 ba cf e0 0f 0c
48 89 00 00 70 3a f0 cd e8 89 11 8d 5d 8b 16 2c 18 31 9a bb 96 df 62 cf
48 89 00 00 79 0e 04 2c 47 a7 85 3f fb ad 12 12 ad 06 f5 cf a5 c3 1e d5
48 89 00 00 81 6a 67 79 7f c8 7a 9a 9b 55 12 84 8f 1c 1d d8 d0 66 9e 5f
48 89 00 00 8a 16 b6 65 27 ac df f9 a1 c8 f2 00 2f c7 44 59 31 74 7b 56
48 89 00 00 92 4a 1d 27 d6 1a 8d 1b 21 05 45 71 2a 11 8b 66 df 15 bf 43
48 89 00 00 99 48 44 28 b4 a3 db f2 1a 75 41 e9 bc da 35 00 2f 7f 4f e0
48 89 00 00 a0 96 4a 47 a6 ac 11 26 8a 18 2a 17 35 49 e9 76 1c a8 86 3c
48 89 00 00 a8 52 b8 2f 69 7c 2e e7 c2 7e 92 b0 2e cf ec c2 25 5c ad a8
Any thoughts, if you see anything, would definitely be helpful! Thanks!
It looks like the payload might be encrypted
Unfortunately, I think you are right. That does make the most sense as to why nothing appears obvious in there, and just random.
Looking at the manual, (didn't bother to do it previously!) it does appear you press the button for 5 seconds, to go into a pairing mode.
I ran the nRF Connect app, and it looks like you can only connect to it while in that pairing mode.
I am guessing they must exchange keys during the pairing time, and the key is probably used from that point on to decode the following payloads from the button.
Weird they decided to do it this way, in comparison to their temp sensors. I guess maybe they felt the status of a button press should be a bit more secure or something.
Anyway, I think this probably ends us trying to support this in Home Assistant, unless you see there is still value in supporting the 1 button device, since we can kind of determine the button press based on the packet being sent, even if we can't decode it fully.
I just saw this issue and I always wanted to add support for those buttons. Those buttons communicate using Bluetooth with "distributed gateway" govee products which are products with wifi connection. I think that what is happening then is that those wifi devices perform a web request to AWS iot or govee server that then performs the action setup in the app (because you can detect the button being pressed with ifttt and there is a cloud history of button press in the app) Now we need to know if when we are changing the action performed on button press in the app are we communicating data using Bluetooth to those buttons or not (most likely not but maybe the rest of the packet data is related to that or related to identifying the device and the action to perform when given to the "distributed gateway" devices which then uses those infos to perform the request) If not can I have more details on the packets? Are the packets data different from one another when pressing the same button (except from time code). Are they constantly changing? Are they different between two buttons?
Is there anyway for home assistant to plug himself on the govee or AWS iot server to detect button press (like ifttt) even if not ideal because local is better but still.? If not govee could update their new api to support those button press detection because it is cloud based.
Implantation questions: If we somehow manage to know how the buttons are working we could detect button press but how to avoid the action setup in the app to happen? (Does the button still work when no actions are selected? Does it still work if we disable all distributed gateway devices to be the only one to detect button press?)
By the way how did you intercept the Bluetooth packets ?
Based on @skilau's data, and from dumping the FW on my H5122 unit, I was able to piece together how to decode the payloads. It appears to use AES-ECB with the zero-padded timestamp as the key :)
Here's a proof-of-concept for decoding the payloads:
from Crypto.Cipher import AES
gh_samples = '''
48 89 00 00 0c 26 78 83 76 43 3b d6 cf a3 5d aa 29 e4 29 b5 34 f1 bc a6
48 89 00 00 13 7e 73 50 e4 0f 51 32 e9 44 79 1e 1c 3b 99 55 26 51 79 e2
48 89 00 00 1a 18 c6 85 44 8a 1e 1c 07 a1 9a 93 f4 a1 0b 58 5c e0 b1 7b
48 89 00 00 27 2e 2a a8 e3 6a 2b 86 62 53 ab 0d d6 04 85 56 23 c4 c7 df
48 89 00 00 2e 5e b8 bd a8 3d e8 78 b3 63 2d 3e 84 ad c9 8e 66 2c 70 dc
48 89 00 00 35 3e 52 e4 fb fd 8f 77 d0 b5 70 c7 62 33 3c 2b 38 ef 65 d5
48 89 00 00 3c 82 49 e5 d5 64 05 f5 dc f2 84 a6 ad 6b 57 ae 62 92 ea 6d
48 89 00 00 43 58 04 d6 eb 38 34 41 b6 83 96 8a 14 ae 83 c4 bc 2c 17 60
48 89 00 00 4a 92 9e e6 46 bb d9 f4 20 38 14 a2 ec 6b 4e 5f c2 d5 88 28
48 89 00 00 52 6c b3 38 da e6 83 82 83 50 87 97 d4 ac eb 9c 2b d3 0b ef
48 89 00 00 60 40 53 50 53 22 4c 01 b2 11 b9 b3 d7 9d 82 12 b5 9c 80 b6
48 89 00 00 69 28 0b f2 43 1a 7b f3 34 34 01 3a 90 b7 f2 ba cf e0 0f 0c
48 89 00 00 70 3a f0 cd e8 89 11 8d 5d 8b 16 2c 18 31 9a bb 96 df 62 cf
48 89 00 00 79 0e 04 2c 47 a7 85 3f fb ad 12 12 ad 06 f5 cf a5 c3 1e d5
48 89 00 00 81 6a 67 79 7f c8 7a 9a 9b 55 12 84 8f 1c 1d d8 d0 66 9e 5f
48 89 00 00 8a 16 b6 65 27 ac df f9 a1 c8 f2 00 2f c7 44 59 31 74 7b 56
48 89 00 00 92 4a 1d 27 d6 1a 8d 1b 21 05 45 71 2a 11 8b 66 df 15 bf 43
48 89 00 00 99 48 44 28 b4 a3 db f2 1a 75 41 e9 bc da 35 00 2f 7f 4f e0
48 89 00 00 a0 96 4a 47 a6 ac 11 26 8a 18 2a 17 35 49 e9 76 1c a8 86 3c
48 89 00 00 a8 52 b8 2f 69 7c 2e e7 c2 7e 92 b0 2e cf ec c2 25 5c ad a8
'''
gh_samples = [x for x in (bytes.fromhex(x) for x in gh_samples.splitlines()) if x]
def calculate_crc(data):
crc = 0x1d0f
for b in data:
for s in range(7, -1, -1):
mask = 0
if (crc >> 15) ^ (b >> s) & 1:
mask = 0x1021
crc = ((crc << 1) ^ mask) & 0xffff
return crc
def decrypt_data(key, data):
cipher = AES.new(key[::-1], AES.MODE_ECB)
return cipher.decrypt(data[::-1])[::-1]
for gh_sample in gh_samples:
assert len(gh_sample) == 24
b_front_of_device_id = gh_sample[:2]
b_time_ms = gh_sample[2:6]
b_enc_data = gh_sample[6:22]
b_enc_crc = gh_sample[22:24]
# Check that CRC matches what's expected
assert calculate_crc(b_enc_data) == int.from_bytes(b_enc_crc, 'big')
# Decrypt the data
key = b_time_ms + bytes(12)
decrypted = decrypt_data(key, b_enc_data)
# Extract the info
battery_percentage = decrypted[4]
button_pressed = decrypted[5]
print(f'Battery level: {battery_percentage}%, Button pressed: {button_pressed}')
This script prints:
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 0
Battery level: 80%, Button pressed: 1
Battery level: 80%, Button pressed: 1
Battery level: 80%, Button pressed: 1
Battery level: 80%, Button pressed: 1
Battery level: 80%, Button pressed: 1
Battery level: 80%, Button pressed: 1
Battery level: 80%, Button pressed: 1
Battery level: 80%, Button pressed: 1
Battery level: 80%, Button pressed: 1
Battery level: 80%, Button pressed: 1
nice. I'll order some for testing
@gh2o, Wow, that is awesome! Thank you so much for putting it together and figuring it out!
Wow incredible! Thank you !
https://github.com/Bluetooth-Devices/govee-ble/pull/88 adds support for GV5121/GV5122/GV5123/GV5125/GV5126 in the library including the battery sensor and motion, window, and buttons
https://github.com/home-assistant/core/pull/122004 adds support for the GV5121/GV5122/GV5123/GV5125/GV5126 battery sensors in Home Assistant
The motion, window, and buttons will require new platforms in Home Assistant which is more than I have time to work on right now but at least the battery sensors can be monitored. If someone wants to write the event and binary_sensor platforms, they can largely be copied from bthome
Thanks @gh2o for figuring out the encryption
@bdraco : Wow, this is extremely cool! Thank you so much for adding all this support for pretty much all the Govee IOT things! I wasn't expecting the motion sensors and door sensors to be added too, so this is just awesome! :)
I can probably get the vibration sensor working as well if it uses the same protocol. It was out of stock though so have to wait for it
Just wanted to say Thanks again @bdraco and @gh2o! Just installed the latest HA update, and the buttons work great!
How did you do in ha ? I wasn't able to connect them every time I tried to add a device with govee Bluetooth devices it directly says no devices found so I cannot connect the remote, have you done something special on the remote ? In ha?
@Fefedu973 : Assuming you are on currently Home Assistant (2024.08.x), it is built-in.
If you have one of the devices, it will be auto-discovered when you press one of the buttons. You should see it show up in "New devices discovered".
Once you add it on that page, it will just be inserted into the "Govee Bluetooth" section.
I have 2 of the H5126, and the button presses show up very fast. Perhaps faster than my Ikea Zigbee buttons. :)
Oh ok ! Thank you !
Is your feature request related to a problem? Please describe. I'm looking for a Bluetooth button(s) that I can use with HA. Ideally, H5125 could be used to control 6 devices.
Describe the solution you'd like I'd like to be able to use those remotes with Home Assistant as for example Shelly BLU Button, but with 6 buttons on a device I could control multiple devices with a single physical device.
Additional context https://us.govee.com/products/govee-wireless-button-sensor https://us.govee.com/products/goveelife-smart-mini-double-button-switch https://us.govee.com/products/goveelife-wireless-mini-smart-6-button-sensor