ESPHome  2024.11.0
tuya_cover.cpp
Go to the documentation of this file.
1 #include "esphome/core/log.h"
2 #include "tuya_cover.h"
3 
4 namespace esphome {
5 namespace tuya {
6 
7 const uint8_t COMMAND_OPEN = 0x00;
8 const uint8_t COMMAND_CLOSE = 0x02;
9 const uint8_t COMMAND_STOP = 0x01;
10 
11 using namespace esphome::cover;
12 
13 static 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).
20  this->set_direction_(this->invert_position_);
21 
22  // Handle configured restore mode.
23  switch (this->restore_mode_) {
24  case COVER_NO_RESTORE:
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  uint8_t report_id = *this->position_id_;
43  if (this->position_report_id_.has_value()) {
44  // A position report datapoint is configured; listen to that instead.
45  report_id = *this->position_report_id_;
46  }
47 
48  this->parent_->register_listener(report_id, [this](const TuyaDatapoint &datapoint) {
49  if (datapoint.value_int == 123) {
50  ESP_LOGD(TAG, "Ignoring MCU position report - not calibrated");
51  return;
52  }
53  auto pos = float(datapoint.value_uint - this->min_value_) / this->value_range_;
54  this->position = this->invert_position_report_ ? pos : 1.0f - pos;
55  this->publish_state();
56  });
57 }
58 
60  if (call.get_stop()) {
61  if (this->control_id_.has_value()) {
62  this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_STOP);
63  } else {
64  auto pos = this->position;
65  pos = this->invert_position_report_ ? pos : 1.0f - pos;
66  auto position_int = static_cast<uint32_t>(pos * this->value_range_);
67  position_int = position_int + this->min_value_;
68 
69  parent_->force_set_integer_datapoint_value(*this->position_id_, position_int);
70  }
71  }
72  if (call.get_position().has_value()) {
73  auto pos = *call.get_position();
74  if (this->control_id_.has_value() && (pos == COVER_OPEN || pos == COVER_CLOSED)) {
75  if (pos == COVER_OPEN) {
76  this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_OPEN);
77  } else {
78  this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_CLOSE);
79  }
80  } else {
81  pos = this->invert_position_report_ ? pos : 1.0f - pos;
82  auto position_int = static_cast<uint32_t>(pos * this->value_range_);
83  position_int = position_int + this->min_value_;
84 
85  parent_->force_set_integer_datapoint_value(*this->position_id_, position_int);
86  }
87  }
88 
89  this->publish_state();
90 }
91 
92 void TuyaCover::set_direction_(bool inverted) {
93  if (!this->direction_id_.has_value()) {
94  return;
95  }
96 
97  if (inverted) {
98  ESP_LOGD(TAG, "Setting direction: inverted");
99  } else {
100  ESP_LOGD(TAG, "Setting direction: normal");
101  }
102 
103  this->parent_->set_boolean_datapoint_value(*this->direction_id_, inverted);
104 }
105 
107  ESP_LOGCONFIG(TAG, "Tuya Cover:");
108  if (this->invert_position_) {
109  if (this->direction_id_.has_value()) {
110  ESP_LOGCONFIG(TAG, " Inverted");
111  } else {
112  ESP_LOGCONFIG(TAG, " Configured as Inverted, but direction_datapoint isn't configured");
113  }
114  }
115  if (this->invert_position_report_) {
116  ESP_LOGCONFIG(TAG, " Position Reporting Inverted");
117  }
118  if (this->control_id_.has_value()) {
119  ESP_LOGCONFIG(TAG, " Control has datapoint ID %u", *this->control_id_);
120  }
121  if (this->direction_id_.has_value()) {
122  ESP_LOGCONFIG(TAG, " Direction has datapoint ID %u", *this->direction_id_);
123  }
124  if (this->position_id_.has_value()) {
125  ESP_LOGCONFIG(TAG, " Position has datapoint ID %u", *this->position_id_);
126  }
127  if (this->position_report_id_.has_value()) {
128  ESP_LOGCONFIG(TAG, " Position Report has datapoint ID %u", *this->position_report_id_);
129  }
130 }
131 
133  auto traits = cover::CoverTraits();
134  traits.set_supports_stop(true);
135  traits.set_supports_position(true);
136  return traits;
137 }
138 
139 } // namespace tuya
140 } // namespace esphome
const uint8_t COMMAND_OPEN
Definition: tuya_cover.cpp:7
const uint8_t COMMAND_STOP
Definition: tuya_cover.cpp:9
const float COVER_CLOSED
Definition: cover.cpp:10
bool has_value() const
Definition: optional.h:87
cover::CoverTraits get_traits() override
Definition: tuya_cover.cpp:132
void set_direction_(bool inverted)
Definition: tuya_cover.cpp:92
const float COVER_OPEN
Definition: cover.cpp:9
const uint8_t COMMAND_CLOSE
Definition: tuya_cover.cpp:8
void setup() override
Definition: tuya_cover.cpp:15
uint8_t report_id
Definition: tt21100.cpp:13
void control(const cover::CoverCall &call) override
Definition: tuya_cover.cpp:59
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
float position
Definition: cover.h:14
const optional< float > & get_position() const
Definition: cover.cpp:97
void dump_config() override
Definition: tuya_cover.cpp:106
bool get_stop() const
Definition: cover.cpp:147