ESPHome  2025.3.3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
api_connection.cpp
Go to the documentation of this file.
1 #include "api_connection.h"
2 #ifdef USE_API
3 #include <cerrno>
4 #include <cinttypes>
5 #include <utility>
8 #include "esphome/core/hal.h"
9 #include "esphome/core/log.h"
10 #include "esphome/core/version.h"
11 
12 #ifdef USE_DEEP_SLEEP
14 #endif
15 #ifdef USE_HOMEASSISTANT_TIME
17 #endif
18 #ifdef USE_BLUETOOTH_PROXY
20 #endif
21 #ifdef USE_VOICE_ASSISTANT
23 #endif
24 
25 namespace esphome {
26 namespace api {
27 
28 static const char *const TAG = "api.connection";
29 static const int ESP32_CAMERA_STOP_STREAM = 5000;
30 
31 // helper for allowing only unique entries in the queue
33  DeferredMessage item(source, send_message);
34 
35  auto iter = std::find_if(this->deferred_queue_.begin(), this->deferred_queue_.end(),
36  [&item](const DeferredMessage &test) -> bool { return test == item; });
37 
38  if (iter != this->deferred_queue_.end()) {
39  (*iter) = item;
40  } else {
41  this->deferred_queue_.push_back(item);
42  }
43 }
44 
46  while (!deferred_queue_.empty()) {
47  DeferredMessage &de = deferred_queue_.front();
48  if (de.send_message_(this->api_connection_, de.source_)) {
49  // O(n) but memory efficiency is more important than speed here which is why std::vector was chosen
50  deferred_queue_.erase(deferred_queue_.begin());
51  } else {
52  break;
53  }
54  }
55 }
56 
57 void DeferredMessageQueue::defer(void *source, send_message_t *send_message) {
58  this->dmq_push_back_with_dedup_(source, send_message);
59 }
60 
61 APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent)
62  : parent_(parent), deferred_message_queue_(this), initial_state_iterator_(this), list_entities_iterator_(this) {
63  this->proto_write_buffer_.reserve(64);
64 
65 #if defined(USE_API_PLAINTEXT)
66  this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))};
67 #elif defined(USE_API_NOISE)
68  this->helper_ = std::unique_ptr<APIFrameHelper>{new APINoiseFrameHelper(std::move(sock), parent->get_noise_ctx())};
69 #else
70 #error "No frame helper defined"
71 #endif
72 }
74  this->last_traffic_ = millis();
75 
76  APIError err = this->helper_->init();
77  if (err != APIError::OK) {
79  ESP_LOGW(TAG, "%s: Helper init failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
80  errno);
81  return;
82  }
83  this->client_info_ = helper_->getpeername();
84  this->client_peername_ = this->client_info_;
85  this->helper_->set_log_info(this->client_info_);
86 }
87 
89 #ifdef USE_BLUETOOTH_PROXY
90  if (bluetooth_proxy::global_bluetooth_proxy->get_api_connection() == this) {
92  }
93 #endif
94 #ifdef USE_VOICE_ASSISTANT
95  if (voice_assistant::global_voice_assistant->get_api_connection() == this) {
97  }
98 #endif
99 }
100 
102  if (this->remove_)
103  return;
104 
105  if (!network::is_connected()) {
106  // when network is disconnected force disconnect immediately
107  // don't wait for timeout
108  this->on_fatal_error();
109  ESP_LOGW(TAG, "%s: Network unavailable, disconnecting", this->client_combined_info_.c_str());
110  return;
111  }
112  if (this->next_close_) {
113  // requested a disconnect
114  this->helper_->close();
115  this->remove_ = true;
116  return;
117  }
118 
119  APIError err = this->helper_->loop();
120  if (err != APIError::OK) {
121  on_fatal_error();
122  ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
123  api_error_to_str(err), errno);
124  return;
125  }
126  ReadPacketBuffer buffer;
127  err = this->helper_->read_packet(&buffer);
128  if (err == APIError::WOULD_BLOCK) {
129  // pass
130  } else if (err != APIError::OK) {
131  on_fatal_error();
132  if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) {
133  ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str());
134  } else if (err == APIError::CONNECTION_CLOSED) {
135  ESP_LOGW(TAG, "%s: Connection closed", this->client_combined_info_.c_str());
136  } else {
137  ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
138  errno);
139  }
140  return;
141  } else {
142  this->last_traffic_ = millis();
143  // read a packet
144  this->read_message(buffer.data_len, buffer.type, &buffer.container[buffer.data_offset]);
145  if (this->remove_)
146  return;
147  }
148 
150 
151  if (!this->list_entities_iterator_.completed())
155 
156  static uint32_t keepalive = 60000;
157  static uint8_t max_ping_retries = 60;
158  static uint16_t ping_retry_interval = 1000;
159  const uint32_t now = millis();
160  if (this->sent_ping_) {
161  // Disconnect if not responded within 2.5*keepalive
162  if (now - this->last_traffic_ > (keepalive * 5) / 2) {
163  on_fatal_error();
164  ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_combined_info_.c_str());
165  }
166  } else if (now - this->last_traffic_ > keepalive && now > this->next_ping_retry_) {
167  ESP_LOGVV(TAG, "Sending keepalive PING...");
168  this->sent_ping_ = this->send_ping_request(PingRequest());
169  if (!this->sent_ping_) {
170  this->next_ping_retry_ = now + ping_retry_interval;
171  this->ping_retries_++;
172  if (this->ping_retries_ >= max_ping_retries) {
173  on_fatal_error();
174  ESP_LOGE(TAG, "%s: Sending keepalive failed %d time(s). Disconnecting...", this->client_combined_info_.c_str(),
175  this->ping_retries_);
176  } else if (this->ping_retries_ >= 10) {
177  ESP_LOGW(TAG, "%s: Sending keepalive failed %d time(s), will retry in %d ms",
178  this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
179  } else {
180  ESP_LOGD(TAG, "%s: Sending keepalive failed %d time(s), will retry in %d ms",
181  this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
182  }
183  }
184  }
185 
186 #ifdef USE_ESP32_CAMERA
187  if (this->image_reader_.available() && this->helper_->can_write_without_blocking()) {
188  uint32_t to_send = std::min((size_t) 1024, this->image_reader_.available());
189  auto buffer = this->create_buffer();
190  // fixed32 key = 1;
191  buffer.encode_fixed32(1, esp32_camera::global_esp32_camera->get_object_id_hash());
192  // bytes data = 2;
193  buffer.encode_bytes(2, this->image_reader_.peek_data_buffer(), to_send);
194  // bool done = 3;
195  bool done = this->image_reader_.available() == to_send;
196  buffer.encode_bool(3, done);
197  bool success = this->send_buffer(buffer, 44);
198 
199  if (success) {
200  this->image_reader_.consume_data(to_send);
201  }
202  if (success && done) {
203  this->image_reader_.return_image();
204  }
205  }
206 #endif
207 
208  if (state_subs_at_ != -1) {
209  const auto &subs = this->parent_->get_state_subs();
210  if (state_subs_at_ >= (int) subs.size()) {
211  state_subs_at_ = -1;
212  } else {
213  auto &it = subs[state_subs_at_];
215  resp.entity_id = it.entity_id;
216  resp.attribute = it.attribute.value();
217  resp.once = it.once;
219  state_subs_at_++;
220  }
221  }
222  }
223 }
224 
225 std::string get_default_unique_id(const std::string &component_type, EntityBase *entity) {
226  return App.get_name() + component_type + entity->get_object_id();
227 }
228 
230  // remote initiated disconnect_client
231  // don't close yet, we still need to send the disconnect response
232  // close will happen on next loop
233  ESP_LOGD(TAG, "%s requested disconnected", this->client_combined_info_.c_str());
234  this->next_close_ = true;
235  DisconnectResponse resp;
236  return resp;
237 }
239  // pass
240 }
241 
242 #ifdef USE_BINARY_SENSOR
244  if (!this->state_subscription_)
245  return false;
246 
247  if (!APIConnection::try_send_binary_sensor_state(this, binary_sensor, state)) {
249  }
250 
251  return true;
252 }
254  if (!APIConnection::try_send_binary_sensor_info(this, binary_sensor)) {
256  }
257 }
259  binary_sensor::BinarySensor *binary_sensor = reinterpret_cast<binary_sensor::BinarySensor *>(v_binary_sensor);
260  return APIConnection::try_send_binary_sensor_state(api, binary_sensor, binary_sensor->state);
261 }
263  bool state) {
265  resp.key = binary_sensor->get_object_id_hash();
266  resp.state = state;
267  resp.missing_state = !binary_sensor->has_state();
268  return api->send_binary_sensor_state_response(resp);
269 }
271  binary_sensor::BinarySensor *binary_sensor = reinterpret_cast<binary_sensor::BinarySensor *>(v_binary_sensor);
273  msg.object_id = binary_sensor->get_object_id();
274  msg.key = binary_sensor->get_object_id_hash();
275  if (binary_sensor->has_own_name())
276  msg.name = binary_sensor->get_name();
277  msg.unique_id = get_default_unique_id("binary_sensor", binary_sensor);
278  msg.device_class = binary_sensor->get_device_class();
279  msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
280  msg.disabled_by_default = binary_sensor->is_disabled_by_default();
281  msg.icon = binary_sensor->get_icon();
282  msg.entity_category = static_cast<enums::EntityCategory>(binary_sensor->get_entity_category());
284 }
285 #endif
286 
287 #ifdef USE_COVER
289  if (!this->state_subscription_)
290  return false;
291 
292  if (!APIConnection::try_send_cover_state(this, cover)) {
294  }
295 
296  return true;
297 }
299  if (!APIConnection::try_send_cover_info(this, cover)) {
301  }
302 }
304  cover::Cover *cover = reinterpret_cast<cover::Cover *>(v_cover);
305  auto traits = cover->get_traits();
306  CoverStateResponse resp{};
307  resp.key = cover->get_object_id_hash();
308  resp.legacy_state =
310  resp.position = cover->position;
311  if (traits.get_supports_tilt())
312  resp.tilt = cover->tilt;
313  resp.current_operation = static_cast<enums::CoverOperation>(cover->current_operation);
314  return api->send_cover_state_response(resp);
315 }
317  cover::Cover *cover = reinterpret_cast<cover::Cover *>(v_cover);
318  auto traits = cover->get_traits();
320  msg.key = cover->get_object_id_hash();
321  msg.object_id = cover->get_object_id();
322  if (cover->has_own_name())
323  msg.name = cover->get_name();
324  msg.unique_id = get_default_unique_id("cover", cover);
325  msg.assumed_state = traits.get_is_assumed_state();
326  msg.supports_position = traits.get_supports_position();
327  msg.supports_tilt = traits.get_supports_tilt();
328  msg.supports_stop = traits.get_supports_stop();
329  msg.device_class = cover->get_device_class();
331  msg.icon = cover->get_icon();
332  msg.entity_category = static_cast<enums::EntityCategory>(cover->get_entity_category());
333  return api->send_list_entities_cover_response(msg);
334 }
336  cover::Cover *cover = App.get_cover_by_key(msg.key);
337  if (cover == nullptr)
338  return;
339 
340  auto call = cover->make_call();
341  if (msg.has_legacy_command) {
342  switch (msg.legacy_command) {
344  call.set_command_open();
345  break;
347  call.set_command_close();
348  break;
350  call.set_command_stop();
351  break;
352  }
353  }
354  if (msg.has_position)
355  call.set_position(msg.position);
356  if (msg.has_tilt)
357  call.set_tilt(msg.tilt);
358  if (msg.stop)
359  call.set_command_stop();
360  call.perform();
361 }
362 #endif
363 
364 #ifdef USE_FAN
366  if (!this->state_subscription_)
367  return false;
368 
369  if (!APIConnection::try_send_fan_state(this, fan)) {
371  }
372 
373  return true;
374 }
376  if (!APIConnection::try_send_fan_info(this, fan)) {
378  }
379 }
381  fan::Fan *fan = reinterpret_cast<fan::Fan *>(v_fan);
382  auto traits = fan->get_traits();
383  FanStateResponse resp{};
384  resp.key = fan->get_object_id_hash();
385  resp.state = fan->state;
386  if (traits.supports_oscillation())
387  resp.oscillating = fan->oscillating;
388  if (traits.supports_speed()) {
389  resp.speed_level = fan->speed;
390  }
391  if (traits.supports_direction())
392  resp.direction = static_cast<enums::FanDirection>(fan->direction);
393  if (traits.supports_preset_modes())
394  resp.preset_mode = fan->preset_mode;
395  return api->send_fan_state_response(resp);
396 }
398  fan::Fan *fan = reinterpret_cast<fan::Fan *>(v_fan);
399  auto traits = fan->get_traits();
401  msg.key = fan->get_object_id_hash();
402  msg.object_id = fan->get_object_id();
403  if (fan->has_own_name())
404  msg.name = fan->get_name();
405  msg.unique_id = get_default_unique_id("fan", fan);
406  msg.supports_oscillation = traits.supports_oscillation();
407  msg.supports_speed = traits.supports_speed();
408  msg.supports_direction = traits.supports_direction();
409  msg.supported_speed_count = traits.supported_speed_count();
410  for (auto const &preset : traits.supported_preset_modes())
411  msg.supported_preset_modes.push_back(preset);
413  msg.icon = fan->get_icon();
414  msg.entity_category = static_cast<enums::EntityCategory>(fan->get_entity_category());
415  return api->send_list_entities_fan_response(msg);
416 }
418  fan::Fan *fan = App.get_fan_by_key(msg.key);
419  if (fan == nullptr)
420  return;
421 
422  auto call = fan->make_call();
423  if (msg.has_state)
424  call.set_state(msg.state);
425  if (msg.has_oscillating)
426  call.set_oscillating(msg.oscillating);
427  if (msg.has_speed_level) {
428  // Prefer level
429  call.set_speed(msg.speed_level);
430  }
431  if (msg.has_direction)
432  call.set_direction(static_cast<fan::FanDirection>(msg.direction));
433  if (msg.has_preset_mode)
434  call.set_preset_mode(msg.preset_mode);
435  call.perform();
436 }
437 #endif
438 
439 #ifdef USE_LIGHT
441  if (!this->state_subscription_)
442  return false;
443 
444  if (!APIConnection::try_send_light_state(this, light)) {
446  }
447 
448  return true;
449 }
451  if (!APIConnection::try_send_light_info(this, light)) {
453  }
454 }
456  light::LightState *light = reinterpret_cast<light::LightState *>(v_light);
457  auto traits = light->get_traits();
458  auto values = light->remote_values;
459  auto color_mode = values.get_color_mode();
460  LightStateResponse resp{};
461 
462  resp.key = light->get_object_id_hash();
463  resp.state = values.is_on();
464  resp.color_mode = static_cast<enums::ColorMode>(color_mode);
465  resp.brightness = values.get_brightness();
466  resp.color_brightness = values.get_color_brightness();
467  resp.red = values.get_red();
468  resp.green = values.get_green();
469  resp.blue = values.get_blue();
470  resp.white = values.get_white();
471  resp.color_temperature = values.get_color_temperature();
472  resp.cold_white = values.get_cold_white();
473  resp.warm_white = values.get_warm_white();
474  if (light->supports_effects())
475  resp.effect = light->get_effect_name();
476  return api->send_light_state_response(resp);
477 }
479  light::LightState *light = reinterpret_cast<light::LightState *>(v_light);
480  auto traits = light->get_traits();
482  msg.key = light->get_object_id_hash();
483  msg.object_id = light->get_object_id();
484  if (light->has_own_name())
485  msg.name = light->get_name();
486  msg.unique_id = get_default_unique_id("light", light);
487 
489  msg.icon = light->get_icon();
490  msg.entity_category = static_cast<enums::EntityCategory>(light->get_entity_category());
491 
492  for (auto mode : traits.get_supported_color_modes())
493  msg.supported_color_modes.push_back(static_cast<enums::ColorMode>(mode));
494 
495  msg.legacy_supports_brightness = traits.supports_color_capability(light::ColorCapability::BRIGHTNESS);
496  msg.legacy_supports_rgb = traits.supports_color_capability(light::ColorCapability::RGB);
498  msg.legacy_supports_rgb && (traits.supports_color_capability(light::ColorCapability::WHITE) ||
499  traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE));
500  msg.legacy_supports_color_temperature = traits.supports_color_capability(light::ColorCapability::COLOR_TEMPERATURE) ||
501  traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE);
502 
504  msg.min_mireds = traits.get_min_mireds();
505  msg.max_mireds = traits.get_max_mireds();
506  }
507  if (light->supports_effects()) {
508  msg.effects.emplace_back("None");
509  for (auto *effect : light->get_effects())
510  msg.effects.push_back(effect->get_name());
511  }
512  return api->send_list_entities_light_response(msg);
513 }
516  if (light == nullptr)
517  return;
518 
519  auto call = light->make_call();
520  if (msg.has_state)
521  call.set_state(msg.state);
522  if (msg.has_brightness)
523  call.set_brightness(msg.brightness);
524  if (msg.has_color_mode)
525  call.set_color_mode(static_cast<light::ColorMode>(msg.color_mode));
526  if (msg.has_color_brightness)
528  if (msg.has_rgb) {
529  call.set_red(msg.red);
530  call.set_green(msg.green);
531  call.set_blue(msg.blue);
532  }
533  if (msg.has_white)
534  call.set_white(msg.white);
535  if (msg.has_color_temperature)
537  if (msg.has_cold_white)
538  call.set_cold_white(msg.cold_white);
539  if (msg.has_warm_white)
540  call.set_warm_white(msg.warm_white);
541  if (msg.has_transition_length)
543  if (msg.has_flash_length)
544  call.set_flash_length(msg.flash_length);
545  if (msg.has_effect)
546  call.set_effect(msg.effect);
547  call.perform();
548 }
549 #endif
550 
551 #ifdef USE_SENSOR
553  if (!this->state_subscription_)
554  return false;
555 
556  if (!APIConnection::try_send_sensor_state(this, sensor, state)) {
558  }
559 
560  return true;
561 }
563  if (!APIConnection::try_send_sensor_info(this, sensor)) {
565  }
566 }
568  sensor::Sensor *sensor = reinterpret_cast<sensor::Sensor *>(v_sensor);
569  return APIConnection::try_send_sensor_state(api, sensor, sensor->state);
570 }
572  SensorStateResponse resp{};
573  resp.key = sensor->get_object_id_hash();
574  resp.state = state;
575  resp.missing_state = !sensor->has_state();
576  return api->send_sensor_state_response(resp);
577 }
579  sensor::Sensor *sensor = reinterpret_cast<sensor::Sensor *>(v_sensor);
581  msg.key = sensor->get_object_id_hash();
582  msg.object_id = sensor->get_object_id();
583  if (sensor->has_own_name())
584  msg.name = sensor->get_name();
585  msg.unique_id = sensor->unique_id();
586  if (msg.unique_id.empty())
587  msg.unique_id = get_default_unique_id("sensor", sensor);
588  msg.icon = sensor->get_icon();
591  msg.force_update = sensor->get_force_update();
592  msg.device_class = sensor->get_device_class();
593  msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class());
595  msg.entity_category = static_cast<enums::EntityCategory>(sensor->get_entity_category());
596  return api->send_list_entities_sensor_response(msg);
597 }
598 #endif
599 
600 #ifdef USE_SWITCH
602  if (!this->state_subscription_)
603  return false;
604 
605  if (!APIConnection::try_send_switch_state(this, a_switch, state)) {
607  }
608 
609  return true;
610 }
612  if (!APIConnection::try_send_switch_info(this, a_switch)) {
614  }
615 }
617  switch_::Switch *a_switch = reinterpret_cast<switch_::Switch *>(v_a_switch);
618  return APIConnection::try_send_switch_state(api, a_switch, a_switch->state);
619 }
621  SwitchStateResponse resp{};
622  resp.key = a_switch->get_object_id_hash();
623  resp.state = state;
624  return api->send_switch_state_response(resp);
625 }
627  switch_::Switch *a_switch = reinterpret_cast<switch_::Switch *>(v_a_switch);
629  msg.key = a_switch->get_object_id_hash();
630  msg.object_id = a_switch->get_object_id();
631  if (a_switch->has_own_name())
632  msg.name = a_switch->get_name();
633  msg.unique_id = get_default_unique_id("switch", a_switch);
634  msg.icon = a_switch->get_icon();
635  msg.assumed_state = a_switch->assumed_state();
637  msg.entity_category = static_cast<enums::EntityCategory>(a_switch->get_entity_category());
638  msg.device_class = a_switch->get_device_class();
639  return api->send_list_entities_switch_response(msg);
640 }
642  switch_::Switch *a_switch = App.get_switch_by_key(msg.key);
643  if (a_switch == nullptr)
644  return;
645 
646  if (msg.state) {
647  a_switch->turn_on();
648  } else {
649  a_switch->turn_off();
650  }
651 }
652 #endif
653 
654 #ifdef USE_TEXT_SENSOR
656  if (!this->state_subscription_)
657  return false;
658 
659  if (!APIConnection::try_send_text_sensor_state(this, text_sensor, std::move(state))) {
661  }
662 
663  return true;
664 }
666  if (!APIConnection::try_send_text_sensor_info(this, text_sensor)) {
668  }
669 }
671  text_sensor::TextSensor *text_sensor = reinterpret_cast<text_sensor::TextSensor *>(v_text_sensor);
672  return APIConnection::try_send_text_sensor_state(api, text_sensor, text_sensor->state);
673 }
675  std::string state) {
677  resp.key = text_sensor->get_object_id_hash();
678  resp.state = std::move(state);
679  resp.missing_state = !text_sensor->has_state();
680  return api->send_text_sensor_state_response(resp);
681 }
683  text_sensor::TextSensor *text_sensor = reinterpret_cast<text_sensor::TextSensor *>(v_text_sensor);
685  msg.key = text_sensor->get_object_id_hash();
686  msg.object_id = text_sensor->get_object_id();
687  msg.name = text_sensor->get_name();
688  msg.unique_id = text_sensor->unique_id();
689  if (msg.unique_id.empty())
690  msg.unique_id = get_default_unique_id("text_sensor", text_sensor);
691  msg.icon = text_sensor->get_icon();
692  msg.disabled_by_default = text_sensor->is_disabled_by_default();
693  msg.entity_category = static_cast<enums::EntityCategory>(text_sensor->get_entity_category());
694  msg.device_class = text_sensor->get_device_class();
696 }
697 #endif
698 
699 #ifdef USE_CLIMATE
701  if (!this->state_subscription_)
702  return false;
703 
704  if (!APIConnection::try_send_climate_state(this, climate)) {
706  }
707 
708  return true;
709 }
711  if (!APIConnection::try_send_climate_info(this, climate)) {
713  }
714 }
716  climate::Climate *climate = reinterpret_cast<climate::Climate *>(v_climate);
717  auto traits = climate->get_traits();
718  ClimateStateResponse resp{};
719  resp.key = climate->get_object_id_hash();
720  resp.mode = static_cast<enums::ClimateMode>(climate->mode);
721  resp.action = static_cast<enums::ClimateAction>(climate->action);
722  if (traits.get_supports_current_temperature())
723  resp.current_temperature = climate->current_temperature;
724  if (traits.get_supports_two_point_target_temperature()) {
725  resp.target_temperature_low = climate->target_temperature_low;
726  resp.target_temperature_high = climate->target_temperature_high;
727  } else {
728  resp.target_temperature = climate->target_temperature;
729  }
730  if (traits.get_supports_fan_modes() && climate->fan_mode.has_value())
731  resp.fan_mode = static_cast<enums::ClimateFanMode>(climate->fan_mode.value());
732  if (!traits.get_supported_custom_fan_modes().empty() && climate->custom_fan_mode.has_value())
733  resp.custom_fan_mode = climate->custom_fan_mode.value();
734  if (traits.get_supports_presets() && climate->preset.has_value()) {
735  resp.preset = static_cast<enums::ClimatePreset>(climate->preset.value());
736  }
737  if (!traits.get_supported_custom_presets().empty() && climate->custom_preset.has_value())
738  resp.custom_preset = climate->custom_preset.value();
739  if (traits.get_supports_swing_modes())
740  resp.swing_mode = static_cast<enums::ClimateSwingMode>(climate->swing_mode);
741  if (traits.get_supports_current_humidity())
742  resp.current_humidity = climate->current_humidity;
743  if (traits.get_supports_target_humidity())
744  resp.target_humidity = climate->target_humidity;
745  return api->send_climate_state_response(resp);
746 }
748  climate::Climate *climate = reinterpret_cast<climate::Climate *>(v_climate);
749  auto traits = climate->get_traits();
751  msg.key = climate->get_object_id_hash();
752  msg.object_id = climate->get_object_id();
753  if (climate->has_own_name())
754  msg.name = climate->get_name();
755  msg.unique_id = get_default_unique_id("climate", climate);
756 
758  msg.icon = climate->get_icon();
759  msg.entity_category = static_cast<enums::EntityCategory>(climate->get_entity_category());
760 
761  msg.supports_current_temperature = traits.get_supports_current_temperature();
762  msg.supports_current_humidity = traits.get_supports_current_humidity();
763  msg.supports_two_point_target_temperature = traits.get_supports_two_point_target_temperature();
764  msg.supports_target_humidity = traits.get_supports_target_humidity();
765 
766  for (auto mode : traits.get_supported_modes())
767  msg.supported_modes.push_back(static_cast<enums::ClimateMode>(mode));
768 
769  msg.visual_min_temperature = traits.get_visual_min_temperature();
770  msg.visual_max_temperature = traits.get_visual_max_temperature();
771  msg.visual_target_temperature_step = traits.get_visual_target_temperature_step();
772  msg.visual_current_temperature_step = traits.get_visual_current_temperature_step();
773  msg.visual_min_humidity = traits.get_visual_min_humidity();
774  msg.visual_max_humidity = traits.get_visual_max_humidity();
775 
776  msg.legacy_supports_away = traits.supports_preset(climate::CLIMATE_PRESET_AWAY);
777  msg.supports_action = traits.get_supports_action();
778 
779  for (auto fan_mode : traits.get_supported_fan_modes())
780  msg.supported_fan_modes.push_back(static_cast<enums::ClimateFanMode>(fan_mode));
781  for (auto const &custom_fan_mode : traits.get_supported_custom_fan_modes())
783  for (auto preset : traits.get_supported_presets())
784  msg.supported_presets.push_back(static_cast<enums::ClimatePreset>(preset));
785  for (auto const &custom_preset : traits.get_supported_custom_presets())
787  for (auto swing_mode : traits.get_supported_swing_modes())
788  msg.supported_swing_modes.push_back(static_cast<enums::ClimateSwingMode>(swing_mode));
789  return api->send_list_entities_climate_response(msg);
790 }
792  climate::Climate *climate = App.get_climate_by_key(msg.key);
793  if (climate == nullptr)
794  return;
795 
796  auto call = climate->make_call();
797  if (msg.has_mode)
798  call.set_mode(static_cast<climate::ClimateMode>(msg.mode));
799  if (msg.has_target_temperature)
805  if (msg.has_target_humidity)
807  if (msg.has_fan_mode)
808  call.set_fan_mode(static_cast<climate::ClimateFanMode>(msg.fan_mode));
809  if (msg.has_custom_fan_mode)
810  call.set_fan_mode(msg.custom_fan_mode);
811  if (msg.has_preset)
812  call.set_preset(static_cast<climate::ClimatePreset>(msg.preset));
813  if (msg.has_custom_preset)
814  call.set_preset(msg.custom_preset);
815  if (msg.has_swing_mode)
816  call.set_swing_mode(static_cast<climate::ClimateSwingMode>(msg.swing_mode));
817  call.perform();
818 }
819 #endif
820 
821 #ifdef USE_NUMBER
823  if (!this->state_subscription_)
824  return false;
825 
826  if (!APIConnection::try_send_number_state(this, number, state)) {
828  }
829 
830  return true;
831 }
833  if (!APIConnection::try_send_number_info(this, number)) {
835  }
836 }
838  number::Number *number = reinterpret_cast<number::Number *>(v_number);
839  return APIConnection::try_send_number_state(api, number, number->state);
840 }
842  NumberStateResponse resp{};
843  resp.key = number->get_object_id_hash();
844  resp.state = state;
845  resp.missing_state = !number->has_state();
846  return api->send_number_state_response(resp);
847 }
849  number::Number *number = reinterpret_cast<number::Number *>(v_number);
851  msg.key = number->get_object_id_hash();
852  msg.object_id = number->get_object_id();
853  if (number->has_own_name())
854  msg.name = number->get_name();
855  msg.unique_id = get_default_unique_id("number", number);
856  msg.icon = number->get_icon();
858  msg.entity_category = static_cast<enums::EntityCategory>(number->get_entity_category());
860  msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode());
861  msg.device_class = number->traits.get_device_class();
862 
863  msg.min_value = number->traits.get_min_value();
864  msg.max_value = number->traits.get_max_value();
865  msg.step = number->traits.get_step();
866 
867  return api->send_list_entities_number_response(msg);
868 }
870  number::Number *number = App.get_number_by_key(msg.key);
871  if (number == nullptr)
872  return;
873 
874  auto call = number->make_call();
875  call.set_value(msg.state);
876  call.perform();
877 }
878 #endif
879 
880 #ifdef USE_DATETIME_DATE
882  if (!this->state_subscription_)
883  return false;
884 
885  if (!APIConnection::try_send_date_state(this, date)) {
887  }
888 
889  return true;
890 }
892  if (!APIConnection::try_send_date_info(this, date)) {
894  }
895 }
897  datetime::DateEntity *date = reinterpret_cast<datetime::DateEntity *>(v_date);
898  DateStateResponse resp{};
899  resp.key = date->get_object_id_hash();
900  resp.missing_state = !date->has_state();
901  resp.year = date->year;
902  resp.month = date->month;
903  resp.day = date->day;
904  return api->send_date_state_response(resp);
905 }
907  datetime::DateEntity *date = reinterpret_cast<datetime::DateEntity *>(v_date);
909  msg.key = date->get_object_id_hash();
910  msg.object_id = date->get_object_id();
911  if (date->has_own_name())
912  msg.name = date->get_name();
913  msg.unique_id = get_default_unique_id("date", date);
914  msg.icon = date->get_icon();
916  msg.entity_category = static_cast<enums::EntityCategory>(date->get_entity_category());
917 
918  return api->send_list_entities_date_response(msg);
919 }
922  if (date == nullptr)
923  return;
924 
925  auto call = date->make_call();
926  call.set_date(msg.year, msg.month, msg.day);
927  call.perform();
928 }
929 #endif
930 
931 #ifdef USE_DATETIME_TIME
933  if (!this->state_subscription_)
934  return false;
935 
936  if (!APIConnection::try_send_time_state(this, time)) {
938  }
939 
940  return true;
941 }
943  if (!APIConnection::try_send_time_info(this, time)) {
945  }
946 }
948  datetime::TimeEntity *time = reinterpret_cast<datetime::TimeEntity *>(v_time);
949  TimeStateResponse resp{};
950  resp.key = time->get_object_id_hash();
951  resp.missing_state = !time->has_state();
952  resp.hour = time->hour;
953  resp.minute = time->minute;
954  resp.second = time->second;
955  return api->send_time_state_response(resp);
956 }
958  datetime::TimeEntity *time = reinterpret_cast<datetime::TimeEntity *>(v_time);
960  msg.key = time->get_object_id_hash();
961  msg.object_id = time->get_object_id();
962  if (time->has_own_name())
963  msg.name = time->get_name();
964  msg.unique_id = get_default_unique_id("time", time);
965  msg.icon = time->get_icon();
967  msg.entity_category = static_cast<enums::EntityCategory>(time->get_entity_category());
968 
969  return api->send_list_entities_time_response(msg);
970 }
973  if (time == nullptr)
974  return;
975 
976  auto call = time->make_call();
977  call.set_time(msg.hour, msg.minute, msg.second);
978  call.perform();
979 }
980 #endif
981 
982 #ifdef USE_DATETIME_DATETIME
984  if (!this->state_subscription_)
985  return false;
986 
987  if (!APIConnection::try_send_datetime_state(this, datetime)) {
989  }
990 
991  return true;
992 }
994  if (!APIConnection::try_send_datetime_info(this, datetime)) {
996  }
997 }
999  datetime::DateTimeEntity *datetime = reinterpret_cast<datetime::DateTimeEntity *>(v_datetime);
1000  DateTimeStateResponse resp{};
1001  resp.key = datetime->get_object_id_hash();
1002  resp.missing_state = !datetime->has_state();
1003  if (datetime->has_state()) {
1004  ESPTime state = datetime->state_as_esptime();
1005  resp.epoch_seconds = state.timestamp;
1006  }
1007  return api->send_date_time_state_response(resp);
1008 }
1010  datetime::DateTimeEntity *datetime = reinterpret_cast<datetime::DateTimeEntity *>(v_datetime);
1012  msg.key = datetime->get_object_id_hash();
1013  msg.object_id = datetime->get_object_id();
1014  if (datetime->has_own_name())
1015  msg.name = datetime->get_name();
1016  msg.unique_id = get_default_unique_id("datetime", datetime);
1017  msg.icon = datetime->get_icon();
1018  msg.disabled_by_default = datetime->is_disabled_by_default();
1019  msg.entity_category = static_cast<enums::EntityCategory>(datetime->get_entity_category());
1020 
1021  return api->send_list_entities_date_time_response(msg);
1022 }
1025  if (datetime == nullptr)
1026  return;
1027 
1028  auto call = datetime->make_call();
1029  call.set_datetime(msg.epoch_seconds);
1030  call.perform();
1031 }
1032 #endif
1033 
1034 #ifdef USE_TEXT
1036  if (!this->state_subscription_)
1037  return false;
1038 
1039  if (!APIConnection::try_send_text_state(this, text, std::move(state))) {
1041  }
1042 
1043  return true;
1044 }
1046  if (!APIConnection::try_send_text_info(this, text)) {
1048  }
1049 }
1051  text::Text *text = reinterpret_cast<text::Text *>(v_text);
1052  return APIConnection::try_send_text_state(api, text, text->state);
1053 }
1055  TextStateResponse resp{};
1056  resp.key = text->get_object_id_hash();
1057  resp.state = std::move(state);
1058  resp.missing_state = !text->has_state();
1059  return api->send_text_state_response(resp);
1060 }
1062  text::Text *text = reinterpret_cast<text::Text *>(v_text);
1064  msg.key = text->get_object_id_hash();
1065  msg.object_id = text->get_object_id();
1066  msg.name = text->get_name();
1067  msg.icon = text->get_icon();
1069  msg.entity_category = static_cast<enums::EntityCategory>(text->get_entity_category());
1070  msg.mode = static_cast<enums::TextMode>(text->traits.get_mode());
1071 
1072  msg.min_length = text->traits.get_min_length();
1073  msg.max_length = text->traits.get_max_length();
1074  msg.pattern = text->traits.get_pattern();
1075 
1076  return api->send_list_entities_text_response(msg);
1077 }
1079  text::Text *text = App.get_text_by_key(msg.key);
1080  if (text == nullptr)
1081  return;
1082 
1083  auto call = text->make_call();
1084  call.set_value(msg.state);
1085  call.perform();
1086 }
1087 #endif
1088 
1089 #ifdef USE_SELECT
1091  if (!this->state_subscription_)
1092  return false;
1093 
1094  if (!APIConnection::try_send_select_state(this, select, std::move(state))) {
1096  }
1097 
1098  return true;
1099 }
1101  if (!APIConnection::try_send_select_info(this, select)) {
1103  }
1104 }
1106  select::Select *select = reinterpret_cast<select::Select *>(v_select);
1107  return APIConnection::try_send_select_state(api, select, select->state);
1108 }
1110  SelectStateResponse resp{};
1111  resp.key = select->get_object_id_hash();
1112  resp.state = std::move(state);
1113  resp.missing_state = !select->has_state();
1114  return api->send_select_state_response(resp);
1115 }
1117  select::Select *select = reinterpret_cast<select::Select *>(v_select);
1119  msg.key = select->get_object_id_hash();
1120  msg.object_id = select->get_object_id();
1121  if (select->has_own_name())
1122  msg.name = select->get_name();
1123  msg.unique_id = get_default_unique_id("select", select);
1124  msg.icon = select->get_icon();
1126  msg.entity_category = static_cast<enums::EntityCategory>(select->get_entity_category());
1127 
1128  for (const auto &option : select->traits.get_options())
1129  msg.options.push_back(option);
1130 
1131  return api->send_list_entities_select_response(msg);
1132 }
1134  select::Select *select = App.get_select_by_key(msg.key);
1135  if (select == nullptr)
1136  return;
1137 
1138  auto call = select->make_call();
1139  call.set_option(msg.state);
1140  call.perform();
1141 }
1142 #endif
1143 
1144 #ifdef USE_BUTTON
1146  if (!APIConnection::try_send_button_info(this, button)) {
1148  }
1149 }
1151  button::Button *button = reinterpret_cast<button::Button *>(v_button);
1153  msg.key = button->get_object_id_hash();
1154  msg.object_id = button->get_object_id();
1155  if (button->has_own_name())
1156  msg.name = button->get_name();
1157  msg.unique_id = get_default_unique_id("button", button);
1158  msg.icon = button->get_icon();
1160  msg.entity_category = static_cast<enums::EntityCategory>(button->get_entity_category());
1161  msg.device_class = button->get_device_class();
1162  return api->send_list_entities_button_response(msg);
1163 }
1165  button::Button *button = App.get_button_by_key(msg.key);
1166  if (button == nullptr)
1167  return;
1168 
1169  button->press();
1170 }
1171 #endif
1172 
1173 #ifdef USE_LOCK
1175  if (!this->state_subscription_)
1176  return false;
1177 
1178  if (!APIConnection::try_send_lock_state(this, a_lock, state)) {
1180  }
1181 
1182  return true;
1183 }
1185  if (!APIConnection::try_send_lock_info(this, a_lock)) {
1187  }
1188 }
1190  lock::Lock *a_lock = reinterpret_cast<lock::Lock *>(v_a_lock);
1191  return APIConnection::try_send_lock_state(api, a_lock, a_lock->state);
1192 }
1194  LockStateResponse resp{};
1195  resp.key = a_lock->get_object_id_hash();
1196  resp.state = static_cast<enums::LockState>(state);
1197  return api->send_lock_state_response(resp);
1198 }
1200  lock::Lock *a_lock = reinterpret_cast<lock::Lock *>(v_a_lock);
1202  msg.key = a_lock->get_object_id_hash();
1203  msg.object_id = a_lock->get_object_id();
1204  if (a_lock->has_own_name())
1205  msg.name = a_lock->get_name();
1206  msg.unique_id = get_default_unique_id("lock", a_lock);
1207  msg.icon = a_lock->get_icon();
1208  msg.assumed_state = a_lock->traits.get_assumed_state();
1210  msg.entity_category = static_cast<enums::EntityCategory>(a_lock->get_entity_category());
1211  msg.supports_open = a_lock->traits.get_supports_open();
1212  msg.requires_code = a_lock->traits.get_requires_code();
1213  return api->send_list_entities_lock_response(msg);
1214 }
1216  lock::Lock *a_lock = App.get_lock_by_key(msg.key);
1217  if (a_lock == nullptr)
1218  return;
1219 
1220  switch (msg.command) {
1221  case enums::LOCK_UNLOCK:
1222  a_lock->unlock();
1223  break;
1224  case enums::LOCK_LOCK:
1225  a_lock->lock();
1226  break;
1227  case enums::LOCK_OPEN:
1228  a_lock->open();
1229  break;
1230  }
1231 }
1232 #endif
1233 
1234 #ifdef USE_VALVE
1236  if (!this->state_subscription_)
1237  return false;
1238 
1239  if (!APIConnection::try_send_valve_state(this, valve)) {
1241  }
1242 
1243  return true;
1244 }
1246  if (!APIConnection::try_send_valve_info(this, valve)) {
1248  }
1249 }
1251  valve::Valve *valve = reinterpret_cast<valve::Valve *>(v_valve);
1252  ValveStateResponse resp{};
1253  resp.key = valve->get_object_id_hash();
1254  resp.position = valve->position;
1255  resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation);
1256  return api->send_valve_state_response(resp);
1257 }
1259  valve::Valve *valve = reinterpret_cast<valve::Valve *>(v_valve);
1260  auto traits = valve->get_traits();
1262  msg.key = valve->get_object_id_hash();
1263  msg.object_id = valve->get_object_id();
1264  if (valve->has_own_name())
1265  msg.name = valve->get_name();
1266  msg.unique_id = get_default_unique_id("valve", valve);
1267  msg.icon = valve->get_icon();
1269  msg.entity_category = static_cast<enums::EntityCategory>(valve->get_entity_category());
1270  msg.device_class = valve->get_device_class();
1271  msg.assumed_state = traits.get_is_assumed_state();
1272  msg.supports_position = traits.get_supports_position();
1273  msg.supports_stop = traits.get_supports_stop();
1274  return api->send_list_entities_valve_response(msg);
1275 }
1277  valve::Valve *valve = App.get_valve_by_key(msg.key);
1278  if (valve == nullptr)
1279  return;
1280 
1281  auto call = valve->make_call();
1282  if (msg.has_position)
1283  call.set_position(msg.position);
1284  if (msg.stop)
1285  call.set_command_stop();
1286  call.perform();
1287 }
1288 #endif
1289 
1290 #ifdef USE_MEDIA_PLAYER
1292  if (!this->state_subscription_)
1293  return false;
1294 
1295  if (!APIConnection::try_send_media_player_state(this, media_player)) {
1297  }
1298 
1299  return true;
1300 }
1302  if (!APIConnection::try_send_media_player_info(this, media_player)) {
1304  }
1305 }
1307  media_player::MediaPlayer *media_player = reinterpret_cast<media_player::MediaPlayer *>(v_media_player);
1308  MediaPlayerStateResponse resp{};
1309  resp.key = media_player->get_object_id_hash();
1310 
1313  : media_player->state;
1314  resp.state = static_cast<enums::MediaPlayerState>(report_state);
1315  resp.volume = media_player->volume;
1316  resp.muted = media_player->is_muted();
1317  return api->send_media_player_state_response(resp);
1318 }
1320  media_player::MediaPlayer *media_player = reinterpret_cast<media_player::MediaPlayer *>(v_media_player);
1322  msg.key = media_player->get_object_id_hash();
1323  msg.object_id = media_player->get_object_id();
1324  if (media_player->has_own_name())
1325  msg.name = media_player->get_name();
1326  msg.unique_id = get_default_unique_id("media_player", media_player);
1327  msg.icon = media_player->get_icon();
1328  msg.disabled_by_default = media_player->is_disabled_by_default();
1329  msg.entity_category = static_cast<enums::EntityCategory>(media_player->get_entity_category());
1330 
1331  auto traits = media_player->get_traits();
1332  msg.supports_pause = traits.get_supports_pause();
1333 
1334  for (auto &supported_format : traits.get_supported_formats()) {
1335  MediaPlayerSupportedFormat media_format;
1336  media_format.format = supported_format.format;
1337  media_format.sample_rate = supported_format.sample_rate;
1338  media_format.num_channels = supported_format.num_channels;
1339  media_format.purpose = static_cast<enums::MediaPlayerFormatPurpose>(supported_format.purpose);
1340  media_format.sample_bytes = supported_format.sample_bytes;
1341  msg.supported_formats.push_back(media_format);
1342  }
1343 
1345 }
1348  if (media_player == nullptr)
1349  return;
1350 
1351  auto call = media_player->make_call();
1352  if (msg.has_command) {
1353  call.set_command(static_cast<media_player::MediaPlayerCommand>(msg.command));
1354  }
1355  if (msg.has_volume) {
1356  call.set_volume(msg.volume);
1357  }
1358  if (msg.has_media_url) {
1359  call.set_media_url(msg.media_url);
1360  }
1361  if (msg.has_announcement) {
1362  call.set_announcement(msg.announcement);
1363  }
1364  call.perform();
1365 }
1366 #endif
1367 
1368 #ifdef USE_ESP32_CAMERA
1369 void APIConnection::set_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
1370  if (!this->state_subscription_)
1371  return;
1372  if (this->image_reader_.available())
1373  return;
1374  if (image->was_requested_by(esphome::esp32_camera::API_REQUESTER) ||
1375  image->was_requested_by(esphome::esp32_camera::IDLE))
1376  this->image_reader_.set_image(std::move(image));
1377 }
1379  if (!APIConnection::try_send_camera_info(this, camera)) {
1381  }
1382 }
1384  esp32_camera::ESP32Camera *camera = reinterpret_cast<esp32_camera::ESP32Camera *>(v_camera);
1386  msg.key = camera->get_object_id_hash();
1387  msg.object_id = camera->get_object_id();
1388  if (camera->has_own_name())
1389  msg.name = camera->get_name();
1390  msg.unique_id = get_default_unique_id("camera", camera);
1392  msg.icon = camera->get_icon();
1393  msg.entity_category = static_cast<enums::EntityCategory>(camera->get_entity_category());
1394  return api->send_list_entities_camera_response(msg);
1395 }
1397  if (esp32_camera::global_esp32_camera == nullptr)
1398  return;
1399 
1400  if (msg.single)
1402  if (msg.stream) {
1404 
1405  App.scheduler.set_timeout(this->parent_, "api_esp32_camera_stop_stream", ESP32_CAMERA_STOP_STREAM, []() {
1407  });
1408  }
1409 }
1410 #endif
1411 
1412 #ifdef USE_HOMEASSISTANT_TIME
1416 }
1417 #endif
1418 
1419 #ifdef USE_BLUETOOTH_PROXY
1422 }
1425 }
1427  if (this->client_api_version_major_ < 1 || this->client_api_version_minor_ < 7) {
1429  for (auto &service : resp.service_data) {
1430  service.legacy_data.assign(service.data.begin(), service.data.end());
1431  service.data.clear();
1432  }
1433  for (auto &manufacturer_data : resp.manufacturer_data) {
1434  manufacturer_data.legacy_data.assign(manufacturer_data.data.begin(), manufacturer_data.data.end());
1435  manufacturer_data.data.clear();
1436  }
1437  return this->send_bluetooth_le_advertisement_response(resp);
1438  }
1439  return this->send_bluetooth_le_advertisement_response(msg);
1440 }
1443 }
1446 }
1449 }
1452 }
1455 }
1458 }
1459 
1462 }
1463 
1469  return resp;
1470 }
1471 #endif
1472 
1473 #ifdef USE_VOICE_ASSISTANT
1475  if (voice_assistant::global_voice_assistant != nullptr) {
1477  }
1478 }
1480  if (voice_assistant::global_voice_assistant != nullptr) {
1481  if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
1482  return;
1483  }
1484 
1485  if (msg.error) {
1487  return;
1488  }
1489  if (msg.port == 0) {
1490  // Use API Audio
1492  } else {
1493  struct sockaddr_storage storage;
1494  socklen_t len = sizeof(storage);
1495  this->helper_->getpeername((struct sockaddr *) &storage, &len);
1497  }
1498  }
1499 };
1501  if (voice_assistant::global_voice_assistant != nullptr) {
1502  if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
1503  return;
1504  }
1505 
1507  }
1508 }
1510  if (voice_assistant::global_voice_assistant != nullptr) {
1511  if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
1512  return;
1513  }
1514 
1516  }
1517 };
1519  if (voice_assistant::global_voice_assistant != nullptr) {
1520  if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
1521  return;
1522  }
1523 
1525  }
1526 };
1527 
1529  if (voice_assistant::global_voice_assistant != nullptr) {
1530  if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
1531  return;
1532  }
1533 
1535  }
1536 }
1537 
1541  if (voice_assistant::global_voice_assistant != nullptr) {
1542  if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
1543  return resp;
1544  }
1545 
1547  for (auto &wake_word : config.available_wake_words) {
1548  VoiceAssistantWakeWord resp_wake_word;
1549  resp_wake_word.id = wake_word.id;
1550  resp_wake_word.wake_word = wake_word.wake_word;
1551  for (const auto &lang : wake_word.trained_languages) {
1552  resp_wake_word.trained_languages.push_back(lang);
1553  }
1554  resp.available_wake_words.push_back(std::move(resp_wake_word));
1555  }
1556  for (auto &wake_word_id : config.active_wake_words) {
1557  resp.active_wake_words.push_back(wake_word_id);
1558  }
1559  resp.max_active_wake_words = config.max_active_wake_words;
1560  }
1561  return resp;
1562 }
1563 
1565  if (voice_assistant::global_voice_assistant != nullptr) {
1566  if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
1567  return;
1568  }
1569 
1571  }
1572 }
1573 
1574 #endif
1575 
1576 #ifdef USE_ALARM_CONTROL_PANEL
1578  if (!this->state_subscription_)
1579  return false;
1580 
1581  if (!APIConnection::try_send_alarm_control_panel_state(this, a_alarm_control_panel)) {
1583  }
1584 
1585  return true;
1586 }
1588  if (!APIConnection::try_send_alarm_control_panel_info(this, a_alarm_control_panel)) {
1589  this->deferred_message_queue_.defer(a_alarm_control_panel, try_send_alarm_control_panel_info);
1590  }
1591 }
1592 bool APIConnection::try_send_alarm_control_panel_state(APIConnection *api, void *v_a_alarm_control_panel) {
1593  alarm_control_panel::AlarmControlPanel *a_alarm_control_panel =
1594  reinterpret_cast<alarm_control_panel::AlarmControlPanel *>(v_a_alarm_control_panel);
1596  resp.key = a_alarm_control_panel->get_object_id_hash();
1597  resp.state = static_cast<enums::AlarmControlPanelState>(a_alarm_control_panel->get_state());
1598  return api->send_alarm_control_panel_state_response(resp);
1599 }
1600 bool APIConnection::try_send_alarm_control_panel_info(APIConnection *api, void *v_a_alarm_control_panel) {
1601  alarm_control_panel::AlarmControlPanel *a_alarm_control_panel =
1602  reinterpret_cast<alarm_control_panel::AlarmControlPanel *>(v_a_alarm_control_panel);
1604  msg.key = a_alarm_control_panel->get_object_id_hash();
1605  msg.object_id = a_alarm_control_panel->get_object_id();
1606  msg.name = a_alarm_control_panel->get_name();
1607  msg.unique_id = get_default_unique_id("alarm_control_panel", a_alarm_control_panel);
1608  msg.icon = a_alarm_control_panel->get_icon();
1609  msg.disabled_by_default = a_alarm_control_panel->is_disabled_by_default();
1610  msg.entity_category = static_cast<enums::EntityCategory>(a_alarm_control_panel->get_entity_category());
1611  msg.supported_features = a_alarm_control_panel->get_supported_features();
1612  msg.requires_code = a_alarm_control_panel->get_requires_code();
1613  msg.requires_code_to_arm = a_alarm_control_panel->get_requires_code_to_arm();
1615 }
1618  if (a_alarm_control_panel == nullptr)
1619  return;
1620 
1621  auto call = a_alarm_control_panel->make_call();
1622  switch (msg.command) {
1624  call.disarm();
1625  break;
1627  call.arm_away();
1628  break;
1630  call.arm_home();
1631  break;
1633  call.arm_night();
1634  break;
1636  call.arm_vacation();
1637  break;
1639  call.arm_custom_bypass();
1640  break;
1642  call.pending();
1643  break;
1644  }
1645  call.set_code(msg.code);
1646  call.perform();
1647 }
1648 #endif
1649 
1650 #ifdef USE_EVENT
1651 void APIConnection::send_event(event::Event *event, std::string event_type) {
1652  if (!APIConnection::try_send_event(this, event, std::move(event_type))) {
1654  }
1655 }
1657  if (!APIConnection::try_send_event_info(this, event)) {
1659  }
1660 }
1662  event::Event *event = reinterpret_cast<event::Event *>(v_event);
1663  return APIConnection::try_send_event(api, event, *(event->last_event_type));
1664 }
1665 bool APIConnection::try_send_event(APIConnection *api, event::Event *event, std::string event_type) {
1666  EventResponse resp{};
1667  resp.key = event->get_object_id_hash();
1668  resp.event_type = std::move(event_type);
1669  return api->send_event_response(resp);
1670 }
1672  event::Event *event = reinterpret_cast<event::Event *>(v_event);
1674  msg.key = event->get_object_id_hash();
1675  msg.object_id = event->get_object_id();
1676  if (event->has_own_name())
1677  msg.name = event->get_name();
1678  msg.unique_id = get_default_unique_id("event", event);
1679  msg.icon = event->get_icon();
1680  msg.disabled_by_default = event->is_disabled_by_default();
1681  msg.entity_category = static_cast<enums::EntityCategory>(event->get_entity_category());
1682  msg.device_class = event->get_device_class();
1683  for (const auto &event_type : event->get_event_types())
1684  msg.event_types.push_back(event_type);
1685  return api->send_list_entities_event_response(msg);
1686 }
1687 #endif
1688 
1689 #ifdef USE_UPDATE
1691  if (!this->state_subscription_)
1692  return false;
1693 
1694  if (!APIConnection::try_send_update_state(this, update)) {
1696  }
1697 
1698  return true;
1699 }
1701  if (!APIConnection::try_send_update_info(this, update)) {
1703  }
1704 }
1706  update::UpdateEntity *update = reinterpret_cast<update::UpdateEntity *>(v_update);
1707  UpdateStateResponse resp{};
1708  resp.key = update->get_object_id_hash();
1709  resp.missing_state = !update->has_state();
1710  if (update->has_state()) {
1711  resp.in_progress = update->state == update::UpdateState::UPDATE_STATE_INSTALLING;
1712  if (update->update_info.has_progress) {
1713  resp.has_progress = true;
1714  resp.progress = update->update_info.progress;
1715  }
1716  resp.current_version = update->update_info.current_version;
1717  resp.latest_version = update->update_info.latest_version;
1718  resp.title = update->update_info.title;
1719  resp.release_summary = update->update_info.summary;
1720  resp.release_url = update->update_info.release_url;
1721  }
1722 
1723  return api->send_update_state_response(resp);
1724 }
1726  update::UpdateEntity *update = reinterpret_cast<update::UpdateEntity *>(v_update);
1728  msg.key = update->get_object_id_hash();
1729  msg.object_id = update->get_object_id();
1730  if (update->has_own_name())
1731  msg.name = update->get_name();
1732  msg.unique_id = get_default_unique_id("update", update);
1733  msg.icon = update->get_icon();
1735  msg.entity_category = static_cast<enums::EntityCategory>(update->get_entity_category());
1736  msg.device_class = update->get_device_class();
1737  return api->send_list_entities_update_response(msg);
1738 }
1741  if (update == nullptr)
1742  return;
1743 
1744  switch (msg.command) {
1746  update->perform();
1747  break;
1749  update->check();
1750  break;
1752  ESP_LOGE(TAG, "UPDATE_COMMAND_NONE not handled. Check client is sending the correct command");
1753  break;
1754  default:
1755  ESP_LOGW(TAG, "Unknown update command: %" PRIu32, msg.command);
1756  break;
1757  }
1758 }
1759 #endif
1760 
1761 bool APIConnection::try_send_log_message(int level, const char *tag, const char *line) {
1762  if (this->log_subscription_ < level)
1763  return false;
1764 
1765  // Send raw so that we don't copy too much
1766  auto buffer = this->create_buffer();
1767  // LogLevel level = 1;
1768  buffer.encode_uint32(1, static_cast<uint32_t>(level));
1769  // string message = 3;
1770  buffer.encode_string(3, line, strlen(line));
1771  // SubscribeLogsResponse - 29
1772  return this->send_buffer(buffer, 29);
1773 }
1774 
1776  this->client_info_ = msg.client_info;
1777  this->client_peername_ = this->helper_->getpeername();
1778  this->client_combined_info_ = this->client_info_ + " (" + this->client_peername_ + ")";
1779  this->helper_->set_log_info(this->client_combined_info_);
1782  ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu32 ".%" PRIu32, this->client_info_.c_str(),
1783  this->client_peername_.c_str(), this->client_api_version_major_, this->client_api_version_minor_);
1784 
1785  HelloResponse resp;
1786  resp.api_version_major = 1;
1787  resp.api_version_minor = 10;
1788  resp.server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
1789  resp.name = App.get_name();
1790 
1791  this->connection_state_ = ConnectionState::CONNECTED;
1792  return resp;
1793 }
1795  bool correct = this->parent_->check_password(msg.password);
1796 
1797  ConnectResponse resp;
1798  // bool invalid_password = 1;
1799  resp.invalid_password = !correct;
1800  if (correct) {
1801  ESP_LOGD(TAG, "%s: Connected successfully", this->client_combined_info_.c_str());
1802  this->connection_state_ = ConnectionState::AUTHENTICATED;
1804 #ifdef USE_HOMEASSISTANT_TIME
1806  this->send_time_request();
1807  }
1808 #endif
1809  }
1810  return resp;
1811 }
1813  DeviceInfoResponse resp{};
1814  resp.uses_password = this->parent_->uses_password();
1815  resp.name = App.get_name();
1816  resp.friendly_name = App.get_friendly_name();
1817  resp.suggested_area = App.get_area();
1818  resp.mac_address = get_mac_address_pretty();
1819  resp.esphome_version = ESPHOME_VERSION;
1820  resp.compilation_time = App.get_compilation_time();
1821 #if defined(USE_ESP8266) || defined(USE_ESP32)
1822  resp.manufacturer = "Espressif";
1823 #elif defined(USE_RP2040)
1824  resp.manufacturer = "Raspberry Pi";
1825 #elif defined(USE_BK72XX)
1826  resp.manufacturer = "Beken";
1827 #elif defined(USE_RTL87XX)
1828  resp.manufacturer = "Realtek";
1829 #elif defined(USE_HOST)
1830  resp.manufacturer = "Host";
1831 #endif
1832  resp.model = ESPHOME_BOARD;
1833 #ifdef USE_DEEP_SLEEP
1834  resp.has_deep_sleep = deep_sleep::global_has_deep_sleep;
1835 #endif
1836 #ifdef ESPHOME_PROJECT_NAME
1837  resp.project_name = ESPHOME_PROJECT_NAME;
1838  resp.project_version = ESPHOME_PROJECT_VERSION;
1839 #endif
1840 #ifdef USE_WEBSERVER
1841  resp.webserver_port = USE_WEBSERVER_PORT;
1842 #endif
1843 #ifdef USE_BLUETOOTH_PROXY
1844  resp.legacy_bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->get_legacy_version();
1845  resp.bluetooth_proxy_feature_flags = bluetooth_proxy::global_bluetooth_proxy->get_feature_flags();
1847 #endif
1848 #ifdef USE_VOICE_ASSISTANT
1849  resp.legacy_voice_assistant_version = voice_assistant::global_voice_assistant->get_legacy_version();
1850  resp.voice_assistant_feature_flags = voice_assistant::global_voice_assistant->get_feature_flags();
1851 #endif
1852  return resp;
1853 }
1855  for (auto &it : this->parent_->get_state_subs()) {
1856  if (it.entity_id == msg.entity_id && it.attribute.value() == msg.attribute) {
1857  it.callback(msg.state);
1858  }
1859  }
1860 }
1862  bool found = false;
1863  for (auto *service : this->parent_->get_user_services()) {
1864  if (service->execute_service(msg)) {
1865  found = true;
1866  }
1867  }
1868  if (!found) {
1869  ESP_LOGV(TAG, "Could not find matching service!");
1870  }
1871 }
1873  state_subs_at_ = 0;
1874 }
1875 bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) {
1876  if (this->remove_)
1877  return false;
1878  if (!this->helper_->can_write_without_blocking()) {
1879  delay(0);
1880  APIError err = this->helper_->loop();
1881  if (err != APIError::OK) {
1882  on_fatal_error();
1883  ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
1884  api_error_to_str(err), errno);
1885  return false;
1886  }
1887  if (!this->helper_->can_write_without_blocking()) {
1888  // SubscribeLogsResponse
1889  if (message_type != 29) {
1890  ESP_LOGV(TAG, "Cannot send message because of TCP buffer space");
1891  }
1892  delay(0);
1893  return false;
1894  }
1895  }
1896 
1897  APIError err = this->helper_->write_packet(message_type, buffer.get_buffer()->data(), buffer.get_buffer()->size());
1898  if (err == APIError::WOULD_BLOCK)
1899  return false;
1900  if (err != APIError::OK) {
1901  on_fatal_error();
1902  if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
1903  ESP_LOGW(TAG, "%s: Connection reset", this->client_combined_info_.c_str());
1904  } else {
1905  ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", this->client_combined_info_.c_str(), api_error_to_str(err),
1906  errno);
1907  }
1908  return false;
1909  }
1910  // Do not set last_traffic_ on send
1911  return true;
1912 }
1914  this->on_fatal_error();
1915  ESP_LOGD(TAG, "%s: tried to access without authentication.", this->client_combined_info_.c_str());
1916 }
1918  this->on_fatal_error();
1919  ESP_LOGD(TAG, "%s: tried to access without full connection.", this->client_combined_info_.c_str());
1920 }
1922  this->helper_->close();
1923  this->remove_ = true;
1924 }
1925 
1926 } // namespace api
1927 } // namespace esphome
1928 #endif
bool get_force_update() const
Get whether force update mode is enabled.
Definition: sensor.h:78
Base class for all switches.
Definition: switch.h:39
bool state
Definition: fan.h:34
value_type const & value() const
Definition: optional.h:89
float current_humidity
The current humidity of the climate device, as reported from the integration.
Definition: climate.h:182
static bool try_send_light_state(APIConnection *api, void *v_light)
bool send_list_entities_binary_sensor_response(const ListEntitiesBinarySensorResponse &msg)
bool state
The current on/off state of the fan.
Definition: fan.h:110
bool send_text_sensor_state(text_sensor::TextSensor *text_sensor, std::string state)
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition: climate.h:202
bool send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel)
bool has_own_name() const
Definition: entity_base.h:23
bool send_date_state_response(const DateStateResponse &msg)
void send_fan_info(fan::Fan *fan)
AlarmControlPanelState get_state() const
Get the state.
enums::EntityCategory entity_category
Definition: api_pb2.h:661
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition: light_state.h:63
std::vector< std::string > supported_preset_modes
Definition: api_pb2.h:501
LightCall & set_color_brightness(optional< float > brightness)
Set the color brightness of the light from 0.0 (no color) to 1.0 (fully on)
Definition: light_call.cpp:592
bool oscillating
The current oscillation state of the fan.
Definition: fan.h:112
static bool try_send_time_info(APIConnection *api, void *v_time)
static bool try_send_event(APIConnection *api, void *v_event)
bool has_state() const
Return whether this number has gotten a full state yet.
Definition: number.h:52
bool send_fan_state_response(const FanStateResponse &msg)
std::vector< MediaPlayerSupportedFormat > supported_formats
Definition: api_pb2.h:1301
static bool try_send_cover_state(APIConnection *api, void *v_cover)
void datetime_command(const DateTimeCommandRequest &msg) override
std::vector< uint8_t > * get_buffer() const
Definition: proto.h:268
void request_image(CameraRequester requester)
std::vector< std::string > active_wake_words
Definition: api_pb2.h:1895
media_player::MediaPlayer * get_media_player_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:418
void dmq_push_back_with_dedup_(void *source, send_message_t *send_message)
bool try_send_log_message(int level, const char *tag, const char *line)
MediaPlayerCall & set_command(MediaPlayerCommand command)
FanDirection direction
The current direction of the fan.
Definition: fan.h:116
Base class for all cover devices.
Definition: cover.h:111
const std::vector< UserServiceDescriptor * > & get_user_services() const
Definition: api_server.h:124
LightCall & set_red(optional< float > red)
Set the red RGB value of the light from 0.0 to 1.0.
Definition: light_call.cpp:600
void start_stream(CameraRequester requester)
static bool try_send_button_info(APIConnection *api, void *v_button)
void send_valve_info(valve::Valve *valve)
enums::EntityCategory entity_category
Definition: api_pb2.h:1200
LightCall & set_color_temperature(optional< float > color_temperature)
Set the color temperature of the light in mireds for CWWW or RGBWW lights.
Definition: light_call.cpp:632
void on_set_configuration(const std::vector< std::string > &active_wake_words)
void on_voice_assistant_audio(const VoiceAssistantAudio &msg) override
void bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) override
TextMode get_mode() const
Definition: text_traits.h:29
bool send_text_state_response(const TextStateResponse &msg)
std::string state
Definition: text.h:26
enums::EntityCategory entity_category
Definition: api_pb2.h:1252
bool send_ping_request(const PingRequest &msg)
LightCall & set_cold_white(optional< float > cold_white)
Set the cold white value of the light from 0.0 to 1.0.
Definition: light_call.cpp:640
bool send_switch_state(switch_::Switch *a_switch, bool state)
TimeCall & set_time(uint8_t hour, uint8_t minute, uint8_t second)
Definition: time_entity.cpp:66
void update_command(const UpdateCommandRequest &msg) override
float target_temperature
The target temperature of the climate device.
Definition: climate.h:186
VoiceAssistant * global_voice_assistant
std::string get_effect_name()
Return the name of the current effect, or if no effect is active "None".
climate::Climate * get_climate_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:328
LockState state
The current reported state of the lock.
Definition: lock.h:122
std::string get_device_class()
Get the device class, using the manual override if set.
Definition: entity_base.cpp:78
select::Select * get_select_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:388
CoverCall make_call()
Construct a new cover call used to control the cover.
Definition: cover.cpp:149
void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) override
bool send_event_response(const EventResponse &msg)
void on_voice_assistant_response(const VoiceAssistantResponse &msg) override
TextTraits traits
Definition: text.h:27
BluetoothConnectionsFreeResponse subscribe_bluetooth_connections_free(const SubscribeBluetoothConnectionsFreeRequest &msg) override
datetime::DateTimeEntity * get_datetime_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:368
std::string get_default_unique_id(const std::string &component_type, EntityBase *entity)
static bool try_send_select_info(APIConnection *api, void *v_select)
InitialStateIterator initial_state_iterator_
static bool try_send_climate_state(APIConnection *api, void *v_climate)
const char * api_error_to_str(APIError err)
bool send_valve_state(valve::Valve *valve)
virtual std::string unique_id()
Override this method to set the unique ID of this sensor.
Definition: text_sensor.cpp:68
TextCall & set_value(const std::string &value)
Definition: text_call.cpp:10
CoverOperation current_operation
The current operation of the cover (idle, opening, closing).
Definition: cover.h:116
std::vector< VoiceAssistantWakeWord > available_wake_words
Definition: api_pb2.h:1881
static bool try_send_datetime_info(APIConnection *api, void *v_datetime)
float position
The position of the valve from 0.0 (fully closed) to 1.0 (fully open).
Definition: valve.h:116
std::vector< enums::ClimatePreset > supported_presets
Definition: api_pb2.h:1011
Base class for all buttons.
Definition: button.h:29
enums::EntityCategory entity_category
Definition: api_pb2.h:1153
std::vector< std::string > options
Definition: api_pb2.h:1151
bool send_fan_state(fan::Fan *fan)
A more user-friendly version of struct tm from time.h.
Definition: time.h:15
virtual FanTraits get_traits()=0
void send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel)
bool send_climate_state_response(const ClimateStateResponse &msg)
enums::EntityCategory entity_category
Definition: api_pb2.h:695
enums::EntityCategory entity_category
Definition: api_pb2.h:1962
static bool try_send_text_state(APIConnection *api, void *v_text)
lock::Lock * get_lock_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:398
bool send_binary_sensor_state_response(const BinarySensorStateResponse &msg)
const UpdateState & state
Definition: update_entity.h:40
static bool try_send_datetime_state(APIConnection *api, void *v_datetime)
bool check_password(const std::string &password) const
Definition: api_server.cpp:149
bool supports_effects()
Return whether the light has any effects that meet the trait requirements.
static bool try_send_sensor_state(APIConnection *api, void *v_sensor)
bool send_climate_state(climate::Climate *climate)
bool(APIConnection *, void *) send_message_t
ClimateMode mode
The active mode of the climate device.
Definition: climate.h:173
void send_update_info(update::UpdateEntity *update)
virtual bool get_requires_code() const =0
Returns if the alarm_control_panel has a code.
bool send_list_entities_valve_response(const ListEntitiesValveResponse &msg)
button::Button * get_button_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:268
virtual bool assumed_state()
Return whether this switch uses an assumed state - i.e.
Definition: switch.cpp:58
uint32_t socklen_t
Definition: headers.h:97
bool send_list_entities_fan_response(const ListEntitiesFanResponse &msg)
DisconnectResponse disconnect(const DisconnectRequest &msg) override
virtual bool is_status_binary_sensor() const
bool send_number_state_response(const NumberStateResponse &msg)
bool send_lock_state(lock::Lock *a_lock, lock::LockState state)
bool send_text_state(text::Text *text, std::string state)
const std::string & get_area() const
Get the area of this Application set by pre_setup().
Definition: application.h:208
const std::string & get_friendly_name() const
Get the friendly name of this Application set by pre_setup().
Definition: application.h:205
std::unique_ptr< APIFrameHelper > helper_
SelectTraits traits
Definition: select.h:34
enums::ClimateSwingMode swing_mode
Definition: api_pb2.h:1074
float target_temperature_high
The maximum target temperature of the climate device, for climate devices with split target temperatu...
Definition: climate.h:191
void media_player_command(const MediaPlayerCommandRequest &msg) override
enums::EntityCategory entity_category
Definition: api_pb2.h:2199
float current_temperature
The current temperature of the climate device, as reported from the integration.
Definition: climate.h:179
void defer(void *source, send_message_t *send_message)
bool send_list_entities_select_response(const ListEntitiesSelectResponse &msg)
Color temperature can be controlled.
void client_subscription(api::APIConnection *client, bool subscribe)
HomeassistantTime * global_homeassistant_time
void send_event_info(event::Event *event)
LightCall & set_color_mode(optional< ColorMode > color_mode)
Set the color mode of the light.
Definition: light_call.cpp:584
enums::ColorMode color_mode
Definition: api_pb2.h:616
void send_lock_info(lock::Lock *a_lock)
std::vector< BluetoothServiceData > service_data
Definition: api_pb2.h:1379
NumberCall & set_value(float value)
Definition: number_call.cpp:10
bool send_list_entities_event_response(const ListEntitiesEventResponse &msg)
DeferredMessageQueue deferred_message_queue_
enums::EntityCategory entity_category
Definition: api_pb2.h:2113
bool has_value() const
Definition: optional.h:87
void execute_service(const ExecuteServiceRequest &msg) override
std::vector< std::string > supported_custom_presets
Definition: api_pb2.h:1012
int get_max_length() const
Definition: text_traits.h:21
Base-class for all text inputs.
Definition: text.h:24
ValveCall & set_command_stop()
Set the command to stop the valve.
Definition: valve.cpp:59
TextCall make_call()
Instantiate a TextCall object to modify this text component&#39;s state.
Definition: text.h:35
void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) override
LightCall & set_transition_length(optional< uint32_t > transition_length)
Set the transition length of this call in milliseconds.
Definition: light_call.cpp:560
float target_humidity
The target humidity of the climate device.
Definition: climate.h:196
virtual ValveTraits get_traits()=0
ClimateCall & set_swing_mode(ClimateSwingMode swing_mode)
Set the swing mode of the climate device.
Definition: climate.cpp:237
AlarmControlPanelCall make_call()
Make a AlarmControlPanelCall.
void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) override
float tilt
The current tilt value of the cover from 0.0 to 1.0.
Definition: cover.h:124
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
Definition: util.cpp:15
void stop_stream(CameraRequester requester)
void send_switch_info(switch_::Switch *a_switch)
std::string get_object_id() const
Definition: entity_base.cpp:43
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
virtual MediaPlayerTraits get_traits()=0
ClimateSwingMode swing_mode
Definition: climate.h:581
void on_no_setup_connection() override
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
Definition: automation.h:95
alarm_control_panel::AlarmControlPanel * get_alarm_control_panel_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:431
ValveCall make_call()
Construct a new valve call used to control the valve.
Definition: valve.cpp:127
static bool try_send_switch_info(APIConnection *api, void *v_a_switch)
enums::ClimateFanMode fan_mode
Definition: api_pb2.h:1072
void send_text_info(text::Text *text)
LockTraits traits
Definition: lock.h:124
optional< std::string > custom_fan_mode
The active custom fan mode of the climate device.
Definition: climate.h:205
cover::Cover * get_cover_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:308
virtual CoverTraits get_traits()=0
void send_climate_info(climate::Climate *climate)
void bluetooth_device_request(const api::BluetoothDeviceRequest &msg)
BluetoothProxy * global_bluetooth_proxy
Device is in away preset.
Definition: climate_mode.h:88
static bool try_send_climate_info(APIConnection *api, void *v_climate)
static bool try_send_alarm_control_panel_state(APIConnection *api, void *v_a_alarm_control_panel)
ClimateCall & set_target_temperature_low(float target_temperature_low)
Set the low point target temperature of the climate device.
Definition: climate.cpp:260
virtual std::string unique_id()
Override this method to set the unique ID of this sensor.
Definition: sensor.cpp:88
bool send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg)
ClimateCall make_call()
Make a climate device control call, this is used to control the climate device, see the ClimateCall d...
Definition: climate.cpp:479
std::vector< std::string > event_types
Definition: api_pb2.h:2115
fan::Fan * get_fan_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:298
void perform()
Perform the valve call.
Definition: valve.cpp:71
void lock()
Turn this lock on.
Definition: lock.cpp:30
static bool try_send_number_info(APIConnection *api, void *v_number)
enums::EntityCategory entity_category
Definition: api_pb2.h:956
std::string get_icon() const
Definition: entity_base.cpp:30
std::shared_ptr< APINoiseContext > get_noise_ctx()
Definition: api_server.h:39
ClimateCall & set_target_temperature(float target_temperature)
Set the target temperature of the climate device.
Definition: climate.cpp:256
enums::ClimatePreset preset
Definition: api_pb2.h:1078
void time_command(const TimeCommandRequest &msg) override
void date_command(const DateCommandRequest &msg) override
float state
This member variable stores the last state that has passed through all filters.
Definition: sensor.h:131
enums::EntityCategory entity_category
Definition: api_pb2.h:2013
Trigger< std::string, std::string > * get_client_connected_trigger() const
Definition: api_server.h:126
bool send_list_entities_text_sensor_response(const ListEntitiesTextSensorResponse &msg)
FanCall & set_speed(int speed)
Definition: fan.h:59
std::vector< std::string > trained_languages
Definition: api_pb2.h:1861
bool send_sensor_state(sensor::Sensor *sensor, float state)
void send_button_info(button::Button *button)
void send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor)
static bool try_send_number_state(APIConnection *api, void *v_number)
Brightness of cold and warm white output can be controlled.
void bluetooth_gatt_read(const api::BluetoothGATTReadRequest &msg)
static bool try_send_light_info(APIConnection *api, void *v_light)
void press()
Press this button.
Definition: button.cpp:9
bool send_select_state(select::Select *select, std::string state)
std::vector< std::string > get_options() const
bool send_list_entities_light_response(const ListEntitiesLightResponse &msg)
std::string preset_mode
Definition: fan.h:118
DateCall & set_date(uint16_t year, uint8_t month, uint8_t day)
Definition: date_entity.cpp:97
enums::EntityCategory entity_category
Definition: api_pb2.h:441
ESP32Camera * global_esp32_camera
optional< ClimatePreset > preset
The active preset of the climate device.
Definition: climate.h:208
enums::FanDirection direction
Definition: api_pb2.h:541
const UpdateInfo & update_info
Definition: update_entity.h:39
std::vector< std::string > effects
Definition: api_pb2.h:569
time_t timestamp
unix epoch time (seconds since UTC Midnight January 1, 1970)
Definition: time.h:37
bool send_text_sensor_state_response(const TextSensorStateResponse &msg)
virtual bool has_state() const
Return whether this binary sensor has outputted a state.
static bool try_send_media_player_state(APIConnection *api, void *v_media_player)
uint8_t custom_preset
Definition: climate.h:579
void send_light_info(light::LightState *light)
static bool try_send_lock_info(APIConnection *api, void *v_a_lock)
void send_time_info(datetime::TimeEntity *time)
std::vector< uint8_t > proto_write_buffer_
static bool try_send_cover_info(APIConnection *api, void *v_cover)
bool send_list_entities_cover_response(const ListEntitiesCoverResponse &msg)
Base-class for all numbers.
Definition: number.h:39
bool send_time_state(datetime::TimeEntity *time)
Brightness of white channel can be controlled separately from other channels.
int speed
The current fan speed level.
Definition: fan.h:114
static bool try_send_text_sensor_info(APIConnection *api, void *v_text_sensor)
bool send_list_entities_camera_response(const ListEntitiesCameraResponse &msg)
ClimateCall & set_preset(ClimatePreset preset)
Set the preset of the climate device.
Definition: climate.cpp:199
bool has_state() const
Return whether this text input has gotten a full state yet.
Definition: text.h:32
static bool try_send_update_state(APIConnection *api, void *v_update)
std::vector< std::string > supported_custom_fan_modes
Definition: api_pb2.h:1010
BedjetMode mode
BedJet operating mode.
Definition: bedjet_codec.h:183
enums::LockCommand command
Definition: api_pb2.h:1231
bool send_list_entities_button_response(const ListEntitiesButtonResponse &msg)
bool has_state() const
Return whether this Datetime has gotten a full state yet.
Definition: datetime_base.h:17
void on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &msg) override
static bool try_send_time_state(APIConnection *api, void *v_time)
ClimateCall & set_fan_mode(ClimateFanMode fan_mode)
Set the fan mode of the climate device.
Definition: climate.cpp:157
const float COVER_OPEN
Definition: cover.cpp:9
bool send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg)
void bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) override
ClimateTraits get_traits()
Get the traits of this climate device with all overrides applied.
Definition: climate.cpp:440
void turn_on()
Turn this switch on.
Definition: switch.cpp:11
static bool try_send_fan_info(APIConnection *api, void *v_fan)
SelectCall make_call()
Instantiate a SelectCall object to modify this select component&#39;s state.
Definition: select.h:42
std::string get_unit_of_measurement()
Get the unit of measurement, using the manual override if set.
Definition: entity_base.cpp:87
bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor, bool state)
void bluetooth_device_request(const BluetoothDeviceRequest &msg) override
enums::AlarmControlPanelStateCommand command
Definition: api_pb2.h:1942
bool state
The current reported state of the binary sensor.
Definition: binary_sensor.h:61
FanCall & set_oscillating(bool oscillating)
Definition: fan.h:50
static bool try_send_valve_info(APIConnection *api, void *v_valve)
Application App
Global storage of Application pointer - only one Application can exist.
void bluetooth_gatt_write(const api::BluetoothGATTWriteRequest &msg)
StateClass get_state_class()
Get the state class, using the manual override if set.
Definition: sensor.cpp:33
bool send_update_state(update::UpdateEntity *update)
void send_media_player_info(media_player::MediaPlayer *media_player)
std::vector< std::string > active_wake_words
Definition: api_pb2.h:1882
enums::EntityCategory entity_category
Definition: api_pb2.h:1104
const std::vector< LightEffect * > & get_effects() const
Get all effects for this light state.
ColorMode get_color_mode() const
Get the color mode of these light color values.
LightCall & set_state(optional< bool > state)
Set the binary ON/OFF state of the light.
Definition: light_call.cpp:552
void on_disconnect_response(const DisconnectResponse &value) override
light::LightState * get_light_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:318
static bool try_send_switch_state(APIConnection *api, void *v_a_switch)
void on_get_time_response(const GetTimeResponse &value) override
bool get_assumed_state() const
Definition: lock.h:44
void button_command(const ButtonCommandRequest &msg) override
void bluetooth_gatt_write_descriptor(const api::BluetoothGATTWriteDescriptorRequest &msg)
Master brightness of the light can be controlled.
void bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) override
const std::string & get_name() const
Get the name of this Application set by pre_setup().
Definition: application.h:202
bool send_list_entities_number_response(const ListEntitiesNumberResponse &msg)
bool send_switch_state_response(const SwitchStateResponse &msg)
enums::EntityCategory entity_category
Definition: api_pb2.h:2147
bool send_cover_state(cover::Cover *cover)
bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override
LightCall & set_warm_white(optional< float > warm_white)
Set the warm white value of the light from 0.0 to 1.0.
Definition: light_call.cpp:648
VoiceAssistantConfigurationResponse voice_assistant_get_configuration(const VoiceAssistantConfigurationRequest &msg) override
void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) override
switch_::Switch * get_switch_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:258
bool send_list_entities_lock_response(const ListEntitiesLockResponse &msg)
ClimateCall & set_target_humidity(float target_humidity)
Set the target humidity of the climate device.
Definition: climate.cpp:268
void unsubscribe_api_connection(api::APIConnection *api_connection)
static bool try_send_lock_state(APIConnection *api, void *v_a_lock)
ClimateFanMode fan_mode
Definition: climate.h:573
bool send_date_time_state_response(const DateTimeStateResponse &msg)
bool send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) override
void send_camera_info(esp32_camera::ESP32Camera *camera)
esphome::binary_sensor::BinarySensor * binary_sensor
Definition: statsd.h:41
NumberTraits traits
Definition: number.h:49
void bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) override
std::string client_info
Definition: api_pb2.h:244
enums::MediaPlayerFormatPurpose purpose
Definition: api_pb2.h:1280
void unsubscribe_bluetooth_le_advertisements(const UnsubscribeBluetoothLEAdvertisementsRequest &msg) override
void bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) override
bool send_list_entities_sensor_response(const ListEntitiesSensorResponse &msg)
std::vector< enums::ClimateFanMode > supported_fan_modes
Definition: api_pb2.h:1008
static bool try_send_date_info(APIConnection *api, void *v_date)
void on_audio(const api::VoiceAssistantAudio &msg)
static bool try_send_fan_state(APIConnection *api, void *v_fan)
optional< std::string > custom_preset
The active custom preset mode of the climate device.
Definition: climate.h:211
LightCall & set_effect(optional< std::string > effect)
Set the effect of the light by its name.
Definition: light_call.cpp:656
bool send_list_entities_alarm_control_panel_response(const ListEntitiesAlarmControlPanelResponse &msg)
ClimateCall & set_target_temperature_high(float target_temperature_high)
Set the high point target temperature of the climate device.
Definition: climate.cpp:264
esp32_camera::CameraImageReader image_reader_
void bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg)
void set_image(std::shared_ptr< CameraImage > image)
static bool try_send_valve_state(APIConnection *api, void *v_valve)
bool send_select_state_response(const SelectStateResponse &msg)
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition: climate.h:199
float position
The position of the cover from 0.0 (fully closed) to 1.0 (fully open).
Definition: cover.h:122
void on_timer_event(const api::VoiceAssistantTimerEventResponse &msg)
static bool try_send_event_info(APIConnection *api, void *v_event)
void switch_command(const SwitchCommandRequest &msg) override
ConnectResponse connect(const ConnectRequest &msg) override
MediaPlayerCall & set_announcement(bool announce)
static bool try_send_binary_sensor_info(APIConnection *api, void *v_binary_sensor)
EntityCategory get_entity_category() const
Definition: entity_base.cpp:39
datetime::DateEntity * get_date_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:348
NumberCall make_call()
Definition: number.h:45
FanCall & set_state(bool binary_state)
Definition: fan.h:41
void select_command(const SelectCommandRequest &msg) override
bool send_light_state_response(const LightStateResponse &msg)
ESPTime state_as_esptime() const override
std::string size_t len
Definition: helpers.h:301
FanCall & set_preset_mode(const std::string &preset_mode)
Definition: fan.h:75
void open()
Open (unlatch) this lock.
Definition: lock.cpp:40
DeviceInfoResponse device_info(const DeviceInfoRequest &msg) override
bool send_list_entities_date_time_response(const ListEntitiesDateTimeResponse &msg)
bool send_date_state(datetime::DateEntity *date)
static bool try_send_sensor_info(APIConnection *api, void *v_sensor)
void send_text_sensor_info(text_sensor::TextSensor *text_sensor)
enums::EntityCategory entity_category
Definition: api_pb2.h:2244
bool send_media_player_state_response(const MediaPlayerStateResponse &msg)
text::Text * get_text_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:378
bool send_subscribe_home_assistant_state_response(const SubscribeHomeAssistantStateResponse &msg)
ClimateCall & set_mode(ClimateMode mode)
Set the mode of the climate device.
Definition: climate.cpp:133
const std::vector< HomeAssistantStateSubscription > & get_state_subs() const
Definition: api_server.cpp:375
void send_date_info(datetime::DateEntity *date)
std::string state
Definition: select.h:33
number::Number * get_number_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:338
enums::EntityCategory entity_category
Definition: api_pb2.h:500
static bool try_send_camera_info(APIConnection *api, void *v_camera)
bool send_list_entities_switch_response(const ListEntitiesSwitchResponse &msg)
static bool try_send_text_sensor_state(APIConnection *api, void *v_text_sensor)
enums::UpdateCommand command
Definition: api_pb2.h:2281
FanCall make_call()
Definition: fan.cpp:114
void send_select_info(select::Select *select)
LightCall & set_flash_length(optional< uint32_t > flash_length)
Start and set the flash length of this call in milliseconds.
Definition: light_call.cpp:568
static bool try_send_alarm_control_panel_info(APIConnection *api, void *v_a_alarm_control_panel)
bool send_list_entities_date_response(const ListEntitiesDateResponse &msg)
void send_datetime_info(datetime::DateTimeEntity *datetime)
bool get_requires_code() const
Definition: lock.h:42
static bool try_send_binary_sensor_state(APIConnection *api, void *v_binary_sensor)
LightCall & set_green(optional< float > green)
Set the green RGB value of the light from 0.0 to 1.0.
Definition: light_call.cpp:608
static bool try_send_media_player_info(APIConnection *api, void *v_media_player)
void send_number_info(number::Number *number)
bool uses_password() const
Definition: api_server.cpp:148
Base-class for all selects.
Definition: select.h:31
bool send_light_state(light::LightState *light)
std::vector< enums::ColorMode > supported_color_modes
Definition: api_pb2.h:562
void set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function< void()> func)
Definition: scheduler.cpp:22
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void on_unauthenticated_access() override
bool has_state() const
Return whether this sensor has gotten a full state (that passed through all filters) yet...
Definition: sensor.cpp:97
void bluetooth_gatt_read_descriptor(const api::BluetoothGATTReadDescriptorRequest &msg)
void text_command(const TextCommandRequest &msg) override
bool has_state() const
Return whether this select component has gotten a full state yet.
Definition: select.h:39
void lock_command(const LockCommandRequest &msg) override
std::vector< BluetoothServiceData > manufacturer_data
Definition: api_pb2.h:1380
void unlock()
Turn this lock off.
Definition: lock.cpp:35
Base class for all valve devices.
Definition: valve.h:105
bool send_media_player_state(media_player::MediaPlayer *media_player)
bool send_sensor_state_response(const SensorStateResponse &msg)
bool send_cover_state_response(const CoverStateResponse &msg)
ValveOperation current_operation
The current operation of the valve (idle, opening, closing).
Definition: valve.h:110
bool send_list_entities_text_response(const ListEntitiesTextResponse &msg)
Base class for all binary_sensor-type classes.
Definition: binary_sensor.h:37
Color can be controlled using RGB format (includes a brightness control for the color).
void set_camera_state(std::shared_ptr< esp32_camera::CameraImage > image)
LightColorValues remote_values
The remote color values reported to the frontend.
Definition: light_state.h:106
DeferredMessage(void *source, send_message_t *send_message)
static bool try_send_date_state(APIConnection *api, void *v_date)
bool send_list_entities_update_response(const ListEntitiesUpdateResponse &msg)
LockState
Enum for all states a lock can be in.
Definition: lock.h:26
void light_command(const LightCommandRequest &msg) override
bool send_list_entities_time_response(const ListEntitiesTimeResponse &msg)
NumberMode get_mode() const
Definition: number_traits.h:29
valve::Valve * get_valve_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:408
bool send_alarm_control_panel_state_response(const AlarmControlPanelStateResponse &msg)
bool send_list_entities_climate_response(const ListEntitiesClimateResponse &msg)
int8_t get_accuracy_decimals()
Get the accuracy in decimals, using the manual override if set.
Definition: sensor.cpp:25
void on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &msg) override
LightCall & set_white(optional< float > white)
Set the white value value of the light from 0.0 to 1.0 for RGBW[W] lights.
Definition: light_call.cpp:624
LightCall & set_brightness(optional< float > brightness)
Set the target brightness of the light from 0.0 (fully off) to 1.0 (fully on)
Definition: light_call.cpp:576
bool send_datetime_state(datetime::DateTimeEntity *datetime)
update::UpdateEntity * get_update_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:453
void number_command(const NumberCommandRequest &msg) override
ListEntitiesIterator list_entities_iterator_
void subscribe_api_connection(api::APIConnection *api_connection, uint32_t flags)
int get_min_length() const
Definition: text_traits.h:19
static bool try_send_update_info(APIConnection *api, void *v_update)
enums::LegacyCoverCommand legacy_command
Definition: api_pb2.h:473
Base-class for all sensors.
Definition: sensor.h:57
std::string get_mac_address_pretty()
Get the device MAC address as a string, in colon-separated uppercase hex notation.
Definition: helpers.cpp:733
datetime::TimeEntity * get_time_by_key(uint32_t key, bool include_internal=false)
Definition: application.h:358
bool send_lock_state_response(const LockStateResponse &msg)
void on_home_assistant_state_response(const HomeAssistantStateResponse &msg) override
virtual uint32_t get_supported_features() const =0
A numeric representation of the supported features as per HomeAssistant.
LightCall & set_blue(optional< float > blue)
Set the blue RGB value of the light from 0.0 to 1.0.
Definition: light_call.cpp:616
std::vector< enums::ClimateSwingMode > supported_swing_modes
Definition: api_pb2.h:1009
void on_announce(const api::VoiceAssistantAnnounceRequest &msg)
void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) override
DateTimeCall & set_datetime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
void send_event(event::Event *event, std::string event_type)
enums::SensorStateClass state_class
Definition: api_pb2.h:658
HelloResponse hello(const HelloRequest &msg) override
bool send_valve_state_response(const ValveStateResponse &msg)
std::string get_compilation_time() const
Definition: application.h:215
ValveCall & set_position(float position)
Set the call to a certain target position.
Definition: valve.cpp:67
static bool try_send_select_state(APIConnection *api, void *v_select)
bool send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &msg)
enums::EntityCategory entity_category
Definition: api_pb2.h:572
bool send_time_state_response(const TimeStateResponse &msg)
enums::EntityCategory entity_category
Definition: api_pb2.h:1015
std::vector< uint8_t > container
enums::MediaPlayerCommand command
Definition: api_pb2.h:1331
MediaPlayerCall & set_media_url(const std::string &url)
bool is_disabled_by_default() const
Definition: entity_base.cpp:26
void climate_command(const ClimateCommandRequest &msg) override
bool send_number_state(number::Number *number, float state)
APIConnection(std::unique_ptr< socket::Socket > socket, APIServer *parent)
bool state
The current reported state of the binary sensor.
Definition: switch.h:53
ProtoWriteBuffer create_buffer() override
uint8_t custom_fan_mode
Definition: climate.h:574
bool get_supports_open() const
Definition: lock.h:40
uint32_t get_object_id_hash()
Definition: entity_base.cpp:76
esphome::sensor::Sensor * sensor
Definition: statsd.h:38
std::string get_pattern() const
Definition: text_traits.h:25
float target_temperature_low
The minimum target temperature of the climate device, for climate devices with split target temperatu...
Definition: climate.h:189
SelectCall & set_option(const std::string &option)
Definition: select_call.cpp:10
void cover_command(const CoverCommandRequest &msg) override
void bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg)
std::vector< enums::ClimateMode > supported_modes
Definition: api_pb2.h:1002
const StringRef & get_name() const
Definition: entity_base.cpp:10
std::vector< DeferredMessage > deferred_queue_
void bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) override
void send_cover_info(cover::Cover *cover)
void camera_image(const CameraImageRequest &msg) override
FanCall & set_direction(FanDirection direction)
Definition: fan.h:66
void send_sensor_info(sensor::Sensor *sensor)
ClimatePreset preset
Definition: climate.h:578
void valve_command(const ValveCommandRequest &msg) override
void voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) override
MediaPlayerCall & set_volume(float volume)
Base class for all locks.
Definition: lock.h:103
ClimateAction action
The active state of the climate device.
Definition: climate.h:176
ClimateDevice - This is the base class for all climate integrations.
Definition: climate.h:168
void on_event(const api::VoiceAssistantEventResponse &msg)
void turn_off()
Turn this switch off.
Definition: switch.cpp:15
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26
virtual bool get_requires_code_to_arm() const =0
Returns if the alarm_control_panel requires a code to arm.
static bool try_send_text_info(APIConnection *api, void *v_text)
void fan_command(const FanCommandRequest &msg) override
enums::EntityCategory entity_category
Definition: api_pb2.h:2063
bool send_update_state_response(const UpdateStateResponse &msg)