ESPHome 2026.8.0-dev
Loading...
Searching...
No Matches
api_connection.h
Go to the documentation of this file.
1#pragma once
2
4#ifdef USE_API
5#include "api_frame_helper.h"
6#ifdef USE_API_NOISE
8#endif
9#ifdef USE_API_PLAINTEXT
11#endif
12#include "api_pb2.h"
13#include "api_pb2_service.h"
14#include "list_entities.h"
15#include "subscribe_state.h"
18#ifdef USE_ESP32_CRASH_HANDLER
20#endif
21#ifdef USE_RP2_CRASH_HANDLER
23#endif
24#ifdef USE_ESP8266_CRASH_HANDLER
26#endif
29
30#include <functional>
31#include <limits>
32#include <vector>
33
34namespace esphome {
35class ComponentIterator;
36} // namespace esphome
37
38namespace esphome::api {
39
40// Forward-declared to break the api_server.h cycle; full-type inlines are in api_connection_buffer.h.
41class APIServer;
42
43// Keepalive timeout in milliseconds
44static constexpr uint32_t KEEPALIVE_TIMEOUT_MS = 60000;
45// Maximum number of entities to process in a single batch during initial state/info sending
46static constexpr size_t MAX_INITIAL_PER_BATCH = 34;
47// Verify MAX_MESSAGES_PER_BATCH (defined in api_frame_helper.h) can hold the initial batch
48static_assert(MAX_MESSAGES_PER_BATCH >= MAX_INITIAL_PER_BATCH,
49 "MAX_MESSAGES_PER_BATCH must be >= MAX_INITIAL_PER_BATCH");
50
51#ifdef USE_BENCHMARK
52class APIConnection;
56#endif
57
59 public:
60 friend class APIServer;
62#ifdef USE_BENCHMARK
64 friend void bench_clear_batch(APIConnection *conn);
66#endif
67 APIConnection(std::unique_ptr<socket::Socket> socket, APIServer *parent);
69
70 void start();
71 void loop();
72
73 protected:
74 // read_message_ is defined here (instead of in APIServerConnectionBase) so the
75 // compiler can devirtualize and inline on_* handler calls within this final class.
76 void read_message_(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data);
77
78 // Auth helpers defined here (not in ProtoService) so the compiler can
79 // devirtualize is_connection_setup()/on_no_setup_connection() calls
80 // within this final class.
82 if (!this->is_connection_setup()) {
84 return false;
85 }
86 return true;
87 }
88 inline bool check_authenticated_() { return this->check_connection_setup_(); }
89
90 public:
95#ifdef USE_BINARY_SENSOR
97#endif
98#ifdef USE_COVER
99 bool send_cover_state(cover::Cover *cover);
101#endif
102#ifdef USE_FAN
103 bool send_fan_state(fan::Fan *fan);
105#endif
106#ifdef USE_LIGHT
109#endif
110#ifdef USE_SENSOR
111 bool send_sensor_state(sensor::Sensor *sensor);
112#endif
113#ifdef USE_SWITCH
114 bool send_switch_state(switch_::Switch *a_switch);
116#endif
117#ifdef USE_TEXT_SENSOR
119#endif
120#ifdef USE_CAMERA
121 void set_camera_state(std::shared_ptr<camera::CameraImage> image);
123#endif
124#ifdef USE_CLIMATE
127#endif
128#ifdef USE_NUMBER
129 bool send_number_state(number::Number *number);
131#endif
132#ifdef USE_DATETIME_DATE
135#endif
136#ifdef USE_DATETIME_TIME
139#endif
140#ifdef USE_DATETIME_DATETIME
143#endif
144#ifdef USE_TEXT
145 bool send_text_state(text::Text *text);
147#endif
148#ifdef USE_SELECT
149 bool send_select_state(select::Select *select);
151#endif
152#ifdef USE_BUTTON
154#endif
155#ifdef USE_LOCK
156 bool send_lock_state(lock::Lock *a_lock);
158#endif
159#ifdef USE_VALVE
160 bool send_valve_state(valve::Valve *valve);
162#endif
163#ifdef USE_MEDIA_PLAYER
166#endif
167 bool try_send_log_message(int level, const char *tag, const char *line, size_t message_len);
168#ifdef USE_API_HOMEASSISTANT_SERVICES
169 // Returns whether this client has subscribed to Home Assistant actions; the message
170 // is only handed to the send path when subscribed. A true return does not guarantee
171 // delivery - it lets the caller warn when no connected client has the subscription.
174 return false;
175 this->send_message(call);
176 return true;
177 }
178#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
180#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
181#endif // USE_API_HOMEASSISTANT_SERVICES
182#ifdef USE_BLUETOOTH_PROXY
185
196
197#endif
198#ifdef USE_HOMEASSISTANT_TIME
200 GetTimeRequest req;
201 this->send_message(req);
202 }
203#endif
204
205#ifdef USE_VOICE_ASSISTANT
214#endif
215
216#ifdef USE_ZWAVE_PROXY
217 void on_z_wave_proxy_frame(const ZWaveProxyFrame &msg);
219#endif
220
221#ifdef USE_ALARM_CONTROL_PANEL
224#endif
225
226#ifdef USE_WATER_HEATER
229#endif
230
231#if defined(USE_IR_RF) || defined(USE_RADIO_FREQUENCY)
234#endif
235
236#ifdef USE_SERIAL_PROXY
243#endif
244
245#ifdef USE_EVENT
246 void send_event(event::Event *event);
247#endif
248
249#ifdef USE_UPDATE
252#endif
253
256 // we initiated ping
257 this->flags_.sent_ping = false;
258 }
259#ifdef USE_API_HOMEASSISTANT_STATES
261#endif
262#ifdef USE_HOMEASSISTANT_TIME
263 void on_get_time_response(const GetTimeResponse &value);
264#endif
265 void on_hello_request(const HelloRequest &msg);
267 void on_ping_request();
271 this->flags_.state_subscription = true;
272 // Start initial state iterator only if no iterator is active
273 // If list_entities is running, we'll start initial_state when it completes
276 }
277 }
279 this->flags_.log_subscription = msg.level;
280 if (msg.dump_config)
282#ifdef USE_ESP32_CRASH_HANDLER
285#endif
286#ifdef USE_RP2_CRASH_HANDLER
288#endif
289#ifdef USE_ESP8266_CRASH_HANDLER
291#endif
292 }
293#ifdef USE_API_HOMEASSISTANT_SERVICES
295#endif
296#ifdef USE_API_HOMEASSISTANT_STATES
298#endif
299#ifdef USE_API_USER_DEFINED_ACTIONS
301#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
302 void send_execute_service_response(uint32_t call_id, bool success, StringRef error_message);
303#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
304 void send_execute_service_response(uint32_t call_id, bool success, StringRef error_message,
305 const uint8_t *response_data, size_t response_data_len);
306#endif // USE_API_USER_DEFINED_ACTION_RESPONSES_JSON
307#endif // USE_API_USER_DEFINED_ACTION_RESPONSES
308#endif
309#ifdef USE_API_NOISE
311#endif
312
318 this->is_authenticated();
319 }
320 bool is_marked_for_removal() const { return this->flags_.remove; }
321 uint8_t get_log_subscription_level() const { return this->flags_.log_subscription; }
322
323 // Get client API version for feature detection
324 bool client_supports_api_version(uint16_t major, uint16_t minor) const {
325 return this->client_api_version_major_ > major ||
326 (this->client_api_version_major_ == major && this->client_api_version_minor_ >= minor);
327 }
328
329 void on_fatal_error();
331
332 // Function pointer type for type-erased message encoding
333 using MessageEncodeFn = uint8_t *(*) (const void *, ProtoWriteBuffer &PROTO_ENCODE_DEBUG_PARAM);
334 // Function pointer type for type-erased size calculation
335 using CalculateSizeFn = uint32_t (*)(const void *);
336
337 template<typename T> bool send_message(const T &msg) {
338 if constexpr (T::ESTIMATED_SIZE == 0) {
339 return this->send_message_(0, T::MESSAGE_TYPE, &encode_msg_noop, &msg);
340 } else {
341 return this->send_message_(msg.calculate_size(), T::MESSAGE_TYPE, &proto_encode_msg<T>, &msg);
342 }
343 }
344
345 void prepare_first_message_buffer(APIBuffer &shared_buf, size_t header_padding, size_t total_size) {
346 shared_buf.clear();
347 // Reserve space for header padding + message + footer
348 // - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext)
349 // - Footer: space for MAC (16 bytes for Noise, 0 for Plaintext)
350 // Reserve full size but only set initial size to header padding
351 // so message encoding starts at the correct position
352 shared_buf.reserve_and_resize(total_size, header_padding);
353 }
354
355 // Convenience overload - computes frame overhead internally
357 const uint8_t header_padding = this->helper_->frame_header_padding();
358 const uint8_t footer_size = this->helper_->frame_footer_size();
359 this->prepare_first_message_buffer(shared_buf, header_padding, payload_size + header_padding + footer_size);
360 }
361
362 bool try_to_clear_buffer(bool log_out_of_space) {
363 if (this->flags_.remove)
364 return false;
365 if (this->helper_->can_write_without_blocking())
366 return true;
367 return this->try_to_clear_buffer_slow_(log_out_of_space);
368 }
369 bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type);
370
371 const char *get_name() const { return this->helper_->get_client_name(); }
373 const char *get_peername_to(std::span<char, socket::SOCKADDR_STR_LEN> buf) const {
374 return this->helper_->get_peername_to(buf);
375 }
376
377 protected:
378 bool try_to_clear_buffer_slow_(bool log_out_of_space);
379
380 // Helper function to handle authentication completion
382
383 // Pattern B helpers: send response and return success/failure
384 bool send_hello_response_(const HelloRequest &msg);
386 bool send_ping_response_();
388#ifdef USE_API_NOISE
390#endif
391#ifdef USE_BLUETOOTH_PROXY
393#endif
394#ifdef USE_VOICE_ASSISTANT
396#endif
397
398#ifdef USE_CAMERA
400#endif
401
402#ifdef USE_API_HOMEASSISTANT_STATES
404#endif
405
406 // Size thunk — converts void* back to concrete type for direct calculate_size() call
407 template<typename T> static uint32_t calc_size(const void *msg) {
408 return static_cast<const T *>(msg)->calculate_size();
409 }
410
411 // Shared no-op encode thunk for empty messages (ESTIMATED_SIZE == 0)
412 static uint8_t *encode_msg_noop(const void *, ProtoWriteBuffer &buf PROTO_ENCODE_DEBUG_PARAM) {
413 return buf.get_pos();
414 }
415
416 // Non-template buffer management for send_message
417 bool send_message_(uint32_t payload_size, uint8_t message_type, MessageEncodeFn encode_fn, const void *msg);
418
419 // Core batch encoding logic. ALWAYS_INLINE so encode_fn devirtualizes at hot call sites.
420 // Defined in api_connection_buffer.h (needs APIServer complete).
421 static uint16_t ESPHOME_ALWAYS_INLINE encode_to_buffer(uint32_t calculated_size, MessageEncodeFn encode_fn,
422 const void *msg, APIConnection *conn, uint32_t remaining_size);
423
424 // Noinline version of encode_to_buffer for cold paths (entity info, zero-payload messages).
425 // All cold callers share this single copy instead of each getting an ALWAYS_INLINE expansion.
426 static uint16_t encode_to_buffer_slow(uint32_t calculated_size, MessageEncodeFn encode_fn, const void *msg,
427 APIConnection *conn, uint32_t remaining_size);
428
429 // Thin template wrapper — uses noinline encode_to_buffer_slow since
430 // encode_message_to_buffer callers are cold paths (zero-payload control messages).
431 // Hot paths (state/info) go through fill_and_encode_entity_state/info instead.
432 // batch_message_type_ is already set by dispatch_message_ before reaching here.
433 template<typename T> static uint16_t encode_message_to_buffer(T &msg, APIConnection *conn, uint32_t remaining_size) {
434 if constexpr (T::ESTIMATED_SIZE == 0) {
435 return encode_to_buffer_slow(0, &encode_msg_noop, &msg, conn, remaining_size);
436 } else {
437 return encode_to_buffer_slow(msg.calculate_size(), &proto_encode_msg<T>, &msg, conn, remaining_size);
438 }
439 }
440
441 // Non-template core — fills state fields and encodes
443 CalculateSizeFn size_fn, MessageEncodeFn encode_fn, APIConnection *conn,
444 uint32_t remaining_size);
445
446 // Thin template wrapper
447 template<typename T>
448 static uint16_t fill_and_encode_entity_state(EntityBase *entity, T &msg, APIConnection *conn,
449 uint32_t remaining_size) {
450 return fill_and_encode_entity_state(entity, msg, &calc_size<T>, &proto_encode_msg<T>, conn, remaining_size);
451 }
452
453 // Non-template core — fills info fields, allocates buffers, and encodes
455 CalculateSizeFn size_fn, MessageEncodeFn encode_fn, APIConnection *conn,
456 uint32_t remaining_size);
457
458 // Thin template wrapper
459 template<typename T>
460 static uint16_t fill_and_encode_entity_info(EntityBase *entity, T &msg, APIConnection *conn,
461 uint32_t remaining_size) {
462 return fill_and_encode_entity_info(entity, msg, &calc_size<T>, &proto_encode_msg<T>, conn, remaining_size);
463 }
464
465 // Non-template core — fills device_class, then delegates to fill_and_encode_entity_info
467 StringRef &device_class_field, CalculateSizeFn size_fn,
468 MessageEncodeFn encode_fn, APIConnection *conn,
469 uint32_t remaining_size);
470
471 // Thin template wrapper
472 template<typename T>
474 StringRef &device_class_field, APIConnection *conn,
475 uint32_t remaining_size) {
476 return fill_and_encode_entity_info_with_device_class(entity, msg, device_class_field, &calc_size<T>,
477 &proto_encode_msg<T>, conn, remaining_size);
478 }
479
480#ifdef USE_VOICE_ASSISTANT
481 // Helper to check voice assistant validity and connection ownership
482 inline bool check_voice_assistant_api_connection_() const;
483#endif
484
485 // Send keepalive ping or disconnect unresponsive client.
486 // Cold path — extracted from loop() to reduce instruction cache pressure.
487 void __attribute__((noinline)) check_keepalive_(uint32_t now);
488
489 // Process active iterator (list_entities/initial_state) during connection setup.
490 // Extracted from loop() — only runs during initial handshake, NONE in steady state.
491 void __attribute__((noinline)) process_active_iterator_();
492
493 // Helper method to process multiple entities from an iterator in a batch.
494 // Takes ComponentIterator base class reference to avoid duplicate template instantiations.
496
497#ifdef USE_BINARY_SENSOR
498 static uint16_t try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
499 static uint16_t try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
500#endif
501#ifdef USE_COVER
502 static uint16_t try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
503 static uint16_t try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
504#endif
505#ifdef USE_FAN
506 static uint16_t try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
507 static uint16_t try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
508#endif
509#ifdef USE_LIGHT
510 static uint16_t try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
511 static uint16_t try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
512#endif
513#ifdef USE_SENSOR
514 static uint16_t try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
515 static uint16_t try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
516#endif
517#ifdef USE_SWITCH
518 static uint16_t try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
519 static uint16_t try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
520#endif
521#ifdef USE_TEXT_SENSOR
522 static uint16_t try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
523 static uint16_t try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
524#endif
525#ifdef USE_CLIMATE
526 static uint16_t try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
527 static uint16_t try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
528#endif
529#ifdef USE_NUMBER
530 static uint16_t try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
531 static uint16_t try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
532#endif
533#ifdef USE_DATETIME_DATE
534 static uint16_t try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
535 static uint16_t try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
536#endif
537#ifdef USE_DATETIME_TIME
538 static uint16_t try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
539 static uint16_t try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
540#endif
541#ifdef USE_DATETIME_DATETIME
542 static uint16_t try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
543 static uint16_t try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
544#endif
545#ifdef USE_TEXT
546 static uint16_t try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
547 static uint16_t try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
548#endif
549#ifdef USE_SELECT
550 static uint16_t try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
551 static uint16_t try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
552#endif
553#ifdef USE_BUTTON
554 static uint16_t try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
555#endif
556#ifdef USE_LOCK
557 static uint16_t try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
558 static uint16_t try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
559#endif
560#ifdef USE_VALVE
561 static uint16_t try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
562 static uint16_t try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
563#endif
564#ifdef USE_MEDIA_PLAYER
565 static uint16_t try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
566 static uint16_t try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
567#endif
568#ifdef USE_ALARM_CONTROL_PANEL
569 static uint16_t try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
570 static uint16_t try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
571#endif
572#ifdef USE_WATER_HEATER
573 static uint16_t try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
574 static uint16_t try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
575#endif
576#ifdef USE_INFRARED
577 static uint16_t try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
578#endif
579#ifdef USE_RADIO_FREQUENCY
580 static uint16_t try_send_radio_frequency_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
581#endif
582#ifdef USE_EVENT
583 static uint16_t try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn,
584 uint32_t remaining_size);
585 static uint16_t try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
586#endif
587#ifdef USE_UPDATE
588 static uint16_t try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
589 static uint16_t try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
590#endif
591#ifdef USE_CAMERA
592 static uint16_t try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
593#endif
594
595 // Method for ListEntitiesDone batching
596 static uint16_t try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
597
598 // Method for DisconnectRequest batching
599 static uint16_t try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
600
601 // Batch message method for ping requests
602 static uint16_t try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size);
603
604 // === Optimal member ordering for 32-bit systems ===
605
606 // Group 1: Pointers (4 bytes each on 32-bit)
607#if defined(USE_API_NOISE) && defined(USE_API_PLAINTEXT)
608 std::unique_ptr<APIFrameHelper> helper_;
609#elif defined(USE_API_NOISE)
610 std::unique_ptr<APINoiseFrameHelper> helper_;
611#elif defined(USE_API_PLAINTEXT)
612 std::unique_ptr<APIPlaintextFrameHelper> helper_;
613#endif
615
616 // Group 2: Iterator union (saves ~16 bytes vs separate iterators)
617 // These iterators are never active simultaneously - list_entities runs to completion
618 // before initial_state begins, so we use a union with explicit construction/destruction.
619 enum class ActiveIterator : uint8_t { NONE, LIST_ENTITIES, INITIAL_STATE };
620
624 // Constructor/destructor do nothing - use placement new/explicit destructor
628
629 // Helper methods for iterator lifecycle management
633#if defined(USE_API_NOISE) && defined(USE_API_PLAINTEXT)
634 // Swap the plaintext helper for a Noise helper after the client opened
635 // with a Noise hello on an unprovisioned device (zero-PSK provisioning).
637#endif
638#ifdef USE_CAMERA
639 std::unique_ptr<camera::CameraImageReader> image_reader_;
640#endif
641
642 // Group 3: 4-byte types
644#ifdef USE_API_HOMEASSISTANT_STATES
646#endif
647
648 // Function pointer type for message encoding
649 using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size);
650
651 // Generic batching mechanism for both state updates and entity info
653 // Sentinel value for unused aux_data_index
654 static constexpr uint8_t AUX_DATA_UNUSED = std::numeric_limits<uint8_t>::max();
655
656 struct BatchItem {
657 EntityBase *entity; // 4 bytes - Entity pointer
658 uint8_t message_type; // 1 byte - Message type for protocol and dispatch
659 uint8_t estimated_size; // 1 byte - Estimated message size (max 255 bytes)
660 uint8_t aux_data_index{AUX_DATA_UNUSED}; // 1 byte - For events: index into entity's event_types
661 // 1 byte padding
662 };
663
664 std::vector<BatchItem> items;
666
667 // No pre-allocation - log connections never use batching, and for
668 // connections that do, buffers are released after initial sync anyway
669
670 // Add item to the batch (with deduplication)
671 void add_item(EntityBase *entity, uint8_t message_type, uint8_t estimated_size,
672 uint8_t aux_data_index = AUX_DATA_UNUSED) {
673 // Dedup: O(n) scan but optimized for RAM over performance
674 // Skip deduplication for events - they are edge-triggered, every occurrence matters
675#ifdef USE_EVENT
676 if (message_type != EventResponse::MESSAGE_TYPE)
677#endif
678 {
679 for (const auto &item : this->items) {
680 if (item.entity == entity && item.message_type == message_type)
681 return; // Already queued
682 }
683 }
684 this->items.push_back({entity, message_type, estimated_size, aux_data_index});
685 }
686 // Add item to the front of the batch (for high priority messages like ping)
687 void add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size) {
688 // Swap to front avoids expensive vector::insert which shifts all elements
689 this->items.push_back({entity, message_type, estimated_size, AUX_DATA_UNUSED});
690 if (this->items.size() > 1) {
691 std::swap(this->items.front(), this->items.back());
692 }
693 }
694
695 // Clear all items
696 void clear() {
697 items.clear();
699 }
700
701 // Remove processed items from the front — noinline to keep memmove out of warm callers
702 void remove_front(size_t count) __attribute__((noinline)) { items.erase(items.begin(), items.begin() + count); }
703
704 bool empty() const { return items.empty(); }
705 size_t size() const { return items.size(); }
706 const BatchItem &operator[](size_t index) const { return items[index]; }
707
708 // Release excess capacity - only releases if items already empty
710 // Safe to call: batch is processed before release_buffer is called,
711 // and if any items remain (partial processing), we must not clear them.
712 // Use swap trick since shrink_to_fit() is non-binding and may be ignored.
713 if (items.empty()) {
714 std::vector<BatchItem>().swap(items);
715 }
716 }
717 };
718
719 // DeferredBatch here (16 bytes, 4-byte aligned)
721
722 // ConnectionState enum for type safety
723 enum class ConnectionState : uint8_t {
725 CONNECTED = 1,
726 AUTHENTICATED = 2,
727 };
728
729 // Group 5: Pack all small members together to minimize padding
730 // This group starts at a 4-byte boundary after DeferredBatch
731 struct APIFlags {
732 // Connection state only needs 2 bits (3 states)
733 uint8_t connection_state : 2;
734 // Log subscription needs 3 bits (log levels 0-7)
735 uint8_t log_subscription : 3;
736 // Boolean flags (1 bit each)
737 uint8_t remove : 1;
739 uint8_t sent_ping : 1;
740
742 uint8_t next_close : 1;
743 uint8_t batch_scheduled : 1;
744 uint8_t batch_first_message : 1; // For batch buffer allocation
745 uint8_t should_try_send_immediately : 1; // True after initial states are sent
746 uint8_t may_have_remaining_data : 1; // Read loop hit limit, retry without ready check
747#ifdef HAS_PROTO_MESSAGE_DUMP
748 uint8_t log_only_mode : 1;
749#endif
750 } flags_{}; // 2 bytes total
751
752 // 2-byte types immediately after flags_ (no padding between them)
755 // 1-byte types to fill remaining space before next 4-byte boundary
757 uint8_t batch_message_type_{0}; // Current message type during batch encoding
758 // Total: 2 (flags) + 2 + 2 + 1 + 1 = 8 bytes, aligned to 4-byte boundary
759
760 // Actual header size used by encode_to_buffer for the current message.
761 // Read by process_batch_multi_ to pass into MessageInfo.
763
764 // Defined in api_connection_buffer.h (needs APIServer complete).
766 // Message will use 8 more bytes than the minimum size, and typical
767 // MTU is 1500. Sometimes users will see as low as 1460 MTU.
768 // If its IPv6 the header is 40 bytes, and if its IPv4
769 // the header is 20 bytes. So we have 1460 - 40 = 1420 bytes
770 // available for the payload. But we also need to add the size of
771 // the protobuf overhead, which is 8 bytes.
772 //
773 // To be safe we pick 1390 bytes as the maximum size
774 // to send in one go. This is the maximum size of a single packet
775 // that can be sent over the network.
776 // This is to avoid fragmentation of the packet.
777 static constexpr size_t MAX_BATCH_PACKET_SIZE = 1390; // MTU
778
779 bool schedule_batch_();
780 void process_batch_();
781 void process_batch_multi_(APIBuffer &shared_buf, size_t num_items, uint8_t header_padding, uint8_t footer_size)
782 __attribute__((noinline));
784 this->deferred_batch_.clear();
785 this->flags_.batch_scheduled = false;
786 }
787
788 // Dispatch message encoding based on message_type - replaces function pointer storage
789 // Switch assigns pointer, single call site for smaller code size
790 uint16_t dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, bool batch_first);
791
792#ifdef HAS_PROTO_MESSAGE_DUMP
794 this->flags_.log_only_mode = true;
795 this->dispatch_message_(item, MAX_BATCH_PACKET_SIZE, true);
796 this->flags_.log_only_mode = false;
797 }
798#endif
799
800 // Helper to check if a message type should bypass batching
801 // Returns true if:
802 // 1. It's an UpdateStateResponse (always send immediately to handle cases where
803 // the main loop is blocked, e.g., during OTA updates)
804 // 2. It's an EventResponse (events are edge-triggered - every occurrence matters)
805 // 3. OR: User has opted into immediate sending (should_try_send_immediately = true
806 // AND batch_delay = 0)
807 inline bool should_send_immediately_(uint8_t message_type) const {
808 return (
809#ifdef USE_UPDATE
810 message_type == UpdateStateResponse::MESSAGE_TYPE ||
811#endif
812#ifdef USE_EVENT
813 message_type == EventResponse::MESSAGE_TYPE ||
814#endif
815 (this->flags_.should_try_send_immediately && this->get_batch_delay_ms_() == 0));
816 }
817
818 // Helper method to send a message either immediately or via batching
819 // Tries immediate send if should_send_immediately_() returns true and buffer has space
820 // Falls back to batching if immediate send fails or isn't applicable
821 bool send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size,
822 uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED);
823
824 // Helper function to schedule a deferred message with known message type
825 bool schedule_message_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size,
826 uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED) {
827 this->deferred_batch_.add_item(entity, message_type, estimated_size, aux_data_index);
828 return this->schedule_batch_();
829 }
830
831 // Helper function to schedule a high priority message at the front of the batch
832 // Out-of-line: callers (on_shutdown, check_keepalive_) are cold paths
833 bool schedule_message_front_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size);
834
835 // Helper function to log client messages with name and peername
836 void log_client_(int level, const LogString *message);
837 // Helper function to log API errors with errno
838 void log_warning_(const LogString *message, APIError err);
839 // Helper to handle fatal errors with logging
840 inline void fatal_error_with_log_(const LogString *message, APIError err) {
841 this->on_fatal_error();
842 this->log_warning_(message, err);
843 }
844};
845
846} // namespace esphome::api
847#endif
StringRef is a reference to a string owned by something else.
Definition string_ref.h:26
Byte buffer that skips zero-initialization on resize().
Definition api_buffer.h:36
void reserve_and_resize(size_t reserve_size, size_t new_size) ESPHOME_ALWAYS_INLINE
Reserve capacity for max(reserve_size, new_size) bytes, then set size to new_size.
Definition api_buffer.h:49
struct esphome::api::APIConnection::APIFlags flags_
static uint16_t try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg)
void on_camera_image_request(const CameraImageRequest &msg)
void on_media_player_command_request(const MediaPlayerCommandRequest &msg)
static uint16_t try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_text_command_request(const TextCommandRequest &msg)
static uint16_t try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
bool send_media_player_state(media_player::MediaPlayer *media_player)
void on_update_command_request(const UpdateCommandRequest &msg)
std::unique_ptr< APIPlaintextFrameHelper > helper_
bool send_time_state(datetime::TimeEntity *time)
bool schedule_message_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, uint8_t aux_data_index=DeferredBatch::AUX_DATA_UNUSED)
void on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &msg)
static uint16_t encode_message_to_buffer(T &msg, APIConnection *conn, uint32_t remaining_size)
static uint16_t fill_and_encode_entity_state(EntityBase *entity, T &msg, APIConnection *conn, uint32_t remaining_size)
void __attribute__((noinline)) process_active_iterator_()
bool send_water_heater_state(water_heater::WaterHeater *water_heater)
void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg)
void send_execute_service_response(uint32_t call_id, bool success, StringRef error_message)
static uint16_t try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_button_command_request(const ButtonCommandRequest &msg)
void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg)
void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg)
static uint16_t try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_valve_command_request(const ValveCommandRequest &msg)
void on_bluetooth_device_request(const BluetoothDeviceRequest &msg)
static uint16_t try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
uint16_t dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, bool batch_first)
static uint32_t calc_size(const void *msg)
bool send_text_sensor_state(text_sensor::TextSensor *text_sensor)
static uint16_t try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg)
bool send_fan_state(fan::Fan *fan)
void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg)
bool check_voice_assistant_api_connection_() const
void send_serial_proxy_data(const SerialProxyDataReceived &msg)
bool send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, uint8_t aux_data_index=DeferredBatch::AUX_DATA_UNUSED)
static uint16_t try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
union esphome::api::APIConnection::IteratorUnion iterator_storage_
static uint16_t try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_cover_command_request(const CoverCommandRequest &msg)
std::unique_ptr< APIFrameHelper > helper_
static uint16_t try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void set_camera_state(std::shared_ptr< camera::CameraImage > image)
static uint16_t try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_z_wave_proxy_frame(const ZWaveProxyFrame &msg)
static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, T &msg, StringRef &device_class_field, APIConnection *conn, uint32_t remaining_size)
bool send_sensor_state(sensor::Sensor *sensor)
const char * get_peername_to(std::span< char, socket::SOCKADDR_STR_LEN > buf) const
Get peer name (IP address) into caller-provided buffer, returns buf for convenience.
static constexpr size_t MAX_BATCH_PACKET_SIZE
void log_batch_item_(const DeferredBatch::BatchItem &item)
static uint16_t try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_fan_command_request(const FanCommandRequest &msg)
static uint16_t try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
const char * get_name() const
friend void bench_clear_batch(APIConnection *conn)
void on_disconnect_request(const DisconnectRequest &msg)
void on_climate_command_request(const ClimateCommandRequest &msg)
bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor)
void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg)
bool send_valve_state(valve::Valve *valve)
bool send_voice_assistant_get_configuration_response_(const VoiceAssistantConfigurationRequest &msg)
bool send_select_state(select::Select *select)
void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg)
bool send_switch_state(switch_::Switch *a_switch)
void send_event(event::Event *event)
static uint16_t try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_z_wave_proxy_request(const ZWaveProxyRequest &msg)
static uint16_t try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
bool send_noise_encryption_set_key_response_(const NoiseEncryptionSetKeyRequest &msg)
void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &msg)
static uint16_t try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t fill_and_encode_entity_state(EntityBase *entity, StateResponseProtoMessage &msg, CalculateSizeFn size_fn, MessageEncodeFn encode_fn, APIConnection *conn, uint32_t remaining_size)
static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg, StringRef &device_class_field, CalculateSizeFn size_fn, MessageEncodeFn encode_fn, APIConnection *conn, uint32_t remaining_size)
void on_date_command_request(const DateCommandRequest &msg)
void log_client_(int level, const LogString *message)
void on_subscribe_logs_request(const SubscribeLogsRequest &msg)
static uint16_t try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &msg)
uint8_t *(*)(const void *, ProtoWriteBuffer &PROTO_ENCODE_DEBUG_PARAM) MessageEncodeFn
void send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg)
bool should_send_immediately_(uint8_t message_type) const
bool send_lock_state(lock::Lock *a_lock)
void on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &msg)
void on_select_command_request(const SelectCommandRequest &msg)
bool send_message(const T &msg)
static uint16_t try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg)
void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &msg)
void on_homeassistant_action_response(const HomeassistantActionResponse &msg)
void prepare_first_message_buffer(APIBuffer &shared_buf, size_t payload_size)
void on_switch_command_request(const SwitchCommandRequest &msg)
bool send_update_state(update::UpdateEntity *update)
bool send_homeassistant_action(const HomeassistantActionRequest &call)
static uint16_t try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_get_time_response(const GetTimeResponse &value)
void fatal_error_with_log_(const LogString *message, APIError err)
static uint16_t try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg)
void log_warning_(const LogString *message, APIError err)
void on_serial_proxy_request(const SerialProxyRequest &msg)
static uint16_t try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_lock_command_request(const LockCommandRequest &msg)
void begin_iterator_(ActiveIterator type)
void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg)
std::unique_ptr< camera::CameraImageReader > image_reader_
void on_execute_service_request(const ExecuteServiceRequest &msg)
APIConnection(std::unique_ptr< socket::Socket > socket, APIServer *parent)
static uint16_t try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
bool send_date_state(datetime::DateEntity *date)
friend void bench_enable_immediate_send(APIConnection *conn)
void on_number_command_request(const NumberCommandRequest &msg)
bool send_number_state(number::Number *number)
static uint16_t encode_to_buffer_slow(uint32_t calculated_size, MessageEncodeFn encode_fn, const void *msg, APIConnection *conn, uint32_t remaining_size)
std::unique_ptr< APINoiseFrameHelper > helper_
bool schedule_message_front_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size)
static uint16_t try_send_radio_frequency_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
bool send_hello_response_(const HelloRequest &msg)
bool send_light_state(light::LightState *light)
static uint8_t * encode_msg_noop(const void *, ProtoWriteBuffer &buf PROTO_ENCODE_DEBUG_PARAM)
friend void bench_process_batch(APIConnection *conn)
static uint16_t try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
uint16_t(*)(EntityBase *, APIConnection *, uint32_t remaining_size) MessageCreatorPtr
static uint16_t try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &msg)
void on_time_command_request(const TimeCommandRequest &msg)
uint8_t get_log_subscription_level() const
static uint16_t try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
bool send_message_(uint32_t payload_size, uint8_t message_type, MessageEncodeFn encode_fn, const void *msg)
void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg)
bool send_subscribe_bluetooth_connections_free_response_()
void prepare_first_message_buffer(APIBuffer &shared_buf, size_t header_padding, size_t total_size)
void on_hello_request(const HelloRequest &msg)
void on_voice_assistant_audio(const VoiceAssistantAudio &msg)
bool send_datetime_state(datetime::DateTimeEntity *datetime)
void on_serial_proxy_write_request(const SerialProxyWriteRequest &msg)
void on_light_command_request(const LightCommandRequest &msg)
bool send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel)
static uint16_t try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg, CalculateSizeFn size_fn, MessageEncodeFn encode_fn, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg)
bool send_text_state(text::Text *text)
static uint16_t try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t fill_and_encode_entity_info(EntityBase *entity, T &msg, APIConnection *conn, uint32_t remaining_size)
void on_date_time_command_request(const DateTimeCommandRequest &msg)
void read_message_(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data)
static uint16_t ESPHOME_ALWAYS_INLINE encode_to_buffer(uint32_t calculated_size, MessageEncodeFn encode_fn, const void *msg, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg)
static uint16_t try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg)
bool try_send_log_message(int level, const char *tag, const char *line, size_t message_len)
void process_iterator_batch_(ComponentIterator &iterator)
static uint16_t try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_unsubscribe_bluetooth_le_advertisements_request()
bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type)
bool client_supports_api_version(uint16_t major, uint16_t minor) const
void process_batch_multi_(APIBuffer &shared_buf, size_t num_items, uint8_t header_padding, uint8_t footer_size) __attribute__((noinline))
static uint16_t try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_water_heater_command_request(const WaterHeaterCommandRequest &msg)
bool send_climate_state(climate::Climate *climate)
bool try_to_clear_buffer(bool log_out_of_space)
bool send_cover_state(cover::Cover *cover)
static uint16_t try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
bool try_to_clear_buffer_slow_(bool log_out_of_space)
void on_home_assistant_state_response(const HomeAssistantStateResponse &msg)
void __attribute__((noinline)) check_keepalive_(uint32_t now)
uint32_t(*)(const void *) CalculateSizeFn
static uint16_t try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
static uint16_t try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size)
void on_voice_assistant_response(const VoiceAssistantResponse &msg)
static constexpr uint8_t MESSAGE_TYPE
Definition api_pb2.h:2841
static constexpr uint8_t MESSAGE_TYPE
Definition api_pb2.h:605
static constexpr uint8_t ESTIMATED_SIZE
Definition api_pb2.h:606
static constexpr uint8_t MESSAGE_TYPE
Definition api_pb2.h:2981
Base class for all binary_sensor-type classes.
ClimateDevice - This is the base class for all climate integrations.
Definition climate.h:187
Base class for all cover devices.
Definition cover.h:110
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition light_state.h:93
Base class for all locks.
Definition lock.h:112
Base-class for all numbers.
Definition number.h:29
Base-class for all selects.
Definition select.h:29
Base-class for all sensors.
Definition sensor.h:47
Base class for all switches.
Definition switch.h:38
Base-class for all text inputs.
Definition text.h:21
Base class for all valve devices.
Definition valve.h:103
struct @66::@67 __attribute__
Wake the main loop task from an ISR. ISR-safe.
Definition main_task.h:32
const LogString * message
Definition component.cpp:35
uint16_t type
uint8_t * proto_encode_msg(const void *msg, ProtoWriteBuffer &buf PROTO_ENCODE_DEBUG_PARAM)
Definition proto.h:885
void bench_process_batch(APIConnection *conn)
void bench_enable_immediate_send(APIConnection *conn)
void bench_clear_batch(APIConnection *conn)
void crash_handler_log()
Log crash data if a crash was detected on previous boot.
void crash_handler_clear()
Clear the magic marker and mark crash data as consumed.
void crash_handler_log()
Log crash data if a crash was detected on previous boot.
void crash_handler_log()
Log crash data if a crash was detected on previous boot.
const char int line
Definition log.h:74
const char * tag
Definition log.h:74
Application App
Global storage of Application pointer - only one Application can exist.
static void uint32_t
void remove_front(size_t count) __attribute__((noinline))
const BatchItem & operator[](size_t index) const
void add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size)
void add_item(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, uint8_t aux_data_index=AUX_DATA_UNUSED)
uint32_t payload_size()