mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/dev' into empty_messages
This commit is contained in:
		| @@ -53,6 +53,7 @@ SERVICE_ARG_NATIVE_TYPES = { | ||||
| CONF_ENCRYPTION = "encryption" | ||||
| CONF_BATCH_DELAY = "batch_delay" | ||||
| CONF_CUSTOM_SERVICES = "custom_services" | ||||
| CONF_HOMEASSISTANT_STATES = "homeassistant_states" | ||||
|  | ||||
|  | ||||
| def validate_encryption_key(value): | ||||
| @@ -118,6 +119,7 @@ CONFIG_SCHEMA = cv.All( | ||||
|                 cv.Range(max=cv.TimePeriod(milliseconds=65535)), | ||||
|             ), | ||||
|             cv.Optional(CONF_CUSTOM_SERVICES, default=False): cv.boolean, | ||||
|             cv.Optional(CONF_HOMEASSISTANT_STATES, default=False): cv.boolean, | ||||
|             cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation( | ||||
|                 single=True | ||||
|             ), | ||||
| @@ -146,6 +148,9 @@ async def to_code(config): | ||||
|     if config.get(CONF_ACTIONS) or config[CONF_CUSTOM_SERVICES]: | ||||
|         cg.add_define("USE_API_SERVICES") | ||||
|  | ||||
|     if config[CONF_HOMEASSISTANT_STATES]: | ||||
|         cg.add_define("USE_API_HOMEASSISTANT_STATES") | ||||
|  | ||||
|     if actions := config.get(CONF_ACTIONS, []): | ||||
|         for conf in actions: | ||||
|             template_args = [] | ||||
|   | ||||
| @@ -781,11 +781,13 @@ message HomeassistantServiceResponse { | ||||
| message SubscribeHomeAssistantStatesRequest { | ||||
|   option (id) = 38; | ||||
|   option (source) = SOURCE_CLIENT; | ||||
|   option (ifdef) = "USE_API_HOMEASSISTANT_STATES"; | ||||
| } | ||||
|  | ||||
| message SubscribeHomeAssistantStateResponse { | ||||
|   option (id) = 39; | ||||
|   option (source) = SOURCE_SERVER; | ||||
|   option (ifdef) = "USE_API_HOMEASSISTANT_STATES"; | ||||
|   string entity_id = 1; | ||||
|   string attribute = 2; | ||||
|   bool once = 3; | ||||
| @@ -795,6 +797,7 @@ message HomeAssistantStateResponse { | ||||
|   option (id) = 40; | ||||
|   option (source) = SOURCE_CLIENT; | ||||
|   option (no_delay) = true; | ||||
|   option (ifdef) = "USE_API_HOMEASSISTANT_STATES"; | ||||
|  | ||||
|   string entity_id = 1; | ||||
|   string state = 2; | ||||
|   | ||||
| @@ -242,6 +242,7 @@ void APIConnection::loop() { | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   if (state_subs_at_ >= 0) { | ||||
|     const auto &subs = this->parent_->get_state_subs(); | ||||
|     if (state_subs_at_ < static_cast<int>(subs.size())) { | ||||
| @@ -259,6 +260,7 @@ void APIConnection::loop() { | ||||
|       state_subs_at_ = -1; | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| bool APIConnection::send_disconnect_response(const DisconnectRequest &msg) { | ||||
| @@ -1512,6 +1514,7 @@ bool APIConnection::send_device_info_response(const DeviceInfoRequest &msg) { | ||||
|   return this->send_message(resp, DeviceInfoResponse::MESSAGE_TYPE); | ||||
| } | ||||
|  | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
| void APIConnection::on_home_assistant_state_response(const HomeAssistantStateResponse &msg) { | ||||
|   for (auto &it : this->parent_->get_state_subs()) { | ||||
|     if (it.entity_id == msg.entity_id && it.attribute.value() == msg.attribute) { | ||||
| @@ -1519,6 +1522,7 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes | ||||
|     } | ||||
|   } | ||||
| } | ||||
| #endif | ||||
| #ifdef USE_API_SERVICES | ||||
| void APIConnection::execute_service(const ExecuteServiceRequest &msg) { | ||||
|   bool found = false; | ||||
| @@ -1550,9 +1554,11 @@ bool APIConnection::send_noise_encryption_set_key_response(const NoiseEncryption | ||||
|   return this->send_message(resp, NoiseEncryptionSetKeyResponse::MESSAGE_TYPE); | ||||
| } | ||||
| #endif | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
| void APIConnection::subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) { | ||||
|   state_subs_at_ = 0; | ||||
| } | ||||
| #endif | ||||
| bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { | ||||
|   if (this->flags_.remove) | ||||
|     return false; | ||||
| @@ -1590,10 +1596,12 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { | ||||
|   // Do not set last_traffic_ on send | ||||
|   return true; | ||||
| } | ||||
| #ifdef USE_API_PASSWORD | ||||
| void APIConnection::on_unauthenticated_access() { | ||||
|   this->on_fatal_error(); | ||||
|   ESP_LOGD(TAG, "%s access without authentication", this->get_client_combined_info().c_str()); | ||||
| } | ||||
| #endif | ||||
| void APIConnection::on_no_setup_connection() { | ||||
|   this->on_fatal_error(); | ||||
|   ESP_LOGD(TAG, "%s access without full connection", this->get_client_combined_info().c_str()); | ||||
|   | ||||
| @@ -188,7 +188,9 @@ class APIConnection : public APIServerConnection { | ||||
|     // we initiated ping | ||||
|     this->flags_.sent_ping = false; | ||||
|   } | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   void on_home_assistant_state_response(const HomeAssistantStateResponse &msg) override; | ||||
| #endif | ||||
| #ifdef USE_HOMEASSISTANT_TIME | ||||
|   void on_get_time_response(const GetTimeResponse &value) override; | ||||
| #endif | ||||
| @@ -210,7 +212,9 @@ class APIConnection : public APIServerConnection { | ||||
|   void subscribe_homeassistant_services(const SubscribeHomeassistantServicesRequest &msg) override { | ||||
|     this->flags_.service_call_subscription = true; | ||||
|   } | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) override; | ||||
| #endif | ||||
|   bool send_get_time_response(const GetTimeRequest &msg) override; | ||||
| #ifdef USE_API_SERVICES | ||||
|   void execute_service(const ExecuteServiceRequest &msg) override; | ||||
| @@ -228,7 +232,9 @@ class APIConnection : public APIServerConnection { | ||||
|   } | ||||
|   uint8_t get_log_subscription_level() const { return this->flags_.log_subscription; } | ||||
|   void on_fatal_error() override; | ||||
| #ifdef USE_API_PASSWORD | ||||
|   void on_unauthenticated_access() override; | ||||
| #endif | ||||
|   void on_no_setup_connection() override; | ||||
|   ProtoWriteBuffer create_buffer(uint32_t reserve_size) override { | ||||
|     // FIXME: ensure no recursive writes can happen | ||||
| @@ -492,7 +498,9 @@ class APIConnection : public APIServerConnection { | ||||
|  | ||||
|   // Group 4: 4-byte types | ||||
|   uint32_t last_traffic_; | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   int state_subs_at_ = -1; | ||||
| #endif | ||||
|  | ||||
|   // Function pointer type for message encoding | ||||
|   using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size, bool is_single); | ||||
|   | ||||
| @@ -871,6 +871,7 @@ void HomeassistantServiceResponse::calculate_size(uint32_t &total_size) const { | ||||
|   ProtoSize::add_repeated_message(total_size, 1, this->variables); | ||||
|   ProtoSize::add_bool_field(total_size, 1, this->is_event); | ||||
| } | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
| void SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer buffer) const { | ||||
|   buffer.encode_string(1, this->entity_id_ref_); | ||||
|   buffer.encode_string(2, this->attribute_ref_); | ||||
| @@ -897,6 +898,7 @@ bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDel | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
| #endif | ||||
| bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { | ||||
|   switch (field_id) { | ||||
|     case 1: | ||||
|   | ||||
| @@ -1092,6 +1092,7 @@ class HomeassistantServiceResponse : public ProtoMessage { | ||||
|  | ||||
|  protected: | ||||
| }; | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
| class SubscribeHomeAssistantStatesRequest : public ProtoMessage { | ||||
|  public: | ||||
|   static constexpr uint8_t MESSAGE_TYPE = 38; | ||||
| @@ -1142,6 +1143,7 @@ class HomeAssistantStateResponse : public ProtoDecodableMessage { | ||||
|  protected: | ||||
|   bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; | ||||
| }; | ||||
| #endif | ||||
| class GetTimeRequest : public ProtoMessage { | ||||
|  public: | ||||
|   static constexpr uint8_t MESSAGE_TYPE = 36; | ||||
|   | ||||
| @@ -1066,6 +1066,7 @@ void HomeassistantServiceResponse::dump_to(std::string &out) const { | ||||
|   } | ||||
|   dump_field(out, "is_event", this->is_event); | ||||
| } | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
| void SubscribeHomeAssistantStatesRequest::dump_to(std::string &out) const { | ||||
|   out.append("SubscribeHomeAssistantStatesRequest {}"); | ||||
| } | ||||
| @@ -1081,6 +1082,7 @@ void HomeAssistantStateResponse::dump_to(std::string &out) const { | ||||
|   dump_field(out, "state", this->state); | ||||
|   dump_field(out, "attribute", this->attribute); | ||||
| } | ||||
| #endif | ||||
| void GetTimeRequest::dump_to(std::string &out) const { out.append("GetTimeRequest {}"); } | ||||
| void GetTimeResponse::dump_to(std::string &out) const { dump_field(out, "epoch_seconds", this->epoch_seconds); } | ||||
| #ifdef USE_API_SERVICES | ||||
|   | ||||
| @@ -176,6 +176,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, | ||||
|       this->on_get_time_response(msg); | ||||
|       break; | ||||
|     } | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|     case SubscribeHomeAssistantStatesRequest::MESSAGE_TYPE: { | ||||
|       SubscribeHomeAssistantStatesRequest msg; | ||||
|       // Empty message: no decode needed | ||||
| @@ -185,6 +186,8 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, | ||||
|       this->on_subscribe_home_assistant_states_request(msg); | ||||
|       break; | ||||
|     } | ||||
| #endif | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|     case HomeAssistantStateResponse::MESSAGE_TYPE: { | ||||
|       HomeAssistantStateResponse msg; | ||||
|       msg.decode(msg_data, msg_size); | ||||
| @@ -194,6 +197,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, | ||||
|       this->on_home_assistant_state_response(msg); | ||||
|       break; | ||||
|     } | ||||
| #endif | ||||
| #ifdef USE_API_SERVICES | ||||
|     case ExecuteServiceRequest::MESSAGE_TYPE: { | ||||
|       ExecuteServiceRequest msg; | ||||
| @@ -641,11 +645,13 @@ void APIServerConnection::on_subscribe_homeassistant_services_request( | ||||
|     this->subscribe_homeassistant_services(msg); | ||||
|   } | ||||
| } | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
| void APIServerConnection::on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) { | ||||
|   if (this->check_authenticated_()) { | ||||
|     this->subscribe_home_assistant_states(msg); | ||||
|   } | ||||
| } | ||||
| #endif | ||||
| void APIServerConnection::on_get_time_request(const GetTimeRequest &msg) { | ||||
|   if (this->check_connection_setup_() && !this->send_get_time_response(msg)) { | ||||
|     this->on_fatal_error(); | ||||
|   | ||||
| @@ -62,9 +62,13 @@ class APIServerConnectionBase : public ProtoService { | ||||
|  | ||||
|   virtual void on_subscribe_homeassistant_services_request(const SubscribeHomeassistantServicesRequest &value){}; | ||||
|  | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   virtual void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &value){}; | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   virtual void on_home_assistant_state_response(const HomeAssistantStateResponse &value){}; | ||||
| #endif | ||||
|   virtual void on_get_time_request(const GetTimeRequest &value){}; | ||||
|   virtual void on_get_time_response(const GetTimeResponse &value){}; | ||||
|  | ||||
| @@ -215,7 +219,9 @@ class APIServerConnection : public APIServerConnectionBase { | ||||
|   virtual void subscribe_states(const SubscribeStatesRequest &msg) = 0; | ||||
|   virtual void subscribe_logs(const SubscribeLogsRequest &msg) = 0; | ||||
|   virtual void subscribe_homeassistant_services(const SubscribeHomeassistantServicesRequest &msg) = 0; | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   virtual void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) = 0; | ||||
| #endif | ||||
|   virtual bool send_get_time_response(const GetTimeRequest &msg) = 0; | ||||
| #ifdef USE_API_SERVICES | ||||
|   virtual void execute_service(const ExecuteServiceRequest &msg) = 0; | ||||
| @@ -333,7 +339,9 @@ class APIServerConnection : public APIServerConnectionBase { | ||||
|   void on_subscribe_states_request(const SubscribeStatesRequest &msg) override; | ||||
|   void on_subscribe_logs_request(const SubscribeLogsRequest &msg) override; | ||||
|   void on_subscribe_homeassistant_services_request(const SubscribeHomeassistantServicesRequest &msg) override; | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) override; | ||||
| #endif | ||||
|   void on_get_time_request(const GetTimeRequest &msg) override; | ||||
| #ifdef USE_API_SERVICES | ||||
|   void on_execute_service_request(const ExecuteServiceRequest &msg) override; | ||||
|   | ||||
| @@ -375,6 +375,7 @@ void APIServer::send_homeassistant_service_call(const HomeassistantServiceRespon | ||||
|   } | ||||
| } | ||||
|  | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
| void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute, | ||||
|                                                std::function<void(std::string)> f) { | ||||
|   this->state_subs_.push_back(HomeAssistantStateSubscription{ | ||||
| @@ -398,6 +399,7 @@ void APIServer::get_home_assistant_state(std::string entity_id, optional<std::st | ||||
| const std::vector<APIServer::HomeAssistantStateSubscription> &APIServer::get_state_subs() const { | ||||
|   return this->state_subs_; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| uint16_t APIServer::get_port() const { return this->port_; } | ||||
|  | ||||
|   | ||||
| @@ -126,6 +126,7 @@ class APIServer : public Component, public Controller { | ||||
|  | ||||
|   bool is_connected() const; | ||||
|  | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   struct HomeAssistantStateSubscription { | ||||
|     std::string entity_id; | ||||
|     optional<std::string> attribute; | ||||
| @@ -138,6 +139,7 @@ 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; | ||||
| #endif | ||||
| #ifdef USE_API_SERVICES | ||||
|   const std::vector<UserServiceDescriptor *> &get_user_services() const { return this->user_services_; } | ||||
| #endif | ||||
| @@ -171,7 +173,9 @@ class APIServer : public Component, public Controller { | ||||
|   std::string password_; | ||||
| #endif | ||||
|   std::vector<uint8_t> shared_write_buffer_;  // Shared proto write buffer for all connections | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   std::vector<HomeAssistantStateSubscription> state_subs_; | ||||
| #endif | ||||
| #ifdef USE_API_SERVICES | ||||
|   std::vector<UserServiceDescriptor *> user_services_; | ||||
| #endif | ||||
|   | ||||
| @@ -83,6 +83,7 @@ class CustomAPIDevice { | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_API_HOMEASSISTANT_STATES | ||||
|   /** Subscribe to the state (or attribute state) of an entity from Home Assistant. | ||||
|    * | ||||
|    * Usage: | ||||
| @@ -134,6 +135,7 @@ class CustomAPIDevice { | ||||
|     auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1); | ||||
|     global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), f); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   /** Call a Home Assistant service from ESPHome. | ||||
|    * | ||||
|   | ||||
| @@ -860,7 +860,9 @@ class ProtoService { | ||||
|   virtual bool is_authenticated() = 0; | ||||
|   virtual bool is_connection_setup() = 0; | ||||
|   virtual void on_fatal_error() = 0; | ||||
| #ifdef USE_API_PASSWORD | ||||
|   virtual void on_unauthenticated_access() = 0; | ||||
| #endif | ||||
|   virtual void on_no_setup_connection() = 0; | ||||
|   /** | ||||
|    * Create a buffer with a reserved size. | ||||
| @@ -898,6 +900,7 @@ class ProtoService { | ||||
|   } | ||||
|  | ||||
|   bool check_authenticated_() { | ||||
| #ifdef USE_API_PASSWORD | ||||
|     if (!this->check_connection_setup_()) { | ||||
|       return false; | ||||
|     } | ||||
| @@ -906,6 +909,9 @@ class ProtoService { | ||||
|       return false; | ||||
|     } | ||||
|     return true; | ||||
| #else | ||||
|     return this->check_connection_setup_(); | ||||
| #endif | ||||
|   } | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -51,8 +51,7 @@ DISPLAY_ROTATIONS = { | ||||
|  | ||||
| def validate_rotation(value): | ||||
|     value = cv.string(value) | ||||
|     if value.endswith("°"): | ||||
|         value = value[:-1] | ||||
|     value = value.removesuffix("°") | ||||
|     return cv.enum(DISPLAY_ROTATIONS, int=True)(value) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -38,3 +38,4 @@ def setup_home_assistant_entity(var, config): | ||||
|     cg.add(var.set_entity_id(config[CONF_ENTITY_ID])) | ||||
|     if CONF_ATTRIBUTE in config: | ||||
|         cg.add(var.set_attribute(config[CONF_ATTRIBUTE])) | ||||
|     cg.add_define("USE_API_HOMEASSISTANT_STATES") | ||||
|   | ||||
| @@ -151,13 +151,13 @@ void IDFI2CBus::dump_config() { | ||||
|       break; | ||||
|   } | ||||
|   if (this->scan_) { | ||||
|     ESP_LOGI(TAG, "Results from bus scan:"); | ||||
|     ESP_LOGCONFIG(TAG, "Results from bus scan:"); | ||||
|     if (scan_results_.empty()) { | ||||
|       ESP_LOGI(TAG, "Found no devices"); | ||||
|       ESP_LOGCONFIG(TAG, "Found no devices"); | ||||
|     } else { | ||||
|       for (const auto &s : scan_results_) { | ||||
|         if (s.second) { | ||||
|           ESP_LOGI(TAG, "Found device at address 0x%02X", s.first); | ||||
|           ESP_LOGCONFIG(TAG, "Found device at address 0x%02X", s.first); | ||||
|         } else { | ||||
|           ESP_LOGE(TAG, "Unknown error at address 0x%02X", s.first); | ||||
|         } | ||||
|   | ||||
| @@ -409,7 +409,7 @@ def validate_printf(value): | ||||
|     [cCdiouxXeEfgGaAnpsSZ]             # type | ||||
|     ) | ||||
|     """  # noqa | ||||
|     matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.X) | ||||
|     matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.VERBOSE) | ||||
|     if len(matches) != len(value[CONF_ARGS]): | ||||
|         raise cv.Invalid( | ||||
|             f"Found {len(matches)} printf-patterns ({', '.join(matches)}), but {len(value[CONF_ARGS])} args were given!" | ||||
|   | ||||
| @@ -33,7 +33,7 @@ def validate_printf(value): | ||||
|     [cCdiouxXeEfgGaAnpsSZ]             # type | ||||
|     ) | ||||
|     """  # noqa | ||||
|     matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.X) | ||||
|     matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.VERBOSE) | ||||
|     if len(matches) != len(value[CONF_ARGS]): | ||||
|         raise cv.Invalid( | ||||
|             f"Found {len(matches)} printf-patterns ({', '.join(matches)}), but {len(value[CONF_ARGS])} args were given!" | ||||
|   | ||||
| @@ -155,8 +155,7 @@ def _read_audio_file_and_type(file_config): | ||||
|     import puremagic | ||||
|  | ||||
|     file_type: str = puremagic.from_string(data) | ||||
|     if file_type.startswith("."): | ||||
|         file_type = file_type[1:] | ||||
|     file_type = file_type.removeprefix(".") | ||||
|  | ||||
|     media_file_type = audio.AUDIO_FILE_TYPE_ENUM["NONE"] | ||||
|     if file_type in ("wav"): | ||||
|   | ||||
| @@ -27,8 +27,7 @@ SetDecelerationAction = stepper_ns.class_("SetDecelerationAction", automation.Ac | ||||
| def validate_acceleration(value): | ||||
|     value = cv.string(value) | ||||
|     for suffix in ("steps/s^2", "steps/s*s", "steps/s/s", "steps/ss", "steps/(s*s)"): | ||||
|         if value.endswith(suffix): | ||||
|             value = value[: -len(suffix)] | ||||
|         value = value.removesuffix(suffix) | ||||
|  | ||||
|     if value == "inf": | ||||
|         return 1e6 | ||||
| @@ -48,8 +47,7 @@ def validate_acceleration(value): | ||||
| def validate_speed(value): | ||||
|     value = cv.string(value) | ||||
|     for suffix in ("steps/s", "steps/s"): | ||||
|         if value.endswith(suffix): | ||||
|             value = value[: -len(suffix)] | ||||
|         value = value.removesuffix(suffix) | ||||
|  | ||||
|     if value == "inf": | ||||
|         return 1e6 | ||||
|   | ||||
| @@ -109,6 +109,7 @@ | ||||
| #define USE_API | ||||
| #define USE_API_CLIENT_CONNECTED_TRIGGER | ||||
| #define USE_API_CLIENT_DISCONNECTED_TRIGGER | ||||
| #define USE_API_HOMEASSISTANT_STATES | ||||
| #define USE_API_NOISE | ||||
| #define USE_API_PLAINTEXT | ||||
| #define USE_API_SERVICES | ||||
|   | ||||
| @@ -771,8 +771,7 @@ class MockObj(Expression): | ||||
|         if attr.startswith("P") and self.op not in ["::", ""]: | ||||
|             attr = attr[1:] | ||||
|             next_op = "->" | ||||
|         if attr.startswith("_"): | ||||
|             attr = attr[1:] | ||||
|         attr = attr.removeprefix("_") | ||||
|         return MockObj(f"{self.base}{self.op}{attr}", next_op) | ||||
|  | ||||
|     def __call__(self, *args: SafeExpType) -> "MockObj": | ||||
|   | ||||
| @@ -76,7 +76,7 @@ def get_include_text(): | ||||
|  | ||||
|  | ||||
| def replace_file_content(text, pattern, repl): | ||||
|     content_new, count = re.subn(pattern, repl, text, flags=re.M) | ||||
|     content_new, count = re.subn(pattern, repl, text, flags=re.MULTILINE) | ||||
|     return content_new, count | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user