ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
tfluna.cpp
Go to the documentation of this file.
1#include "tfluna.h"
2#include <cstddef>
3#include "esphome/core/log.h"
5
6namespace esphome::tfluna {
7
8// see https://files.waveshare.com/upload/a/ac/SJ-PM-TF-Luna_A05_Product_Manual.pdf
9static constexpr uint8_t SAVE_REGISTER = 0x20;
10static constexpr uint8_t VERSION_REVISION_REGISTER = 0x0A;
11static constexpr uint8_t DISTANCE_LOW_REGISTER = 0x00;
12static constexpr uint8_t RESTORE_FACTORY_DEFAULTS_REGISTER = 0x29;
13static constexpr uint8_t SHUTDOWN_REBOOT_REGISTER = 0x21;
14static constexpr uint8_t MODE_REGISTER = 0x23;
15static constexpr uint8_t MODE_TRIGGER = 0x01;
16static constexpr uint8_t TRIGGER_ONESHOT_REGISTER = 0x24;
17static constexpr uint8_t MAX_READ_ATTEMPTS = 5;
18static constexpr uint8_t READ_RETRY_MS = 5;
19ESPHOME_LOG_TAG(TAG, "tfluna");
20
21static constexpr uint32_t SETUP_TIMEOUT_ID = 0;
22static constexpr uint32_t READ_RETRY_TIMEOUT_ID = 1;
23
24void TFLuna::dump_config() {
25 ESP_LOGCONFIG(TAG, "TF-Luna (i2c):");
26 LOG_I2C_DEVICE(this);
27 LOG_UPDATE_INTERVAL(this);
28 ESP_LOGCONFIG(TAG, " Firmware: %s", this->version_);
29
30#ifdef USE_SENSOR
31 LOG_SENSOR(" ", "Distance:", this->distance_sensor_);
32 LOG_SENSOR(" ", "Temperature:", this->temperature_sensor_);
33 LOG_SENSOR(" ", "Signal Strength:", this->signal_strength_sensor_);
34 LOG_SENSOR(" ", "Timestamp:", this->timestamp_sensor_);
35#endif
36#ifdef USE_TEXT_SENSOR
37 LOG_TEXT_SENSOR(" ", "Version:", this->version_text_sensor_);
38#endif
39#ifdef USE_BUTTON
40 LOG_BUTTON(" ", "Factory Reset:", this->reset_button_);
41 LOG_BUTTON(" ", "Restart:", this->restart_button_);
42#endif
43}
44
45void TFLuna::setup() {
46 uint8_t mode;
47 if (!this->read_byte(MODE_REGISTER, &mode)) {
48 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
49 this->mark_failed();
50 return;
51 }
52 if (mode != MODE_TRIGGER) {
53 if (!this->write_byte(MODE_REGISTER, MODE_TRIGGER)) {
54 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
55 this->mark_failed();
56 return;
57 }
58
59 if (!this->write_byte(SAVE_REGISTER, 1)) {
60 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
61 this->mark_failed();
62 return;
63 }
64 }
65
66 uint8_t raw_version[3];
67 if (!this->read_bytes(VERSION_REVISION_REGISTER, raw_version, sizeof(raw_version))) {
68 this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
69 return;
70 } else {
71 snprintf(this->version_, sizeof(this->version_), "%d.%d.%d", raw_version[2], raw_version[1], raw_version[0]);
72#ifdef USE_TEXT_SENSOR
73 if (this->version_text_sensor_ != nullptr) {
74 this->version_text_sensor_->publish_state(version_);
75 }
76#endif
77 }
78}
79
81 uint8_t buf[8];
82 if (!this->read_bytes(DISTANCE_LOW_REGISTER, buf, sizeof(buf))) {
83 this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
84 return false;
85 }
86 // Layout:
87 // buf[0..1] = distance (LE), buf[2..3] = signal (LE),
88 // buf[4..5] = temperature (LE), buf[6..7] = timestamp (LE)
89 uint16_t distance = encode_uint16(buf[1], buf[0]);
90 uint16_t signal_strength = encode_uint16(buf[3], buf[2]);
91 int16_t temperature_raw = encode_uint16(buf[5], buf[4]);
92 uint16_t timestamp = encode_uint16(buf[7], buf[6]);
93
94 if (timestamp == this->previous_timestamp_) {
95 return false;
96 }
97
98#ifdef USE_SENSOR
99 if (this->timestamp_sensor_ != nullptr) {
100 this->timestamp_sensor_->publish_state(timestamp);
101 }
102 if (this->distance_sensor_ != nullptr) {
103 // distance is unreliable when strength is below 100 or saturated at 0xFFFF
104 this->distance_sensor_->publish_state(signal_strength < 100 || signal_strength == 0xFFFF ? NAN : distance);
105 }
106
107 if (this->temperature_sensor_ != nullptr) {
108 this->temperature_sensor_->publish_state(temperature_raw / (float) 100);
109 }
110
111 if (this->signal_strength_sensor_ != nullptr) {
112 this->signal_strength_sensor_->publish_state(signal_strength);
113 }
114#endif
115 this->status_clear_warning();
117 return true;
118}
119
121 if (this->read_data_()) {
122 this->attempt_ = 0;
123 } else {
124 if (this->attempt_ < MAX_READ_ATTEMPTS) {
125 this->attempt_++;
126 this->set_timeout(READ_RETRY_TIMEOUT_ID, READ_RETRY_MS, [this]() { this->read_data_timeout_(); });
127 } else {
128 this->status_set_warning("Hung device, restarting...");
129 this->restart();
130 }
131 }
132}
133
134void TFLuna::update() {
135 this->cancel_timeout(READ_RETRY_TIMEOUT_ID);
136 this->attempt_ = 0;
137 if (!this->write_byte(TRIGGER_ONESHOT_REGISTER, 0x01)) {
138 this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
139 return;
140 }
141 this->read_data_timeout_();
142}
143
144void TFLuna::factory_reset() {
145 if (!this->write_byte(RESTORE_FACTORY_DEFAULTS_REGISTER, 1)) {
146 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
147 return;
148 }
149 this->status_set_warning("Factory reset issued; waiting for device to become ready");
150 this->set_timeout(SETUP_TIMEOUT_ID, 100, [this]() { this->setup(); });
151}
152
153void TFLuna::restart() {
154 if (!this->write_byte(SHUTDOWN_REBOOT_REGISTER, 0x02)) {
155 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
156 return;
157 }
158}
159
160} // namespace esphome::tfluna
BedjetMode mode
BedJet operating mode.
void mark_failed()
Mark this component as failed.
virtual void setup()
Where the component's initialization should happen.
Definition component.cpp:84
bool cancel_timeout(const char *name)
Cancel a timeout function.
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
Definition component.cpp:96
void status_clear_warning()
Definition component.h:291
bool write_byte(uint8_t a_register, uint8_t data) const
Definition i2c.h:265
bool read_byte(uint8_t a_register, uint8_t *data)
Definition i2c.h:240
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
Definition i2c.h:217
uint16_t previous_timestamp_
Definition tfluna.h:48
ESPHOME_LOG_TAG(TAG, "tfluna")
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition helpers.h:980
static void uint32_t
uint16_t timestamp
Definition tt21100.cpp:2