ESPHome 2025.5.0
Loading...
Searching...
No Matches
anova.cpp
Go to the documentation of this file.
1#include "anova.h"
2#include "esphome/core/log.h"
3
4#ifdef USE_ESP32
5
6namespace esphome {
7namespace anova {
8
9static const char *const TAG = "anova";
10
11using namespace esphome::climate;
12
13void Anova::dump_config() { LOG_CLIMATE("", "Anova BLE Cooker", this); }
14
17 this->current_request_ = 0;
18}
19
20void Anova::loop() {}
21
22void Anova::control(const ClimateCall &call) {
23 if (call.get_mode().has_value()) {
24 ClimateMode mode = *call.get_mode();
25 AnovaPacket *pkt;
26 switch (mode) {
28 pkt = this->codec_->get_stop_request();
29 break;
31 pkt = this->codec_->get_start_request();
32 break;
33 default:
34 ESP_LOGW(TAG, "Unsupported mode: %d", mode);
35 return;
36 }
37 auto status =
38 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
39 pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
40 if (status) {
41 ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
42 }
43 }
44 if (call.get_target_temperature().has_value()) {
45 auto *pkt = this->codec_->get_set_target_temp_request(*call.get_target_temperature());
46 auto status =
47 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
48 pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
49 if (status) {
50 ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
51 }
52 }
53}
54
55void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) {
56 switch (event) {
57 case ESP_GATTC_DISCONNECT_EVT: {
58 this->current_temperature = NAN;
59 this->target_temperature = NAN;
60 this->publish_state();
61 break;
62 }
63 case ESP_GATTC_SEARCH_CMPL_EVT: {
64 auto *chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
65 if (chr == nullptr) {
66 ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
67 ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
68 break;
69 }
70 this->char_handle_ = chr->handle;
71
72 auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
73 chr->handle);
74 if (status) {
75 ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
76 }
77 break;
78 }
79 case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
80 this->node_state = espbt::ClientState::ESTABLISHED;
81 this->current_request_ = 0;
82 this->update();
83 break;
84 }
85 case ESP_GATTC_NOTIFY_EVT: {
86 if (param->notify.handle != this->char_handle_)
87 break;
88 this->codec_->decode(param->notify.value, param->notify.value_len);
89 if (this->codec_->has_target_temp()) {
90 this->target_temperature = this->codec_->target_temp_;
91 }
92 if (this->codec_->has_current_temp()) {
93 this->current_temperature = this->codec_->current_temp_;
94 }
95 if (this->codec_->has_running()) {
97 }
98 if (this->codec_->has_unit()) {
99 this->fahrenheit_ = (this->codec_->unit_ == 'f');
100 ESP_LOGD(TAG, "Anova units is %s", this->fahrenheit_ ? "fahrenheit" : "celsius");
101 this->current_request_++;
102 }
103 this->publish_state();
104
105 if (this->current_request_ > 1) {
106 AnovaPacket *pkt = nullptr;
107 switch (this->current_request_++) {
108 case 2:
109 pkt = this->codec_->get_read_target_temp_request();
110 break;
111 case 3:
112 pkt = this->codec_->get_read_current_temp_request();
113 break;
114 default:
115 this->current_request_ = 1;
116 break;
117 }
118 if (pkt != nullptr) {
119 auto status =
120 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
121 pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
122 if (status) {
123 ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(),
124 status);
125 }
126 }
127 }
128 break;
129 }
130 default:
131 break;
132 }
133}
134
135void Anova::set_unit_of_measurement(const char *unit) { this->fahrenheit_ = !strncmp(unit, "f", 1); }
136
138 if (this->node_state != espbt::ClientState::ESTABLISHED)
139 return;
140
141 if (this->current_request_ < 2) {
142 auto *pkt = this->codec_->get_read_device_status_request();
143 if (this->current_request_ == 0)
144 this->codec_->get_set_unit_request(this->fahrenheit_ ? 'f' : 'c');
145 auto status =
146 esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
147 pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
148 if (status) {
149 ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
150 }
151 this->current_request_++;
152 }
153}
154
155} // namespace anova
156} // namespace esphome
157
158#endif
uint8_t status
Definition bl0942.h:8
const StringRef & get_name() const
void dump_config() override
Definition anova.cpp:13
void update() override
Definition anova.cpp:137
void setup() override
Definition anova.cpp:15
void loop() override
Definition anova.cpp:20
std::unique_ptr< AnovaCodec > codec_
Definition anova.h:42
uint8_t current_request_
Definition anova.h:45
uint16_t char_handle_
Definition anova.h:44
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) override
Definition anova.cpp:55
void control(const climate::ClimateCall &call) override
Definition anova.cpp:22
void set_unit_of_measurement(const char *unit)
Definition anova.cpp:135
This class is used to encode all control actions on a climate device.
Definition climate.h:33
const optional< float > & get_target_temperature() const
Definition climate.cpp:274
ClimateMode mode
The active mode of the climate device.
Definition climate.h:173
float target_temperature
The target temperature of the climate device.
Definition climate.h:186
float current_temperature
The current temperature of the climate device, as reported from the integration.
Definition climate.h:179
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:395
BLECharacteristic * get_characteristic(espbt::ESPBTUUID service, espbt::ESPBTUUID chr)
ClimateMode
Enum for all modes a climate device can be in.
@ CLIMATE_MODE_HEAT
The climate device is set to heat to reach the target temperature.
@ CLIMATE_MODE_OFF
The climate device is off.
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:85