Skip to content

Instantly share code, notes, and snippets.

@joshspicer
Created December 6, 2020 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshspicer/0b7e4e411e4f7eb3d5d9493f8c6f5baf to your computer and use it in GitHub Desktop.
Save joshspicer/0b7e4e411e4f7eb3d5d9493f8c6f5baf to your computer and use it in GitHub Desktop.
Govee 5072 Bluetooth LE
#!/usr/bin/env python3
# Taken from: https://github.com/Thrilleratplay/GoveeWatcher/blob/master/python/goveeWatcher.py
# Tested with Govee Temp/Humidity BT LE (model 5072)
from time import sleep
import os
import sys
from bleson import get_provider, Observer, UUID16
from bleson.logger import log, set_level, ERROR, DEBUG
# Disable warnings
set_level(ERROR)
# # Uncomment for debug log level
# set_level(DEBUG)
# https://macaddresschanger.com/bluetooth-mac-lookup/A4%3AC1%3A38
# OUI Prefix Company
# A4:C1:38 Telink Semiconductor (Taipei) Co. Ltd.
GOVEE_BT_mac_OUI_PREFIX = "A4:C1:38"
H5075_UPDATE_UUID16 = UUID16(0xEC88)
govee_devices = {}
# ###########################################################################
FORMAT_PRECISION = ".2f"
# Decode Temperature into degrees Celcius
def decode_temp_in_c(encoded_data):
return format((encoded_data / 10000), FORMAT_PRECISION)
# Decode Temperature into degrees Fahrenheit
def decode_temp_in_f(encoded_data):
return format((((encoded_data / 10000) * 1.8) + 32), FORMAT_PRECISION)
# Decode percent humidity
def decode_humidity(encoded_data):
return format(((encoded_data % 1000) / 10), FORMAT_PRECISION)
def print_values(mac):
govee_device = govee_devices[mac]
print(
f"{govee_device['name']} ({govee_device['address']}) - \
Temperature {govee_device['tempInC']}C / {govee_device['tempInF']}F - \
Humidity: {govee_device['humidity']}% - \
Battery: {govee_device['battery']}%"
)
def print_rssi(mac):
govee_device = govee_devices[mac]
print(
f"{govee_device['name']} ({govee_device['address']}) - \
RSSI: {govee_device['rssi']}"
)
# On BLE advertisement callback
def on_advertisement(advertisement):
log.debug(advertisement)
if advertisement.address.address.startswith(GOVEE_BT_mac_OUI_PREFIX):
mac = advertisement.address.address
if mac not in govee_devices:
govee_devices[mac] = {}
if H5075_UPDATE_UUID16 in advertisement.uuid16s:
# HACK: Proper decoding is done in bleson > 0.10
name = advertisement.name
encoded_data = int(advertisement.mfg_data.hex()[6:12], 16)
battery = int(advertisement.mfg_data.hex()[12:14], 16)
govee_devices[mac]["address"] = mac
govee_devices[mac]["name"] = name
govee_devices[mac]["mfg_data"] = advertisement.mfg_data
govee_devices[mac]["data"] = encoded_data
govee_devices[mac]["tempInC"] = decode_temp_in_c(encoded_data)
govee_devices[mac]["tempInF"] = decode_temp_in_f(encoded_data)
govee_devices[mac]["humidity"] = decode_humidity(encoded_data)
govee_devices[mac]["battery"] = battery
print_values(mac)
if advertisement.rssi is not None and advertisement.rssi != 0:
govee_devices[mac]["rssi"] = advertisement.rssi
print_rssi(mac)
log.debug(govee_devices[mac])
# ###########################################################################
adapter = get_provider().get_adapter()
observer = Observer(adapter)
observer.on_advertising_data = on_advertisement
try:
while True:
observer.start()
sleep(2)
observer.stop()
except KeyboardInterrupt:
try:
observer.stop()
sys.exit(0)
except SystemExit:
observer.stop()
os._exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment