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 ESP_LOGVV(TAG,
"parse_device(): MAC address %s found.", device.
address_str().c_str());
53 float signal_strength = float(device.
get_rssi());
60 std::size_t data_size = service_data.data.size() + 2;
61 if (data_size > MAX_DATA_SIZE) {
62 ESP_LOGVV(TAG,
"parse_device(): maximum data size exceeded!");
67 esp_bt_uuid_t uuid = service_data.uuid.get_uuid();
68 uint8_t data[MAX_DATA_SIZE] = {
static_cast<uint8_t
>(uuid.uuid.uuid16),
static_cast<uint8_t
>(uuid.uuid.uuid16 >> 8)};
69 std::copy(service_data.data.begin(), service_data.data.end(), std::begin(data) + 2);
78 if (result->temperature.
has_value() && this->temperature_ !=
nullptr)
80 if (result->external_temperature.
has_value() && this->external_temperature_ !=
nullptr)
82 if (result->humidity.
has_value() && this->humidity_ !=
nullptr)
84 if (result->battery_level.
has_value() && this->battery_level_ !=
nullptr)
103 for (
const auto &mapping : DEVICE_PARSER_MAP) {
104 if (device_name.starts_with(mapping.prefix)) {
112 ESP_LOGVV(TAG,
"update_device_type_(): unknown device type %s.", device_name.c_str());
115static inline uint16_t read_uint16(
const uint8_t *data, std::size_t offset) {
116 return static_cast<uint16_t
>(data[offset + 0]) | (
static_cast<uint16_t
>(data[offset + 1]) << 8);
119static inline int16_t read_int16(
const uint8_t *data, std::size_t offset) {
120 return static_cast<int16_t
>(read_uint16(data, offset));
123static inline uint32_t read_uint32(
const uint8_t *data, std::size_t offset) {
124 return static_cast<uint32_t
>(data[offset + 0]) | (
static_cast<uint32_t
>(data[offset + 1]) << 8) |
125 (
static_cast<uint32_t
>(data[offset + 2]) << 16) | (
static_cast<uint32_t
>(data[offset + 3]) << 24);
137static float tp96_battery(uint16_t voltage) {
138 float level = 52.317286f * tanh(
static_cast<float>(voltage) / 273.624277936f - 8.76485439394f) + 51.06925f;
139 return std::max(0.0f, std::min(level, 100.0f));
142static optional<ParseResult> parse_tp972(
const uint8_t *data, std::size_t data_size) {
143 if (data_size != 23) {
144 ESP_LOGVV(TAG,
"parse_tp972(): payload has wrong size of %d (!= 23)!", data_size);
151 result.external_temperature =
static_cast<float>(read_uint16(data, 1)) - 54.0f;
154 result.battery_level = tp96_battery(read_uint16(data, 3));
157 result.temperature =
static_cast<float>(read_uint32(data, 9)) - 54.0f;
162static optional<ParseResult> parse_tp96(
const uint8_t *data, std::size_t data_size) {
163 if (data_size != 7) {
164 ESP_LOGVV(TAG,
"parse_tp96(): payload has wrong size of %d (!= 7)!", data_size);
171 result.temperature =
static_cast<float>(read_uint16(data, 1)) - 30.0f;
174 result.battery_level = tp96_battery(read_uint16(data, 3));
177 result.external_temperature =
static_cast<float>(read_uint16(data, 5)) - 30.0f;
182static optional<ParseResult> parse_tp3(
const uint8_t *data, std::size_t data_size) {
184 ESP_LOGVV(TAG,
"parse_tp3(): payload has wrong size of %d (< 6)!", data_size);
191 result.temperature =
static_cast<float>(read_int16(data, 1)) * 0.1f;
194 result.humidity =
static_cast<float>(data[3]);
197 result.battery_level =
static_cast<float>(data[4] & 0x3) * 50.0;