95 lines
2.3 KiB
C++
95 lines
2.3 KiB
C++
#include "wts01.h"
|
|
#include "esphome/core/log.h"
|
|
#include <cmath>
|
|
|
|
namespace esphome {
|
|
namespace wts01 {
|
|
|
|
constexpr uint8_t HEADER_1 = 0x55;
|
|
constexpr uint8_t HEADER_2 = 0x01;
|
|
constexpr uint8_t HEADER_3 = 0x01;
|
|
constexpr uint8_t HEADER_4 = 0x04;
|
|
|
|
static const char *const TAG = "wts01";
|
|
|
|
void WTS01Sensor::loop() {
|
|
// Process all available data at once
|
|
while (this->available()) {
|
|
uint8_t c;
|
|
if (this->read_byte(&c)) {
|
|
this->handle_char_(c);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WTS01Sensor::dump_config() { LOG_SENSOR("", "WTS01 Sensor", this); }
|
|
|
|
void WTS01Sensor::handle_char_(uint8_t c) {
|
|
// State machine for processing the header. Reset if something doesn't match.
|
|
if (this->buffer_pos_ == 0 && c != HEADER_1) {
|
|
return;
|
|
}
|
|
|
|
if (this->buffer_pos_ == 1 && c != HEADER_2) {
|
|
this->buffer_pos_ = 0;
|
|
return;
|
|
}
|
|
|
|
if (this->buffer_pos_ == 2 && c != HEADER_3) {
|
|
this->buffer_pos_ = 0;
|
|
return;
|
|
}
|
|
|
|
if (this->buffer_pos_ == 3 && c != HEADER_4) {
|
|
this->buffer_pos_ = 0;
|
|
return;
|
|
}
|
|
|
|
// Add byte to buffer
|
|
this->buffer_[this->buffer_pos_++] = c;
|
|
|
|
// Process complete packet
|
|
if (this->buffer_pos_ >= PACKET_SIZE) {
|
|
this->process_packet_();
|
|
this->buffer_pos_ = 0;
|
|
}
|
|
}
|
|
|
|
void WTS01Sensor::process_packet_() {
|
|
// Based on Tasmota implementation
|
|
// Format: 55 01 01 04 01 11 16 12 95
|
|
// header T Td Ck - T = Temperature, Td = Temperature decimal, Ck = Checksum
|
|
uint8_t calculated_checksum = 0;
|
|
for (uint8_t i = 0; i < PACKET_SIZE - 1; i++) {
|
|
calculated_checksum += this->buffer_[i];
|
|
}
|
|
|
|
uint8_t received_checksum = this->buffer_[PACKET_SIZE - 1];
|
|
if (calculated_checksum != received_checksum) {
|
|
ESP_LOGW(TAG, "WTS01 Checksum doesn't match: 0x%02X != 0x%02X", received_checksum, calculated_checksum);
|
|
return;
|
|
}
|
|
|
|
// Extract temperature value
|
|
const uint8_t raw = this->buffer_[6];
|
|
|
|
// WTS01 encodes sign in bit 7, magnitude in bits 0-6
|
|
const bool negative = (raw & 0x80) != 0;
|
|
const uint8_t magnitude = raw & 0x7F;
|
|
|
|
const float decimal = static_cast<float>(this->buffer_[7]) / 100.0f;
|
|
|
|
float temperature = static_cast<float>(magnitude) + decimal;
|
|
|
|
if (negative) {
|
|
temperature = -temperature;
|
|
}
|
|
|
|
ESP_LOGV(TAG, "Received new temperature: %.2f°C", temperature);
|
|
|
|
this->publish_state(temperature);
|
|
}
|
|
|
|
} // namespace wts01
|
|
} // namespace esphome
|