Hi everyone,
I have bought a rather cheap meat thermometer for my beefer box last year and always wanted to build some esp-based gateway to home assistant since the bluetooth range of this device is rather short (at least for this kind of device). I have banged my head on some esphome configuration, did some research and trail-and-error configuration and want to share my (highly wip) config with you all.
Device: ThermoPro TP904
(ThermoPro Meat Thermometer Digital Grill Thermometer Wireless Roasting Thermometer with 2 Probes for BBQ Smoker Rechargeable Kitchen Thermometer with Alarm Function Supports Mobile Phone Bluetooth 5.0 : Amazon.de: Home & Kitchen) ← no affiliate, just an example
ESPHome Configuration:
... (default part left out for brevity)
esp32_ble_tracker:
ble_client:
- id: tp904
mac_address: E4:C1:51:AB:65:57
auto_connect: false
on_connect:
then:
- logger.log:
format: "Connected to TP904."
switch:
- platform: template
name: "BBQ Thermometer"
optimistic: true
turn_on_action:
- ble_client.connect: tp904
- ble_client.ble_write:
id: tp904
service_uuid: 1086FFF0-3343-4817-8BB2-B32206336CE8
characteristic_uuid: 1086FFF1-3343-4817-8BB2-B32206336CE8
value: [0x01, 0x09, 0x8a, 0x7a, 0x13, 0xb7, 0x3e, 0xd6, 0x8b, 0x67, 0xc2, 0xa0]
turn_off_action:
- ble_client.disconnect: tp904
sensor:
- platform: ble_client
name: "TP904 BLE Parser"
type: characteristic
ble_client_id: tp904
service_uuid: 1086FFF0-3343-4817-8BB2-B32206336CE8
characteristic_uuid: 1086FFF2-3343-4817-8BB2-B32206336CE8
notify: true
lambda: |-
// accept only full measurement frames
if (x.size() != 19 && x.size() != 20) return NAN;
if (x[0] != 0x30) return NAN;
// ---- Publish raw frame as hex string ----
//std::string out;
//char buf[3];
//for (size_t i = 0; i < x.size(); i++) {
// snprintf(buf, sizeof(buf), "%02X", x[i]);
// out += buf;
//}
//id(probes_raw).publish_state(out);
// Probe 1: chars 11–13 -> 22.6
uint16_t p1 =
((x[5] & 0x0F) * 100) + // char 11
((x[6] >> 4) * 10) + // char 12
(x[6] & 0x0F); // char 13
// Probe 2: chars 15–17 -> 23.5
uint16_t p2 =
((x[7] & 0x0F) * 100) + // char 15
((x[8] >> 4) * 10) + // char 16
(x[8] & 0x0F); // char 17
if (p1 <= 999)
id(tp904_probe1).publish_state(p1 / 10.0f);
if (p2 <= 999)
id(tp904_probe2).publish_state(p2 / 10.0f);
return NAN;
- platform: template
name: "TP904 Probe 1"
id: tp904_probe1
icon: mdi:temperature-celsius
unit_of_measurement: "°C"
accuracy_decimals: 1
- platform: template
name: "TP904 Probe 2"
id: tp904_probe2
icon: mdi:temperature-celsius
unit_of_measurement: "°C"
accuracy_decimals: 1
#text_sensor:
# - platform: template
# name: "TP904 Raw Frame"
# id: probes_raw
You can uncomment the ---- Publish raw frame as hex string ----part and the text_sensor to see the raw message received through the notified characteristic but its very noisy and for development purpose only.
When using it you have to turn on the switch (and sometimes try this 2-3 times until you see real temperature values).
Feel free to use and share your experience as well as improve it.
