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