ESPHome 2026.3.3
Loading...
Searching...
No Matches
tuya_cover.cpp
Go to the documentation of this file.
1#include "esphome/core/log.h"
2#include "tuya_cover.h"
3
4namespace esphome {
5namespace tuya {
6
7const uint8_t COMMAND_OPEN = 0x00;
8const uint8_t COMMAND_CLOSE = 0x02;
9const uint8_t COMMAND_STOP = 0x01;
10
11using namespace esphome::cover;
12
13static const char *const TAG = "tuya.cover";
14
16 this->value_range_ = this->max_value_ - this->min_value_;
17
18 this->parent_->add_on_initialized_callback([this]() {
19 // Set the direction (if configured/supported).
21
22 // Handle configured restore mode.
23 switch (this->restore_mode_) {
25 break;
26 case COVER_RESTORE: {
27 auto restore = this->restore_state_();
28 if (restore.has_value())
29 restore->apply(this);
30 break;
31 }
33 auto restore = this->restore_state_();
34 if (restore.has_value()) {
35 restore->to_call(this).perform();
36 }
37 break;
38 }
39 }
40 });
41
42 if (!this->position_id_.has_value()) {
43 return;
44 }
45 uint8_t report_id = *this->position_id_;
46 if (this->position_report_id_.has_value()) {
47 // A position report datapoint is configured; listen to that instead.
48 report_id = *this->position_report_id_;
49 }
50
51 this->parent_->register_listener(report_id, [this](const TuyaDatapoint &datapoint) {
52 if (datapoint.value_int == 123) {
53 ESP_LOGD(TAG, "Ignoring MCU position report - not calibrated");
54 return;
55 }
56 auto pos = float(datapoint.value_uint - this->min_value_) / this->value_range_;
57 this->position = this->invert_position_report_ ? pos : 1.0f - pos;
58 this->publish_state();
59 });
60}
61
63 if (call.get_stop()) {
64 if (this->control_id_.has_value()) {
65 this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_STOP);
66 } else if (this->position_id_.has_value()) {
67 auto pos = this->position;
68 pos = this->invert_position_report_ ? pos : 1.0f - pos;
69 auto position_int = static_cast<uint32_t>(pos * this->value_range_);
70 position_int = position_int + this->min_value_;
71
72 this->parent_->force_set_integer_datapoint_value(*this->position_id_, position_int);
73 }
74 }
75 auto pos_opt = call.get_position();
76 if (pos_opt.has_value()) {
77 auto pos = *pos_opt;
78 if (this->control_id_.has_value() && (pos == COVER_OPEN || pos == COVER_CLOSED)) {
79 if (pos == COVER_OPEN) {
80 this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_OPEN);
81 } else {
82 this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_CLOSE);
83 }
84 } else if (this->position_id_.has_value()) {
85 pos = this->invert_position_report_ ? pos : 1.0f - pos;
86 auto position_int = static_cast<uint32_t>(pos * this->value_range_);
87 position_int = position_int + this->min_value_;
88
89 this->parent_->force_set_integer_datapoint_value(*this->position_id_, position_int);
90 }
91 }
92
93 this->publish_state();
94}
95
96void TuyaCover::set_direction_(bool inverted) {
97 if (!this->direction_id_.has_value()) {
98 return;
99 }
100
101 if (inverted) {
102 ESP_LOGD(TAG, "Setting direction: inverted");
103 } else {
104 ESP_LOGD(TAG, "Setting direction: normal");
105 }
106
107 this->parent_->set_boolean_datapoint_value(*this->direction_id_, inverted);
108}
109
111 ESP_LOGCONFIG(TAG, "Tuya Cover:");
112 if (this->invert_position_) {
113 if (this->direction_id_.has_value()) {
114 ESP_LOGCONFIG(TAG, " Inverted");
115 } else {
116 ESP_LOGCONFIG(TAG, " Configured as Inverted, but direction_datapoint isn't configured");
117 }
118 }
119 if (this->invert_position_report_) {
120 ESP_LOGCONFIG(TAG, " Position Reporting Inverted");
121 }
122 if (this->control_id_.has_value()) {
123 ESP_LOGCONFIG(TAG, " Control has datapoint ID %u", *this->control_id_);
124 }
125 if (this->direction_id_.has_value()) {
126 ESP_LOGCONFIG(TAG, " Direction has datapoint ID %u", *this->direction_id_);
127 }
128 if (this->position_id_.has_value()) {
129 ESP_LOGCONFIG(TAG, " Position has datapoint ID %u", *this->position_id_);
130 }
131 if (this->position_report_id_.has_value()) {
132 ESP_LOGCONFIG(TAG, " Position Report has datapoint ID %u", *this->position_report_id_);
133 }
134}
135
137 auto traits = cover::CoverTraits();
138 traits.set_supports_stop(true);
139 traits.set_supports_position(true);
140 return traits;
141}
142
143} // namespace tuya
144} // namespace esphome
optional< CoverRestoreState > restore_state_()
Definition cover.cpp:180
void publish_state(bool save=true)
Publish the current state of the cover.
Definition cover.cpp:143
float position
The position of the cover from 0.0 (fully closed) to 1.0 (fully open).
Definition cover.h:121
void dump_config() override
optional< uint8_t > control_id_
Definition tuya_cover.h:38
cover::CoverTraits get_traits() override
optional< uint8_t > position_report_id_
Definition tuya_cover.h:41
void set_direction_(bool inverted)
optional< uint8_t > direction_id_
Definition tuya_cover.h:39
void setup() override
optional< uint8_t > position_id_
Definition tuya_cover.h:40
void control(const cover::CoverCall &call) override
TuyaCoverRestoreMode restore_mode_
Definition tuya_cover.h:37
void add_on_initialized_callback(std::function< void()> callback)
Definition tuya.h:115
void set_boolean_datapoint_value(uint8_t datapoint_id, bool value)
Definition tuya.cpp:618
void force_set_integer_datapoint_value(uint8_t datapoint_id, uint32_t value)
Definition tuya.cpp:646
void register_listener(uint8_t datapoint_id, const std::function< void(TuyaDatapoint)> &func)
Definition tuya.cpp:747
void force_set_enum_datapoint_value(uint8_t datapoint_id, uint8_t value)
Definition tuya.cpp:654
const uint8_t COMMAND_OPEN
Definition tuya_cover.cpp:7
@ COVER_RESTORE_AND_CALL
Definition tuya_cover.h:13
const uint8_t COMMAND_CLOSE
Definition tuya_cover.cpp:8
const uint8_t COMMAND_STOP
Definition tuya_cover.cpp:9
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
size_t size_t pos
Definition helpers.h:929
static void uint32_t
uint8_t report_id
Definition tt21100.cpp:1