esphome 2025.5.0b3__py3-none-any.whl → 2025.5.0b4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,7 +30,7 @@ static const char *const TAG = "api.connection";
30
30
  static const int ESP32_CAMERA_STOP_STREAM = 5000;
31
31
 
32
32
  // helper for allowing only unique entries in the queue
33
- void DeferredMessageQueue::dmq_push_back_with_dedup_(void *source, send_message_t *send_message) {
33
+ void DeferredMessageQueue::dmq_push_back_with_dedup_(void *source, send_message_t send_message) {
34
34
  DeferredMessage item(source, send_message);
35
35
 
36
36
  auto iter = std::find_if(this->deferred_queue_.begin(), this->deferred_queue_.end(),
@@ -46,7 +46,7 @@ void DeferredMessageQueue::dmq_push_back_with_dedup_(void *source, send_message_
46
46
  void DeferredMessageQueue::process_queue() {
47
47
  while (!deferred_queue_.empty()) {
48
48
  DeferredMessage &de = deferred_queue_.front();
49
- if (de.send_message_(this->api_connection_, de.source_)) {
49
+ if ((this->api_connection_->*(de.send_message_))(de.source_)) {
50
50
  // O(n) but memory efficiency is more important than speed here which is why std::vector was chosen
51
51
  deferred_queue_.erase(deferred_queue_.begin());
52
52
  } else {
@@ -55,7 +55,7 @@ void DeferredMessageQueue::process_queue() {
55
55
  }
56
56
  }
57
57
 
58
- void DeferredMessageQueue::defer(void *source, send_message_t *send_message) {
58
+ void DeferredMessageQueue::defer(void *source, send_message_t send_message) {
59
59
  this->dmq_push_back_with_dedup_(source, send_message);
60
60
  }
61
61
 
@@ -79,7 +79,11 @@ APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *pa
79
79
  #endif
80
80
  }
81
81
  void APIConnection::start() {
82
- this->last_traffic_ = millis();
82
+ this->last_traffic_ = App.get_loop_component_start_time();
83
+
84
+ // Set next_ping_retry_ to prevent immediate ping
85
+ // This ensures the first ping happens after the keepalive period
86
+ this->next_ping_retry_ = this->last_traffic_ + KEEPALIVE_TIMEOUT_MS;
83
87
 
84
88
  APIError err = this->helper_->init();
85
89
  if (err != APIError::OK) {
@@ -154,24 +158,25 @@ void APIConnection::loop() {
154
158
  return;
155
159
  }
156
160
 
157
- this->deferred_message_queue_.process_queue();
161
+ if (!this->deferred_message_queue_.empty() && this->helper_->can_write_without_blocking()) {
162
+ this->deferred_message_queue_.process_queue();
163
+ }
158
164
 
159
165
  if (!this->list_entities_iterator_.completed())
160
166
  this->list_entities_iterator_.advance();
161
167
  if (!this->initial_state_iterator_.completed() && this->list_entities_iterator_.completed())
162
168
  this->initial_state_iterator_.advance();
163
169
 
164
- static uint32_t keepalive = 60000;
165
170
  static uint8_t max_ping_retries = 60;
166
171
  static uint16_t ping_retry_interval = 1000;
167
172
  const uint32_t now = App.get_loop_component_start_time();
168
173
  if (this->sent_ping_) {
169
174
  // Disconnect if not responded within 2.5*keepalive
170
- if (now - this->last_traffic_ > (keepalive * 5) / 2) {
175
+ if (now - this->last_traffic_ > (KEEPALIVE_TIMEOUT_MS * 5) / 2) {
171
176
  on_fatal_error();
172
177
  ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_combined_info_.c_str());
173
178
  }
174
- } else if (now - this->last_traffic_ > keepalive && now > this->next_ping_retry_) {
179
+ } else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && now > this->next_ping_retry_) {
175
180
  ESP_LOGVV(TAG, "Sending keepalive PING...");
176
181
  this->sent_ping_ = this->send_ping_request(PingRequest());
177
182
  if (!this->sent_ping_) {
@@ -268,96 +273,65 @@ void APIConnection::on_disconnect_response(const DisconnectResponse &value) {
268
273
 
269
274
  #ifdef USE_BINARY_SENSOR
270
275
  bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor, bool state) {
271
- if (!this->state_subscription_)
272
- return false;
273
-
274
- if (!APIConnection::try_send_binary_sensor_state(this, binary_sensor, state)) {
275
- this->deferred_message_queue_.defer(binary_sensor, try_send_binary_sensor_state);
276
- }
277
-
278
- return true;
276
+ return this->send_state_with_value_(binary_sensor, &APIConnection::try_send_binary_sensor_state_,
277
+ &APIConnection::try_send_binary_sensor_state_, state);
279
278
  }
280
279
  void APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor) {
281
- if (!APIConnection::try_send_binary_sensor_info(this, binary_sensor)) {
282
- this->deferred_message_queue_.defer(binary_sensor, try_send_binary_sensor_info);
283
- }
280
+ this->send_info_(static_cast<EntityBase *>(binary_sensor),
281
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_binary_sensor_info_));
284
282
  }
285
- bool APIConnection::try_send_binary_sensor_state(APIConnection *api, void *v_binary_sensor) {
286
- binary_sensor::BinarySensor *binary_sensor = reinterpret_cast<binary_sensor::BinarySensor *>(v_binary_sensor);
287
- return APIConnection::try_send_binary_sensor_state(api, binary_sensor, binary_sensor->state);
283
+ bool APIConnection::try_send_binary_sensor_state_(binary_sensor::BinarySensor *binary_sensor) {
284
+ return this->try_send_binary_sensor_state_(binary_sensor, binary_sensor->state);
288
285
  }
289
- bool APIConnection::try_send_binary_sensor_state(APIConnection *api, binary_sensor::BinarySensor *binary_sensor,
290
- bool state) {
291
- BinarySensorStateResponse resp;
292
- resp.key = binary_sensor->get_object_id_hash();
293
- resp.state = state;
294
- resp.missing_state = !binary_sensor->has_state();
295
- return api->send_binary_sensor_state_response(resp);
286
+ bool APIConnection::try_send_binary_sensor_state_(binary_sensor::BinarySensor *binary_sensor, bool state) {
287
+ BinarySensorStateResponse msg;
288
+ msg.state = state;
289
+ msg.missing_state = !binary_sensor->has_state();
290
+ msg.key = binary_sensor->get_object_id_hash();
291
+ return this->send_binary_sensor_state_response(msg);
296
292
  }
297
- bool APIConnection::try_send_binary_sensor_info(APIConnection *api, void *v_binary_sensor) {
298
- binary_sensor::BinarySensor *binary_sensor = reinterpret_cast<binary_sensor::BinarySensor *>(v_binary_sensor);
293
+ bool APIConnection::try_send_binary_sensor_info_(binary_sensor::BinarySensor *binary_sensor) {
299
294
  ListEntitiesBinarySensorResponse msg;
300
- msg.object_id = binary_sensor->get_object_id();
301
- msg.key = binary_sensor->get_object_id_hash();
302
- if (binary_sensor->has_own_name())
303
- msg.name = binary_sensor->get_name();
304
- msg.unique_id = get_default_unique_id("binary_sensor", binary_sensor);
305
295
  msg.device_class = binary_sensor->get_device_class();
306
296
  msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
307
- msg.disabled_by_default = binary_sensor->is_disabled_by_default();
308
- msg.icon = binary_sensor->get_icon();
309
- msg.entity_category = static_cast<enums::EntityCategory>(binary_sensor->get_entity_category());
310
- return api->send_list_entities_binary_sensor_response(msg);
297
+ msg.unique_id = get_default_unique_id("binary_sensor", binary_sensor);
298
+ return this->try_send_entity_info_(static_cast<EntityBase *>(binary_sensor), msg,
299
+ &APIConnection::send_list_entities_binary_sensor_response);
311
300
  }
312
301
  #endif
313
302
 
314
303
  #ifdef USE_COVER
315
304
  bool APIConnection::send_cover_state(cover::Cover *cover) {
316
- if (!this->state_subscription_)
317
- return false;
318
-
319
- if (!APIConnection::try_send_cover_state(this, cover)) {
320
- this->deferred_message_queue_.defer(cover, try_send_cover_state);
321
- }
322
-
323
- return true;
305
+ return this->send_state_(static_cast<EntityBase *>(cover),
306
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_cover_state_));
324
307
  }
325
308
  void APIConnection::send_cover_info(cover::Cover *cover) {
326
- if (!APIConnection::try_send_cover_info(this, cover)) {
327
- this->deferred_message_queue_.defer(cover, try_send_cover_info);
328
- }
309
+ this->send_info_(static_cast<EntityBase *>(cover),
310
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_cover_info_));
329
311
  }
330
- bool APIConnection::try_send_cover_state(APIConnection *api, void *v_cover) {
331
- cover::Cover *cover = reinterpret_cast<cover::Cover *>(v_cover);
312
+ bool APIConnection::try_send_cover_state_(cover::Cover *cover) {
313
+ CoverStateResponse msg;
332
314
  auto traits = cover->get_traits();
333
- CoverStateResponse resp{};
334
- resp.key = cover->get_object_id_hash();
335
- resp.legacy_state =
315
+ msg.legacy_state =
336
316
  (cover->position == cover::COVER_OPEN) ? enums::LEGACY_COVER_STATE_OPEN : enums::LEGACY_COVER_STATE_CLOSED;
337
- resp.position = cover->position;
317
+ msg.position = cover->position;
338
318
  if (traits.get_supports_tilt())
339
- resp.tilt = cover->tilt;
340
- resp.current_operation = static_cast<enums::CoverOperation>(cover->current_operation);
341
- return api->send_cover_state_response(resp);
319
+ msg.tilt = cover->tilt;
320
+ msg.current_operation = static_cast<enums::CoverOperation>(cover->current_operation);
321
+ msg.key = cover->get_object_id_hash();
322
+ return this->send_cover_state_response(msg);
342
323
  }
343
- bool APIConnection::try_send_cover_info(APIConnection *api, void *v_cover) {
344
- cover::Cover *cover = reinterpret_cast<cover::Cover *>(v_cover);
345
- auto traits = cover->get_traits();
324
+ bool APIConnection::try_send_cover_info_(cover::Cover *cover) {
346
325
  ListEntitiesCoverResponse msg;
347
- msg.key = cover->get_object_id_hash();
348
- msg.object_id = cover->get_object_id();
349
- if (cover->has_own_name())
350
- msg.name = cover->get_name();
351
- msg.unique_id = get_default_unique_id("cover", cover);
326
+ auto traits = cover->get_traits();
352
327
  msg.assumed_state = traits.get_is_assumed_state();
353
328
  msg.supports_position = traits.get_supports_position();
354
329
  msg.supports_tilt = traits.get_supports_tilt();
355
330
  msg.supports_stop = traits.get_supports_stop();
356
331
  msg.device_class = cover->get_device_class();
357
- msg.disabled_by_default = cover->is_disabled_by_default();
358
- msg.icon = cover->get_icon();
359
- msg.entity_category = static_cast<enums::EntityCategory>(cover->get_entity_category());
360
- return api->send_list_entities_cover_response(msg);
332
+ msg.unique_id = get_default_unique_id("cover", cover);
333
+ return this->try_send_entity_info_(static_cast<EntityBase *>(cover), msg,
334
+ &APIConnection::send_list_entities_cover_response);
361
335
  }
362
336
  void APIConnection::cover_command(const CoverCommandRequest &msg) {
363
337
  cover::Cover *cover = App.get_cover_by_key(msg.key);
@@ -390,56 +364,41 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) {
390
364
 
391
365
  #ifdef USE_FAN
392
366
  bool APIConnection::send_fan_state(fan::Fan *fan) {
393
- if (!this->state_subscription_)
394
- return false;
395
-
396
- if (!APIConnection::try_send_fan_state(this, fan)) {
397
- this->deferred_message_queue_.defer(fan, try_send_fan_state);
398
- }
399
-
400
- return true;
367
+ return this->send_state_(static_cast<EntityBase *>(fan),
368
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_fan_state_));
401
369
  }
402
370
  void APIConnection::send_fan_info(fan::Fan *fan) {
403
- if (!APIConnection::try_send_fan_info(this, fan)) {
404
- this->deferred_message_queue_.defer(fan, try_send_fan_info);
405
- }
371
+ this->send_info_(static_cast<EntityBase *>(fan),
372
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_fan_info_));
406
373
  }
407
- bool APIConnection::try_send_fan_state(APIConnection *api, void *v_fan) {
408
- fan::Fan *fan = reinterpret_cast<fan::Fan *>(v_fan);
374
+ bool APIConnection::try_send_fan_state_(fan::Fan *fan) {
375
+ FanStateResponse msg;
409
376
  auto traits = fan->get_traits();
410
- FanStateResponse resp{};
411
- resp.key = fan->get_object_id_hash();
412
- resp.state = fan->state;
377
+ msg.state = fan->state;
413
378
  if (traits.supports_oscillation())
414
- resp.oscillating = fan->oscillating;
379
+ msg.oscillating = fan->oscillating;
415
380
  if (traits.supports_speed()) {
416
- resp.speed_level = fan->speed;
381
+ msg.speed_level = fan->speed;
417
382
  }
418
383
  if (traits.supports_direction())
419
- resp.direction = static_cast<enums::FanDirection>(fan->direction);
384
+ msg.direction = static_cast<enums::FanDirection>(fan->direction);
420
385
  if (traits.supports_preset_modes())
421
- resp.preset_mode = fan->preset_mode;
422
- return api->send_fan_state_response(resp);
386
+ msg.preset_mode = fan->preset_mode;
387
+ msg.key = fan->get_object_id_hash();
388
+ return this->send_fan_state_response(msg);
423
389
  }
424
- bool APIConnection::try_send_fan_info(APIConnection *api, void *v_fan) {
425
- fan::Fan *fan = reinterpret_cast<fan::Fan *>(v_fan);
426
- auto traits = fan->get_traits();
390
+ bool APIConnection::try_send_fan_info_(fan::Fan *fan) {
427
391
  ListEntitiesFanResponse msg;
428
- msg.key = fan->get_object_id_hash();
429
- msg.object_id = fan->get_object_id();
430
- if (fan->has_own_name())
431
- msg.name = fan->get_name();
432
- msg.unique_id = get_default_unique_id("fan", fan);
392
+ auto traits = fan->get_traits();
433
393
  msg.supports_oscillation = traits.supports_oscillation();
434
394
  msg.supports_speed = traits.supports_speed();
435
395
  msg.supports_direction = traits.supports_direction();
436
396
  msg.supported_speed_count = traits.supported_speed_count();
437
397
  for (auto const &preset : traits.supported_preset_modes())
438
398
  msg.supported_preset_modes.push_back(preset);
439
- msg.disabled_by_default = fan->is_disabled_by_default();
440
- msg.icon = fan->get_icon();
441
- msg.entity_category = static_cast<enums::EntityCategory>(fan->get_entity_category());
442
- return api->send_list_entities_fan_response(msg);
399
+ msg.unique_id = get_default_unique_id("fan", fan);
400
+ return this->try_send_entity_info_(static_cast<EntityBase *>(fan), msg,
401
+ &APIConnection::send_list_entities_fan_response);
443
402
  }
444
403
  void APIConnection::fan_command(const FanCommandRequest &msg) {
445
404
  fan::Fan *fan = App.get_fan_by_key(msg.key);
@@ -465,28 +424,18 @@ void APIConnection::fan_command(const FanCommandRequest &msg) {
465
424
 
466
425
  #ifdef USE_LIGHT
467
426
  bool APIConnection::send_light_state(light::LightState *light) {
468
- if (!this->state_subscription_)
469
- return false;
470
-
471
- if (!APIConnection::try_send_light_state(this, light)) {
472
- this->deferred_message_queue_.defer(light, try_send_light_state);
473
- }
474
-
475
- return true;
427
+ return this->send_state_(static_cast<EntityBase *>(light),
428
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_light_state_));
476
429
  }
477
430
  void APIConnection::send_light_info(light::LightState *light) {
478
- if (!APIConnection::try_send_light_info(this, light)) {
479
- this->deferred_message_queue_.defer(light, try_send_light_info);
480
- }
431
+ this->send_info_(static_cast<EntityBase *>(light),
432
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_light_info_));
481
433
  }
482
- bool APIConnection::try_send_light_state(APIConnection *api, void *v_light) {
483
- light::LightState *light = reinterpret_cast<light::LightState *>(v_light);
434
+ bool APIConnection::try_send_light_state_(light::LightState *light) {
435
+ LightStateResponse resp;
484
436
  auto traits = light->get_traits();
485
437
  auto values = light->remote_values;
486
438
  auto color_mode = values.get_color_mode();
487
- LightStateResponse resp{};
488
-
489
- resp.key = light->get_object_id_hash();
490
439
  resp.state = values.is_on();
491
440
  resp.color_mode = static_cast<enums::ColorMode>(color_mode);
492
441
  resp.brightness = values.get_brightness();
@@ -500,25 +449,14 @@ bool APIConnection::try_send_light_state(APIConnection *api, void *v_light) {
500
449
  resp.warm_white = values.get_warm_white();
501
450
  if (light->supports_effects())
502
451
  resp.effect = light->get_effect_name();
503
- return api->send_light_state_response(resp);
452
+ resp.key = light->get_object_id_hash();
453
+ return this->send_light_state_response(resp);
504
454
  }
505
- bool APIConnection::try_send_light_info(APIConnection *api, void *v_light) {
506
- light::LightState *light = reinterpret_cast<light::LightState *>(v_light);
507
- auto traits = light->get_traits();
455
+ bool APIConnection::try_send_light_info_(light::LightState *light) {
508
456
  ListEntitiesLightResponse msg;
509
- msg.key = light->get_object_id_hash();
510
- msg.object_id = light->get_object_id();
511
- if (light->has_own_name())
512
- msg.name = light->get_name();
513
- msg.unique_id = get_default_unique_id("light", light);
514
-
515
- msg.disabled_by_default = light->is_disabled_by_default();
516
- msg.icon = light->get_icon();
517
- msg.entity_category = static_cast<enums::EntityCategory>(light->get_entity_category());
518
-
457
+ auto traits = light->get_traits();
519
458
  for (auto mode : traits.get_supported_color_modes())
520
459
  msg.supported_color_modes.push_back(static_cast<enums::ColorMode>(mode));
521
-
522
460
  msg.legacy_supports_brightness = traits.supports_color_capability(light::ColorCapability::BRIGHTNESS);
523
461
  msg.legacy_supports_rgb = traits.supports_color_capability(light::ColorCapability::RGB);
524
462
  msg.legacy_supports_white_value =
@@ -526,17 +464,19 @@ bool APIConnection::try_send_light_info(APIConnection *api, void *v_light) {
526
464
  traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE));
527
465
  msg.legacy_supports_color_temperature = traits.supports_color_capability(light::ColorCapability::COLOR_TEMPERATURE) ||
528
466
  traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE);
529
-
530
467
  if (msg.legacy_supports_color_temperature) {
531
468
  msg.min_mireds = traits.get_min_mireds();
532
469
  msg.max_mireds = traits.get_max_mireds();
533
470
  }
534
471
  if (light->supports_effects()) {
535
472
  msg.effects.emplace_back("None");
536
- for (auto *effect : light->get_effects())
473
+ for (auto *effect : light->get_effects()) {
537
474
  msg.effects.push_back(effect->get_name());
475
+ }
538
476
  }
539
- return api->send_list_entities_light_response(msg);
477
+ msg.unique_id = get_default_unique_id("light", light);
478
+ return this->try_send_entity_info_(static_cast<EntityBase *>(light), msg,
479
+ &APIConnection::send_list_entities_light_response);
540
480
  }
541
481
  void APIConnection::light_command(const LightCommandRequest &msg) {
542
482
  light::LightState *light = App.get_light_by_key(msg.key);
@@ -577,93 +517,65 @@ void APIConnection::light_command(const LightCommandRequest &msg) {
577
517
 
578
518
  #ifdef USE_SENSOR
579
519
  bool APIConnection::send_sensor_state(sensor::Sensor *sensor, float state) {
580
- if (!this->state_subscription_)
581
- return false;
582
-
583
- if (!APIConnection::try_send_sensor_state(this, sensor, state)) {
584
- this->deferred_message_queue_.defer(sensor, try_send_sensor_state);
585
- }
586
-
587
- return true;
520
+ return this->send_state_with_value_(sensor, &APIConnection::try_send_sensor_state_,
521
+ &APIConnection::try_send_sensor_state_, state);
588
522
  }
589
523
  void APIConnection::send_sensor_info(sensor::Sensor *sensor) {
590
- if (!APIConnection::try_send_sensor_info(this, sensor)) {
591
- this->deferred_message_queue_.defer(sensor, try_send_sensor_info);
592
- }
524
+ this->send_info_(static_cast<EntityBase *>(sensor),
525
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_sensor_info_));
593
526
  }
594
- bool APIConnection::try_send_sensor_state(APIConnection *api, void *v_sensor) {
595
- sensor::Sensor *sensor = reinterpret_cast<sensor::Sensor *>(v_sensor);
596
- return APIConnection::try_send_sensor_state(api, sensor, sensor->state);
527
+ bool APIConnection::try_send_sensor_state_(sensor::Sensor *sensor) {
528
+ return this->try_send_sensor_state_(sensor, sensor->state);
597
529
  }
598
- bool APIConnection::try_send_sensor_state(APIConnection *api, sensor::Sensor *sensor, float state) {
599
- SensorStateResponse resp{};
600
- resp.key = sensor->get_object_id_hash();
530
+ bool APIConnection::try_send_sensor_state_(sensor::Sensor *sensor, float state) {
531
+ SensorStateResponse resp;
601
532
  resp.state = state;
602
533
  resp.missing_state = !sensor->has_state();
603
- return api->send_sensor_state_response(resp);
534
+
535
+ resp.key = sensor->get_object_id_hash();
536
+ return this->send_sensor_state_response(resp);
604
537
  }
605
- bool APIConnection::try_send_sensor_info(APIConnection *api, void *v_sensor) {
606
- sensor::Sensor *sensor = reinterpret_cast<sensor::Sensor *>(v_sensor);
538
+ bool APIConnection::try_send_sensor_info_(sensor::Sensor *sensor) {
607
539
  ListEntitiesSensorResponse msg;
608
- msg.key = sensor->get_object_id_hash();
609
- msg.object_id = sensor->get_object_id();
610
- if (sensor->has_own_name())
611
- msg.name = sensor->get_name();
612
- msg.unique_id = sensor->unique_id();
613
- if (msg.unique_id.empty())
614
- msg.unique_id = get_default_unique_id("sensor", sensor);
615
- msg.icon = sensor->get_icon();
616
540
  msg.unit_of_measurement = sensor->get_unit_of_measurement();
617
541
  msg.accuracy_decimals = sensor->get_accuracy_decimals();
618
542
  msg.force_update = sensor->get_force_update();
619
543
  msg.device_class = sensor->get_device_class();
620
544
  msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class());
621
- msg.disabled_by_default = sensor->is_disabled_by_default();
622
- msg.entity_category = static_cast<enums::EntityCategory>(sensor->get_entity_category());
623
- return api->send_list_entities_sensor_response(msg);
545
+ msg.unique_id = sensor->unique_id();
546
+ if (msg.unique_id.empty())
547
+ msg.unique_id = get_default_unique_id("sensor", sensor);
548
+ return this->try_send_entity_info_(static_cast<EntityBase *>(sensor), msg,
549
+ &APIConnection::send_list_entities_sensor_response);
624
550
  }
625
551
  #endif
626
552
 
627
553
  #ifdef USE_SWITCH
628
554
  bool APIConnection::send_switch_state(switch_::Switch *a_switch, bool state) {
629
- if (!this->state_subscription_)
630
- return false;
631
-
632
- if (!APIConnection::try_send_switch_state(this, a_switch, state)) {
633
- this->deferred_message_queue_.defer(a_switch, try_send_switch_state);
634
- }
635
-
636
- return true;
555
+ return this->send_state_with_value_(a_switch, &APIConnection::try_send_switch_state_,
556
+ &APIConnection::try_send_switch_state_, state);
637
557
  }
638
558
  void APIConnection::send_switch_info(switch_::Switch *a_switch) {
639
- if (!APIConnection::try_send_switch_info(this, a_switch)) {
640
- this->deferred_message_queue_.defer(a_switch, try_send_switch_info);
641
- }
559
+ this->send_info_(static_cast<EntityBase *>(a_switch),
560
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_switch_info_));
642
561
  }
643
- bool APIConnection::try_send_switch_state(APIConnection *api, void *v_a_switch) {
644
- switch_::Switch *a_switch = reinterpret_cast<switch_::Switch *>(v_a_switch);
645
- return APIConnection::try_send_switch_state(api, a_switch, a_switch->state);
562
+ bool APIConnection::try_send_switch_state_(switch_::Switch *a_switch) {
563
+ return this->try_send_switch_state_(a_switch, a_switch->state);
646
564
  }
647
- bool APIConnection::try_send_switch_state(APIConnection *api, switch_::Switch *a_switch, bool state) {
648
- SwitchStateResponse resp{};
649
- resp.key = a_switch->get_object_id_hash();
565
+ bool APIConnection::try_send_switch_state_(switch_::Switch *a_switch, bool state) {
566
+ SwitchStateResponse resp;
650
567
  resp.state = state;
651
- return api->send_switch_state_response(resp);
568
+
569
+ resp.key = a_switch->get_object_id_hash();
570
+ return this->send_switch_state_response(resp);
652
571
  }
653
- bool APIConnection::try_send_switch_info(APIConnection *api, void *v_a_switch) {
654
- switch_::Switch *a_switch = reinterpret_cast<switch_::Switch *>(v_a_switch);
572
+ bool APIConnection::try_send_switch_info_(switch_::Switch *a_switch) {
655
573
  ListEntitiesSwitchResponse msg;
656
- msg.key = a_switch->get_object_id_hash();
657
- msg.object_id = a_switch->get_object_id();
658
- if (a_switch->has_own_name())
659
- msg.name = a_switch->get_name();
660
- msg.unique_id = get_default_unique_id("switch", a_switch);
661
- msg.icon = a_switch->get_icon();
662
574
  msg.assumed_state = a_switch->assumed_state();
663
- msg.disabled_by_default = a_switch->is_disabled_by_default();
664
- msg.entity_category = static_cast<enums::EntityCategory>(a_switch->get_entity_category());
665
575
  msg.device_class = a_switch->get_device_class();
666
- return api->send_list_entities_switch_response(msg);
576
+ msg.unique_id = get_default_unique_id("switch", a_switch);
577
+ return this->try_send_entity_info_(static_cast<EntityBase *>(a_switch), msg,
578
+ &APIConnection::send_list_entities_switch_response);
667
579
  }
668
580
  void APIConnection::switch_command(const SwitchCommandRequest &msg) {
669
581
  switch_::Switch *a_switch = App.get_switch_by_key(msg.key);
@@ -680,70 +592,48 @@ void APIConnection::switch_command(const SwitchCommandRequest &msg) {
680
592
 
681
593
  #ifdef USE_TEXT_SENSOR
682
594
  bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor, std::string state) {
683
- if (!this->state_subscription_)
684
- return false;
685
-
686
- if (!APIConnection::try_send_text_sensor_state(this, text_sensor, std::move(state))) {
687
- this->deferred_message_queue_.defer(text_sensor, try_send_text_sensor_state);
688
- }
689
-
690
- return true;
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));
691
597
  }
692
598
  void APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor) {
693
- if (!APIConnection::try_send_text_sensor_info(this, text_sensor)) {
694
- this->deferred_message_queue_.defer(text_sensor, try_send_text_sensor_info);
695
- }
599
+ this->send_info_(static_cast<EntityBase *>(text_sensor),
600
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_text_sensor_info_));
696
601
  }
697
- bool APIConnection::try_send_text_sensor_state(APIConnection *api, void *v_text_sensor) {
698
- text_sensor::TextSensor *text_sensor = reinterpret_cast<text_sensor::TextSensor *>(v_text_sensor);
699
- return APIConnection::try_send_text_sensor_state(api, text_sensor, text_sensor->state);
602
+ bool APIConnection::try_send_text_sensor_state_(text_sensor::TextSensor *text_sensor) {
603
+ return this->try_send_text_sensor_state_(text_sensor, text_sensor->state);
700
604
  }
701
- bool APIConnection::try_send_text_sensor_state(APIConnection *api, text_sensor::TextSensor *text_sensor,
702
- std::string state) {
703
- TextSensorStateResponse resp{};
704
- resp.key = text_sensor->get_object_id_hash();
605
+ bool APIConnection::try_send_text_sensor_state_(text_sensor::TextSensor *text_sensor, std::string state) {
606
+ TextSensorStateResponse resp;
705
607
  resp.state = std::move(state);
706
608
  resp.missing_state = !text_sensor->has_state();
707
- return api->send_text_sensor_state_response(resp);
609
+
610
+ resp.key = text_sensor->get_object_id_hash();
611
+ return this->send_text_sensor_state_response(resp);
708
612
  }
709
- bool APIConnection::try_send_text_sensor_info(APIConnection *api, void *v_text_sensor) {
710
- text_sensor::TextSensor *text_sensor = reinterpret_cast<text_sensor::TextSensor *>(v_text_sensor);
613
+ bool APIConnection::try_send_text_sensor_info_(text_sensor::TextSensor *text_sensor) {
711
614
  ListEntitiesTextSensorResponse msg;
712
- msg.key = text_sensor->get_object_id_hash();
713
- msg.object_id = text_sensor->get_object_id();
714
- msg.name = text_sensor->get_name();
615
+ msg.device_class = text_sensor->get_device_class();
715
616
  msg.unique_id = text_sensor->unique_id();
716
617
  if (msg.unique_id.empty())
717
618
  msg.unique_id = get_default_unique_id("text_sensor", text_sensor);
718
- msg.icon = text_sensor->get_icon();
719
- msg.disabled_by_default = text_sensor->is_disabled_by_default();
720
- msg.entity_category = static_cast<enums::EntityCategory>(text_sensor->get_entity_category());
721
- msg.device_class = text_sensor->get_device_class();
722
- return api->send_list_entities_text_sensor_response(msg);
619
+ return this->try_send_entity_info_(static_cast<EntityBase *>(text_sensor), msg,
620
+ &APIConnection::send_list_entities_text_sensor_response);
723
621
  }
724
622
  #endif
725
623
 
726
624
  #ifdef USE_CLIMATE
727
625
  bool APIConnection::send_climate_state(climate::Climate *climate) {
728
- if (!this->state_subscription_)
729
- return false;
730
-
731
- if (!APIConnection::try_send_climate_state(this, climate)) {
732
- this->deferred_message_queue_.defer(climate, try_send_climate_state);
733
- }
734
-
735
- return true;
626
+ return this->send_state_(static_cast<EntityBase *>(climate),
627
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_climate_state_));
736
628
  }
737
629
  void APIConnection::send_climate_info(climate::Climate *climate) {
738
- if (!APIConnection::try_send_climate_info(this, climate)) {
739
- this->deferred_message_queue_.defer(climate, try_send_climate_info);
740
- }
630
+ this->send_info_(static_cast<EntityBase *>(climate),
631
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_climate_info_));
741
632
  }
742
- bool APIConnection::try_send_climate_state(APIConnection *api, void *v_climate) {
743
- climate::Climate *climate = reinterpret_cast<climate::Climate *>(v_climate);
744
- auto traits = climate->get_traits();
745
- ClimateStateResponse resp{};
633
+ bool APIConnection::try_send_climate_state_(climate::Climate *climate) {
634
+ ClimateStateResponse resp;
746
635
  resp.key = climate->get_object_id_hash();
636
+ auto traits = climate->get_traits();
747
637
  resp.mode = static_cast<enums::ClimateMode>(climate->mode);
748
638
  resp.action = static_cast<enums::ClimateAction>(climate->action);
749
639
  if (traits.get_supports_current_temperature())
@@ -769,40 +659,25 @@ bool APIConnection::try_send_climate_state(APIConnection *api, void *v_climate)
769
659
  resp.current_humidity = climate->current_humidity;
770
660
  if (traits.get_supports_target_humidity())
771
661
  resp.target_humidity = climate->target_humidity;
772
- return api->send_climate_state_response(resp);
662
+ return this->send_climate_state_response(resp);
773
663
  }
774
- bool APIConnection::try_send_climate_info(APIConnection *api, void *v_climate) {
775
- climate::Climate *climate = reinterpret_cast<climate::Climate *>(v_climate);
776
- auto traits = climate->get_traits();
664
+ bool APIConnection::try_send_climate_info_(climate::Climate *climate) {
777
665
  ListEntitiesClimateResponse msg;
778
- msg.key = climate->get_object_id_hash();
779
- msg.object_id = climate->get_object_id();
780
- if (climate->has_own_name())
781
- msg.name = climate->get_name();
782
- msg.unique_id = get_default_unique_id("climate", climate);
783
-
784
- msg.disabled_by_default = climate->is_disabled_by_default();
785
- msg.icon = climate->get_icon();
786
- msg.entity_category = static_cast<enums::EntityCategory>(climate->get_entity_category());
787
-
666
+ auto traits = climate->get_traits();
788
667
  msg.supports_current_temperature = traits.get_supports_current_temperature();
789
668
  msg.supports_current_humidity = traits.get_supports_current_humidity();
790
669
  msg.supports_two_point_target_temperature = traits.get_supports_two_point_target_temperature();
791
670
  msg.supports_target_humidity = traits.get_supports_target_humidity();
792
-
793
671
  for (auto mode : traits.get_supported_modes())
794
672
  msg.supported_modes.push_back(static_cast<enums::ClimateMode>(mode));
795
-
796
673
  msg.visual_min_temperature = traits.get_visual_min_temperature();
797
674
  msg.visual_max_temperature = traits.get_visual_max_temperature();
798
675
  msg.visual_target_temperature_step = traits.get_visual_target_temperature_step();
799
676
  msg.visual_current_temperature_step = traits.get_visual_current_temperature_step();
800
677
  msg.visual_min_humidity = traits.get_visual_min_humidity();
801
678
  msg.visual_max_humidity = traits.get_visual_max_humidity();
802
-
803
679
  msg.legacy_supports_away = traits.supports_preset(climate::CLIMATE_PRESET_AWAY);
804
680
  msg.supports_action = traits.get_supports_action();
805
-
806
681
  for (auto fan_mode : traits.get_supported_fan_modes())
807
682
  msg.supported_fan_modes.push_back(static_cast<enums::ClimateFanMode>(fan_mode));
808
683
  for (auto const &custom_fan_mode : traits.get_supported_custom_fan_modes())
@@ -813,7 +688,9 @@ bool APIConnection::try_send_climate_info(APIConnection *api, void *v_climate) {
813
688
  msg.supported_custom_presets.push_back(custom_preset);
814
689
  for (auto swing_mode : traits.get_supported_swing_modes())
815
690
  msg.supported_swing_modes.push_back(static_cast<enums::ClimateSwingMode>(swing_mode));
816
- return api->send_list_entities_climate_response(msg);
691
+ msg.unique_id = get_default_unique_id("climate", climate);
692
+ return this->try_send_entity_info_(static_cast<EntityBase *>(climate), msg,
693
+ &APIConnection::send_list_entities_climate_response);
817
694
  }
818
695
  void APIConnection::climate_command(const ClimateCommandRequest &msg) {
819
696
  climate::Climate *climate = App.get_climate_by_key(msg.key);
@@ -847,51 +724,35 @@ void APIConnection::climate_command(const ClimateCommandRequest &msg) {
847
724
 
848
725
  #ifdef USE_NUMBER
849
726
  bool APIConnection::send_number_state(number::Number *number, float state) {
850
- if (!this->state_subscription_)
851
- return false;
852
-
853
- if (!APIConnection::try_send_number_state(this, number, state)) {
854
- this->deferred_message_queue_.defer(number, try_send_number_state);
855
- }
856
-
857
- return true;
727
+ return this->send_state_with_value_(number, &APIConnection::try_send_number_state_,
728
+ &APIConnection::try_send_number_state_, state);
858
729
  }
859
730
  void APIConnection::send_number_info(number::Number *number) {
860
- if (!APIConnection::try_send_number_info(this, number)) {
861
- this->deferred_message_queue_.defer(number, try_send_number_info);
862
- }
731
+ this->send_info_(static_cast<EntityBase *>(number),
732
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_number_info_));
863
733
  }
864
- bool APIConnection::try_send_number_state(APIConnection *api, void *v_number) {
865
- number::Number *number = reinterpret_cast<number::Number *>(v_number);
866
- return APIConnection::try_send_number_state(api, number, number->state);
734
+ bool APIConnection::try_send_number_state_(number::Number *number) {
735
+ return this->try_send_number_state_(number, number->state);
867
736
  }
868
- bool APIConnection::try_send_number_state(APIConnection *api, number::Number *number, float state) {
869
- NumberStateResponse resp{};
870
- resp.key = number->get_object_id_hash();
737
+ bool APIConnection::try_send_number_state_(number::Number *number, float state) {
738
+ NumberStateResponse resp;
871
739
  resp.state = state;
872
740
  resp.missing_state = !number->has_state();
873
- return api->send_number_state_response(resp);
741
+
742
+ resp.key = number->get_object_id_hash();
743
+ return this->send_number_state_response(resp);
874
744
  }
875
- bool APIConnection::try_send_number_info(APIConnection *api, void *v_number) {
876
- number::Number *number = reinterpret_cast<number::Number *>(v_number);
745
+ bool APIConnection::try_send_number_info_(number::Number *number) {
877
746
  ListEntitiesNumberResponse msg;
878
- msg.key = number->get_object_id_hash();
879
- msg.object_id = number->get_object_id();
880
- if (number->has_own_name())
881
- msg.name = number->get_name();
882
- msg.unique_id = get_default_unique_id("number", number);
883
- msg.icon = number->get_icon();
884
- msg.disabled_by_default = number->is_disabled_by_default();
885
- msg.entity_category = static_cast<enums::EntityCategory>(number->get_entity_category());
886
747
  msg.unit_of_measurement = number->traits.get_unit_of_measurement();
887
748
  msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode());
888
749
  msg.device_class = number->traits.get_device_class();
889
-
890
750
  msg.min_value = number->traits.get_min_value();
891
751
  msg.max_value = number->traits.get_max_value();
892
752
  msg.step = number->traits.get_step();
893
-
894
- return api->send_list_entities_number_response(msg);
753
+ msg.unique_id = get_default_unique_id("number", number);
754
+ return this->try_send_entity_info_(static_cast<EntityBase *>(number), msg,
755
+ &APIConnection::send_list_entities_number_response);
895
756
  }
896
757
  void APIConnection::number_command(const NumberCommandRequest &msg) {
897
758
  number::Number *number = App.get_number_by_key(msg.key);
@@ -906,43 +767,28 @@ void APIConnection::number_command(const NumberCommandRequest &msg) {
906
767
 
907
768
  #ifdef USE_DATETIME_DATE
908
769
  bool APIConnection::send_date_state(datetime::DateEntity *date) {
909
- if (!this->state_subscription_)
910
- return false;
911
-
912
- if (!APIConnection::try_send_date_state(this, date)) {
913
- this->deferred_message_queue_.defer(date, try_send_date_state);
914
- }
915
-
916
- return true;
770
+ return this->send_state_(static_cast<EntityBase *>(date),
771
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_date_state_));
917
772
  }
918
773
  void APIConnection::send_date_info(datetime::DateEntity *date) {
919
- if (!APIConnection::try_send_date_info(this, date)) {
920
- this->deferred_message_queue_.defer(date, try_send_date_info);
921
- }
774
+ this->send_info_(static_cast<EntityBase *>(date),
775
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_date_info_));
922
776
  }
923
- bool APIConnection::try_send_date_state(APIConnection *api, void *v_date) {
924
- datetime::DateEntity *date = reinterpret_cast<datetime::DateEntity *>(v_date);
925
- DateStateResponse resp{};
926
- resp.key = date->get_object_id_hash();
777
+ bool APIConnection::try_send_date_state_(datetime::DateEntity *date) {
778
+ DateStateResponse resp;
927
779
  resp.missing_state = !date->has_state();
928
780
  resp.year = date->year;
929
781
  resp.month = date->month;
930
782
  resp.day = date->day;
931
- return api->send_date_state_response(resp);
783
+
784
+ resp.key = date->get_object_id_hash();
785
+ return this->send_date_state_response(resp);
932
786
  }
933
- bool APIConnection::try_send_date_info(APIConnection *api, void *v_date) {
934
- datetime::DateEntity *date = reinterpret_cast<datetime::DateEntity *>(v_date);
787
+ bool APIConnection::try_send_date_info_(datetime::DateEntity *date) {
935
788
  ListEntitiesDateResponse msg;
936
- msg.key = date->get_object_id_hash();
937
- msg.object_id = date->get_object_id();
938
- if (date->has_own_name())
939
- msg.name = date->get_name();
940
789
  msg.unique_id = get_default_unique_id("date", date);
941
- msg.icon = date->get_icon();
942
- msg.disabled_by_default = date->is_disabled_by_default();
943
- msg.entity_category = static_cast<enums::EntityCategory>(date->get_entity_category());
944
-
945
- return api->send_list_entities_date_response(msg);
790
+ return this->try_send_entity_info_(static_cast<EntityBase *>(date), msg,
791
+ &APIConnection::send_list_entities_date_response);
946
792
  }
947
793
  void APIConnection::date_command(const DateCommandRequest &msg) {
948
794
  datetime::DateEntity *date = App.get_date_by_key(msg.key);
@@ -957,43 +803,28 @@ void APIConnection::date_command(const DateCommandRequest &msg) {
957
803
 
958
804
  #ifdef USE_DATETIME_TIME
959
805
  bool APIConnection::send_time_state(datetime::TimeEntity *time) {
960
- if (!this->state_subscription_)
961
- return false;
962
-
963
- if (!APIConnection::try_send_time_state(this, time)) {
964
- this->deferred_message_queue_.defer(time, try_send_time_state);
965
- }
966
-
967
- return true;
806
+ return this->send_state_(static_cast<EntityBase *>(time),
807
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_time_state_));
968
808
  }
969
809
  void APIConnection::send_time_info(datetime::TimeEntity *time) {
970
- if (!APIConnection::try_send_time_info(this, time)) {
971
- this->deferred_message_queue_.defer(time, try_send_time_info);
972
- }
810
+ this->send_info_(static_cast<EntityBase *>(time),
811
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_time_info_));
973
812
  }
974
- bool APIConnection::try_send_time_state(APIConnection *api, void *v_time) {
975
- datetime::TimeEntity *time = reinterpret_cast<datetime::TimeEntity *>(v_time);
976
- TimeStateResponse resp{};
977
- resp.key = time->get_object_id_hash();
813
+ bool APIConnection::try_send_time_state_(datetime::TimeEntity *time) {
814
+ TimeStateResponse resp;
978
815
  resp.missing_state = !time->has_state();
979
816
  resp.hour = time->hour;
980
817
  resp.minute = time->minute;
981
818
  resp.second = time->second;
982
- return api->send_time_state_response(resp);
819
+
820
+ resp.key = time->get_object_id_hash();
821
+ return this->send_time_state_response(resp);
983
822
  }
984
- bool APIConnection::try_send_time_info(APIConnection *api, void *v_time) {
985
- datetime::TimeEntity *time = reinterpret_cast<datetime::TimeEntity *>(v_time);
823
+ bool APIConnection::try_send_time_info_(datetime::TimeEntity *time) {
986
824
  ListEntitiesTimeResponse msg;
987
- msg.key = time->get_object_id_hash();
988
- msg.object_id = time->get_object_id();
989
- if (time->has_own_name())
990
- msg.name = time->get_name();
991
825
  msg.unique_id = get_default_unique_id("time", time);
992
- msg.icon = time->get_icon();
993
- msg.disabled_by_default = time->is_disabled_by_default();
994
- msg.entity_category = static_cast<enums::EntityCategory>(time->get_entity_category());
995
-
996
- return api->send_list_entities_time_response(msg);
826
+ return this->try_send_entity_info_(static_cast<EntityBase *>(time), msg,
827
+ &APIConnection::send_list_entities_time_response);
997
828
  }
998
829
  void APIConnection::time_command(const TimeCommandRequest &msg) {
999
830
  datetime::TimeEntity *time = App.get_time_by_key(msg.key);
@@ -1008,44 +839,29 @@ void APIConnection::time_command(const TimeCommandRequest &msg) {
1008
839
 
1009
840
  #ifdef USE_DATETIME_DATETIME
1010
841
  bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) {
1011
- if (!this->state_subscription_)
1012
- return false;
1013
-
1014
- if (!APIConnection::try_send_datetime_state(this, datetime)) {
1015
- this->deferred_message_queue_.defer(datetime, try_send_datetime_state);
1016
- }
1017
-
1018
- return true;
842
+ return this->send_state_(static_cast<EntityBase *>(datetime),
843
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_datetime_state_));
1019
844
  }
1020
845
  void APIConnection::send_datetime_info(datetime::DateTimeEntity *datetime) {
1021
- if (!APIConnection::try_send_datetime_info(this, datetime)) {
1022
- this->deferred_message_queue_.defer(datetime, try_send_datetime_info);
1023
- }
846
+ this->send_info_(static_cast<EntityBase *>(datetime),
847
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_datetime_info_));
1024
848
  }
1025
- bool APIConnection::try_send_datetime_state(APIConnection *api, void *v_datetime) {
1026
- datetime::DateTimeEntity *datetime = reinterpret_cast<datetime::DateTimeEntity *>(v_datetime);
1027
- DateTimeStateResponse resp{};
1028
- resp.key = datetime->get_object_id_hash();
849
+ bool APIConnection::try_send_datetime_state_(datetime::DateTimeEntity *datetime) {
850
+ DateTimeStateResponse resp;
1029
851
  resp.missing_state = !datetime->has_state();
1030
852
  if (datetime->has_state()) {
1031
853
  ESPTime state = datetime->state_as_esptime();
1032
854
  resp.epoch_seconds = state.timestamp;
1033
855
  }
1034
- return api->send_date_time_state_response(resp);
856
+
857
+ resp.key = datetime->get_object_id_hash();
858
+ return this->send_date_time_state_response(resp);
1035
859
  }
1036
- bool APIConnection::try_send_datetime_info(APIConnection *api, void *v_datetime) {
1037
- datetime::DateTimeEntity *datetime = reinterpret_cast<datetime::DateTimeEntity *>(v_datetime);
860
+ bool APIConnection::try_send_datetime_info_(datetime::DateTimeEntity *datetime) {
1038
861
  ListEntitiesDateTimeResponse msg;
1039
- msg.key = datetime->get_object_id_hash();
1040
- msg.object_id = datetime->get_object_id();
1041
- if (datetime->has_own_name())
1042
- msg.name = datetime->get_name();
1043
862
  msg.unique_id = get_default_unique_id("datetime", datetime);
1044
- msg.icon = datetime->get_icon();
1045
- msg.disabled_by_default = datetime->is_disabled_by_default();
1046
- msg.entity_category = static_cast<enums::EntityCategory>(datetime->get_entity_category());
1047
-
1048
- return api->send_list_entities_date_time_response(msg);
863
+ return this->try_send_entity_info_(static_cast<EntityBase *>(datetime), msg,
864
+ &APIConnection::send_list_entities_date_time_response);
1049
865
  }
1050
866
  void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
1051
867
  datetime::DateTimeEntity *datetime = App.get_datetime_by_key(msg.key);
@@ -1060,47 +876,31 @@ void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
1060
876
 
1061
877
  #ifdef USE_TEXT
1062
878
  bool APIConnection::send_text_state(text::Text *text, std::string state) {
1063
- if (!this->state_subscription_)
1064
- return false;
1065
-
1066
- if (!APIConnection::try_send_text_state(this, text, std::move(state))) {
1067
- this->deferred_message_queue_.defer(text, try_send_text_state);
1068
- }
1069
-
1070
- return true;
879
+ return this->send_state_with_value_(text, &APIConnection::try_send_text_state_, &APIConnection::try_send_text_state_,
880
+ std::move(state));
1071
881
  }
1072
882
  void APIConnection::send_text_info(text::Text *text) {
1073
- if (!APIConnection::try_send_text_info(this, text)) {
1074
- this->deferred_message_queue_.defer(text, try_send_text_info);
1075
- }
883
+ this->send_info_(static_cast<EntityBase *>(text),
884
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_text_info_));
1076
885
  }
1077
- bool APIConnection::try_send_text_state(APIConnection *api, void *v_text) {
1078
- text::Text *text = reinterpret_cast<text::Text *>(v_text);
1079
- return APIConnection::try_send_text_state(api, text, text->state);
1080
- }
1081
- bool APIConnection::try_send_text_state(APIConnection *api, text::Text *text, std::string state) {
1082
- TextStateResponse resp{};
1083
- resp.key = text->get_object_id_hash();
886
+ bool APIConnection::try_send_text_state_(text::Text *text) { return this->try_send_text_state_(text, text->state); }
887
+ bool APIConnection::try_send_text_state_(text::Text *text, std::string state) {
888
+ TextStateResponse resp;
1084
889
  resp.state = std::move(state);
1085
890
  resp.missing_state = !text->has_state();
1086
- return api->send_text_state_response(resp);
891
+
892
+ resp.key = text->get_object_id_hash();
893
+ return this->send_text_state_response(resp);
1087
894
  }
1088
- bool APIConnection::try_send_text_info(APIConnection *api, void *v_text) {
1089
- text::Text *text = reinterpret_cast<text::Text *>(v_text);
895
+ bool APIConnection::try_send_text_info_(text::Text *text) {
1090
896
  ListEntitiesTextResponse msg;
1091
- msg.key = text->get_object_id_hash();
1092
- msg.object_id = text->get_object_id();
1093
- msg.name = text->get_name();
1094
- msg.icon = text->get_icon();
1095
- msg.disabled_by_default = text->is_disabled_by_default();
1096
- msg.entity_category = static_cast<enums::EntityCategory>(text->get_entity_category());
1097
897
  msg.mode = static_cast<enums::TextMode>(text->traits.get_mode());
1098
-
1099
898
  msg.min_length = text->traits.get_min_length();
1100
899
  msg.max_length = text->traits.get_max_length();
1101
900
  msg.pattern = text->traits.get_pattern();
1102
-
1103
- return api->send_list_entities_text_response(msg);
901
+ msg.unique_id = get_default_unique_id("text", text);
902
+ return this->try_send_entity_info_(static_cast<EntityBase *>(text), msg,
903
+ &APIConnection::send_list_entities_text_response);
1104
904
  }
1105
905
  void APIConnection::text_command(const TextCommandRequest &msg) {
1106
906
  text::Text *text = App.get_text_by_key(msg.key);
@@ -1115,47 +915,31 @@ void APIConnection::text_command(const TextCommandRequest &msg) {
1115
915
 
1116
916
  #ifdef USE_SELECT
1117
917
  bool APIConnection::send_select_state(select::Select *select, std::string state) {
1118
- if (!this->state_subscription_)
1119
- return false;
1120
-
1121
- if (!APIConnection::try_send_select_state(this, select, std::move(state))) {
1122
- this->deferred_message_queue_.defer(select, try_send_select_state);
1123
- }
1124
-
1125
- return true;
918
+ return this->send_state_with_value_(select, &APIConnection::try_send_select_state_,
919
+ &APIConnection::try_send_select_state_, std::move(state));
1126
920
  }
1127
921
  void APIConnection::send_select_info(select::Select *select) {
1128
- if (!APIConnection::try_send_select_info(this, select)) {
1129
- this->deferred_message_queue_.defer(select, try_send_select_info);
1130
- }
922
+ this->send_info_(static_cast<EntityBase *>(select),
923
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_select_info_));
1131
924
  }
1132
- bool APIConnection::try_send_select_state(APIConnection *api, void *v_select) {
1133
- select::Select *select = reinterpret_cast<select::Select *>(v_select);
1134
- return APIConnection::try_send_select_state(api, select, select->state);
925
+ bool APIConnection::try_send_select_state_(select::Select *select) {
926
+ return this->try_send_select_state_(select, select->state);
1135
927
  }
1136
- bool APIConnection::try_send_select_state(APIConnection *api, select::Select *select, std::string state) {
1137
- SelectStateResponse resp{};
1138
- resp.key = select->get_object_id_hash();
928
+ bool APIConnection::try_send_select_state_(select::Select *select, std::string state) {
929
+ SelectStateResponse resp;
1139
930
  resp.state = std::move(state);
1140
931
  resp.missing_state = !select->has_state();
1141
- return api->send_select_state_response(resp);
932
+
933
+ resp.key = select->get_object_id_hash();
934
+ return this->send_select_state_response(resp);
1142
935
  }
1143
- bool APIConnection::try_send_select_info(APIConnection *api, void *v_select) {
1144
- select::Select *select = reinterpret_cast<select::Select *>(v_select);
936
+ bool APIConnection::try_send_select_info_(select::Select *select) {
1145
937
  ListEntitiesSelectResponse msg;
1146
- msg.key = select->get_object_id_hash();
1147
- msg.object_id = select->get_object_id();
1148
- if (select->has_own_name())
1149
- msg.name = select->get_name();
1150
- msg.unique_id = get_default_unique_id("select", select);
1151
- msg.icon = select->get_icon();
1152
- msg.disabled_by_default = select->is_disabled_by_default();
1153
- msg.entity_category = static_cast<enums::EntityCategory>(select->get_entity_category());
1154
-
1155
938
  for (const auto &option : select->traits.get_options())
1156
939
  msg.options.push_back(option);
1157
-
1158
- return api->send_list_entities_select_response(msg);
940
+ msg.unique_id = get_default_unique_id("select", select);
941
+ return this->try_send_entity_info_(static_cast<EntityBase *>(select), msg,
942
+ &APIConnection::send_list_entities_select_response);
1159
943
  }
1160
944
  void APIConnection::select_command(const SelectCommandRequest &msg) {
1161
945
  select::Select *select = App.get_select_by_key(msg.key);
@@ -1169,26 +953,18 @@ void APIConnection::select_command(const SelectCommandRequest &msg) {
1169
953
  #endif
1170
954
 
1171
955
  #ifdef USE_BUTTON
1172
- void APIConnection::send_button_info(button::Button *button) {
1173
- if (!APIConnection::try_send_button_info(this, button)) {
1174
- this->deferred_message_queue_.defer(button, try_send_button_info);
1175
- }
956
+ void esphome::api::APIConnection::send_button_info(button::Button *button) {
957
+ this->send_info_(static_cast<EntityBase *>(button),
958
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_button_info_));
1176
959
  }
1177
- bool APIConnection::try_send_button_info(APIConnection *api, void *v_button) {
1178
- button::Button *button = reinterpret_cast<button::Button *>(v_button);
960
+ bool esphome::api::APIConnection::try_send_button_info_(button::Button *button) {
1179
961
  ListEntitiesButtonResponse msg;
1180
- msg.key = button->get_object_id_hash();
1181
- msg.object_id = button->get_object_id();
1182
- if (button->has_own_name())
1183
- msg.name = button->get_name();
1184
- msg.unique_id = get_default_unique_id("button", button);
1185
- msg.icon = button->get_icon();
1186
- msg.disabled_by_default = button->is_disabled_by_default();
1187
- msg.entity_category = static_cast<enums::EntityCategory>(button->get_entity_category());
1188
962
  msg.device_class = button->get_device_class();
1189
- return api->send_list_entities_button_response(msg);
963
+ msg.unique_id = get_default_unique_id("button", button);
964
+ return this->try_send_entity_info_(static_cast<EntityBase *>(button), msg,
965
+ &APIConnection::send_list_entities_button_response);
1190
966
  }
1191
- void APIConnection::button_command(const ButtonCommandRequest &msg) {
967
+ void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg) {
1192
968
  button::Button *button = App.get_button_by_key(msg.key);
1193
969
  if (button == nullptr)
1194
970
  return;
@@ -1199,45 +975,31 @@ void APIConnection::button_command(const ButtonCommandRequest &msg) {
1199
975
 
1200
976
  #ifdef USE_LOCK
1201
977
  bool APIConnection::send_lock_state(lock::Lock *a_lock, lock::LockState state) {
1202
- if (!this->state_subscription_)
1203
- return false;
1204
-
1205
- if (!APIConnection::try_send_lock_state(this, a_lock, state)) {
1206
- this->deferred_message_queue_.defer(a_lock, try_send_lock_state);
1207
- }
1208
-
1209
- return true;
978
+ return this->send_state_with_value_(a_lock, &APIConnection::try_send_lock_state_,
979
+ &APIConnection::try_send_lock_state_, state);
1210
980
  }
1211
981
  void APIConnection::send_lock_info(lock::Lock *a_lock) {
1212
- if (!APIConnection::try_send_lock_info(this, a_lock)) {
1213
- this->deferred_message_queue_.defer(a_lock, try_send_lock_info);
1214
- }
982
+ this->send_info_(static_cast<EntityBase *>(a_lock),
983
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_lock_info_));
1215
984
  }
1216
- bool APIConnection::try_send_lock_state(APIConnection *api, void *v_a_lock) {
1217
- lock::Lock *a_lock = reinterpret_cast<lock::Lock *>(v_a_lock);
1218
- return APIConnection::try_send_lock_state(api, a_lock, a_lock->state);
985
+ bool APIConnection::try_send_lock_state_(lock::Lock *a_lock) {
986
+ return this->try_send_lock_state_(a_lock, a_lock->state);
1219
987
  }
1220
- bool APIConnection::try_send_lock_state(APIConnection *api, lock::Lock *a_lock, lock::LockState state) {
1221
- LockStateResponse resp{};
1222
- resp.key = a_lock->get_object_id_hash();
988
+ bool APIConnection::try_send_lock_state_(lock::Lock *a_lock, lock::LockState state) {
989
+ LockStateResponse resp;
1223
990
  resp.state = static_cast<enums::LockState>(state);
1224
- return api->send_lock_state_response(resp);
991
+
992
+ resp.key = a_lock->get_object_id_hash();
993
+ return this->send_lock_state_response(resp);
1225
994
  }
1226
- bool APIConnection::try_send_lock_info(APIConnection *api, void *v_a_lock) {
1227
- lock::Lock *a_lock = reinterpret_cast<lock::Lock *>(v_a_lock);
995
+ bool APIConnection::try_send_lock_info_(lock::Lock *a_lock) {
1228
996
  ListEntitiesLockResponse msg;
1229
- msg.key = a_lock->get_object_id_hash();
1230
- msg.object_id = a_lock->get_object_id();
1231
- if (a_lock->has_own_name())
1232
- msg.name = a_lock->get_name();
1233
- msg.unique_id = get_default_unique_id("lock", a_lock);
1234
- msg.icon = a_lock->get_icon();
1235
997
  msg.assumed_state = a_lock->traits.get_assumed_state();
1236
- msg.disabled_by_default = a_lock->is_disabled_by_default();
1237
- msg.entity_category = static_cast<enums::EntityCategory>(a_lock->get_entity_category());
1238
998
  msg.supports_open = a_lock->traits.get_supports_open();
1239
999
  msg.requires_code = a_lock->traits.get_requires_code();
1240
- return api->send_list_entities_lock_response(msg);
1000
+ msg.unique_id = get_default_unique_id("lock", a_lock);
1001
+ return this->try_send_entity_info_(static_cast<EntityBase *>(a_lock), msg,
1002
+ &APIConnection::send_list_entities_lock_response);
1241
1003
  }
1242
1004
  void APIConnection::lock_command(const LockCommandRequest &msg) {
1243
1005
  lock::Lock *a_lock = App.get_lock_by_key(msg.key);
@@ -1260,45 +1022,31 @@ void APIConnection::lock_command(const LockCommandRequest &msg) {
1260
1022
 
1261
1023
  #ifdef USE_VALVE
1262
1024
  bool APIConnection::send_valve_state(valve::Valve *valve) {
1263
- if (!this->state_subscription_)
1264
- return false;
1265
-
1266
- if (!APIConnection::try_send_valve_state(this, valve)) {
1267
- this->deferred_message_queue_.defer(valve, try_send_valve_state);
1268
- }
1269
-
1270
- return true;
1025
+ return this->send_state_(static_cast<EntityBase *>(valve),
1026
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_valve_state_));
1271
1027
  }
1272
1028
  void APIConnection::send_valve_info(valve::Valve *valve) {
1273
- if (!APIConnection::try_send_valve_info(this, valve)) {
1274
- this->deferred_message_queue_.defer(valve, try_send_valve_info);
1275
- }
1029
+ this->send_info_(static_cast<EntityBase *>(valve),
1030
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_valve_info_));
1276
1031
  }
1277
- bool APIConnection::try_send_valve_state(APIConnection *api, void *v_valve) {
1278
- valve::Valve *valve = reinterpret_cast<valve::Valve *>(v_valve);
1279
- ValveStateResponse resp{};
1280
- resp.key = valve->get_object_id_hash();
1032
+ bool APIConnection::try_send_valve_state_(valve::Valve *valve) {
1033
+ ValveStateResponse resp;
1281
1034
  resp.position = valve->position;
1282
1035
  resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation);
1283
- return api->send_valve_state_response(resp);
1036
+
1037
+ resp.key = valve->get_object_id_hash();
1038
+ return this->send_valve_state_response(resp);
1284
1039
  }
1285
- bool APIConnection::try_send_valve_info(APIConnection *api, void *v_valve) {
1286
- valve::Valve *valve = reinterpret_cast<valve::Valve *>(v_valve);
1287
- auto traits = valve->get_traits();
1040
+ bool APIConnection::try_send_valve_info_(valve::Valve *valve) {
1288
1041
  ListEntitiesValveResponse msg;
1289
- msg.key = valve->get_object_id_hash();
1290
- msg.object_id = valve->get_object_id();
1291
- if (valve->has_own_name())
1292
- msg.name = valve->get_name();
1293
- msg.unique_id = get_default_unique_id("valve", valve);
1294
- msg.icon = valve->get_icon();
1295
- msg.disabled_by_default = valve->is_disabled_by_default();
1296
- msg.entity_category = static_cast<enums::EntityCategory>(valve->get_entity_category());
1042
+ auto traits = valve->get_traits();
1297
1043
  msg.device_class = valve->get_device_class();
1298
1044
  msg.assumed_state = traits.get_is_assumed_state();
1299
1045
  msg.supports_position = traits.get_supports_position();
1300
1046
  msg.supports_stop = traits.get_supports_stop();
1301
- return api->send_list_entities_valve_response(msg);
1047
+ msg.unique_id = get_default_unique_id("valve", valve);
1048
+ return this->try_send_entity_info_(static_cast<EntityBase *>(valve), msg,
1049
+ &APIConnection::send_list_entities_valve_response);
1302
1050
  }
1303
1051
  void APIConnection::valve_command(const ValveCommandRequest &msg) {
1304
1052
  valve::Valve *valve = App.get_valve_by_key(msg.key);
@@ -1316,48 +1064,29 @@ void APIConnection::valve_command(const ValveCommandRequest &msg) {
1316
1064
 
1317
1065
  #ifdef USE_MEDIA_PLAYER
1318
1066
  bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_player) {
1319
- if (!this->state_subscription_)
1320
- return false;
1321
-
1322
- if (!APIConnection::try_send_media_player_state(this, media_player)) {
1323
- this->deferred_message_queue_.defer(media_player, try_send_media_player_state);
1324
- }
1325
-
1326
- return true;
1067
+ return this->send_state_(static_cast<EntityBase *>(media_player),
1068
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_media_player_state_));
1327
1069
  }
1328
1070
  void APIConnection::send_media_player_info(media_player::MediaPlayer *media_player) {
1329
- if (!APIConnection::try_send_media_player_info(this, media_player)) {
1330
- this->deferred_message_queue_.defer(media_player, try_send_media_player_info);
1331
- }
1071
+ this->send_info_(static_cast<EntityBase *>(media_player),
1072
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_media_player_info_));
1332
1073
  }
1333
- bool APIConnection::try_send_media_player_state(APIConnection *api, void *v_media_player) {
1334
- media_player::MediaPlayer *media_player = reinterpret_cast<media_player::MediaPlayer *>(v_media_player);
1335
- MediaPlayerStateResponse resp{};
1336
- resp.key = media_player->get_object_id_hash();
1337
-
1074
+ bool APIConnection::try_send_media_player_state_(media_player::MediaPlayer *media_player) {
1075
+ MediaPlayerStateResponse resp;
1338
1076
  media_player::MediaPlayerState report_state = media_player->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING
1339
1077
  ? media_player::MEDIA_PLAYER_STATE_PLAYING
1340
1078
  : media_player->state;
1341
1079
  resp.state = static_cast<enums::MediaPlayerState>(report_state);
1342
1080
  resp.volume = media_player->volume;
1343
1081
  resp.muted = media_player->is_muted();
1344
- return api->send_media_player_state_response(resp);
1082
+
1083
+ resp.key = media_player->get_object_id_hash();
1084
+ return this->send_media_player_state_response(resp);
1345
1085
  }
1346
- bool APIConnection::try_send_media_player_info(APIConnection *api, void *v_media_player) {
1347
- media_player::MediaPlayer *media_player = reinterpret_cast<media_player::MediaPlayer *>(v_media_player);
1086
+ bool APIConnection::try_send_media_player_info_(media_player::MediaPlayer *media_player) {
1348
1087
  ListEntitiesMediaPlayerResponse msg;
1349
- msg.key = media_player->get_object_id_hash();
1350
- msg.object_id = media_player->get_object_id();
1351
- if (media_player->has_own_name())
1352
- msg.name = media_player->get_name();
1353
- msg.unique_id = get_default_unique_id("media_player", media_player);
1354
- msg.icon = media_player->get_icon();
1355
- msg.disabled_by_default = media_player->is_disabled_by_default();
1356
- msg.entity_category = static_cast<enums::EntityCategory>(media_player->get_entity_category());
1357
-
1358
1088
  auto traits = media_player->get_traits();
1359
1089
  msg.supports_pause = traits.get_supports_pause();
1360
-
1361
1090
  for (auto &supported_format : traits.get_supported_formats()) {
1362
1091
  MediaPlayerSupportedFormat media_format;
1363
1092
  media_format.format = supported_format.format;
@@ -1367,8 +1096,9 @@ bool APIConnection::try_send_media_player_info(APIConnection *api, void *v_media
1367
1096
  media_format.sample_bytes = supported_format.sample_bytes;
1368
1097
  msg.supported_formats.push_back(media_format);
1369
1098
  }
1370
-
1371
- return api->send_list_entities_media_player_response(msg);
1099
+ msg.unique_id = get_default_unique_id("media_player", media_player);
1100
+ return this->try_send_entity_info_(static_cast<EntityBase *>(media_player), msg,
1101
+ &APIConnection::send_list_entities_media_player_response);
1372
1102
  }
1373
1103
  void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
1374
1104
  media_player::MediaPlayer *media_player = App.get_media_player_by_key(msg.key);
@@ -1403,22 +1133,14 @@ void APIConnection::set_camera_state(std::shared_ptr<esp32_camera::CameraImage>
1403
1133
  this->image_reader_.set_image(std::move(image));
1404
1134
  }
1405
1135
  void APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
1406
- if (!APIConnection::try_send_camera_info(this, camera)) {
1407
- this->deferred_message_queue_.defer(camera, try_send_camera_info);
1408
- }
1136
+ this->send_info_(static_cast<EntityBase *>(camera),
1137
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_camera_info_));
1409
1138
  }
1410
- bool APIConnection::try_send_camera_info(APIConnection *api, void *v_camera) {
1411
- esp32_camera::ESP32Camera *camera = reinterpret_cast<esp32_camera::ESP32Camera *>(v_camera);
1139
+ bool APIConnection::try_send_camera_info_(esp32_camera::ESP32Camera *camera) {
1412
1140
  ListEntitiesCameraResponse msg;
1413
- msg.key = camera->get_object_id_hash();
1414
- msg.object_id = camera->get_object_id();
1415
- if (camera->has_own_name())
1416
- msg.name = camera->get_name();
1417
1141
  msg.unique_id = get_default_unique_id("camera", camera);
1418
- msg.disabled_by_default = camera->is_disabled_by_default();
1419
- msg.icon = camera->get_icon();
1420
- msg.entity_category = static_cast<enums::EntityCategory>(camera->get_entity_category());
1421
- return api->send_list_entities_camera_response(msg);
1142
+ return this->try_send_entity_info_(static_cast<EntityBase *>(camera), msg,
1143
+ &APIConnection::send_list_entities_camera_response);
1422
1144
  }
1423
1145
  void APIConnection::camera_image(const CameraImageRequest &msg) {
1424
1146
  if (esp32_camera::global_esp32_camera == nullptr)
@@ -1607,43 +1329,28 @@ void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetCon
1607
1329
 
1608
1330
  #ifdef USE_ALARM_CONTROL_PANEL
1609
1331
  bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
1610
- if (!this->state_subscription_)
1611
- return false;
1612
-
1613
- if (!APIConnection::try_send_alarm_control_panel_state(this, a_alarm_control_panel)) {
1614
- this->deferred_message_queue_.defer(a_alarm_control_panel, try_send_alarm_control_panel_state);
1615
- }
1616
-
1617
- return true;
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_));
1618
1334
  }
1619
1335
  void APIConnection::send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
1620
- if (!APIConnection::try_send_alarm_control_panel_info(this, a_alarm_control_panel)) {
1621
- this->deferred_message_queue_.defer(a_alarm_control_panel, try_send_alarm_control_panel_info);
1622
- }
1336
+ this->send_info_(static_cast<EntityBase *>(a_alarm_control_panel),
1337
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_alarm_control_panel_info_));
1623
1338
  }
1624
- bool APIConnection::try_send_alarm_control_panel_state(APIConnection *api, void *v_a_alarm_control_panel) {
1625
- alarm_control_panel::AlarmControlPanel *a_alarm_control_panel =
1626
- reinterpret_cast<alarm_control_panel::AlarmControlPanel *>(v_a_alarm_control_panel);
1627
- AlarmControlPanelStateResponse resp{};
1628
- resp.key = a_alarm_control_panel->get_object_id_hash();
1339
+ bool APIConnection::try_send_alarm_control_panel_state_(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
1340
+ AlarmControlPanelStateResponse resp;
1629
1341
  resp.state = static_cast<enums::AlarmControlPanelState>(a_alarm_control_panel->get_state());
1630
- return api->send_alarm_control_panel_state_response(resp);
1342
+
1343
+ resp.key = a_alarm_control_panel->get_object_id_hash();
1344
+ return this->send_alarm_control_panel_state_response(resp);
1631
1345
  }
1632
- bool APIConnection::try_send_alarm_control_panel_info(APIConnection *api, void *v_a_alarm_control_panel) {
1633
- alarm_control_panel::AlarmControlPanel *a_alarm_control_panel =
1634
- reinterpret_cast<alarm_control_panel::AlarmControlPanel *>(v_a_alarm_control_panel);
1346
+ bool APIConnection::try_send_alarm_control_panel_info_(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
1635
1347
  ListEntitiesAlarmControlPanelResponse msg;
1636
- msg.key = a_alarm_control_panel->get_object_id_hash();
1637
- msg.object_id = a_alarm_control_panel->get_object_id();
1638
- msg.name = a_alarm_control_panel->get_name();
1639
- msg.unique_id = get_default_unique_id("alarm_control_panel", a_alarm_control_panel);
1640
- msg.icon = a_alarm_control_panel->get_icon();
1641
- msg.disabled_by_default = a_alarm_control_panel->is_disabled_by_default();
1642
- msg.entity_category = static_cast<enums::EntityCategory>(a_alarm_control_panel->get_entity_category());
1643
1348
  msg.supported_features = a_alarm_control_panel->get_supported_features();
1644
1349
  msg.requires_code = a_alarm_control_panel->get_requires_code();
1645
1350
  msg.requires_code_to_arm = a_alarm_control_panel->get_requires_code_to_arm();
1646
- return api->send_list_entities_alarm_control_panel_response(msg);
1351
+ msg.unique_id = get_default_unique_id("alarm_control_panel", a_alarm_control_panel);
1352
+ return this->try_send_entity_info_(static_cast<EntityBase *>(a_alarm_control_panel), msg,
1353
+ &APIConnection::send_list_entities_alarm_control_panel_response);
1647
1354
  }
1648
1355
  void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) {
1649
1356
  alarm_control_panel::AlarmControlPanel *a_alarm_control_panel = App.get_alarm_control_panel_by_key(msg.key);
@@ -1681,63 +1388,45 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe
1681
1388
 
1682
1389
  #ifdef USE_EVENT
1683
1390
  void APIConnection::send_event(event::Event *event, std::string event_type) {
1684
- if (!APIConnection::try_send_event(this, event, std::move(event_type))) {
1685
- this->deferred_message_queue_.defer(event, try_send_event);
1686
- }
1391
+ this->send_state_with_value_(event, &APIConnection::try_send_event_, &APIConnection::try_send_event_,
1392
+ std::move(event_type));
1687
1393
  }
1688
1394
  void APIConnection::send_event_info(event::Event *event) {
1689
- if (!APIConnection::try_send_event_info(this, event)) {
1690
- this->deferred_message_queue_.defer(event, try_send_event_info);
1691
- }
1395
+ this->send_info_(static_cast<EntityBase *>(event),
1396
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_event_info_));
1692
1397
  }
1693
- bool APIConnection::try_send_event(APIConnection *api, void *v_event) {
1694
- event::Event *event = reinterpret_cast<event::Event *>(v_event);
1695
- return APIConnection::try_send_event(api, event, *(event->last_event_type));
1398
+ bool APIConnection::try_send_event_(event::Event *event) {
1399
+ return this->try_send_event_(event, *(event->last_event_type));
1696
1400
  }
1697
- bool APIConnection::try_send_event(APIConnection *api, event::Event *event, std::string event_type) {
1698
- EventResponse resp{};
1699
- resp.key = event->get_object_id_hash();
1401
+ bool APIConnection::try_send_event_(event::Event *event, std::string event_type) {
1402
+ EventResponse resp;
1700
1403
  resp.event_type = std::move(event_type);
1701
- return api->send_event_response(resp);
1404
+
1405
+ resp.key = event->get_object_id_hash();
1406
+ return this->send_event_response(resp);
1702
1407
  }
1703
- bool APIConnection::try_send_event_info(APIConnection *api, void *v_event) {
1704
- event::Event *event = reinterpret_cast<event::Event *>(v_event);
1408
+ bool APIConnection::try_send_event_info_(event::Event *event) {
1705
1409
  ListEntitiesEventResponse msg;
1706
- msg.key = event->get_object_id_hash();
1707
- msg.object_id = event->get_object_id();
1708
- if (event->has_own_name())
1709
- msg.name = event->get_name();
1710
- msg.unique_id = get_default_unique_id("event", event);
1711
- msg.icon = event->get_icon();
1712
- msg.disabled_by_default = event->is_disabled_by_default();
1713
- msg.entity_category = static_cast<enums::EntityCategory>(event->get_entity_category());
1714
1410
  msg.device_class = event->get_device_class();
1715
1411
  for (const auto &event_type : event->get_event_types())
1716
1412
  msg.event_types.push_back(event_type);
1717
- return api->send_list_entities_event_response(msg);
1413
+ msg.unique_id = get_default_unique_id("event", event);
1414
+ return this->try_send_entity_info_(static_cast<EntityBase *>(event), msg,
1415
+ &APIConnection::send_list_entities_event_response);
1718
1416
  }
1719
1417
  #endif
1720
1418
 
1721
1419
  #ifdef USE_UPDATE
1722
1420
  bool APIConnection::send_update_state(update::UpdateEntity *update) {
1723
- if (!this->state_subscription_)
1724
- return false;
1725
-
1726
- if (!APIConnection::try_send_update_state(this, update)) {
1727
- this->deferred_message_queue_.defer(update, try_send_update_state);
1728
- }
1729
-
1730
- return true;
1421
+ return this->send_state_(static_cast<EntityBase *>(update),
1422
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_update_state_));
1731
1423
  }
1732
1424
  void APIConnection::send_update_info(update::UpdateEntity *update) {
1733
- if (!APIConnection::try_send_update_info(this, update)) {
1734
- this->deferred_message_queue_.defer(update, try_send_update_info);
1735
- }
1425
+ this->send_info_(static_cast<EntityBase *>(update),
1426
+ reinterpret_cast<send_message_t>(&APIConnection::try_send_update_info_));
1736
1427
  }
1737
- bool APIConnection::try_send_update_state(APIConnection *api, void *v_update) {
1738
- update::UpdateEntity *update = reinterpret_cast<update::UpdateEntity *>(v_update);
1739
- UpdateStateResponse resp{};
1740
- resp.key = update->get_object_id_hash();
1428
+ bool APIConnection::try_send_update_state_(update::UpdateEntity *update) {
1429
+ UpdateStateResponse resp;
1741
1430
  resp.missing_state = !update->has_state();
1742
1431
  if (update->has_state()) {
1743
1432
  resp.in_progress = update->state == update::UpdateState::UPDATE_STATE_INSTALLING;
@@ -1752,21 +1441,15 @@ bool APIConnection::try_send_update_state(APIConnection *api, void *v_update) {
1752
1441
  resp.release_url = update->update_info.release_url;
1753
1442
  }
1754
1443
 
1755
- return api->send_update_state_response(resp);
1444
+ resp.key = update->get_object_id_hash();
1445
+ return this->send_update_state_response(resp);
1756
1446
  }
1757
- bool APIConnection::try_send_update_info(APIConnection *api, void *v_update) {
1758
- update::UpdateEntity *update = reinterpret_cast<update::UpdateEntity *>(v_update);
1447
+ bool APIConnection::try_send_update_info_(update::UpdateEntity *update) {
1759
1448
  ListEntitiesUpdateResponse msg;
1760
- msg.key = update->get_object_id_hash();
1761
- msg.object_id = update->get_object_id();
1762
- if (update->has_own_name())
1763
- msg.name = update->get_name();
1764
- msg.unique_id = get_default_unique_id("update", update);
1765
- msg.icon = update->get_icon();
1766
- msg.disabled_by_default = update->is_disabled_by_default();
1767
- msg.entity_category = static_cast<enums::EntityCategory>(update->get_entity_category());
1768
1449
  msg.device_class = update->get_device_class();
1769
- return api->send_list_entities_update_response(msg);
1450
+ msg.unique_id = get_default_unique_id("update", update);
1451
+ return this->try_send_entity_info_(static_cast<EntityBase *>(update), msg,
1452
+ &APIConnection::send_list_entities_update_response);
1770
1453
  }
1771
1454
  void APIConnection::update_command(const UpdateCommandRequest &msg) {
1772
1455
  update::UpdateEntity *update = App.get_update_by_key(msg.key);
@@ -1940,26 +1623,29 @@ NoiseEncryptionSetKeyResponse APIConnection::noise_encryption_set_key(const Nois
1940
1623
  void APIConnection::subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) {
1941
1624
  state_subs_at_ = 0;
1942
1625
  }
1943
- bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) {
1626
+ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
1944
1627
  if (this->remove_)
1945
1628
  return false;
1946
- if (!this->helper_->can_write_without_blocking()) {
1947
- delay(0);
1948
- APIError err = this->helper_->loop();
1949
- if (err != APIError::OK) {
1950
- on_fatal_error();
1951
- ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
1952
- api_error_to_str(err), errno);
1953
- return false;
1954
- }
1955
- if (!this->helper_->can_write_without_blocking()) {
1956
- // SubscribeLogsResponse
1957
- if (message_type != 29) {
1958
- ESP_LOGV(TAG, "Cannot send message because of TCP buffer space");
1959
- }
1960
- delay(0);
1961
- return false;
1962
- }
1629
+ if (this->helper_->can_write_without_blocking())
1630
+ return true;
1631
+ delay(0);
1632
+ APIError err = this->helper_->loop();
1633
+ if (err != APIError::OK) {
1634
+ on_fatal_error();
1635
+ ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->client_combined_info_.c_str(),
1636
+ api_error_to_str(err), errno);
1637
+ return false;
1638
+ }
1639
+ if (this->helper_->can_write_without_blocking())
1640
+ return true;
1641
+ if (log_out_of_space) {
1642
+ ESP_LOGV(TAG, "Cannot send message because of TCP buffer space");
1643
+ }
1644
+ return false;
1645
+ }
1646
+ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) {
1647
+ if (!this->try_to_clear_buffer(message_type != 29)) { // SubscribeLogsResponse
1648
+ return false;
1963
1649
  }
1964
1650
 
1965
1651
  APIError err = this->helper_->write_protobuf_packet(message_type, buffer);