Read Govee Temperature Humidity BLE Advertisements with esp32 and esphome!

Thanks so much for this! Worked for me using an H5102.

I wanted to throw in one more detail though: Under, sensor:, you ought to have device_class: "humidity" in order for the sensor to be shown on Homekit (per the Supported Components section).

So effectively this:

sensor:
  - platform: template
    name: "Master Bath Temperature"
    id: govee1_temp
    device_class: "temperature"
    unit_of_measurement: "°C"
    accuracy_decimals: 2
  - platform: template
    name: "Master Bath Humidity"
    id: govee1_humidity
    device_class: "humidity"
    unit_of_measurement: '%'
    accuracy_decimals: 2
  - platform: template

So if anyone’s wondering why yoru humidity is not showing up in homekit, this is why :slight_smile: . Funnily enough, the “Master Bath Temperature” section not explicitly having device_class: "temperature" seems to show up fine on Homekit.

Is there any way to do this passively instead of active in order to save battery?

Fantastic work, John. I copied your code and it worked on the first go. I hadn’t looked at that Govee app in months, but now this temp/hygrometer unit has got a new lease on life!

I wanted to provide an update for this. I recently shifted over to using the new native bluetooth component in Home Assistant. I am using the ZEXMTE long range bluetooth dongle. The system auto identified the Govee sensors and it works very well. I have now shifting all of my automation and dashboards to the new entities and retired the EspHome solution. My sensors are in very different locations in the house but the dongle has no issue hearing “any of them” (the ESP32 also had no issues as well - very impressive performance from the ESP32 since the sensors are very far away including one on the second floor of the house)

Hi John! I realize you’re using the native components, but I’m needing to integrate the govee sensors directly into the esp32, because it’s a thermostat and I need it to function without HA.

I’ve been trying to use the original code at the top but I’m getting all wrong numbers. Any ideas?
What should I use for a Govee 5075?

My suggestion would be to use an ESPHOME BLE Gateway on the ESP32 and have that communicate with HA BLE Integration. This would allow you to use the “official” Govee BLE integration that does all of the heavy lifting (parsing) of the BLE data for you. I had started down this path of trying to get the ESPHOME BLE Gateway to talk to HA via the HACS custom BLE_Monitor integration. That Dev is merging his work with the new HA BLE support.

This would essentially allow an ESP32 to be used as a “BLE repeater” over the ESP32 Wifi into HA. I am not sure this has been fully developed yet, but I am sure someone is working on it. (I would further look into doing it except that the long range BT adapter I put on my HA box covers my entire home so I don’t have a current need)

The auto detection makes this a lot easier doesn’t it! This looks really cool, do you think USB passthrough to a VM (hyper-v) would work?

I am under the impression that USB passthrough under hyper-v is problematic, for non-storage, and/or non-windows guest OS. Can’t recall where I get that from. Could anyone confirm?

Other VM solutions however are mostly fine - VMware or VirtualBox

EDIT: Found an article also saying hyper-v not supporting non-storage USB passthrough, but then it was a 2016 article. So… could anyone confirm one way or another? Is hyper-v getting better USB support these days?

I finally figured it out - hopped onto IRC and talked with some Python experts.

Here’s the code for the Govee H5179 - it is working as expected and I just finished some of the debugging. Hopefully this helps anyone else that is trying to use the ESP32 tracker! :slight_smile:

esp32_ble_tracker:
  on_ble_manufacturer_data_advertise:
    - mac_address: E3:32:80:C3:1C:EC
      manufacturer_id: '8801'
      then:
        - lambda: |-
            float temp_lsb = (int16_t(x[5]) << 8) + int16_t(x[4]);
            float hum_lsb = (int16_t(x[7]) << 8) + int16_t(x[6]);
            float batt_lsb = uint16_t(x[8]);
            
            float temperature = temp_lsb / 100;
            float humidity = hum_lsb / 100;
            float battery_level = batt_lsb;

            id(basement_temperature).publish_state(temperature);
            id(basement_humidity).publish_state(humidity);
            id(basement_battery).publish_state(battery_level);

binary_sensor:
  - platform: ble_presence
    mac_address: E3:32:80:C3:1C:EC
    name: "Basement Govee H5179"

sensor:
  - platform: ble_rssi
    mac_address: E3:32:80:C3:1C:EC
    name: "Basement RSSI"
  - platform: template
    name: "Basement Humidity"
    id: basement_humidity
    unit_of_measurement: '%'
    icon: "mdi:water-percent"
  - platform: template
    name: "Basement Temperature"
    id: basement_temperature
    unit_of_measurement: '°C'
    icon: "mdi:thermometer"
  - platform: template
    name: "Basement Battery"
    id: basement_battery
    unit_of_measurement: '%'
    icon: "mdi:battery"

2 Likes

Hey, I’m a novice to doing anything with esp32 boards or automation in general, but I decided to take a stab at doing this. I have an esp32c3 that I’m trying to hook a govee h5074 up to. After much toil, I finally got the code loaded onto it, but I’m not seeing any matching bluetooth traffic. Can someone check my code to find any problems?

esphome:
  name: test
  platformio_options:
    board_build.flash_mode: dio
    
esp32:
  board: esp32-c3-devkitm-1
  framework:
    type: esp-idf
    version: recommended
    # Custom sdkconfig options
    sdkconfig_options:
      CONFIG_COMPILER_OPTIMIZATION_SIZE: y
      CONFIG_BT_BLE_50_FEATURES_SUPPORTED: y
      CONFIG_BT_BLE_42_FEATURES_SUPPORTED: y
      CONFIG_ESP_TASK_WDT_TIMEOUT_S: "10"
    # Advanced tweaking options
    advanced:
      ignore_efuse_mac_crc: false

# Enable logging
logger:

sensor:
#  - platform: wifi_signal
#    name: "WiFi Signal Strength"
#    update_interval: 60s
  
  - platform: template
    name: "Grow Tent Humidity"
    id: grow_tent_humidity
    unit_of_measurement: '%'
    icon: "mdi:water-percent"
  - platform: template
    name: "Grow Tent Temperature"
    id: grow_tent_temperature
    unit_of_measurement: 'F'
    icon: "mdi:thermometer"
  - platform: template
    name: "Grow Tent RSSI"
    id: grow_tent_rssi
    unit_of_measurement: 'dB'
    icon: "mdi:wifi"
  - platform: template
    name: "Grow Tent Battery"
    id: grow_tent_battery
    unit_of_measurement: '%'
    icon: "mdi:battery"

esp32_ble_tracker:
  on_ble_advertise:
    - mac_address: A4:C1:38:xx:xx:xx
      then:
        - lambda: |-
            for (auto data : x.get_manufacturer_datas()) {
                if(data.data.size()==7) {
                  uint16_t hum_lsb = data.data[3] + (data.data[4] << 8);
                  float humidity= float(hum_lsb)/100.0;
                  int16_t temp_lsb = data.data[1] + (data.data[2] << 8);
                  float temperature = float(temp_lsb)/100*9.0/5.0 + 32.0;
                  int16_t battery=data.data[5];
                  int16_t rssi=x.get_rssi();
                  id(grow_tent_humidity).publish_state(humidity);
                  id(grow_tent_temperature).publish_state(temperature);
                  id(grow_tent_rssi).publish_state(rssi);
                  id(grow_tent_battery).publish_state(battery);

                }
            }

Sorry Im very new but can someone direct me to where I would find the MAC for 5074. I have read many post but it seems it doesnt cover where or how they are obtaining them. No sure I suppose I could just be unawre of what I am look at and skimming right past it. Thank in advance

Welcome!

This is how I find BLE Mac addresses, may help you. Good hunting!

After doing some searching on the topic, I ended in this thread to ask for support. I have a couple of Govee Sensors scanned and read out by an esp32 running with esphome. It is working well and used to monitor temperatures and calculate dew points in order to de-humidify my creeping space. Anyway, I got unusual reading in the last days as the temperatures dropped below 0°C (freezing). After some research I found that the govee 5075 sensors put a minus sign into the data vector of the received data. There is a solution here:

However, I’m not good at bit- and bytewise operations in C and request some help. Or maybe somebody has already done a fix for esphome driven devices. Thanks in advance!

Edit: found it: These units do work with negative (freezing) temps, correct decoding algorithm · Issue #2 · Thrilleratplay/GoveeWatcher (github.com)

Using this I get very slow updates of temperature, but regular updates of humidity and battery. The heat is actively running so the temperature is actively changing. Any ideas?

[10:59:25][D][esp32_ble_tracker:246]: Starting scan...
[10:59:36][D][sensor:094]: 'main_floor Humidity': Sending state 40.40000 % with 1 decimals of accuracy
[10:59:36][D][sensor:094]: 'main_floor Battery': Sending state 69.00000 % with 1 decimals of accuracy
[11:02:09][D][sensor:094]: 'main_floor Humidity': Sending state 41.40000 % with 1 decimals of accuracy
[11:02:09][D][sensor:094]: 'main_floor Battery': Sending state 69.00000 % with 1 decimals of accuracy
[11:03:34][D][sensor:094]: 'main_floor Humidity': Sending state 41.10000 % with 1 decimals of accuracy
[11:03:34][D][sensor:094]: 'main_floor Battery': Sending state 70.00000 % with 1 decimals of accuracy
[11:04:25][D][esp32_ble_tracker:246]: Starting scan...
[11:05:59][D][sensor:094]: 'main_floor Humidity': Sending state 39.50000 % with 1 decimals of accuracy
[11:05:59][D][sensor:094]: 'main_floor Battery': Sending state 70.00000 % with 1 decimals of accuracy
[11:06:05][D][sensor:094]: 'main_floor Humidity': Sending state 39.50000 % with 1 decimals of accuracy
[11:06:05][D][sensor:094]: 'main_floor Battery': Sending state 70.00000 % with 1 decimals of accuracy
[11:07:18][D][sensor:094]: 'main_floor Humidity': Sending state 39.10000 % with 1 decimals of accuracy
[11:07:18][D][sensor:094]: 'main_floor Battery': Sending state 70.00000 % with 1 decimals of accuracy
[11:08:15][D][sensor:094]: 'main_floor Humidity': Sending state 38.60000 % with 1 decimals of accuracy
[11:08:15][D][sensor:094]: 'main_floor Battery': Sending state 70.00000 % with 1 decimals of accuracy
[11:09:27][D][esp32_ble_tracker:246]: Starting scan...
[11:09:56][D][sensor:094]: 'main_floor Humidity': Sending state 37.90000 % with 1 decimals of accuracy
[11:09:56][D][sensor:094]: 'main_floor Temperature': Sending state 22.30520 ▒ F with 1 decimals of accuracy
[11:09:56][D][climate:378]: 'Thermostat Climate Controller' - Sending state:
[11:09:56][D][climate:381]:   Mode: HEAT
[11:09:56][D][climate:383]:   Action: HEATING
[11:09:56][D][climate:401]:   Current Temperature: 22.31▒C
[11:09:56][D][climate:405]:   Target Temperature: Low: 22.44▒C High: 30.00▒C

Just purchased a 2 pack of Govee H5105 Smart Thermo-Hygromoter 2s sensors. Can confirm this code works (thx for those who posted above!):

esp32_ble_tracker:
  on_ble_manufacturer_data_advertise:
    - mac_address: XX:XX:XX:XX:XX:XX #Govee 5105
      manufacturer_id: '0001'
      then:
        - lambda: |-
            const int basenum = (int16_t(x[2]) << 16) + (int16_t(x[3]) << 8) + int16_t(x[4]);
            const float temperature = (basenum / 10000.0f)*9.0/5.0 + 32.0;
            const float humidity = (basenum % 1000) / 10.0f;
            const float battery_level = uint16_t(x[5]) / 1.0f;
            id(govee_1_humidity).publish_state(humidity);
            id(govee_1_temperature).publish_state(temperature);
            id(govee_1_battery).publish_state(battery_level);          
                     
sensor:
  - platform: template
    name: "Temperature"
    id: govee_1_temperature
    unit_of_measurement: "°F"
    accuracy_decimals: 2
  - platform: template
    name: "Humidity"
    id: govee_1_humidity
    unit_of_measurement: '%'
    accuracy_decimals: 2
  - platform: template
    name: "Battery Level"
    id: govee_1_battery
    unit_of_measurement: '%'
    accuracy_decimals: 0