mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Reduce API component memory usage with conditional compilation
This commit is contained in:
		| @@ -135,23 +135,26 @@ async def to_code(config): | ||||
|     cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) | ||||
|     cg.add(var.set_batch_delay(config[CONF_BATCH_DELAY])) | ||||
|  | ||||
|     for conf in config.get(CONF_ACTIONS, []): | ||||
|         template_args = [] | ||||
|         func_args = [] | ||||
|         service_arg_names = [] | ||||
|         for name, var_ in conf[CONF_VARIABLES].items(): | ||||
|             native = SERVICE_ARG_NATIVE_TYPES[var_] | ||||
|             template_args.append(native) | ||||
|             func_args.append((native, name)) | ||||
|             service_arg_names.append(name) | ||||
|         templ = cg.TemplateArguments(*template_args) | ||||
|         trigger = cg.new_Pvariable( | ||||
|             conf[CONF_TRIGGER_ID], templ, conf[CONF_ACTION], service_arg_names | ||||
|         ) | ||||
|         cg.add(var.register_user_service(trigger)) | ||||
|         await automation.build_automation(trigger, func_args, conf) | ||||
|     if actions := config.get(CONF_ACTIONS, []): | ||||
|         cg.add_define("USE_API_YAML_SERVICES") | ||||
|         for conf in actions: | ||||
|             template_args = [] | ||||
|             func_args = [] | ||||
|             service_arg_names = [] | ||||
|             for name, var_ in conf[CONF_VARIABLES].items(): | ||||
|                 native = SERVICE_ARG_NATIVE_TYPES[var_] | ||||
|                 template_args.append(native) | ||||
|                 func_args.append((native, name)) | ||||
|                 service_arg_names.append(name) | ||||
|             templ = cg.TemplateArguments(*template_args) | ||||
|             trigger = cg.new_Pvariable( | ||||
|                 conf[CONF_TRIGGER_ID], templ, conf[CONF_ACTION], service_arg_names | ||||
|             ) | ||||
|             cg.add(var.register_user_service(trigger)) | ||||
|             await automation.build_automation(trigger, func_args, conf) | ||||
|  | ||||
|     if CONF_ON_CLIENT_CONNECTED in config: | ||||
|         cg.add_define("USE_API_CLIENT_CONNECTED_TRIGGER") | ||||
|         await automation.build_automation( | ||||
|             var.get_client_connected_trigger(), | ||||
|             [(cg.std_string, "client_info"), (cg.std_string, "client_address")], | ||||
| @@ -159,6 +162,7 @@ async def to_code(config): | ||||
|         ) | ||||
|  | ||||
|     if CONF_ON_CLIENT_DISCONNECTED in config: | ||||
|         cg.add_define("USE_API_CLIENT_DISCONNECTED_TRIGGER") | ||||
|         await automation.build_automation( | ||||
|             var.get_client_disconnected_trigger(), | ||||
|             [(cg.std_string, "client_info"), (cg.std_string, "client_address")], | ||||
|   | ||||
| @@ -1582,7 +1582,9 @@ ConnectResponse APIConnection::connect(const ConnectRequest &msg) { | ||||
|   if (correct) { | ||||
|     ESP_LOGD(TAG, "%s connected", this->get_client_combined_info().c_str()); | ||||
|     this->connection_state_ = ConnectionState::AUTHENTICATED; | ||||
| #ifdef USE_API_CLIENT_CONNECTED_TRIGGER | ||||
|     this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_); | ||||
| #endif | ||||
| #ifdef USE_HOMEASSISTANT_TIME | ||||
|     if (homeassistant::global_homeassistant_time != nullptr) { | ||||
|       this->send_time_request(); | ||||
|   | ||||
| @@ -184,7 +184,9 @@ void APIServer::loop() { | ||||
|     } | ||||
|  | ||||
|     // Rare case: handle disconnection | ||||
| #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER | ||||
|     this->client_disconnected_trigger_->trigger(client->client_info_, client->client_peername_); | ||||
| #endif | ||||
|     ESP_LOGV(TAG, "Remove connection %s", client->client_info_.c_str()); | ||||
|  | ||||
|     // Swap with the last element and pop (avoids expensive vector shifts) | ||||
|   | ||||
| @@ -105,7 +105,18 @@ class APIServer : public Component, public Controller { | ||||
|   void on_media_player_update(media_player::MediaPlayer *obj) override; | ||||
| #endif | ||||
|   void send_homeassistant_service_call(const HomeassistantServiceResponse &call); | ||||
|   void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); } | ||||
|   void register_user_service(UserServiceDescriptor *descriptor) { | ||||
| #ifdef USE_API_YAML_SERVICES | ||||
|     // Vector is pre-allocated when services are defined in YAML | ||||
|     this->user_services_.push_back(descriptor); | ||||
| #else | ||||
|     // Lazy allocate vector on first use for CustomAPIDevice | ||||
|     if (!this->user_services_) { | ||||
|       this->user_services_ = std::make_unique<std::vector<UserServiceDescriptor *>>(); | ||||
|     } | ||||
|     this->user_services_->push_back(descriptor); | ||||
| #endif | ||||
|   } | ||||
| #ifdef USE_HOMEASSISTANT_TIME | ||||
|   void request_time(); | ||||
| #endif | ||||
| @@ -134,19 +145,34 @@ class APIServer : public Component, public Controller { | ||||
|   void get_home_assistant_state(std::string entity_id, optional<std::string> attribute, | ||||
|                                 std::function<void(std::string)> f); | ||||
|   const std::vector<HomeAssistantStateSubscription> &get_state_subs() const; | ||||
|   const std::vector<UserServiceDescriptor *> &get_user_services() const { return this->user_services_; } | ||||
|   const std::vector<UserServiceDescriptor *> &get_user_services() const { | ||||
| #ifdef USE_API_YAML_SERVICES | ||||
|     return this->user_services_; | ||||
| #else | ||||
|     static const std::vector<UserServiceDescriptor *> empty; | ||||
|     return this->user_services_ ? *this->user_services_ : empty; | ||||
| #endif | ||||
|   } | ||||
|  | ||||
| #ifdef USE_API_CLIENT_CONNECTED_TRIGGER | ||||
|   Trigger<std::string, std::string> *get_client_connected_trigger() const { return this->client_connected_trigger_; } | ||||
| #endif | ||||
| #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER | ||||
|   Trigger<std::string, std::string> *get_client_disconnected_trigger() const { | ||||
|     return this->client_disconnected_trigger_; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|  protected: | ||||
|   void schedule_reboot_timeout_(); | ||||
|   // Pointers and pointer-like types first (4 bytes each) | ||||
|   std::unique_ptr<socket::Socket> socket_ = nullptr; | ||||
| #ifdef USE_API_CLIENT_CONNECTED_TRIGGER | ||||
|   Trigger<std::string, std::string> *client_connected_trigger_ = new Trigger<std::string, std::string>(); | ||||
| #endif | ||||
| #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER | ||||
|   Trigger<std::string, std::string> *client_disconnected_trigger_ = new Trigger<std::string, std::string>(); | ||||
| #endif | ||||
|  | ||||
|   // 4-byte aligned types | ||||
|   uint32_t reboot_timeout_{300000}; | ||||
| @@ -157,7 +183,15 @@ class APIServer : public Component, public Controller { | ||||
|   std::string password_; | ||||
|   std::vector<uint8_t> shared_write_buffer_;  // Shared proto write buffer for all connections | ||||
|   std::vector<HomeAssistantStateSubscription> state_subs_; | ||||
| #ifdef USE_API_YAML_SERVICES | ||||
|   // When services are defined in YAML, we know at compile time that services will be registered | ||||
|   std::vector<UserServiceDescriptor *> user_services_; | ||||
| #else | ||||
|   // Services can still be registered at runtime by CustomAPIDevice components even when not | ||||
|   // defined in YAML. Using unique_ptr allows lazy allocation, saving 12 bytes in the common | ||||
|   // case where no services (YAML or custom) are used. | ||||
|   std::unique_ptr<std::vector<UserServiceDescriptor *>> user_services_; | ||||
| #endif | ||||
|  | ||||
|   // Group smaller types together | ||||
|   uint16_t port_{6053}; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user