Skip to content

Instantly share code, notes, and snippets.

@rubenhorn
Created May 5, 2026 22:19
Show Gist options
  • Select an option

  • Save rubenhorn/41ef8176ddc8a8e3a5d71f9ad41ca06e to your computer and use it in GitHub Desktop.

Select an option

Save rubenhorn/41ef8176ddc8a8e3a5d71f9ad41ca06e to your computer and use it in GitHub Desktop.
Show measurements from nearby ThermoPro TP357 Hygrometers.
#! /usr/bin/env python3
"""
Show measurements from nearby ThermoPro TP357 Hygrometers.
For more advanced features, use Theengs (https://github.com/theengs/decoder/blob/development/examples/python/ScanAndDecode.py)!
"""
import asyncio
from bleak import BleakScanner
def decode_tp357(manufacturer_id: int, payload: bytes):
"""
Decode advertisement data from TP357.
(See https://github.com/theengs/decoder/blob/development/src/devices/TPTH_json.h)
"""
first_byte = (manufacturer_id >> 8) & 0xFF
full_frame = bytes([first_byte]) + payload
# Parse as little endian
temperature = full_frame[0] | (full_frame[1] << 8)
# Convert unsigned 16 bit number to signed
if temperature >= 1 << 15:
temperature -= 1 << 16
temperature /= 10.0
humidity = full_frame[2]
low_battery = bool(full_frame[3] & 0x01)
return {
"temperature": temperature,
"humidity": humidity,
"low_battery": low_battery,
}
async def main():
scanner = BleakScanner()
async with scanner:
async for device, adv in scanner.advertisement_data():
if device.name and device.name.startswith("TP357S "):
manufacturer_id = list(adv.manufacturer_data.keys())[0]
payload = list(adv.manufacturer_data.values())[0]
print("Address:", device.address)
print("Name:", device.name)
print("Data:", decode_tp357(manufacturer_id, payload))
print()
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment