[bluetooth.govee] Fix retrieving data from BLE advertisements and enable encrypted communication for newer Govee devices - #20976
Conversation
|
Maybe relevant: before checking into the OpenHAB code, I tested communication using this project: https://github.com/matthiasblaesing/GVH5075Reader. That is a standalone reader for communication with the Govee device and proofed, that the device worked correctly and there was something broken in the bindings. |
There was a problem hiding this comment.
Pull request overview
This PR updates the Govee Bluetooth binding to (1) correctly parse measurement data from BLE advertisements (manufacturer data) and (2) support the encrypted GATT command channel required by newer Govee devices, making affected thermo/hygrometers usable again.
Changes:
- Refactors advertisement parsing to use manufacturer data and per-model scan payload sizes.
- Adds an encryption handshake + AES/RC4 packet crypto helper for encrypted command communication.
- Removes the old
gattserialmessaging/socket abstraction in favor of direct characteristic notification handling.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/govee/internal/GoveeModel.java | Adds per-model scan payload sizes and broadens model detection to BluetoothDevice. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/govee/internal/GoveeHygrometerHandler.java | Major refactor: switch to manufacturer data parsing, add encryption handshake + direct command execution/notification plumbing. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/govee/internal/EncryptionHelper.java | New helper implementing the device’s mixed AES/ECB + RC4 scheme for 20-byte packets. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/govee/internal/command/hygrometer/TemHumDTO.java | Adds toString() for easier debugging/logging. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/govee/internal/command/hygrometer/GoveeMessage.java | Decouples from GattMessage interface and tightens nullability of payload accessors. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/govee/internal/command/hygrometer/GoveeCommand.java | Removes dependency on the deleted gattserial service interfaces; becomes a simple command base class. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/govee/internal/command/hygrometer/GetBatteryCommand.java | Adjusts battery parsing (needs alignment with response payload handling). |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/gattserial/SimpleMessageServicer.java | Deleted legacy gattserial abstraction. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/gattserial/SimpleMessageHandler.java | Deleted legacy gattserial abstraction. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/gattserial/SimpleMessage.java | Deleted legacy gattserial abstraction. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/gattserial/SimpleGattSocket.java | Deleted legacy gattserial abstraction. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/gattserial/MessageSupplier.java | Deleted legacy gattserial abstraction. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/gattserial/MessageServicer.java | Deleted legacy gattserial abstraction. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/gattserial/MessageHandler.java | Deleted legacy gattserial abstraction. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/gattserial/GattSocket.java | Deleted legacy gattserial abstraction. |
| bundles/org.openhab.binding.bluetooth.govee/src/main/java/org/openhab/binding/bluetooth/gattserial/GattMessage.java | Deleted legacy gattserial abstraction. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Maybe @vkolotov can be of any help here to asses the changes as he did some recent changes to bluez gatt etc and has some usefull knowledge about this. |
|
Copilot gave some valid points, which are mostly straight forward to implement. However retesting is hard because a problem I saw in the last few days resurfaced: The connect/discovery mechanism is highly unstable. I'll have to revisit this. |
|
I've pushed a few fixes for dbus/bluez part related to connection/gatt discovery reliability. Not sure if your binding uses the common part that I fixed, if so - highly recommend pulling changes from the release candidate branch and test it. It was really badly broken. |
|
Also make sure you test it with close proximity, you need to have at least 80 RSSI so that your adapter can connect, 80 is the borderline. |
bed6c0e to
eb07f5e
Compare
|
Updated and tested together with #20985:
|
The Govee temperate and humidity sensors broadcast the current measurements as part of the bluetooth le advertisement package. That data is published in the manufacturerData property of the BluetoothScanNotification. The byte array that is delivered there holds the manufacturer id as the first two bytes followed by the payload. This PR aligns reading the scanning data with that description. The model specific interpretation of the scanning data was moved to the model enum and the model of the device that send the advertisement is acutally determined and not hardcoded to the default of H5074. Signed-off-by: Matthias Bläsing <mblaesing@doppel-helix.eu>
…e requiring encrypted communication Newer firmwares for Govee devices encrypt the communication for the command channel. Every communication on the PROTOCOL_CHAR_UUID characteristic for these devices is expected to be encrypted and if that does not hold, the device will immediately disconnect. The communication is protected by a session key, that is determined by doing a handshake with the auth service on the device. That in turn is authenticated with a pre shared key, that other projects communicating with the devices already determined. The general communication scheme is: - connect to device - do encryption handshake to determine session key - communicate with PROTOCOL_CHAR_UUID using session key - disconnect While working on the implementation the asynchronous implementation allowing multiple threads access to the device simultaniously was found to be problematic. Changes: - ConnectedBluetoothHandler was dropped as superclass and replaced by BeaconBluetoothHandler as the core functionality (reporting the current measurements) is provided by the advertisement data and the connection is only needed to update the configuration. - The socket like implementation (gattserial) was removed and replaced by direct invocation of BluetoothDevice#writeCharacteristic and event listeners for onCharacteristicUpdate. From that infrastructure the implemented commands were retained as they provide the required encoding. - A helper to handle the encryption was added. This helper also provides a NOOP implementation if the device does not have an auth service and thus does not need encryption. Signed-off-by: Matthias Bläsing <mblaesing@doppel-helix.eu>
eb07f5e to
d61ab3b
Compare
|
To get this going again I rebased onto current main branch. As described in #20985 (comment) I'm currently actively running this. |
|
@vkolotov could you please have another look? |
This PR adds changes to fix access to Govee bluetooth devices. There are two issues addressed by the two commits of this PR. Please see the individual commits for details:
Both make the thermo/hydrometer unusable with OpenHAB.
Testing was done with a Govee H5075 thermo/hygrometer.