ESPHome 2025.5.1
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, " Device Pin: %d", this->pin_);
16 ESP_LOGCONFIG(TAG, " Invert Position: %d", (int) this->invert_position_);
17}
18
20 this->position = COVER_OPEN;
23 this->logged_in_ = false;
24}
25
27 if (this->node_state == espbt::ClientState::ESTABLISHED && !this->logged_in_) {
28 auto *packet = this->encoder_->get_send_pin_request(this->pin_);
29 auto status =
30 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
31 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
32 ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
33 if (status) {
34 ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
35 } else {
36 this->logged_in_ = true;
37 }
38 }
39}
40
42 auto traits = CoverTraits();
43 traits.set_supports_stop(true);
44 traits.set_supports_position(true);
45 traits.set_supports_tilt(false);
46 traits.set_is_assumed_state(false);
47 return traits;
48}
49
51 if (this->node_state != espbt::ClientState::ESTABLISHED) {
52 ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", this->get_name().c_str());
53 return;
54 }
55 if (call.get_stop()) {
56 auto *packet = this->encoder_->get_stop_request();
57 auto status =
58 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
59 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
60 if (status) {
61 ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
62 }
63 }
64 if (call.get_position().has_value()) {
65 auto pos = *call.get_position();
66
67 if (this->invert_position_)
68 pos = 1 - pos;
69 auto *packet = this->encoder_->get_set_position_request(100 - (uint8_t) (pos * 100));
70 auto status =
71 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
72 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
73 if (status) {
74 ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
75 }
76 }
77}
78
79void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
80 esp_ble_gattc_cb_param_t *param) {
81 switch (event) {
82 case ESP_GATTC_DISCONNECT_EVT: {
83 this->logged_in_ = false;
84 break;
85 }
86 case ESP_GATTC_SEARCH_CMPL_EVT: {
87 auto *chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
88 if (chr == nullptr) {
89 if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
90 ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", this->get_name().c_str());
91 } else {
92 ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", this->get_name().c_str());
93 }
94 break;
95 }
96 this->char_handle_ = chr->handle;
97
98 auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
99 chr->handle);
100 if (status) {
101 ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
102 }
103 break;
104 }
105 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
106 this->node_state = espbt::ClientState::ESTABLISHED;
107 break;
108 }
109 case ESP_GATTC_NOTIFY_EVT: {
110 if (param->notify.handle != this->char_handle_)
111 break;
112 this->decoder_->decode(param->notify.value, param->notify.value_len);
113
114 if (this->decoder_->has_position()) {
115 this->position = ((float) this->decoder_->position_ / 100.0);
116 if (!this->invert_position_)
117 this->position = 1 - this->position;
118 if (this->position > 0.97)
119 this->position = 1.0;
120 if (this->position < 0.02)
121 this->position = 0.0;
122 this->publish_state();
123 }
124
125 if (this->decoder_->has_pin_response()) {
126 if (this->decoder_->pin_ok_) {
127 ESP_LOGI(TAG, "[%s] AM43 pin accepted.", this->get_name().c_str());
128 auto *packet = this->encoder_->get_position_request();
129 auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
130 this->char_handle_, packet->length, packet->data,
131 ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
132 if (status) {
133 ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
134 }
135 } else {
136 ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
137 }
138 }
139
140 if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_) {
141 ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
142 }
143
144 if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_) {
145 ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
146 }
147 break;
148 }
149 default:
150 break;
151 }
152}
153
154} // namespace am43
155} // namespace esphome
156
157#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