16#ifdef USE_HOMEASSISTANT_TIME
19#ifdef USE_BLUETOOTH_PROXY
22#ifdef USE_VOICE_ASSISTANT
29static const char *
const TAG =
"api.connection";
30static const int ESP32_CAMERA_STOP_STREAM = 5000;
34 DeferredMessage item(source, send_message);
36 auto iter = std::find_if(this->
deferred_queue_.begin(), this->deferred_queue_.end(),
37 [&item](
const DeferredMessage &test) ->
bool { return test == item; });
63 : parent_(parent), deferred_message_queue_(this), initial_state_iterator_(this), list_entities_iterator_(this) {
66#if defined(USE_API_PLAINTEXT) && defined(USE_API_NOISE)
68 if (noise_ctx->has_psk()) {
69 this->helper_ = std::unique_ptr<APIFrameHelper>{new APINoiseFrameHelper(std::move(sock), noise_ctx)};
73#elif defined(USE_API_PLAINTEXT)
74 this->helper_ = std::unique_ptr<APIFrameHelper>{
new APIPlaintextFrameHelper(std::move(sock))};
75#elif defined(USE_API_NOISE)
76 this->helper_ = std::unique_ptr<APIFrameHelper>{
new APINoiseFrameHelper(std::move(sock), parent->get_noise_ctx())};
78#error "No frame helper defined"
81void APIConnection::start() {
86 this->next_ping_retry_ = this->last_traffic_ + KEEPALIVE_TIMEOUT_MS;
88 APIError err = this->helper_->init();
89 if (err != APIError::OK) {
91 ESP_LOGW(TAG,
"%s: Helper init failed: %s errno=%d", this->client_combined_info_.c_str(),
api_error_to_str(err),
95 this->client_info_ = helper_->getpeername();
96 this->client_peername_ = this->client_info_;
97 this->helper_->set_log_info(this->client_info_);
100APIConnection::~APIConnection() {
101#ifdef USE_BLUETOOTH_PROXY
106#ifdef USE_VOICE_ASSISTANT
113void APIConnection::loop() {
120 this->on_fatal_error();
121 ESP_LOGW(TAG,
"%s: Network unavailable, disconnecting", this->client_combined_info_.c_str());
124 if (this->next_close_) {
126 this->helper_->close();
127 this->remove_ =
true;
131 APIError err = this->helper_->loop();
132 if (err != APIError::OK) {
134 ESP_LOGW(TAG,
"%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
139 err = this->helper_->read_packet(&buffer);
140 if (err == APIError::WOULD_BLOCK) {
142 }
else if (err != APIError::OK) {
144 if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) {
145 ESP_LOGW(TAG,
"%s: Connection reset", this->client_combined_info_.c_str());
146 }
else if (err == APIError::CONNECTION_CLOSED) {
147 ESP_LOGW(TAG,
"%s: Connection closed", this->client_combined_info_.c_str());
149 ESP_LOGW(TAG,
"%s: Reading failed: %s errno=%d", this->client_combined_info_.c_str(),
api_error_to_str(err),
161 if (!this->deferred_message_queue_.empty() && this->helper_->can_write_without_blocking()) {
162 this->deferred_message_queue_.process_queue();
165 if (!this->list_entities_iterator_.completed())
166 this->list_entities_iterator_.advance();
167 if (!this->initial_state_iterator_.completed() && this->list_entities_iterator_.completed())
168 this->initial_state_iterator_.advance();
170 static uint8_t max_ping_retries = 60;
171 static uint16_t ping_retry_interval = 1000;
173 if (this->sent_ping_) {
175 if (now - this->last_traffic_ > (KEEPALIVE_TIMEOUT_MS * 5) / 2) {
177 ESP_LOGW(TAG,
"%s didn't respond to ping request in time. Disconnecting...", this->client_combined_info_.c_str());
179 }
else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && now > this->next_ping_retry_) {
180 ESP_LOGVV(TAG,
"Sending keepalive PING...");
181 this->sent_ping_ = this->send_ping_request(
PingRequest());
182 if (!this->sent_ping_) {
183 this->next_ping_retry_ = now + ping_retry_interval;
184 this->ping_retries_++;
185 if (this->ping_retries_ >= max_ping_retries) {
187 ESP_LOGE(TAG,
"%s: Sending keepalive failed %d time(s). Disconnecting...", this->client_combined_info_.c_str(),
188 this->ping_retries_);
189 }
else if (this->ping_retries_ >= 10) {
190 ESP_LOGW(TAG,
"%s: Sending keepalive failed %d time(s), will retry in %d ms",
191 this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
193 ESP_LOGD(TAG,
"%s: Sending keepalive failed %d time(s), will retry in %d ms",
194 this->client_combined_info_.c_str(), this->ping_retries_, ping_retry_interval);
199#ifdef USE_ESP32_CAMERA
200 if (this->image_reader_.available() && this->helper_->can_write_without_blocking()) {
212 uint32_t to_send = std::min((
size_t) 1390, this->image_reader_.available());
213 bool done = this->image_reader_.available() == to_send;
214 uint32_t msg_size = 0;
215 ProtoSize::add_fixed_field<4>(msg_size, 1,
true);
218 msg_size += 1 + ProtoSize::varint(to_send) + to_send;
219 ProtoSize::add_bool_field(msg_size, 1, done);
221 auto buffer = this->create_buffer(msg_size);
225 buffer.encode_bytes(2, this->image_reader_.peek_data_buffer(), to_send);
227 buffer.encode_bool(3, done);
229 bool success = this->send_buffer(buffer, 44);
232 this->image_reader_.consume_data(to_send);
234 if (success && done) {
235 this->image_reader_.return_image();
240 if (state_subs_at_ != -1) {
241 const auto &subs = this->parent_->get_state_subs();
242 if (state_subs_at_ >= (
int) subs.size()) {
245 auto &it = subs[state_subs_at_];
250 if (this->send_subscribe_home_assistant_state_response(resp)) {
265 ESP_LOGD(TAG,
"%s requested disconnected", this->client_combined_info_.c_str());
266 this->next_close_ =
true;
274#ifdef USE_BINARY_SENSOR
276 return this->send_state_with_value_(binary_sensor, &APIConnection::try_send_binary_sensor_state_,
277 &APIConnection::try_send_binary_sensor_state_,
state);
280 this->send_info_(
static_cast<EntityBase *
>(binary_sensor),
281 reinterpret_cast<send_message_t>(&APIConnection::try_send_binary_sensor_info_));
284 return this->try_send_binary_sensor_state_(binary_sensor, binary_sensor->
state);
291 return this->send_binary_sensor_state_response(msg);
298 return this->try_send_entity_info_(
static_cast<EntityBase *
>(binary_sensor), msg,
299 &APIConnection::send_list_entities_binary_sensor_response);
305 return this->send_state_(
static_cast<EntityBase *
>(cover),
306 reinterpret_cast<send_message_t>(&APIConnection::try_send_cover_state_));
309 this->send_info_(
static_cast<EntityBase *
>(cover),
310 reinterpret_cast<send_message_t>(&APIConnection::try_send_cover_info_));
318 if (traits.get_supports_tilt())
322 return this->send_cover_state_response(msg);
333 return this->try_send_entity_info_(
static_cast<EntityBase *
>(cover), msg,
334 &APIConnection::send_list_entities_cover_response);
338 if (cover ==
nullptr)
344 case enums::LEGACY_COVER_COMMAND_OPEN:
345 call.set_command_open();
347 case enums::LEGACY_COVER_COMMAND_CLOSE:
348 call.set_command_close();
350 case enums::LEGACY_COVER_COMMAND_STOP:
351 call.set_command_stop();
367 return this->send_state_(
static_cast<EntityBase *
>(fan),
368 reinterpret_cast<send_message_t>(&APIConnection::try_send_fan_state_));
371 this->send_info_(
static_cast<EntityBase *
>(fan),
372 reinterpret_cast<send_message_t>(&APIConnection::try_send_fan_info_));
374bool APIConnection::try_send_fan_state_(
fan::Fan *fan) {
378 if (traits.supports_oscillation())
380 if (traits.supports_speed()) {
383 if (traits.supports_direction())
385 if (traits.supports_preset_modes())
388 return this->send_fan_state_response(msg);
390bool APIConnection::try_send_fan_info_(
fan::Fan *fan) {
397 for (
auto const &
preset : traits.supported_preset_modes())
400 return this->try_send_entity_info_(
static_cast<EntityBase *
>(fan), msg,
401 &APIConnection::send_list_entities_fan_response);
427 return this->send_state_(
static_cast<EntityBase *
>(light),
428 reinterpret_cast<send_message_t>(&APIConnection::try_send_light_state_));
431 this->send_info_(
static_cast<EntityBase *
>(light),
432 reinterpret_cast<send_message_t>(&APIConnection::try_send_light_info_));
439 resp.
state = values.is_on();
443 resp.
red = values.get_red();
444 resp.
green = values.get_green();
445 resp.
blue = values.get_blue();
446 resp.
white = values.get_white();
453 return this->send_light_state_response(resp);
458 for (
auto mode : traits.get_supported_color_modes())
472 msg.
effects.emplace_back(
"None");
474 msg.
effects.push_back(effect->get_name());
478 return this->try_send_entity_info_(
static_cast<EntityBase *
>(light), msg,
479 &APIConnection::send_list_entities_light_response);
483 if (light ==
nullptr)
496 call.set_red(msg.
red);
497 call.set_green(msg.
green);
498 call.set_blue(msg.
blue);
520 return this->send_state_with_value_(sensor, &APIConnection::try_send_sensor_state_,
521 &APIConnection::try_send_sensor_state_,
state);
524 this->send_info_(
static_cast<EntityBase *
>(sensor),
525 reinterpret_cast<send_message_t>(&APIConnection::try_send_sensor_info_));
528 return this->try_send_sensor_state_(sensor, sensor->
state);
536 return this->send_sensor_state_response(resp);
548 return this->try_send_entity_info_(
static_cast<EntityBase *
>(sensor), msg,
549 &APIConnection::send_list_entities_sensor_response);
555 return this->send_state_with_value_(a_switch, &APIConnection::try_send_switch_state_,
556 &APIConnection::try_send_switch_state_,
state);
559 this->send_info_(
static_cast<EntityBase *
>(a_switch),
560 reinterpret_cast<send_message_t>(&APIConnection::try_send_switch_info_));
563 return this->try_send_switch_state_(a_switch, a_switch->
state);
570 return this->send_switch_state_response(resp);
577 return this->try_send_entity_info_(
static_cast<EntityBase *
>(a_switch), msg,
578 &APIConnection::send_list_entities_switch_response);
582 if (a_switch ==
nullptr)
593#ifdef USE_TEXT_SENSOR
595 return this->send_state_with_value_(text_sensor, &APIConnection::try_send_text_sensor_state_,
596 &APIConnection::try_send_text_sensor_state_, std::move(
state));
599 this->send_info_(
static_cast<EntityBase *
>(text_sensor),
600 reinterpret_cast<send_message_t>(&APIConnection::try_send_text_sensor_info_));
603 return this->try_send_text_sensor_state_(text_sensor, text_sensor->
state);
611 return this->send_text_sensor_state_response(resp);
619 return this->try_send_entity_info_(
static_cast<EntityBase *
>(text_sensor), msg,
620 &APIConnection::send_list_entities_text_sensor_response);
626 return this->send_state_(
static_cast<EntityBase *
>(climate),
627 reinterpret_cast<send_message_t>(&APIConnection::try_send_climate_state_));
630 this->send_info_(
static_cast<EntityBase *
>(climate),
631 reinterpret_cast<send_message_t>(&APIConnection::try_send_climate_info_));
639 if (traits.get_supports_current_temperature())
641 if (traits.get_supports_two_point_target_temperature()) {
656 if (traits.get_supports_swing_modes())
658 if (traits.get_supports_current_humidity())
660 if (traits.get_supports_target_humidity())
662 return this->send_climate_state_response(resp);
671 for (
auto mode : traits.get_supported_modes())
681 for (
auto fan_mode : traits.get_supported_fan_modes())
683 for (
auto const &
custom_fan_mode : traits.get_supported_custom_fan_modes())
685 for (
auto preset : traits.get_supported_presets())
687 for (
auto const &
custom_preset : traits.get_supported_custom_presets())
689 for (
auto swing_mode : traits.get_supported_swing_modes())
692 return this->try_send_entity_info_(
static_cast<EntityBase *
>(climate), msg,
693 &APIConnection::send_list_entities_climate_response);
697 if (climate ==
nullptr)
727 return this->send_state_with_value_(number, &APIConnection::try_send_number_state_,
728 &APIConnection::try_send_number_state_,
state);
731 this->send_info_(
static_cast<EntityBase *
>(number),
732 reinterpret_cast<send_message_t>(&APIConnection::try_send_number_info_));
735 return this->try_send_number_state_(number, number->
state);
743 return this->send_number_state_response(resp);
754 return this->try_send_entity_info_(
static_cast<EntityBase *
>(number), msg,
755 &APIConnection::send_list_entities_number_response);
759 if (number ==
nullptr)
768#ifdef USE_DATETIME_DATE
770 return this->send_state_(
static_cast<EntityBase *
>(date),
771 reinterpret_cast<send_message_t>(&APIConnection::try_send_date_state_));
774 this->send_info_(
static_cast<EntityBase *
>(date),
775 reinterpret_cast<send_message_t>(&APIConnection::try_send_date_info_));
785 return this->send_date_state_response(resp);
790 return this->try_send_entity_info_(
static_cast<EntityBase *
>(date), msg,
791 &APIConnection::send_list_entities_date_response);
804#ifdef USE_DATETIME_TIME
806 return this->send_state_(
static_cast<EntityBase *
>(time),
807 reinterpret_cast<send_message_t>(&APIConnection::try_send_time_state_));
810 this->send_info_(
static_cast<EntityBase *
>(time),
811 reinterpret_cast<send_message_t>(&APIConnection::try_send_time_info_));
821 return this->send_time_state_response(resp);
826 return this->try_send_entity_info_(
static_cast<EntityBase *
>(time), msg,
827 &APIConnection::send_list_entities_time_response);
840#ifdef USE_DATETIME_DATETIME
842 return this->send_state_(
static_cast<EntityBase *
>(datetime),
843 reinterpret_cast<send_message_t>(&APIConnection::try_send_datetime_state_));
846 this->send_info_(
static_cast<EntityBase *
>(datetime),
847 reinterpret_cast<send_message_t>(&APIConnection::try_send_datetime_info_));
858 return this->send_date_time_state_response(resp);
863 return this->try_send_entity_info_(
static_cast<EntityBase *
>(datetime), msg,
864 &APIConnection::send_list_entities_date_time_response);
868 if (datetime ==
nullptr)
879 return this->send_state_with_value_(text, &APIConnection::try_send_text_state_, &APIConnection::try_send_text_state_,
883 this->send_info_(
static_cast<EntityBase *
>(text),
884 reinterpret_cast<send_message_t>(&APIConnection::try_send_text_info_));
886bool APIConnection::try_send_text_state_(
text::Text *text) {
return this->try_send_text_state_(text, text->
state); }
893 return this->send_text_state_response(resp);
902 return this->try_send_entity_info_(
static_cast<EntityBase *
>(text), msg,
903 &APIConnection::send_list_entities_text_response);
918 return this->send_state_with_value_(select, &APIConnection::try_send_select_state_,
919 &APIConnection::try_send_select_state_, std::move(
state));
922 this->send_info_(
static_cast<EntityBase *
>(select),
923 reinterpret_cast<send_message_t>(&APIConnection::try_send_select_info_));
926 return this->try_send_select_state_(select, select->
state);
934 return this->send_select_state_response(resp);
941 return this->try_send_entity_info_(
static_cast<EntityBase *
>(select), msg,
942 &APIConnection::send_list_entities_select_response);
946 if (select ==
nullptr)
957 this->send_info_(
static_cast<EntityBase *
>(button),
958 reinterpret_cast<send_message_t>(&APIConnection::try_send_button_info_));
964 return this->try_send_entity_info_(
static_cast<EntityBase *
>(button), msg,
965 &APIConnection::send_list_entities_button_response);
969 if (button ==
nullptr)
978 return this->send_state_with_value_(a_lock, &APIConnection::try_send_lock_state_,
979 &APIConnection::try_send_lock_state_,
state);
982 this->send_info_(
static_cast<EntityBase *
>(a_lock),
983 reinterpret_cast<send_message_t>(&APIConnection::try_send_lock_info_));
985bool APIConnection::try_send_lock_state_(
lock::Lock *a_lock) {
986 return this->try_send_lock_state_(a_lock, a_lock->
state);
993 return this->send_lock_state_response(resp);
1001 return this->try_send_entity_info_(
static_cast<EntityBase *
>(a_lock), msg,
1002 &APIConnection::send_list_entities_lock_response);
1006 if (a_lock ==
nullptr)
1010 case enums::LOCK_UNLOCK:
1013 case enums::LOCK_LOCK:
1016 case enums::LOCK_OPEN:
1025 return this->send_state_(
static_cast<EntityBase *
>(valve),
1026 reinterpret_cast<send_message_t>(&APIConnection::try_send_valve_state_));
1029 this->send_info_(
static_cast<EntityBase *
>(valve),
1030 reinterpret_cast<send_message_t>(&APIConnection::try_send_valve_info_));
1038 return this->send_valve_state_response(resp);
1048 return this->try_send_entity_info_(
static_cast<EntityBase *
>(valve), msg,
1049 &APIConnection::send_list_entities_valve_response);
1053 if (valve ==
nullptr)
1065#ifdef USE_MEDIA_PLAYER
1067 return this->send_state_(
static_cast<EntityBase *
>(media_player),
1068 reinterpret_cast<send_message_t>(&APIConnection::try_send_media_player_state_));
1071 this->send_info_(
static_cast<EntityBase *
>(media_player),
1072 reinterpret_cast<send_message_t>(&APIConnection::try_send_media_player_info_));
1078 : media_player->
state;
1084 return this->send_media_player_state_response(resp);
1090 for (
auto &supported_format : traits.get_supported_formats()) {
1092 media_format.
format = supported_format.format;
1093 media_format.
sample_rate = supported_format.sample_rate;
1094 media_format.
num_channels = supported_format.num_channels;
1096 media_format.
sample_bytes = supported_format.sample_bytes;
1100 return this->try_send_entity_info_(
static_cast<EntityBase *
>(media_player), msg,
1101 &APIConnection::send_list_entities_media_player_response);
1105 if (media_player ==
nullptr)
1113 call.set_volume(msg.
volume);
1125#ifdef USE_ESP32_CAMERA
1126void APIConnection::set_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
1127 if (!this->state_subscription_)
1129 if (this->image_reader_.available())
1133 this->image_reader_.set_image(std::move(image));
1136 this->send_info_(
static_cast<EntityBase *
>(camera),
1137 reinterpret_cast<send_message_t>(&APIConnection::try_send_camera_info_));
1142 return this->try_send_entity_info_(
static_cast<EntityBase *
>(camera), msg,
1143 &APIConnection::send_list_entities_camera_response);
1161#ifdef USE_HOMEASSISTANT_TIME
1168#ifdef USE_BLUETOOTH_PROXY
1176 if (this->client_api_version_major_ < 1 || this->client_api_version_minor_ < 7) {
1179 service.legacy_data.assign(service.data.begin(), service.data.end());
1180 service.data.clear();
1183 manufacturer_data.legacy_data.assign(manufacturer_data.data.begin(), manufacturer_data.data.end());
1184 manufacturer_data.data.clear();
1186 return this->send_bluetooth_le_advertisement_response(resp);
1188 return this->send_bluetooth_le_advertisement_response(msg);
1223 msg.
mode == enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE);
1227#ifdef USE_VOICE_ASSISTANT
1243 if (msg.
port == 0) {
1249 this->helper_->getpeername((
struct sockaddr *) &storage, &
len);
1301 for (
auto &wake_word : config.available_wake_words) {
1303 resp_wake_word.
id = wake_word.id;
1304 resp_wake_word.
wake_word = wake_word.wake_word;
1305 for (
const auto &lang : wake_word.trained_languages) {
1310 for (
auto &wake_word_id : config.active_wake_words) {
1330#ifdef USE_ALARM_CONTROL_PANEL
1332 return this->send_state_(
static_cast<EntityBase *
>(a_alarm_control_panel),
1333 reinterpret_cast<send_message_t>(&APIConnection::try_send_alarm_control_panel_state_));
1336 this->send_info_(
static_cast<EntityBase *
>(a_alarm_control_panel),
1337 reinterpret_cast<send_message_t>(&APIConnection::try_send_alarm_control_panel_info_));
1344 return this->send_alarm_control_panel_state_response(resp);
1352 return this->try_send_entity_info_(
static_cast<EntityBase *
>(a_alarm_control_panel), msg,
1353 &APIConnection::send_list_entities_alarm_control_panel_response);
1357 if (a_alarm_control_panel ==
nullptr)
1360 auto call = a_alarm_control_panel->
make_call();
1362 case enums::ALARM_CONTROL_PANEL_DISARM:
1365 case enums::ALARM_CONTROL_PANEL_ARM_AWAY:
1368 case enums::ALARM_CONTROL_PANEL_ARM_HOME:
1371 case enums::ALARM_CONTROL_PANEL_ARM_NIGHT:
1374 case enums::ALARM_CONTROL_PANEL_ARM_VACATION:
1375 call.arm_vacation();
1377 case enums::ALARM_CONTROL_PANEL_ARM_CUSTOM_BYPASS:
1378 call.arm_custom_bypass();
1380 case enums::ALARM_CONTROL_PANEL_TRIGGER:
1390void APIConnection::send_event(
event::Event *event, std::string event_type) {
1391 this->send_state_with_value_(event, &APIConnection::try_send_event_, &APIConnection::try_send_event_,
1392 std::move(event_type));
1395 this->send_info_(
static_cast<EntityBase *
>(event),
1396 reinterpret_cast<send_message_t>(&APIConnection::try_send_event_info_));
1401bool APIConnection::try_send_event_(
event::Event *event, std::string event_type) {
1405 resp.
key =
event->get_object_id_hash();
1406 return this->send_event_response(resp);
1414 return this->try_send_entity_info_(
static_cast<EntityBase *
>(event), msg,
1415 &APIConnection::send_list_entities_event_response);
1421 return this->send_state_(
static_cast<EntityBase *
>(update),
1422 reinterpret_cast<send_message_t>(&APIConnection::try_send_update_state_));
1425 this->send_info_(
static_cast<EntityBase *
>(update),
1426 reinterpret_cast<send_message_t>(&APIConnection::try_send_update_info_));
1445 return this->send_update_state_response(resp);
1451 return this->try_send_entity_info_(
static_cast<EntityBase *
>(update), msg,
1452 &APIConnection::send_list_entities_update_response);
1456 if (update ==
nullptr)
1460 case enums::UPDATE_COMMAND_UPDATE:
1463 case enums::UPDATE_COMMAND_CHECK:
1466 case enums::UPDATE_COMMAND_NONE:
1467 ESP_LOGE(TAG,
"UPDATE_COMMAND_NONE not handled. Check client is sending the correct command");
1470 ESP_LOGW(TAG,
"Unknown update command: %" PRIu32, msg.
command);
1476bool APIConnection::try_send_log_message(
int level,
const char *tag,
const char *line) {
1477 if (this->log_subscription_ < level)
1481 const size_t line_length = strlen(line);
1482 uint32_t msg_size = 0;
1493 auto buffer = this->create_buffer(msg_size);
1496 buffer.encode_uint32(1,
static_cast<uint32_t
>(level));
1497 buffer.encode_string(3, line, line_length);
1500 return this->send_buffer(buffer, 29);
1505 this->client_peername_ = this->helper_->getpeername();
1506 this->client_combined_info_ = this->client_info_ +
" (" + this->client_peername_ +
")";
1507 this->helper_->set_log_info(this->client_combined_info_);
1510 ESP_LOGV(TAG,
"Hello from client: '%s' | %s | API Version %" PRIu32
".%" PRIu32, this->client_info_.c_str(),
1511 this->client_peername_.c_str(), this->client_api_version_major_, this->client_api_version_minor_);
1519 this->connection_state_ = ConnectionState::CONNECTED;
1523 bool correct = this->parent_->check_password(msg.
password);
1529 ESP_LOGD(TAG,
"%s: Connected successfully", this->client_combined_info_.c_str());
1530 this->connection_state_ = ConnectionState::AUTHENTICATED;
1531 this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_);
1532#ifdef USE_HOMEASSISTANT_TIME
1534 this->send_time_request();
1547 resp.esphome_version = ESPHOME_VERSION;
1549#if defined(USE_ESP8266) || defined(USE_ESP32)
1550 resp.manufacturer =
"Espressif";
1551#elif defined(USE_RP2040)
1552 resp.manufacturer =
"Raspberry Pi";
1553#elif defined(USE_BK72XX)
1554 resp.manufacturer =
"Beken";
1555#elif defined(USE_RTL87XX)
1556 resp.manufacturer =
"Realtek";
1557#elif defined(USE_HOST)
1558 resp.manufacturer =
"Host";
1560 resp.model = ESPHOME_BOARD;
1561#ifdef USE_DEEP_SLEEP
1564#ifdef ESPHOME_PROJECT_NAME
1565 resp.project_name = ESPHOME_PROJECT_NAME;
1566 resp.project_version = ESPHOME_PROJECT_VERSION;
1569 resp.webserver_port = USE_WEBSERVER_PORT;
1571#ifdef USE_BLUETOOTH_PROXY
1576#ifdef USE_VOICE_ASSISTANT
1581 resp.api_encryption_supported =
true;
1586 for (
auto &it : this->parent_->get_state_subs()) {
1588 it.callback(msg.
state);
1594 for (
auto *service : this->parent_->get_user_services()) {
1595 if (service->execute_service(msg)) {
1600 ESP_LOGV(TAG,
"Could not find matching service!");
1608 ESP_LOGW(TAG,
"Invalid encryption key length");
1613 if (!this->parent_->save_noise_psk(psk,
true)) {
1614 ESP_LOGW(TAG,
"Failed to save encryption key");
1626bool APIConnection::try_to_clear_buffer(
bool log_out_of_space) {
1629 if (this->helper_->can_write_without_blocking())
1632 APIError err = this->helper_->loop();
1633 if (err != APIError::OK) {
1635 ESP_LOGW(TAG,
"%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
1639 if (this->helper_->can_write_without_blocking())
1641 if (log_out_of_space) {
1642 ESP_LOGV(TAG,
"Cannot send message because of TCP buffer space");
1647 if (!this->try_to_clear_buffer(message_type != 29)) {
1651 APIError err = this->helper_->write_protobuf_packet(message_type, buffer);
1652 if (err == APIError::WOULD_BLOCK)
1654 if (err != APIError::OK) {
1656 if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
1657 ESP_LOGW(TAG,
"%s: Connection reset", this->client_combined_info_.c_str());
1659 ESP_LOGW(TAG,
"%s: Packet write failed %s errno=%d", this->client_combined_info_.c_str(),
api_error_to_str(err),
1667void APIConnection::on_unauthenticated_access() {
1668 this->on_fatal_error();
1669 ESP_LOGD(TAG,
"%s: tried to access without authentication.", this->client_combined_info_.c_str());
1671void APIConnection::on_no_setup_connection() {
1672 this->on_fatal_error();
1673 ESP_LOGD(TAG,
"%s: tried to access without full connection.", this->client_combined_info_.c_str());
1675void APIConnection::on_fatal_error() {
1676 this->helper_->close();
1677 this->remove_ =
true;
BedjetMode mode
BedJet operating mode.
datetime::DateEntity * get_date_by_key(uint32_t key, bool include_internal=false)
alarm_control_panel::AlarmControlPanel * get_alarm_control_panel_by_key(uint32_t key, bool include_internal=false)
const std::string & get_area() const
Get the area of this Application set by pre_setup().
const std::string & get_friendly_name() const
Get the friendly name of this Application set by pre_setup().
text::Text * get_text_by_key(uint32_t key, bool include_internal=false)
button::Button * get_button_by_key(uint32_t key, bool include_internal=false)
fan::Fan * get_fan_by_key(uint32_t key, bool include_internal=false)
std::string get_compilation_time() const
light::LightState * get_light_by_key(uint32_t key, bool include_internal=false)
media_player::MediaPlayer * get_media_player_by_key(uint32_t key, bool include_internal=false)
climate::Climate * get_climate_by_key(uint32_t key, bool include_internal=false)
const std::string & get_name() const
Get the name of this Application set by pre_setup().
lock::Lock * get_lock_by_key(uint32_t key, bool include_internal=false)
switch_::Switch * get_switch_by_key(uint32_t key, bool include_internal=false)
number::Number * get_number_by_key(uint32_t key, bool include_internal=false)
datetime::TimeEntity * get_time_by_key(uint32_t key, bool include_internal=false)
update::UpdateEntity * get_update_by_key(uint32_t key, bool include_internal=false)
datetime::DateTimeEntity * get_datetime_by_key(uint32_t key, bool include_internal=false)
valve::Valve * get_valve_by_key(uint32_t key, bool include_internal=false)
select::Select * get_select_by_key(uint32_t key, bool include_internal=false)
cover::Cover * get_cover_by_key(uint32_t key, bool include_internal=false)
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
std::string get_device_class()
Get the device class, using the manual override if set.
std::string get_unit_of_measurement()
Get the unit of measurement, using the manual override if set.
uint32_t get_object_id_hash()
std::string get_object_id() const
void set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function< void()> func)
AlarmControlPanelCall & set_code(const std::string &code)
virtual uint32_t get_supported_features() const =0
A numeric representation of the supported features as per HomeAssistant.
AlarmControlPanelState get_state() const
Get the state.
virtual bool get_requires_code_to_arm() const =0
Returns if the alarm_control_panel requires a code to arm.
virtual bool get_requires_code() const =0
Returns if the alarm_control_panel has a code.
AlarmControlPanelCall make_call()
Make a AlarmControlPanelCall.
bool try_send_button_info_(button::Button *button)
APIConnection(std::unique_ptr< socket::Socket > socket, APIServer *parent)
std::vector< uint8_t > proto_write_buffer_
void send_button_info(button::Button *button)
void button_command(const ButtonCommandRequest &msg) override
std::shared_ptr< APINoiseContext > get_noise_ctx()
enums::AlarmControlPanelStateCommand command
enums::AlarmControlPanelState state
std::vector< BluetoothServiceData > service_data
std::vector< BluetoothServiceData > manufacturer_data
enums::BluetoothScannerMode mode
bool has_target_temperature_high
float target_temperature_low
bool has_target_temperature_low
float target_temperature_high
enums::ClimateSwingMode swing_mode
enums::ClimateFanMode fan_mode
bool has_target_temperature
std::string custom_fan_mode
enums::ClimatePreset preset
std::string custom_preset
enums::ClimateFanMode fan_mode
float target_temperature_low
enums::ClimateSwingMode swing_mode
std::string custom_fan_mode
enums::ClimateAction action
enums::ClimatePreset preset
std::string custom_preset
float current_temperature
float target_temperature_high
enums::LegacyCoverCommand legacy_command
enums::LegacyCoverState legacy_state
enums::CoverOperation current_operation
std::vector< DeferredMessage > deferred_queue_
APIConnection * api_connection_
void dmq_push_back_with_dedup_(void *source, send_message_t send_message)
void defer(void *source, send_message_t send_message)
enums::FanDirection direction
enums::FanDirection direction
uint32_t api_version_major
uint32_t api_version_minor
uint32_t api_version_minor
uint32_t api_version_major
bool has_color_temperature
enums::ColorMode color_mode
bool has_transition_length
uint32_t transition_length
bool has_color_brightness
enums::ColorMode color_mode
bool requires_code_to_arm
uint32_t supported_features
bool is_status_binary_sensor
std::vector< enums::ClimatePreset > supported_presets
std::vector< enums::ClimateSwingMode > supported_swing_modes
float visual_max_humidity
std::vector< enums::ClimateFanMode > supported_fan_modes
bool supports_current_temperature
bool supports_current_humidity
std::vector< enums::ClimateMode > supported_modes
bool supports_target_humidity
float visual_min_humidity
float visual_max_temperature
float visual_target_temperature_step
bool supports_two_point_target_temperature
float visual_min_temperature
float visual_current_temperature_step
bool legacy_supports_away
std::vector< std::string > supported_custom_presets
std::vector< std::string > supported_custom_fan_modes
std::vector< std::string > event_types
std::vector< std::string > supported_preset_modes
int32_t supported_speed_count
bool supports_oscillation
bool legacy_supports_color_temperature
bool legacy_supports_white_value
bool legacy_supports_brightness
std::vector< std::string > effects
std::vector< enums::ColorMode > supported_color_modes
std::string unit_of_measurement
std::vector< std::string > options
int32_t accuracy_decimals
std::string unit_of_measurement
enums::SensorStateClass state_class
enums::LockCommand command
static uint32_t varint(uint32_t value)
ProtoSize class for Protocol Buffer serialization size calculation.
enums::UpdateCommand command
std::string latest_version
std::string current_version
std::string release_summary
enums::ValveOperation current_operation
std::vector< VoiceAssistantWakeWord > available_wake_words
uint32_t max_active_wake_words
std::vector< std::string > active_wake_words
std::vector< std::string > active_wake_words
std::vector< std::string > trained_languages
Base class for all binary_sensor-type classes.
virtual bool has_state() const
Return whether this binary sensor has outputted a state.
bool state
The current reported state of the binary sensor.
virtual bool is_status_binary_sensor() const
void bluetooth_gatt_read(const api::BluetoothGATTReadRequest &msg)
int get_bluetooth_connections_limit()
void bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg)
void bluetooth_device_request(const api::BluetoothDeviceRequest &msg)
void bluetooth_gatt_write_descriptor(const api::BluetoothGATTWriteDescriptorRequest &msg)
void bluetooth_scanner_set_mode(bool active)
void subscribe_api_connection(api::APIConnection *api_connection, uint32_t flags)
uint32_t get_legacy_version() const
uint32_t get_feature_flags() const
void unsubscribe_api_connection(api::APIConnection *api_connection)
int get_bluetooth_connections_free()
void bluetooth_gatt_read_descriptor(const api::BluetoothGATTReadDescriptorRequest &msg)
void bluetooth_gatt_write(const api::BluetoothGATTWriteRequest &msg)
void bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg)
std::string get_bluetooth_mac_address_pretty()
ClimateCall & set_target_temperature(float target_temperature)
Set the target temperature of the climate device.
ClimateCall & set_swing_mode(ClimateSwingMode swing_mode)
Set the swing mode of the climate device.
ClimateCall & set_target_temperature_low(float target_temperature_low)
Set the low point target temperature of the climate device.
ClimateCall & set_preset(ClimatePreset preset)
Set the preset of the climate device.
ClimateCall & set_fan_mode(ClimateFanMode fan_mode)
Set the fan mode of the climate device.
ClimateCall & set_target_humidity(float target_humidity)
Set the target humidity of the climate device.
ClimateCall & set_target_temperature_high(float target_temperature_high)
Set the high point target temperature of the climate device.
ClimateCall & set_mode(ClimateMode mode)
Set the mode of the climate device.
ClimateDevice - This is the base class for all climate integrations.
ClimateMode mode
The active mode of the climate device.
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
ClimateTraits get_traits()
Get the traits of this climate device with all overrides applied.
float target_temperature
The target temperature of the climate device.
float current_humidity
The current humidity of the climate device, as reported from the integration.
optional< std::string > custom_fan_mode
The active custom fan mode of the climate device.
ClimateSwingMode swing_mode
The active swing mode of the climate device.
float target_temperature_low
The minimum target temperature of the climate device, for climate devices with split target temperatu...
optional< std::string > custom_preset
The active custom preset mode of the climate device.
float current_temperature
The current temperature of the climate device, as reported from the integration.
ClimateAction action
The active state of the climate device.
ClimateCall make_call()
Make a climate device control call, this is used to control the climate device, see the ClimateCall d...
optional< ClimatePreset > preset
The active preset of the climate device.
float target_humidity
The target humidity of the climate device.
float target_temperature_high
The maximum target temperature of the climate device, for climate devices with split target temperatu...
void perform()
Perform the cover call.
CoverCall & set_position(float position)
Set the call to a certain target position.
CoverCall & set_command_stop()
Set the command to stop the cover.
CoverCall & set_tilt(float tilt)
Set the call to a certain target tilt.
Base class for all cover devices.
CoverOperation current_operation
The current operation of the cover (idle, opening, closing).
CoverCall make_call()
Construct a new cover call used to control the cover.
float tilt
The current tilt value of the cover from 0.0 to 1.0.
float position
The position of the cover from 0.0 (fully closed) to 1.0 (fully open).
virtual CoverTraits get_traits()=0
DateCall & set_date(uint16_t year, uint8_t month, uint8_t day)
bool has_state() const
Return whether this Datetime has gotten a full state yet.
DateTimeCall & set_datetime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
ESPTime state_as_esptime() const override
TimeCall & set_time(uint8_t hour, uint8_t minute, uint8_t second)
void request_image(CameraRequester requester)
void stop_stream(CameraRequester requester)
void start_stream(CameraRequester requester)
std::set< std::string > get_event_types() const
const std::string * last_event_type
FanCall & set_oscillating(bool oscillating)
FanCall & set_direction(FanDirection direction)
FanCall & set_state(bool binary_state)
FanCall & set_preset_mode(const std::string &preset_mode)
virtual FanTraits get_traits()=0
FanDirection direction
The current direction of the fan.
bool oscillating
The current oscillation state of the fan.
bool state
The current on/off state of the fan.
int speed
The current fan speed level.
void set_epoch_time(uint32_t epoch)
LightCall & set_color_temperature(optional< float > color_temperature)
Set the color temperature of the light in mireds for CWWW or RGBWW lights.
LightCall & set_color_brightness(optional< float > brightness)
Set the color brightness of the light from 0.0 (no color) to 1.0 (fully on)
LightCall & set_effect(optional< std::string > effect)
Set the effect of the light by its name.
LightCall & set_white(optional< float > white)
Set the white value value of the light from 0.0 to 1.0 for RGBW[W] lights.
LightCall & set_warm_white(optional< float > warm_white)
Set the warm white value of the light from 0.0 to 1.0.
LightCall & set_flash_length(optional< uint32_t > flash_length)
Start and set the flash length of this call in milliseconds.
LightCall & set_cold_white(optional< float > cold_white)
Set the cold white value of the light from 0.0 to 1.0.
LightCall & set_brightness(optional< float > brightness)
Set the target brightness of the light from 0.0 (fully off) to 1.0 (fully on)
LightCall & set_state(optional< bool > state)
Set the binary ON/OFF state of the light.
LightCall & set_color_mode(optional< ColorMode > color_mode)
Set the color mode of the light.
LightCall & set_transition_length(optional< uint32_t > transition_length)
Set the transition length of this call in milliseconds.
ColorMode get_color_mode() const
Get the color mode of these light color values.
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
const std::vector< LightEffect * > & get_effects() const
Get all effects for this light state.
LightColorValues remote_values
The remote color values reported to the frontend.
std::string get_effect_name()
Return the name of the current effect, or if no effect is active "None".
bool supports_effects()
Return whether the light has any effects that meet the trait requirements.
Base class for all locks.
void lock()
Turn this lock on.
LockState state
The current reported state of the lock.
void unlock()
Turn this lock off.
void open()
Open (unlatch) this lock.
bool get_requires_code() const
bool get_assumed_state() const
bool get_supports_open() const
NumberCall & set_value(float value)
Base-class for all numbers.
bool has_state() const
Return whether this number has gotten a full state yet.
float get_min_value() const
float get_max_value() const
NumberMode get_mode() const
value_type const & value() const
SelectCall & set_option(const std::string &option)
Base-class for all selects.
SelectCall make_call()
Instantiate a SelectCall object to modify this select component's state.
bool has_state() const
Return whether this select component has gotten a full state yet.
std::vector< std::string > get_options() const
Base-class for all sensors.
bool has_state() const
Return whether this sensor has gotten a full state (that passed through all filters) yet.
float state
This member variable stores the last state that has passed through all filters.
StateClass get_state_class()
Get the state class, using the manual override if set.
virtual std::string unique_id()
Override this method to set the unique ID of this sensor.
int8_t get_accuracy_decimals()
Get the accuracy in decimals, using the manual override if set.
bool get_force_update() const
Get whether force update mode is enabled.
Base class for all switches.
void turn_on()
Turn this switch on.
void turn_off()
Turn this switch off.
bool state
The current reported state of the binary sensor.
virtual bool assumed_state()
Return whether this switch uses an assumed state - i.e.
TextCall & set_value(const std::string &value)
Base-class for all text inputs.
TextCall make_call()
Instantiate a TextCall object to modify this text component's state.
bool has_state() const
Return whether this text input has gotten a full state yet.
TextMode get_mode() const
int get_max_length() const
std::string get_pattern() const
int get_min_length() const
virtual std::string unique_id()
Override this method to set the unique ID of this sensor.
const UpdateState & state
const UpdateInfo & update_info
ValveCall & set_position(float position)
Set the call to a certain target position.
ValveCall & set_command_stop()
Set the command to stop the valve.
void perform()
Perform the valve call.
Base class for all valve devices.
float position
The position of the valve from 0.0 (fully closed) to 1.0 (fully open).
ValveCall make_call()
Construct a new valve call used to control the valve.
ValveOperation current_operation
The current operation of the valve (idle, opening, closing).
virtual ValveTraits get_traits()=0
const Configuration & get_configuration()
uint32_t get_legacy_version() const
void on_timer_event(const api::VoiceAssistantTimerEventResponse &msg)
void on_audio(const api::VoiceAssistantAudio &msg)
void client_subscription(api::APIConnection *client, bool subscribe)
void on_event(const api::VoiceAssistantEventResponse &msg)
void on_announce(const api::VoiceAssistantAnnounceRequest &msg)
uint32_t get_feature_flags() const
void on_set_configuration(const std::vector< std::string > &active_wake_words)
ClimateSwingMode swing_mode
bool(APIConnection::*)(void *) send_message_t
std::string get_default_unique_id(const std::string &component_type, EntityBase *entity)
std::array< uint8_t, 32 > psk_t
const char * api_error_to_str(APIError err)
BluetoothProxy * global_bluetooth_proxy
ClimatePreset
Enum for all preset modes.
@ CLIMATE_PRESET_AWAY
Device is in away preset.
ClimateSwingMode
Enum for all modes a climate swing can be in.
ClimateMode
Enum for all modes a climate device can be in.
bool global_has_deep_sleep
ESP32Camera * global_esp32_camera
FanDirection
Simple enum to represent the direction of a fan.
HomeassistantTime * global_homeassistant_time
ColorMode
Color modes are a combination of color capabilities that can be used at the same time.
@ BRIGHTNESS
Master brightness of the light can be controlled.
@ RGB
Color can be controlled using RGB format (includes a brightness control for the color).
@ COLOR_TEMPERATURE
Color temperature can be controlled.
@ WHITE
Brightness of white channel can be controlled separately from other channels.
@ COLD_WARM_WHITE
Brightness of cold and warm white output can be controlled.
LockState
Enum for all states a lock can be in.
bool is_connected()
Return whether the node is connected to the network (through wifi, eth, ...)
@ UPDATE_STATE_INSTALLING
VoiceAssistant * global_voice_assistant
Providing packet encoding functions for exchanging data with a remote host.
std::string get_mac_address_pretty()
Get the device MAC address as a string, in colon-separated uppercase hex notation.
void IRAM_ATTR HOT delay(uint32_t ms)
Application App
Global storage of Application pointer - only one Application can exist.
size_t base64_decode(const std::string &encoded_string, uint8_t *buf, size_t buf_len)
A more user-friendly version of struct tm from time.h.
std::vector< uint8_t > container
std::string current_version
std::string latest_version