Skip to content

[bluetooth.govee] Fix retrieving data from BLE advertisements and enable encrypted communication for newer Govee devices - #20976

Open
matthiasblaesing wants to merge 2 commits into
openhab:mainfrom
matthiasblaesing:fix_govee
Open

[bluetooth.govee] Fix retrieving data from BLE advertisements and enable encrypted communication for newer Govee devices#20976
matthiasblaesing wants to merge 2 commits into
openhab:mainfrom
matthiasblaesing:fix_govee

Conversation

@matthiasblaesing

Copy link
Copy Markdown

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:

  • Govee bluetooth devices broadcast their measurements as part of the BLE advertisement. This did not work.
  • Govee introduced encryption to the command channel and without it communication does not work

Both make the thermo/hydrometer unusable with OpenHAB.

Testing was done with a Govee H5075 thermo/hygrometer.

@matthiasblaesing

Copy link
Copy Markdown
Author

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 gattserial messaging/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.

@lsiepel

lsiepel commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

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.

@matthiasblaesing
matthiasblaesing marked this pull request as draft June 15, 2026 21:17
@matthiasblaesing

Copy link
Copy Markdown
Author

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.

@vkolotov

vkolotov commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

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.

@vkolotov

Copy link
Copy Markdown
Contributor

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.

@matthiasblaesing

Copy link
Copy Markdown
Author

Updated and tested together with #20985:

  • enhanced tests for manufacturer data parsing (GoveeModelTest)
  • added test for the encryption helper (EncryptionHelperTest)
  • moved the model dependent parsing completely into GooveeModel
  • Use commons-lang3 ArrayUtils#swap instead of own implementation
  • Reverted change to GetBatteryCommand
  • Fixed an issue in executeCommand that caused hangs (notification listening now has a timeout and catches exceptions)

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>
@matthiasblaesing

Copy link
Copy Markdown
Author

To get this going again I rebased onto current main branch. As described in #20985 (comment) I'm currently actively running this.

@matthiasblaesing

Copy link
Copy Markdown
Author

@vkolotov could you please have another look?

@lsiepel lsiepel added the bug An unexpected problem or unintended behavior of an add-on label Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug An unexpected problem or unintended behavior of an add-on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants