mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	bitpack api flags
This commit is contained in:
		| @@ -90,10 +90,10 @@ APIConnection::~APIConnection() { | ||||
| } | ||||
|  | ||||
| void APIConnection::loop() { | ||||
|   if (this->next_close_) { | ||||
|   if (this->flags_.next_close) { | ||||
|     // requested a disconnect | ||||
|     this->helper_->close(); | ||||
|     this->remove_ = true; | ||||
|     this->flags_.remove = true; | ||||
|     return; | ||||
|   } | ||||
|  | ||||
| @@ -134,15 +134,14 @@ void APIConnection::loop() { | ||||
|         } else { | ||||
|           this->read_message(0, buffer.type, nullptr); | ||||
|         } | ||||
|         if (this->remove_) | ||||
|         if (this->flags_.remove) | ||||
|           return; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Process deferred batch if scheduled | ||||
|   if (this->deferred_batch_.batch_scheduled && | ||||
|       now - this->deferred_batch_.batch_start_time >= this->get_batch_delay_ms_()) { | ||||
|   if (this->flags_.batch_scheduled && now - this->deferred_batch_.batch_start_time >= this->get_batch_delay_ms_()) { | ||||
|     this->process_batch_(); | ||||
|   } | ||||
|  | ||||
| @@ -152,7 +151,7 @@ void APIConnection::loop() { | ||||
|     this->initial_state_iterator_.advance(); | ||||
|   } | ||||
|  | ||||
|   if (this->sent_ping_) { | ||||
|   if (this->flags_.sent_ping) { | ||||
|     // Disconnect if not responded within 2.5*keepalive | ||||
|     if (now - this->last_traffic_ > KEEPALIVE_DISCONNECT_TIMEOUT) { | ||||
|       on_fatal_error(); | ||||
| @@ -160,13 +159,13 @@ void APIConnection::loop() { | ||||
|     } | ||||
|   } else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS) { | ||||
|     ESP_LOGVV(TAG, "Sending keepalive PING"); | ||||
|     this->sent_ping_ = this->send_message(PingRequest()); | ||||
|     if (!this->sent_ping_) { | ||||
|     this->flags_.sent_ping = this->send_message(PingRequest()); | ||||
|     if (!this->flags_.sent_ping) { | ||||
|       // If we can't send the ping request directly (tx_buffer full), | ||||
|       // schedule it at the front of the batch so it will be sent with priority | ||||
|       ESP_LOGW(TAG, "Buffer full, ping queued"); | ||||
|       this->schedule_message_front_(nullptr, &APIConnection::try_send_ping_request, PingRequest::MESSAGE_TYPE); | ||||
|       this->sent_ping_ = true;  // Mark as sent to avoid scheduling multiple pings | ||||
|       this->flags_.sent_ping = true;  // Mark as sent to avoid scheduling multiple pings | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -226,13 +225,13 @@ DisconnectResponse APIConnection::disconnect(const DisconnectRequest &msg) { | ||||
|   // don't close yet, we still need to send the disconnect response | ||||
|   // close will happen on next loop | ||||
|   ESP_LOGD(TAG, "%s disconnected", this->get_client_combined_info().c_str()); | ||||
|   this->next_close_ = true; | ||||
|   this->flags_.next_close = true; | ||||
|   DisconnectResponse resp; | ||||
|   return resp; | ||||
| } | ||||
| void APIConnection::on_disconnect_response(const DisconnectResponse &value) { | ||||
|   this->helper_->close(); | ||||
|   this->remove_ = true; | ||||
|   this->flags_.remove = true; | ||||
| } | ||||
|  | ||||
| // Encodes a message to the buffer and returns the total number of bytes used, | ||||
| @@ -1158,7 +1157,7 @@ void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) { | ||||
|  | ||||
| #ifdef USE_ESP32_CAMERA | ||||
| void APIConnection::set_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) { | ||||
|   if (!this->state_subscription_) | ||||
|   if (!this->flags_.state_subscription) | ||||
|     return; | ||||
|   if (this->image_reader_.available()) | ||||
|     return; | ||||
| @@ -1512,7 +1511,7 @@ void APIConnection::update_command(const UpdateCommandRequest &msg) { | ||||
| #endif | ||||
|  | ||||
| bool APIConnection::try_send_log_message(int level, const char *tag, const char *line) { | ||||
|   if (this->log_subscription_ < level) | ||||
|   if (this->flags_.log_subscription < level) | ||||
|     return false; | ||||
|  | ||||
|   // Pre-calculate message size to avoid reallocations | ||||
| @@ -1552,7 +1551,7 @@ HelloResponse APIConnection::hello(const HelloRequest &msg) { | ||||
|   resp.server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")"; | ||||
|   resp.name = App.get_name(); | ||||
|  | ||||
|   this->connection_state_ = ConnectionState::CONNECTED; | ||||
|   this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::CONNECTED); | ||||
|   return resp; | ||||
| } | ||||
| ConnectResponse APIConnection::connect(const ConnectRequest &msg) { | ||||
| @@ -1563,7 +1562,7 @@ ConnectResponse APIConnection::connect(const ConnectRequest &msg) { | ||||
|   resp.invalid_password = !correct; | ||||
|   if (correct) { | ||||
|     ESP_LOGD(TAG, "%s connected", this->get_client_combined_info().c_str()); | ||||
|     this->connection_state_ = ConnectionState::AUTHENTICATED; | ||||
|     this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED); | ||||
|     this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->helper_->getpeername()); | ||||
| #ifdef USE_HOMEASSISTANT_TIME | ||||
|     if (homeassistant::global_homeassistant_time != nullptr) { | ||||
| @@ -1677,7 +1676,7 @@ void APIConnection::subscribe_home_assistant_states(const SubscribeHomeAssistant | ||||
|   state_subs_at_ = 0; | ||||
| } | ||||
| bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { | ||||
|   if (this->remove_) | ||||
|   if (this->flags_.remove) | ||||
|     return false; | ||||
|   if (this->helper_->can_write_without_blocking()) | ||||
|     return true; | ||||
| @@ -1727,7 +1726,7 @@ void APIConnection::on_no_setup_connection() { | ||||
| } | ||||
| void APIConnection::on_fatal_error() { | ||||
|   this->helper_->close(); | ||||
|   this->remove_ = true; | ||||
|   this->flags_.remove = true; | ||||
| } | ||||
|  | ||||
| void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator creator, uint16_t message_type) { | ||||
| @@ -1752,8 +1751,8 @@ void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, MessageCre | ||||
| } | ||||
|  | ||||
| bool APIConnection::schedule_batch_() { | ||||
|   if (!this->deferred_batch_.batch_scheduled) { | ||||
|     this->deferred_batch_.batch_scheduled = true; | ||||
|   if (!this->flags_.batch_scheduled) { | ||||
|     this->flags_.batch_scheduled = true; | ||||
|     this->deferred_batch_.batch_start_time = App.get_loop_component_start_time(); | ||||
|   } | ||||
|   return true; | ||||
| @@ -1769,7 +1768,7 @@ ProtoWriteBuffer APIConnection::allocate_batch_message_buffer(uint16_t size) { | ||||
|  | ||||
| void APIConnection::process_batch_() { | ||||
|   if (this->deferred_batch_.empty()) { | ||||
|     this->deferred_batch_.batch_scheduled = false; | ||||
|     this->flags_.batch_scheduled = false; | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -125,7 +125,7 @@ class APIConnection : public APIServerConnection { | ||||
| #endif | ||||
|   bool try_send_log_message(int level, const char *tag, const char *line); | ||||
|   void send_homeassistant_service_call(const HomeassistantServiceResponse &call) { | ||||
|     if (!this->service_call_subscription_) | ||||
|     if (!this->flags_.service_call_subscription) | ||||
|       return; | ||||
|     this->send_message(call); | ||||
|   } | ||||
| @@ -185,7 +185,7 @@ class APIConnection : public APIServerConnection { | ||||
|   void on_disconnect_response(const DisconnectResponse &value) override; | ||||
|   void on_ping_response(const PingResponse &value) override { | ||||
|     // we initiated ping | ||||
|     this->sent_ping_ = false; | ||||
|     this->flags_.sent_ping = false; | ||||
|   } | ||||
|   void on_home_assistant_state_response(const HomeAssistantStateResponse &msg) override; | ||||
| #ifdef USE_HOMEASSISTANT_TIME | ||||
| @@ -198,16 +198,16 @@ class APIConnection : public APIServerConnection { | ||||
|   DeviceInfoResponse device_info(const DeviceInfoRequest &msg) override; | ||||
|   void list_entities(const ListEntitiesRequest &msg) override { this->list_entities_iterator_.begin(); } | ||||
|   void subscribe_states(const SubscribeStatesRequest &msg) override { | ||||
|     this->state_subscription_ = true; | ||||
|     this->flags_.state_subscription = true; | ||||
|     this->initial_state_iterator_.begin(); | ||||
|   } | ||||
|   void subscribe_logs(const SubscribeLogsRequest &msg) override { | ||||
|     this->log_subscription_ = msg.level; | ||||
|     this->flags_.log_subscription = msg.level; | ||||
|     if (msg.dump_config) | ||||
|       App.schedule_dump_config(); | ||||
|   } | ||||
|   void subscribe_homeassistant_services(const SubscribeHomeassistantServicesRequest &msg) override { | ||||
|     this->service_call_subscription_ = true; | ||||
|     this->flags_.service_call_subscription = true; | ||||
|   } | ||||
|   void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) override; | ||||
|   GetTimeResponse get_time(const GetTimeRequest &msg) override { | ||||
| @@ -219,9 +219,12 @@ class APIConnection : public APIServerConnection { | ||||
|   NoiseEncryptionSetKeyResponse noise_encryption_set_key(const NoiseEncryptionSetKeyRequest &msg) override; | ||||
| #endif | ||||
|  | ||||
|   bool is_authenticated() override { return this->connection_state_ == ConnectionState::AUTHENTICATED; } | ||||
|   bool is_authenticated() override { | ||||
|     return static_cast<ConnectionState>(this->flags_.connection_state) == ConnectionState::AUTHENTICATED; | ||||
|   } | ||||
|   bool is_connection_setup() override { | ||||
|     return this->connection_state_ == ConnectionState ::CONNECTED || this->is_authenticated(); | ||||
|     return static_cast<ConnectionState>(this->flags_.connection_state) == ConnectionState::CONNECTED || | ||||
|            this->is_authenticated(); | ||||
|   } | ||||
|   void on_fatal_error() override; | ||||
|   void on_unauthenticated_access() override; | ||||
| @@ -460,19 +463,37 @@ class APIConnection : public APIServerConnection { | ||||
|   uint16_t client_api_version_major_{0}; | ||||
|   uint16_t client_api_version_minor_{0}; | ||||
|  | ||||
|   // Group all 1-byte types together to minimize padding | ||||
|   // Connection state enum | ||||
|   enum class ConnectionState : uint8_t { | ||||
|     WAITING_FOR_HELLO, | ||||
|     CONNECTED, | ||||
|     AUTHENTICATED, | ||||
|   } connection_state_{ConnectionState::WAITING_FOR_HELLO}; | ||||
|   uint8_t log_subscription_{ESPHOME_LOG_LEVEL_NONE}; | ||||
|   bool remove_{false}; | ||||
|   bool state_subscription_{false}; | ||||
|   bool sent_ping_{false}; | ||||
|   bool service_call_subscription_{false}; | ||||
|   bool next_close_ = false; | ||||
|   // 7 bytes used, 1 byte padding | ||||
|     WAITING_FOR_HELLO = 0, | ||||
|     CONNECTED = 1, | ||||
|     AUTHENTICATED = 2, | ||||
|   }; | ||||
|  | ||||
|   // Group all 1-byte types together to minimize padding | ||||
|   struct APIFlags { | ||||
|     uint8_t connection_state : 2;  // ConnectionState only needs 2 bits (3 states) | ||||
|     uint8_t log_subscription : 3;  // Log levels 0-7 need 3 bits | ||||
|     uint8_t remove : 1; | ||||
|     uint8_t state_subscription : 1; | ||||
|     uint8_t sent_ping : 1; | ||||
|  | ||||
|     uint8_t service_call_subscription : 1; | ||||
|     uint8_t next_close : 1; | ||||
|     uint8_t batch_scheduled : 1;  // Moved from DeferredBatch | ||||
|     uint8_t reserved : 5;         // Reserved for future use | ||||
|  | ||||
|     APIFlags() | ||||
|         : connection_state(0), | ||||
|           log_subscription(ESPHOME_LOG_LEVEL_NONE), | ||||
|           remove(0), | ||||
|           state_subscription(0), | ||||
|           sent_ping(0), | ||||
|           service_call_subscription(0), | ||||
|           next_close(0), | ||||
|           batch_scheduled(0), | ||||
|           reserved(0) {} | ||||
|   } flags_;  // 2 bytes total instead of 7+ bytes | ||||
|  | ||||
|   // Larger objects at the end | ||||
|   InitialStateIterator initial_state_iterator_; | ||||
| @@ -590,7 +611,6 @@ class APIConnection : public APIServerConnection { | ||||
|  | ||||
|     std::vector<BatchItem> items; | ||||
|     uint32_t batch_start_time{0}; | ||||
|     bool batch_scheduled{false}; | ||||
|  | ||||
|     DeferredBatch() { | ||||
|       // Pre-allocate capacity for typical batch sizes to avoid reallocation | ||||
| @@ -603,7 +623,6 @@ class APIConnection : public APIServerConnection { | ||||
|     void add_item_front(EntityBase *entity, MessageCreator creator, uint16_t message_type); | ||||
|     void clear() { | ||||
|       items.clear(); | ||||
|       batch_scheduled = false; | ||||
|       batch_start_time = 0; | ||||
|     } | ||||
|     bool empty() const { return items.empty(); } | ||||
|   | ||||
| @@ -104,7 +104,7 @@ void APIServer::setup() { | ||||
|         return; | ||||
|       } | ||||
|       for (auto &c : this->clients_) { | ||||
|         if (!c->remove_) | ||||
|         if (!c->flags_.remove) | ||||
|           c->try_send_log_message(level, tag, message); | ||||
|       } | ||||
|     }); | ||||
| @@ -116,7 +116,7 @@ void APIServer::setup() { | ||||
|     esp32_camera::global_esp32_camera->add_image_callback( | ||||
|         [this](const std::shared_ptr<esp32_camera::CameraImage> &image) { | ||||
|           for (auto &c : this->clients_) { | ||||
|             if (!c->remove_) | ||||
|             if (!c->flags_.remove) | ||||
|               c->set_camera_state(image); | ||||
|           } | ||||
|         }); | ||||
| @@ -176,7 +176,7 @@ void APIServer::loop() { | ||||
|   while (client_index < this->clients_.size()) { | ||||
|     auto &client = this->clients_[client_index]; | ||||
|  | ||||
|     if (!client->remove_) { | ||||
|     if (!client->flags_.remove) { | ||||
|       // Common case: process active client | ||||
|       client->loop(); | ||||
|       client_index++; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user