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