ESPHome 2025.6.0
Loading...
Searching...
No Matches
am43_cover.cpp
Go to the documentation of this file.
1#include "am43_cover.h"
2#include "esphome/core/log.h"
3
4#ifdef USE_ESP32
5
6namespace esphome {
7namespace am43 {
8
9static const char *const TAG = "am43_cover";
10
11using namespace esphome::cover;
12
14 LOG_COVER("", "AM43 Cover", this);
15 ESP_LOGCONFIG(TAG,
16 " Device Pin: %d\n"
17 " Invert Position: %d",
18 this->pin_, (int) this->invert_position_);
19}
20
22 this->position = COVER_OPEN;
25 this->logged_in_ = false;
26}
27
29 if (this->node_state == espbt::ClientState::ESTABLISHED && !this->logged_in_) {
30 auto *packet = this->encoder_->get_send_pin_request(this->pin_);
31 auto status =
32 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
33 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
34 ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
35 if (status) {
36 ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
37 } else {
38 this->logged_in_ = true;
39 }
40 }
41}
42
44 auto traits = CoverTraits();
45 traits.set_supports_stop(true);
46 traits.set_supports_position(true);
47 traits.set_supports_tilt(false);
48 traits.set_is_assumed_state(false);
49 return traits;
50}
51
53 if (this->node_state != espbt::ClientState::ESTABLISHED) {
54 ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", this->get_name().c_str());
55 return;
56 }
57 if (call.get_stop()) {
58 auto *packet = this->encoder_->get_stop_request();
59 auto status =
60 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
61 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
62 if (status) {
63 ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
64 }
65 }
66 if (call.get_position().has_value()) {
67 auto pos = *call.get_position();
68
69 if (this->invert_position_)
70 pos = 1 - pos;
71 auto *packet = this->encoder_->get_set_position_request(100 - (uint8_t) (pos * 100));
72 auto status =
73 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
74 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
75 if (status) {
76 ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
77 }
78 }
79}
80
81void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
82 esp_ble_gattc_cb_param_t *param) {
83 switch (event) {
84 case ESP_GATTC_DISCONNECT_EVT: {
85 this->logged_in_ = false;
86 break;
87 }
88 case ESP_GATTC_SEARCH_CMPL_EVT: {
89 auto *chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
90 if (chr == nullptr) {
91 if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
92 ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", this->get_name().c_str());
93 } else {
94 ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", this->get_name().c_str());
95 }
96 break;
97 }
98 this->char_handle_ = chr->handle;
99
100 auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
101 chr->handle);
102 if (status) {
103 ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
104 }
105 break;
106 }
107 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
108 this->node_state = espbt::ClientState::ESTABLISHED;
109 break;
110 }
111 case ESP_GATTC_NOTIFY_EVT: {
112 if (param->notify.handle != this->char_handle_)
113 break;
114 this->decoder_->decode(param->notify.value, param->notify.value_len);
115
116 if (this->decoder_->has_position()) {
117 this->position = ((float) this->decoder_->position_ / 100.0);
118 if (!this->invert_position_)
119 this->position = 1 - this->position;
120 if (this->position > 0.97)
121 this->position = 1.0;
122 if (this->position < 0.02)
123 this->position = 0.0;
124 this->publish_state();
125 }
126
127 if (this->decoder_->has_pin_response()) {
128 if (this->decoder_->pin_ok_) {
129 ESP_LOGI(TAG, "[%s] AM43 pin accepted.", this->get_name().c_str());
130 auto *packet = this->encoder_->get_position_request();
131 auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
132 this->char_handle_, packet->length, packet->data,
133 ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
134 if (status) {
135 ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
136 }
137 } else {
138 ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
139 }
140 }
141
142 if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_) {
143 ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
144 }
145
146 if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_) {
147 ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
148 }
149 break;
150 }
151 default:
152 break;
153 }
154}
155
156} // namespace am43
157} // namespace esphome
158
159#endif
uint8_t status
Definition bl0942.h:8
const StringRef & get_name() const
std::unique_ptr< Am43Encoder > encoder_
Definition am43_cover.h:35
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
cover::CoverTraits get_traits() override
std::unique_ptr< Am43Decoder > decoder_
Definition am43_cover.h:36
void control(const cover::CoverCall &call) override
void publish_state(bool save=true)
Publish the current state of the cover.
Definition cover.cpp:166
float position
The position of the cover from 0.0 (fully closed) to 1.0 (fully open).
Definition cover.h:122
BLECharacteristic * get_characteristic(espbt::ESPBTUUID service, espbt::ESPBTUUID chr)
const float COVER_OPEN
Definition cover.cpp:9
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::unique_ptr< T > make_unique(Args &&...args)
Definition helpers.h:86