10static constexpr std::size_t MAX_DATA_SIZE = 24;
12struct DeviceParserMapping {
17static float tp96_battery(uint16_t voltage);
23static const char *
const TAG =
"thermopro_ble";
25static const struct DeviceParserMapping DEVICE_PARSER_MAP[] = {
26 {
"TP972", parse_tp972}, {
"TP970", parse_tp96}, {
"TP96", parse_tp96}, {
"TP3", parse_tp3}};
29 ESP_LOGCONFIG(TAG,
"ThermoPro BLE");
32 LOG_SENSOR(
" ",
"Humidity", this->
humidity_);
39 ESP_LOGVV(TAG,
"parse_device(): unknown MAC address.");
46 ESP_LOGVV(TAG,
"parse_device(): invalid device type.");
50 char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
51 ESP_LOGVV(TAG,
"parse_device(): MAC address %s found.", device.
address_str_to(addr_buf));
54 float signal_strength = float(device.
get_rssi());
61 std::size_t data_size = service_data.data.size() + 2;
62 if (data_size > MAX_DATA_SIZE) {
63 ESP_LOGVV(TAG,
"parse_device(): maximum data size exceeded!");
68 esp_bt_uuid_t uuid = service_data.uuid.get_uuid();
69 uint8_t data[MAX_DATA_SIZE] = {
static_cast<uint8_t
>(uuid.uuid.uuid16),
static_cast<uint8_t
>(uuid.uuid.uuid16 >> 8)};
70 std::copy(service_data.data.begin(), service_data.data.end(), std::begin(data) + 2);
79 if (result->temperature.
has_value() && this->temperature_ !=
nullptr)
81 if (result->external_temperature.
has_value() && this->external_temperature_ !=
nullptr)
83 if (result->humidity.
has_value() && this->humidity_ !=
nullptr)
85 if (result->battery_level.
has_value() && this->battery_level_ !=
nullptr)
104 for (
const auto &mapping : DEVICE_PARSER_MAP) {
105 if (device_name.starts_with(mapping.prefix)) {
113 ESP_LOGVV(TAG,
"update_device_type_(): unknown device type %s.", device_name.c_str());
116static inline uint16_t read_uint16(
const uint8_t *data, std::size_t offset) {
117 return static_cast<uint16_t
>(data[offset + 0]) | (
static_cast<uint16_t
>(data[offset + 1]) << 8);
120static inline int16_t read_int16(
const uint8_t *data, std::size_t offset) {
121 return static_cast<int16_t
>(read_uint16(data, offset));
124static inline uint32_t read_uint32(
const uint8_t *data, std::size_t offset) {
125 return static_cast<uint32_t
>(data[offset + 0]) | (
static_cast<uint32_t
>(data[offset + 1]) << 8) |
126 (
static_cast<uint32_t
>(data[offset + 2]) << 16) | (
static_cast<uint32_t
>(data[offset + 3]) << 24);
138static float tp96_battery(uint16_t voltage) {
139 float level = 52.317286f * tanh(
static_cast<float>(voltage) / 273.624277936f - 8.76485439394f) + 51.06925f;
140 return std::max(0.0f, std::min(level, 100.0f));
143static optional<ParseResult> parse_tp972(
const uint8_t *data, std::size_t data_size) {
144 if (data_size != 23) {
145 ESP_LOGVV(TAG,
"parse_tp972(): payload has wrong size of %d (!= 23)!", data_size);
152 result.external_temperature =
static_cast<float>(read_uint16(data, 1)) - 54.0f;
155 result.battery_level = tp96_battery(read_uint16(data, 3));
158 result.temperature =
static_cast<float>(read_uint32(data, 9)) - 54.0f;
163static optional<ParseResult> parse_tp96(
const uint8_t *data, std::size_t data_size) {
164 if (data_size != 7) {
165 ESP_LOGVV(TAG,
"parse_tp96(): payload has wrong size of %d (!= 7)!", data_size);
172 result.temperature =
static_cast<float>(read_uint16(data, 1)) - 30.0f;
175 result.battery_level = tp96_battery(read_uint16(data, 3));
178 result.external_temperature =
static_cast<float>(read_uint16(data, 5)) - 30.0f;
183static optional<ParseResult> parse_tp3(
const uint8_t *data, std::size_t data_size) {
185 ESP_LOGVV(TAG,
"parse_tp3(): payload has wrong size of %d (< 6)!", data_size);
192 result.temperature =
static_cast<float>(read_int16(data, 1)) * 0.1f;
195 result.humidity =
static_cast<float>(data[3]);
198 result.battery_level =
static_cast<float>(data[4] & 0x3) * 50.0;