Temtop S1+ BLE Integration for Home Assistant (No App Required)
I reverse-engineered the BLE protocol of the Temtop S1+ air quality monitor and built a Python-based integration that sends sensor data directly to Home Assistant — without the official app, without MQTT, without any cloud.
The device sends a 46-byte data packet every few seconds when a client is subscribed. The relevant byte positions were determined by reverse engineering — comparing known display values to the raw hex payload:
Sensor
Byte Position
Calculation
Example
PM2.5
22–23
int.from_bytes(data[22:24], 'big') / 10
0x000e = 14 → 1.4 µg/m³
Temperature
25
data[25] / 10
0xc9 = 201 → 20.1°C
Humidity
26–27
int.from_bytes(data[26:28], 'big') / 10
0x01fc = 508 → 50.8%
AQI
29
data[29]
0x08 → 8
The script connects every 60 seconds, subscribes to notifications for 15 seconds, reads the values, then disconnects. This keeps the BLE connection time minimal and is battery-friendly.
Requirements
Hardware:
Temtop S1+ air quality monitor
Raspberry Pi with Bluetooth (built-in or USB dongle)
Tested with: Raspberry Pi 1 Model B (2011) + TP-Link UB500
Close the Temtop app before starting the script — BLE only allows one active connection at a time. If the app is opened later, the script reconnects automatically within ~90 seconds.
First reading takes ~20 seconds after script start.
This looks great. It doesn’t work on the M10+ as I’ve just tested it, but I’m now wondering how I can work out the UUID for it, guessing its different from the S1.
After reaching out to Temtop, they advised to use an app for debugging BLE called “Lightblue” which did indeed spit out a UUID.
Unfortunately it seems the references used by this model are different from the S1+
$ python3 temtop.py
Temtop M10+ monitor started
Connection error: BleakCharacteristicNotFoundError: Characteristic 00001800-0000-1000-8000-00805f9b34fb was not found!
No data received, retrying…
Next step I spose it to work out what each of the responses means.
The UUID 00001800-0000-1000-8000-00805f9b34fb is a standard Generic Access Service
All BLE devices have this, it only contains the device name. Not what we need.
When looking for sensor data, focus on manufacturer-specific UUIDs.
These don’t start with 00001800, 00001801 or 0000180a. They look more like 00010203-0405-0607-0809-... on the S1+.
Try this script to list all characteristics:
import asyncio
from bleak import BleakClient
MAC = "YOUR_M10_MAC"
async def explore():
try:
async with BleakClient(MAC) as client:
for service in client.services:
print(f"\nService: {service.uuid}")
for char in service.characteristics:
print(f" {char.uuid} - {char.properties}")
except EOFError:
pass
asyncio.run(explore())
Look for a characteristic that:
Has notify in its properties
Belongs to a manufacturer-specific service (unusual UUID, not starting with 00001800 etc.)
For reference, here’s the output from my S1+.
The highlighted service is the one containing sensor data:
Gork helped me modify this for C1+. The C1+ uses the same UUID as the S1+ but there is no PM2.5 or AQI. Basically removed pm25 and changed AQI to CO2. Temp and Humidity are the same & worked from the start. CO2 reading is bytes 30:32 I think...Not 100% sure if value goes over 4 digits. co2 = int.from_bytes(data[30:32], 'big') its a whole number so don't /10.