mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 23:21:54 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/dev' into zwave_proxy
This commit is contained in:
		| @@ -89,6 +89,7 @@ esphome/components/bp5758d/* @Cossid | |||||||
| esphome/components/button/* @esphome/core | esphome/components/button/* @esphome/core | ||||||
| esphome/components/bytebuffer/* @clydebarrow | esphome/components/bytebuffer/* @clydebarrow | ||||||
| esphome/components/camera/* @DT-art1 @bdraco | esphome/components/camera/* @DT-art1 @bdraco | ||||||
|  | esphome/components/camera_encoder/* @DT-art1 | ||||||
| esphome/components/canbus/* @danielschramm @mvturnho | esphome/components/canbus/* @danielschramm @mvturnho | ||||||
| esphome/components/cap1188/* @mreditor97 | esphome/components/cap1188/* @mreditor97 | ||||||
| esphome/components/captive_portal/* @esphome/core | esphome/components/captive_portal/* @esphome/core | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ from esphome.const import ( | |||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     CONF_WEB_SERVER, |     CONF_WEB_SERVER, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -345,6 +345,6 @@ async def alarm_control_panel_is_armed_to_code( | |||||||
|     return cg.new_Pvariable(condition_id, template_arg, paren) |     return cg.new_Pvariable(condition_id, template_arg, paren) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(alarm_control_panel_ns.using) |     cg.add_global(alarm_control_panel_ns.using) | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ from esphome.const import ( | |||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     CONF_VARIABLES, |     CONF_VARIABLES, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| DOMAIN = "api" | DOMAIN = "api" | ||||||
| DEPENDENCIES = ["network"] | DEPENDENCIES = ["network"] | ||||||
| @@ -134,7 +134,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(40.0) | @coroutine_with_priority(CoroPriority.WEB) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     await cg.register_component(var, config) |     await cg.register_component(var, config) | ||||||
|   | |||||||
| @@ -1719,6 +1719,7 @@ message BluetoothScannerStateResponse { | |||||||
|  |  | ||||||
|   BluetoothScannerState state = 1; |   BluetoothScannerState state = 1; | ||||||
|   BluetoothScannerMode mode = 2; |   BluetoothScannerMode mode = 2; | ||||||
|  |   BluetoothScannerMode configured_mode = 3; | ||||||
| } | } | ||||||
|  |  | ||||||
| message BluetoothScannerSetModeRequest { | message BluetoothScannerSetModeRequest { | ||||||
|   | |||||||
| @@ -2159,10 +2159,12 @@ void BluetoothDeviceClearCacheResponse::calculate_size(ProtoSize &size) const { | |||||||
| void BluetoothScannerStateResponse::encode(ProtoWriteBuffer buffer) const { | void BluetoothScannerStateResponse::encode(ProtoWriteBuffer buffer) const { | ||||||
|   buffer.encode_uint32(1, static_cast<uint32_t>(this->state)); |   buffer.encode_uint32(1, static_cast<uint32_t>(this->state)); | ||||||
|   buffer.encode_uint32(2, static_cast<uint32_t>(this->mode)); |   buffer.encode_uint32(2, static_cast<uint32_t>(this->mode)); | ||||||
|  |   buffer.encode_uint32(3, static_cast<uint32_t>(this->configured_mode)); | ||||||
| } | } | ||||||
| void BluetoothScannerStateResponse::calculate_size(ProtoSize &size) const { | void BluetoothScannerStateResponse::calculate_size(ProtoSize &size) const { | ||||||
|   size.add_uint32(1, static_cast<uint32_t>(this->state)); |   size.add_uint32(1, static_cast<uint32_t>(this->state)); | ||||||
|   size.add_uint32(1, static_cast<uint32_t>(this->mode)); |   size.add_uint32(1, static_cast<uint32_t>(this->mode)); | ||||||
|  |   size.add_uint32(1, static_cast<uint32_t>(this->configured_mode)); | ||||||
| } | } | ||||||
| bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { | bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { | ||||||
|   switch (field_id) { |   switch (field_id) { | ||||||
|   | |||||||
| @@ -2217,12 +2217,13 @@ class BluetoothDeviceClearCacheResponse final : public ProtoMessage { | |||||||
| class BluetoothScannerStateResponse final : public ProtoMessage { | class BluetoothScannerStateResponse final : public ProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint8_t MESSAGE_TYPE = 126; |   static constexpr uint8_t MESSAGE_TYPE = 126; | ||||||
|   static constexpr uint8_t ESTIMATED_SIZE = 4; |   static constexpr uint8_t ESTIMATED_SIZE = 6; | ||||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   const char *message_name() const override { return "bluetooth_scanner_state_response"; } |   const char *message_name() const override { return "bluetooth_scanner_state_response"; } | ||||||
| #endif | #endif | ||||||
|   enums::BluetoothScannerState state{}; |   enums::BluetoothScannerState state{}; | ||||||
|   enums::BluetoothScannerMode mode{}; |   enums::BluetoothScannerMode mode{}; | ||||||
|  |   enums::BluetoothScannerMode configured_mode{}; | ||||||
|   void encode(ProtoWriteBuffer buffer) const override; |   void encode(ProtoWriteBuffer buffer) const override; | ||||||
|   void calculate_size(ProtoSize &size) const override; |   void calculate_size(ProtoSize &size) const override; | ||||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   | |||||||
| @@ -1707,6 +1707,7 @@ void BluetoothScannerStateResponse::dump_to(std::string &out) const { | |||||||
|   MessageDumpHelper helper(out, "BluetoothScannerStateResponse"); |   MessageDumpHelper helper(out, "BluetoothScannerStateResponse"); | ||||||
|   dump_field(out, "state", static_cast<enums::BluetoothScannerState>(this->state)); |   dump_field(out, "state", static_cast<enums::BluetoothScannerState>(this->state)); | ||||||
|   dump_field(out, "mode", static_cast<enums::BluetoothScannerMode>(this->mode)); |   dump_field(out, "mode", static_cast<enums::BluetoothScannerMode>(this->mode)); | ||||||
|  |   dump_field(out, "configured_mode", static_cast<enums::BluetoothScannerMode>(this->configured_mode)); | ||||||
| } | } | ||||||
| void BluetoothScannerSetModeRequest::dump_to(std::string &out) const { | void BluetoothScannerSetModeRequest::dump_to(std::string &out) const { | ||||||
|   MessageDumpHelper helper(out, "BluetoothScannerSetModeRequest"); |   MessageDumpHelper helper(out, "BluetoothScannerSetModeRequest"); | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_LN882X, |     PLATFORM_LN882X, | ||||||
|     PLATFORM_RTL87XX, |     PLATFORM_RTL87XX, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
|  |  | ||||||
| @@ -27,7 +27,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(200.0) | @coroutine_with_priority(CoroPriority.NETWORK_TRANSPORT) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     if CORE.is_esp32 or CORE.is_libretiny: |     if CORE.is_esp32 or CORE.is_libretiny: | ||||||
|         # https://github.com/ESP32Async/AsyncTCP |         # https://github.com/ESP32Async/AsyncTCP | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ from esphome import automation | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ID, CONF_MIC_GAIN | from esphome.const import CONF_ID, CONF_MIC_GAIN | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@kbx81"] | CODEOWNERS = ["@kbx81"] | ||||||
| IS_PLATFORM_COMPONENT = True | IS_PLATFORM_COMPONENT = True | ||||||
| @@ -35,7 +35,7 @@ async def audio_adc_set_mic_gain_to_code(config, action_id, template_arg, args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_define("USE_AUDIO_ADC") |     cg.add_define("USE_AUDIO_ADC") | ||||||
|     cg.add_global(audio_adc_ns.using) |     cg.add_global(audio_adc_ns.using) | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ from esphome.automation import maybe_simple_id | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ID, CONF_VOLUME | from esphome.const import CONF_ID, CONF_VOLUME | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@kbx81"] | CODEOWNERS = ["@kbx81"] | ||||||
| IS_PLATFORM_COMPONENT = True | IS_PLATFORM_COMPONENT = True | ||||||
| @@ -51,7 +51,7 @@ async def audio_dac_set_volume_to_code(config, action_id, template_arg, args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_define("USE_AUDIO_DAC") |     cg.add_define("USE_AUDIO_DAC") | ||||||
|     cg.add_global(audio_dac_ns.using) |     cg.add_global(audio_dac_ns.using) | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_VIBRATION, |     DEVICE_CLASS_VIBRATION, | ||||||
|     DEVICE_CLASS_WINDOW, |     DEVICE_CLASS_WINDOW, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
| from esphome.util import Registry | from esphome.util import Registry | ||||||
| @@ -652,7 +652,7 @@ async def binary_sensor_is_off_to_code(config, condition_id, template_arg, args) | |||||||
|     return cg.new_Pvariable(condition_id, template_arg, paren, False) |     return cg.new_Pvariable(condition_id, template_arg, paren, False) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(binary_sensor_ns.using) |     cg.add_global(binary_sensor_ns.using) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ void log_binary_sensor(const char *tag, const char *prefix, const char *type, Bi | |||||||
|  |  | ||||||
|   ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); |   ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); | ||||||
|  |  | ||||||
|   if (!obj->get_device_class().empty()) { |   if (!obj->get_device_class_ref().empty()) { | ||||||
|     ESP_LOGCONFIG(tag, "%s  Device Class: '%s'", prefix, obj->get_device_class().c_str()); |     ESP_LOGCONFIG(tag, "%s  Device Class: '%s'", prefix, obj->get_device_class_ref().c_str()); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,6 +24,9 @@ void BluetoothProxy::setup() { | |||||||
|   this->connections_free_response_.limit = BLUETOOTH_PROXY_MAX_CONNECTIONS; |   this->connections_free_response_.limit = BLUETOOTH_PROXY_MAX_CONNECTIONS; | ||||||
|   this->connections_free_response_.free = BLUETOOTH_PROXY_MAX_CONNECTIONS; |   this->connections_free_response_.free = BLUETOOTH_PROXY_MAX_CONNECTIONS; | ||||||
|  |  | ||||||
|  |   // Capture the configured scan mode from YAML before any API changes | ||||||
|  |   this->configured_scan_active_ = this->parent_->get_scan_active(); | ||||||
|  |  | ||||||
|   this->parent_->add_scanner_state_callback([this](esp32_ble_tracker::ScannerState state) { |   this->parent_->add_scanner_state_callback([this](esp32_ble_tracker::ScannerState state) { | ||||||
|     if (this->api_connection_ != nullptr) { |     if (this->api_connection_ != nullptr) { | ||||||
|       this->send_bluetooth_scanner_state_(state); |       this->send_bluetooth_scanner_state_(state); | ||||||
| @@ -36,6 +39,9 @@ void BluetoothProxy::send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerSta | |||||||
|   resp.state = static_cast<api::enums::BluetoothScannerState>(state); |   resp.state = static_cast<api::enums::BluetoothScannerState>(state); | ||||||
|   resp.mode = this->parent_->get_scan_active() ? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE |   resp.mode = this->parent_->get_scan_active() ? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE | ||||||
|                                                : api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE; |                                                : api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE; | ||||||
|  |   resp.configured_mode = this->configured_scan_active_ | ||||||
|  |                              ? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE | ||||||
|  |                              : api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE; | ||||||
|   this->api_connection_->send_message(resp, api::BluetoothScannerStateResponse::MESSAGE_TYPE); |   this->api_connection_->send_message(resp, api::BluetoothScannerStateResponse::MESSAGE_TYPE); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -161,7 +161,8 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, publ | |||||||
|   // Group 4: 1-byte types grouped together |   // Group 4: 1-byte types grouped together | ||||||
|   bool active_; |   bool active_; | ||||||
|   uint8_t connection_count_{0}; |   uint8_t connection_count_{0}; | ||||||
|   // 2 bytes used, 2 bytes padding |   bool configured_scan_active_{false};  // Configured scan mode from YAML | ||||||
|  |   // 3 bytes used, 1 byte padding | ||||||
| }; | }; | ||||||
|  |  | ||||||
| extern BluetoothProxy *global_bluetooth_proxy;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) | extern BluetoothProxy *global_bluetooth_proxy;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_RESTART, |     DEVICE_CLASS_RESTART, | ||||||
|     DEVICE_CLASS_UPDATE, |     DEVICE_CLASS_UPDATE, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -134,6 +134,6 @@ async def button_press_to_code(config, action_id, template_arg, args): | |||||||
|     return cg.new_Pvariable(action_id, template_arg, paren) |     return cg.new_Pvariable(action_id, template_arg, paren) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(button_ns.using) |     cg.add_global(button_ns.using) | ||||||
|   | |||||||
| @@ -14,8 +14,8 @@ void log_button(const char *tag, const char *prefix, const char *type, Button *o | |||||||
|  |  | ||||||
|   ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); |   ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); | ||||||
|  |  | ||||||
|   if (!obj->get_icon().empty()) { |   if (!obj->get_icon_ref().empty()) { | ||||||
|     ESP_LOGCONFIG(tag, "%s  Icon: '%s'", prefix, obj->get_icon().c_str()); |     ESP_LOGCONFIG(tag, "%s  Icon: '%s'", prefix, obj->get_icon_ref().c_str()); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								esphome/components/camera/buffer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								esphome/components/camera/buffer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <cinttypes> | ||||||
|  | #include <cstddef> | ||||||
|  |  | ||||||
|  | namespace esphome::camera { | ||||||
|  |  | ||||||
|  | /// Interface for a generic buffer that stores image data. | ||||||
|  | class Buffer { | ||||||
|  |  public: | ||||||
|  |   /// Returns a pointer to the buffer's data. | ||||||
|  |   virtual uint8_t *get_data_buffer() = 0; | ||||||
|  |   /// Returns the length of the buffer in bytes. | ||||||
|  |   virtual size_t get_data_length() = 0; | ||||||
|  |   virtual ~Buffer() = default; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace esphome::camera | ||||||
							
								
								
									
										20
									
								
								esphome/components/camera/buffer_impl.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								esphome/components/camera/buffer_impl.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | #include "buffer_impl.h" | ||||||
|  |  | ||||||
|  | namespace esphome::camera { | ||||||
|  |  | ||||||
|  | BufferImpl::BufferImpl(size_t size) { | ||||||
|  |   this->data_ = this->allocator_.allocate(size); | ||||||
|  |   this->size_ = size; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | BufferImpl::BufferImpl(CameraImageSpec *spec) { | ||||||
|  |   this->data_ = this->allocator_.allocate(spec->bytes_per_image()); | ||||||
|  |   this->size_ = spec->bytes_per_image(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | BufferImpl::~BufferImpl() { | ||||||
|  |   if (this->data_ != nullptr) | ||||||
|  |     this->allocator_.deallocate(this->data_, this->size_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace esphome::camera | ||||||
							
								
								
									
										26
									
								
								esphome/components/camera/buffer_impl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								esphome/components/camera/buffer_impl.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "buffer.h" | ||||||
|  | #include "camera.h" | ||||||
|  |  | ||||||
|  | namespace esphome::camera { | ||||||
|  |  | ||||||
|  | /// Default implementation of Buffer Interface. | ||||||
|  | /// Uses a RAMAllocator for memory reservation. | ||||||
|  | class BufferImpl : public Buffer { | ||||||
|  |  public: | ||||||
|  |   explicit BufferImpl(size_t size); | ||||||
|  |   explicit BufferImpl(CameraImageSpec *spec); | ||||||
|  |   // -------- Buffer -------- | ||||||
|  |   uint8_t *get_data_buffer() override { return data_; } | ||||||
|  |   size_t get_data_length() override { return size_; } | ||||||
|  |   // ------------------------ | ||||||
|  |   ~BufferImpl() override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   RAMAllocator<uint8_t> allocator_; | ||||||
|  |   size_t size_{}; | ||||||
|  |   uint8_t *data_{}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace esphome::camera | ||||||
| @@ -15,6 +15,26 @@ namespace camera { | |||||||
|  */ |  */ | ||||||
| enum CameraRequester : uint8_t { IDLE, API_REQUESTER, WEB_REQUESTER }; | enum CameraRequester : uint8_t { IDLE, API_REQUESTER, WEB_REQUESTER }; | ||||||
|  |  | ||||||
|  | /// Enumeration of different pixel formats. | ||||||
|  | enum PixelFormat : uint8_t { | ||||||
|  |   PIXEL_FORMAT_GRAYSCALE = 0,  ///< 8-bit grayscale. | ||||||
|  |   PIXEL_FORMAT_RGB565,         ///< 16-bit RGB (5-6-5). | ||||||
|  |   PIXEL_FORMAT_BGR888,         ///< RGB pixel data in 8-bit format, stored as B, G, R (1 byte each). | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /// Returns string name for a given PixelFormat. | ||||||
|  | inline const char *to_string(PixelFormat format) { | ||||||
|  |   switch (format) { | ||||||
|  |     case PIXEL_FORMAT_GRAYSCALE: | ||||||
|  |       return "PIXEL_FORMAT_GRAYSCALE"; | ||||||
|  |     case PIXEL_FORMAT_RGB565: | ||||||
|  |       return "PIXEL_FORMAT_RGB565"; | ||||||
|  |     case PIXEL_FORMAT_BGR888: | ||||||
|  |       return "PIXEL_FORMAT_BGR888"; | ||||||
|  |   } | ||||||
|  |   return "PIXEL_FORMAT_UNKNOWN"; | ||||||
|  | } | ||||||
|  |  | ||||||
| /** Abstract camera image base class. | /** Abstract camera image base class. | ||||||
|  *  Encapsulates the JPEG encoded data and it is shared among |  *  Encapsulates the JPEG encoded data and it is shared among | ||||||
|  *  all connected clients. |  *  all connected clients. | ||||||
| @@ -43,6 +63,29 @@ class CameraImageReader { | |||||||
|   virtual ~CameraImageReader() {} |   virtual ~CameraImageReader() {} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /// Specification of a caputured camera image. | ||||||
|  | /// This struct defines the format and size details for images captured | ||||||
|  | /// or processed by a camera component. | ||||||
|  | struct CameraImageSpec { | ||||||
|  |   uint16_t width; | ||||||
|  |   uint16_t height; | ||||||
|  |   PixelFormat format; | ||||||
|  |   size_t bytes_per_pixel() { | ||||||
|  |     switch (format) { | ||||||
|  |       case PIXEL_FORMAT_GRAYSCALE: | ||||||
|  |         return 1; | ||||||
|  |       case PIXEL_FORMAT_RGB565: | ||||||
|  |         return 2; | ||||||
|  |       case PIXEL_FORMAT_BGR888: | ||||||
|  |         return 3; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 1; | ||||||
|  |   } | ||||||
|  |   size_t bytes_per_row() { return bytes_per_pixel() * width; } | ||||||
|  |   size_t bytes_per_image() { return bytes_per_pixel() * width * height; } | ||||||
|  | }; | ||||||
|  |  | ||||||
| /** Abstract camera base class. Collaborates with API. | /** Abstract camera base class. Collaborates with API. | ||||||
|  *  1) API server starts and installs callback (add_image_callback) |  *  1) API server starts and installs callback (add_image_callback) | ||||||
|  *     which is called by the camera when a new image is available. |  *     which is called by the camera when a new image is available. | ||||||
|   | |||||||
							
								
								
									
										69
									
								
								esphome/components/camera/encoder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								esphome/components/camera/encoder.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "buffer.h" | ||||||
|  | #include "camera.h" | ||||||
|  |  | ||||||
|  | namespace esphome::camera { | ||||||
|  |  | ||||||
|  | /// Result codes from the encoder used to control camera pipeline flow. | ||||||
|  | enum EncoderError : uint8_t { | ||||||
|  |   ENCODER_ERROR_SUCCESS = 0,   ///< Encoding succeeded, continue pipeline normally. | ||||||
|  |   ENCODER_ERROR_SKIP_FRAME,    ///< Skip current frame, try again on next frame. | ||||||
|  |   ENCODER_ERROR_RETRY_FRAME,   ///< Retry current frame, after buffer growth or for incremental encoding. | ||||||
|  |   ENCODER_ERROR_CONFIGURATION  ///< Fatal config error, shut down pipeline. | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /// Converts EncoderError to string. | ||||||
|  | inline const char *to_string(EncoderError error) { | ||||||
|  |   switch (error) { | ||||||
|  |     case ENCODER_ERROR_SUCCESS: | ||||||
|  |       return "ENCODER_ERROR_SUCCESS"; | ||||||
|  |     case ENCODER_ERROR_SKIP_FRAME: | ||||||
|  |       return "ENCODER_ERROR_SKIP_FRAME"; | ||||||
|  |     case ENCODER_ERROR_RETRY_FRAME: | ||||||
|  |       return "ENCODER_ERROR_RETRY_FRAME"; | ||||||
|  |     case ENCODER_ERROR_CONFIGURATION: | ||||||
|  |       return "ENCODER_ERROR_CONFIGURATION"; | ||||||
|  |   } | ||||||
|  |   return "ENCODER_ERROR_INVALID"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Interface for an encoder buffer supporting resizing and variable-length data. | ||||||
|  | class EncoderBuffer { | ||||||
|  |  public: | ||||||
|  |   ///  Sets logical buffer size, reallocates if needed. | ||||||
|  |   ///  @param size Required size in bytes. | ||||||
|  |   ///  @return true on success, false on allocation failure. | ||||||
|  |   virtual bool set_buffer_size(size_t size) = 0; | ||||||
|  |  | ||||||
|  |   /// Returns a pointer to the buffer data. | ||||||
|  |   virtual uint8_t *get_data() const = 0; | ||||||
|  |  | ||||||
|  |   /// Returns number of bytes currently used. | ||||||
|  |   virtual size_t get_size() const = 0; | ||||||
|  |  | ||||||
|  |   ///  Returns total allocated buffer size. | ||||||
|  |   virtual size_t get_max_size() const = 0; | ||||||
|  |  | ||||||
|  |   virtual ~EncoderBuffer() = default; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /// Interface for image encoders used in a camera pipeline. | ||||||
|  | class Encoder { | ||||||
|  |  public: | ||||||
|  |   /// Encodes pixel data from a previous camera pipeline stage. | ||||||
|  |   /// @param spec Specification of the input pixel data. | ||||||
|  |   /// @param pixels Image pixels in RGB or grayscale format, as specified in @p spec. | ||||||
|  |   /// @return EncoderError Indicating the result of the encoding operation. | ||||||
|  |   virtual EncoderError encode_pixels(CameraImageSpec *spec, Buffer *pixels) = 0; | ||||||
|  |  | ||||||
|  |   /// Returns the encoder's output buffer. | ||||||
|  |   /// @return Pointer to an EncoderBuffer containing encoded data. | ||||||
|  |   virtual EncoderBuffer *get_output_buffer() = 0; | ||||||
|  |  | ||||||
|  |   ///  Prints the encoder's configuration to the log. | ||||||
|  |   virtual void dump_config() = 0; | ||||||
|  |   virtual ~Encoder() = default; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace esphome::camera | ||||||
							
								
								
									
										62
									
								
								esphome/components/camera_encoder/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								esphome/components/camera_encoder/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components.esp32 import add_idf_component | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import CONF_BUFFER_SIZE, CONF_ID, CONF_TYPE | ||||||
|  | from esphome.core import CORE | ||||||
|  | from esphome.types import ConfigType | ||||||
|  |  | ||||||
|  | CODEOWNERS = ["@DT-art1"] | ||||||
|  |  | ||||||
|  | AUTO_LOAD = ["camera"] | ||||||
|  |  | ||||||
|  | CONF_BUFFER_EXPAND_SIZE = "buffer_expand_size" | ||||||
|  | CONF_ENCODER_BUFFER_ID = "encoder_buffer_id" | ||||||
|  | CONF_QUALITY = "quality" | ||||||
|  |  | ||||||
|  | ESP32_CAMERA_ENCODER = "esp32_camera" | ||||||
|  |  | ||||||
|  | camera_ns = cg.esphome_ns.namespace("camera") | ||||||
|  | camera_encoder_ns = cg.esphome_ns.namespace("camera_encoder") | ||||||
|  |  | ||||||
|  | Encoder = camera_ns.class_("Encoder") | ||||||
|  | EncoderBufferImpl = camera_encoder_ns.class_("EncoderBufferImpl") | ||||||
|  |  | ||||||
|  | ESP32CameraJPEGEncoder = camera_encoder_ns.class_("ESP32CameraJPEGEncoder", Encoder) | ||||||
|  |  | ||||||
|  | MAX_JPEG_BUFFER_SIZE_2MB = 2 * 1024 * 1024 | ||||||
|  |  | ||||||
|  | ESP32_CAMERA_ENCODER_SCHEMA = cv.Schema( | ||||||
|  |     { | ||||||
|  |         cv.GenerateID(): cv.declare_id(ESP32CameraJPEGEncoder), | ||||||
|  |         cv.Optional(CONF_QUALITY, default=80): cv.int_range(1, 100), | ||||||
|  |         cv.Optional(CONF_BUFFER_SIZE, default=4096): cv.int_range( | ||||||
|  |             1024, MAX_JPEG_BUFFER_SIZE_2MB | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_BUFFER_EXPAND_SIZE, default=1024): cv.int_range( | ||||||
|  |             0, MAX_JPEG_BUFFER_SIZE_2MB | ||||||
|  |         ), | ||||||
|  |         cv.GenerateID(CONF_ENCODER_BUFFER_ID): cv.declare_id(EncoderBufferImpl), | ||||||
|  |     } | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = cv.typed_schema( | ||||||
|  |     { | ||||||
|  |         ESP32_CAMERA_ENCODER: ESP32_CAMERA_ENCODER_SCHEMA, | ||||||
|  |     }, | ||||||
|  |     default_type=ESP32_CAMERA_ENCODER, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config: ConfigType) -> None: | ||||||
|  |     buffer = cg.new_Pvariable(config[CONF_ENCODER_BUFFER_ID]) | ||||||
|  |     cg.add(buffer.set_buffer_size(config[CONF_BUFFER_SIZE])) | ||||||
|  |     if config[CONF_TYPE] == ESP32_CAMERA_ENCODER: | ||||||
|  |         if CORE.using_esp_idf: | ||||||
|  |             add_idf_component(name="espressif/esp32-camera", ref="2.1.0") | ||||||
|  |         cg.add_build_flag("-DUSE_ESP32_CAMERA_JPEG_ENCODER") | ||||||
|  |         var = cg.new_Pvariable( | ||||||
|  |             config[CONF_ID], | ||||||
|  |             config[CONF_QUALITY], | ||||||
|  |             buffer, | ||||||
|  |         ) | ||||||
|  |         cg.add(var.set_buffer_expand_size(config[CONF_BUFFER_EXPAND_SIZE])) | ||||||
							
								
								
									
										23
									
								
								esphome/components/camera_encoder/encoder_buffer_impl.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								esphome/components/camera_encoder/encoder_buffer_impl.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | #include "encoder_buffer_impl.h" | ||||||
|  |  | ||||||
|  | namespace esphome::camera_encoder { | ||||||
|  |  | ||||||
|  | bool EncoderBufferImpl::set_buffer_size(size_t size) { | ||||||
|  |   if (size > this->capacity_) { | ||||||
|  |     uint8_t *p = this->allocator_.reallocate(this->data_, size); | ||||||
|  |     if (p == nullptr) | ||||||
|  |       return false; | ||||||
|  |  | ||||||
|  |     this->data_ = p; | ||||||
|  |     this->capacity_ = size; | ||||||
|  |   } | ||||||
|  |   this->size_ = size; | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | EncoderBufferImpl::~EncoderBufferImpl() { | ||||||
|  |   if (this->data_ != nullptr) | ||||||
|  |     this->allocator_.deallocate(this->data_, this->capacity_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace esphome::camera_encoder | ||||||
							
								
								
									
										25
									
								
								esphome/components/camera_encoder/encoder_buffer_impl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								esphome/components/camera_encoder/encoder_buffer_impl.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/camera/encoder.h" | ||||||
|  | #include "esphome/core/helpers.h" | ||||||
|  |  | ||||||
|  | namespace esphome::camera_encoder { | ||||||
|  |  | ||||||
|  | class EncoderBufferImpl : public camera::EncoderBuffer { | ||||||
|  |  public: | ||||||
|  |   // --- EncoderBuffer  --- | ||||||
|  |   bool set_buffer_size(size_t size) override; | ||||||
|  |   uint8_t *get_data() const override { return this->data_; } | ||||||
|  |   size_t get_size() const override { return this->size_; } | ||||||
|  |   size_t get_max_size() const override { return this->capacity_; } | ||||||
|  |   // ---------------------- | ||||||
|  |   ~EncoderBufferImpl() override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   RAMAllocator<uint8_t> allocator_; | ||||||
|  |   size_t capacity_{}; | ||||||
|  |   size_t size_{}; | ||||||
|  |   uint8_t *data_{}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace esphome::camera_encoder | ||||||
| @@ -0,0 +1,82 @@ | |||||||
|  | #ifdef USE_ESP32_CAMERA_JPEG_ENCODER | ||||||
|  |  | ||||||
|  | #include "esp32_camera_jpeg_encoder.h" | ||||||
|  |  | ||||||
|  | namespace esphome::camera_encoder { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "camera_encoder"; | ||||||
|  |  | ||||||
|  | ESP32CameraJPEGEncoder::ESP32CameraJPEGEncoder(uint8_t quality, camera::EncoderBuffer *output) { | ||||||
|  |   this->quality_ = quality; | ||||||
|  |   this->output_ = output; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | camera::EncoderError ESP32CameraJPEGEncoder::encode_pixels(camera::CameraImageSpec *spec, camera::Buffer *pixels) { | ||||||
|  |   this->bytes_written_ = 0; | ||||||
|  |   this->out_of_output_memory_ = false; | ||||||
|  |   bool success = fmt2jpg_cb(pixels->get_data_buffer(), pixels->get_data_length(), spec->width, spec->height, | ||||||
|  |                             to_internal_(spec->format), this->quality_, callback_, this); | ||||||
|  |  | ||||||
|  |   if (!success) | ||||||
|  |     return camera::ENCODER_ERROR_CONFIGURATION; | ||||||
|  |  | ||||||
|  |   if (this->out_of_output_memory_) { | ||||||
|  |     if (this->buffer_expand_size_ <= 0) | ||||||
|  |       return camera::ENCODER_ERROR_SKIP_FRAME; | ||||||
|  |  | ||||||
|  |     size_t current_size = this->output_->get_max_size(); | ||||||
|  |     size_t new_size = this->output_->get_max_size() + this->buffer_expand_size_; | ||||||
|  |     if (!this->output_->set_buffer_size(new_size)) { | ||||||
|  |       ESP_LOGE(TAG, "Failed to expand output buffer."); | ||||||
|  |       this->buffer_expand_size_ = 0; | ||||||
|  |       return camera::ENCODER_ERROR_SKIP_FRAME; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ESP_LOGD(TAG, "Output buffer expanded (%u -> %u).", current_size, this->output_->get_max_size()); | ||||||
|  |     return camera::ENCODER_ERROR_RETRY_FRAME; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this->output_->set_buffer_size(this->bytes_written_); | ||||||
|  |   return camera::ENCODER_ERROR_SUCCESS; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ESP32CameraJPEGEncoder::dump_config() { | ||||||
|  |   ESP_LOGCONFIG(TAG, | ||||||
|  |                 "ESP32 Camera JPEG Encoder:\n" | ||||||
|  |                 "  Size: %zu\n" | ||||||
|  |                 "  Quality: %d\n" | ||||||
|  |                 "  Expand: %d\n", | ||||||
|  |                 this->output_->get_max_size(), this->quality_, this->buffer_expand_size_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | size_t ESP32CameraJPEGEncoder::callback_(void *arg, size_t index, const void *data, size_t len) { | ||||||
|  |   ESP32CameraJPEGEncoder *that = reinterpret_cast<ESP32CameraJPEGEncoder *>(arg); | ||||||
|  |   uint8_t *buffer = that->output_->get_data(); | ||||||
|  |   size_t buffer_length = that->output_->get_max_size(); | ||||||
|  |   if (index + len > buffer_length) { | ||||||
|  |     that->out_of_output_memory_ = true; | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   std::memcpy(&buffer[index], data, len); | ||||||
|  |   that->bytes_written_ += len; | ||||||
|  |   return len; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pixformat_t ESP32CameraJPEGEncoder::to_internal_(camera::PixelFormat format) { | ||||||
|  |   switch (format) { | ||||||
|  |     case camera::PIXEL_FORMAT_GRAYSCALE: | ||||||
|  |       return PIXFORMAT_GRAYSCALE; | ||||||
|  |     case camera::PIXEL_FORMAT_RGB565: | ||||||
|  |       return PIXFORMAT_RGB565; | ||||||
|  |     // Internal representation for RGB is in byte order: B, G, R | ||||||
|  |     case camera::PIXEL_FORMAT_BGR888: | ||||||
|  |       return PIXFORMAT_RGB888; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return PIXFORMAT_GRAYSCALE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace esphome::camera_encoder | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -0,0 +1,39 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #ifdef USE_ESP32_CAMERA_JPEG_ENCODER | ||||||
|  |  | ||||||
|  | #include <esp_camera.h> | ||||||
|  |  | ||||||
|  | #include "esphome/components/camera/encoder.h" | ||||||
|  |  | ||||||
|  | namespace esphome::camera_encoder { | ||||||
|  |  | ||||||
|  | /// Encoder that uses the software-based JPEG implementation from Espressif's esp32-camera component. | ||||||
|  | class ESP32CameraJPEGEncoder : public camera::Encoder { | ||||||
|  |  public: | ||||||
|  |   /// Constructs a ESP32CameraJPEGEncoder instance. | ||||||
|  |   /// @param quality Sets the quality of the encoded image (1-100). | ||||||
|  |   /// @param output Pointer to preallocated output buffer. | ||||||
|  |   ESP32CameraJPEGEncoder(uint8_t quality, camera::EncoderBuffer *output); | ||||||
|  |   /// Sets the number of bytes to expand the output buffer on underflow during encoding. | ||||||
|  |   /// @param buffer_expand_size Number of bytes to expand the buffer. | ||||||
|  |   void set_buffer_expand_size(size_t buffer_expand_size) { this->buffer_expand_size_ = buffer_expand_size; } | ||||||
|  |   // -------- Encoder -------- | ||||||
|  |   camera::EncoderError encode_pixels(camera::CameraImageSpec *spec, camera::Buffer *pixels) override; | ||||||
|  |   camera::EncoderBuffer *get_output_buffer() override { return output_; } | ||||||
|  |   void dump_config() override; | ||||||
|  |   // ------------------------- | ||||||
|  |  protected: | ||||||
|  |   static size_t callback_(void *arg, size_t index, const void *data, size_t len); | ||||||
|  |   pixformat_t to_internal_(camera::PixelFormat format); | ||||||
|  |  | ||||||
|  |   camera::EncoderBuffer *output_{}; | ||||||
|  |   size_t buffer_expand_size_{}; | ||||||
|  |   size_t bytes_written_{}; | ||||||
|  |   uint8_t quality_{}; | ||||||
|  |   bool out_of_output_memory_{}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace esphome::camera_encoder | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -10,7 +10,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_LN882X, |     PLATFORM_LN882X, | ||||||
|     PLATFORM_RTL87XX, |     PLATFORM_RTL87XX, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| AUTO_LOAD = ["web_server_base", "ota.web_server"] | AUTO_LOAD = ["web_server_base", "ota.web_server"] | ||||||
| DEPENDENCIES = ["wifi"] | DEPENDENCIES = ["wifi"] | ||||||
| @@ -40,7 +40,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(64.0) | @coroutine_with_priority(CoroPriority.COMMUNICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     paren = await cg.get_variable(config[CONF_WEB_SERVER_BASE_ID]) |     paren = await cg.get_variable(config[CONF_WEB_SERVER_BASE_ID]) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ from esphome.const import ( | |||||||
|     CONF_VISUAL, |     CONF_VISUAL, | ||||||
|     CONF_WEB_SERVER, |     CONF_WEB_SERVER, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -517,6 +517,6 @@ async def climate_control_to_code(config, action_id, template_arg, args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(climate_ns.using) |     cg.add_global(climate_ns.using) | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_SHUTTER, |     DEVICE_CLASS_SHUTTER, | ||||||
|     DEVICE_CLASS_WINDOW, |     DEVICE_CLASS_WINDOW, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -263,6 +263,6 @@ async def cover_control_to_code(config, action_id, template_arg, args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(cover_ns.using) |     cg.add_global(cover_ns.using) | ||||||
|   | |||||||
| @@ -19,8 +19,8 @@ const extern float COVER_CLOSED; | |||||||
|     if (traits_.get_is_assumed_state()) { \ |     if (traits_.get_is_assumed_state()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Assumed State: YES", prefix); \ |       ESP_LOGCONFIG(TAG, "%s  Assumed State: YES", prefix); \ | ||||||
|     } \ |     } \ | ||||||
|     if (!(obj)->get_device_class().empty()) { \ |     if (!(obj)->get_device_class_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ from esphome.const import ( | |||||||
|     CONF_WEB_SERVER, |     CONF_WEB_SERVER, | ||||||
|     CONF_YEAR, |     CONF_YEAR, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -172,7 +172,7 @@ async def new_datetime(config, *args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(datetime_ns.using) |     cg.add_global(datetime_ns.using) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,8 +16,8 @@ namespace datetime { | |||||||
| #define LOG_DATETIME_DATE(prefix, type, obj) \ | #define LOG_DATETIME_DATE(prefix, type, obj) \ | ||||||
|   if ((obj) != nullptr) { \ |   if ((obj) != nullptr) { \ | ||||||
|     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ |     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ | ||||||
|     if (!(obj)->get_icon().empty()) { \ |     if (!(obj)->get_icon_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,8 +16,8 @@ namespace datetime { | |||||||
| #define LOG_DATETIME_DATETIME(prefix, type, obj) \ | #define LOG_DATETIME_DATETIME(prefix, type, obj) \ | ||||||
|   if ((obj) != nullptr) { \ |   if ((obj) != nullptr) { \ | ||||||
|     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ |     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ | ||||||
|     if (!(obj)->get_icon().empty()) { \ |     if (!(obj)->get_icon_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,8 +16,8 @@ namespace datetime { | |||||||
| #define LOG_DATETIME_TIME(prefix, type, obj) \ | #define LOG_DATETIME_TIME(prefix, type, obj) \ | ||||||
|   if ((obj) != nullptr) { \ |   if ((obj) != nullptr) { \ | ||||||
|     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ |     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ | ||||||
|     if (!(obj)->get_icon().empty()) { \ |     if (!(obj)->get_icon_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ from esphome.const import ( | |||||||
|     CONF_UPDATE_INTERVAL, |     CONF_UPDATE_INTERVAL, | ||||||
|     SCHEDULER_DONT_RUN, |     SCHEDULER_DONT_RUN, | ||||||
| ) | ) | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| IS_PLATFORM_COMPONENT = True | IS_PLATFORM_COMPONENT = True | ||||||
|  |  | ||||||
| @@ -176,7 +176,7 @@ async def display_page_show_to_code(config, action_id, template_arg, args): | |||||||
|     DisplayPageShowNextAction, |     DisplayPageShowNextAction, | ||||||
|     maybe_simple_id( |     maybe_simple_id( | ||||||
|         { |         { | ||||||
|             cv.Required(CONF_ID): cv.templatable(cv.use_id(Display)), |             cv.GenerateID(CONF_ID): cv.templatable(cv.use_id(Display)), | ||||||
|         } |         } | ||||||
|     ), |     ), | ||||||
| ) | ) | ||||||
| @@ -190,7 +190,7 @@ async def display_page_show_next_to_code(config, action_id, template_arg, args): | |||||||
|     DisplayPageShowPrevAction, |     DisplayPageShowPrevAction, | ||||||
|     maybe_simple_id( |     maybe_simple_id( | ||||||
|         { |         { | ||||||
|             cv.Required(CONF_ID): cv.templatable(cv.use_id(Display)), |             cv.GenerateID(CONF_ID): cv.templatable(cv.use_id(Display)), | ||||||
|         } |         } | ||||||
|     ), |     ), | ||||||
| ) | ) | ||||||
| @@ -218,7 +218,7 @@ async def display_is_displaying_page_to_code(config, condition_id, template_arg, | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(display_ns.using) |     cg.add_global(display_ns.using) | ||||||
|     cg.add_define("USE_DISPLAY") |     cg.add_define("USE_DISPLAY") | ||||||
|   | |||||||
| @@ -855,11 +855,6 @@ async def to_code(config): | |||||||
|  |  | ||||||
|         cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]]) |         cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]]) | ||||||
|  |  | ||||||
|         # platformio/toolchain-esp32ulp does not support linux_aarch64 yet and has not been updated for over 2 years |  | ||||||
|         # This is espressif's own published version which is more up to date. |  | ||||||
|         cg.add_platformio_option( |  | ||||||
|             "platform_packages", ["espressif/toolchain-esp32ulp@2.35.0-20220830"] |  | ||||||
|         ) |  | ||||||
|         add_idf_sdkconfig_option(f"CONFIG_IDF_TARGET_{variant}", True) |         add_idf_sdkconfig_option(f"CONFIG_IDF_TARGET_{variant}", True) | ||||||
|         add_idf_sdkconfig_option( |         add_idf_sdkconfig_option( | ||||||
|             f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True |             f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ from esphome.const import ( | |||||||
|     CONF_SERVICE_UUID, |     CONF_SERVICE_UUID, | ||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.enum import StrEnum | from esphome.enum import StrEnum | ||||||
| from esphome.types import ConfigType | from esphome.types import ConfigType | ||||||
|  |  | ||||||
| @@ -368,7 +368,7 @@ async def to_code(config): | |||||||
| # This needs to be run as a job with very low priority so that all components have | # This needs to be run as a job with very low priority so that all components have | ||||||
| # chance to call register_ble_tracker and register_client before the list is checked | # chance to call register_ble_tracker and register_client before the list is checked | ||||||
| # and added to the global defines list. | # and added to the global defines list. | ||||||
| @coroutine_with_priority(-1000) | @coroutine_with_priority(CoroPriority.FINAL) | ||||||
| async def _add_ble_features(): | async def _add_ble_features(): | ||||||
|     # Add feature-specific defines based on what's needed |     # Add feature-specific defines based on what's needed | ||||||
|     if BLEFeatures.ESP_BT_DEVICE in _required_features: |     if BLEFeatures.ESP_BT_DEVICE in _required_features: | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_ESP8266, |     PLATFORM_ESP8266, | ||||||
|     ThreadModel, |     ThreadModel, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.helpers import copy_file_if_changed | from esphome.helpers import copy_file_if_changed | ||||||
|  |  | ||||||
| from .boards import BOARDS, ESP8266_LD_SCRIPTS | from .boards import BOARDS, ESP8266_LD_SCRIPTS | ||||||
| @@ -176,7 +176,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(1000) | @coroutine_with_priority(CoroPriority.PLATFORM) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add(esp8266_ns.setup_preferences()) |     cg.add(esp8266_ns.setup_preferences()) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ from esphome.const import ( | |||||||
|     CONF_PULLUP, |     CONF_PULLUP, | ||||||
|     PLATFORM_ESP8266, |     PLATFORM_ESP8266, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| from . import boards | from . import boards | ||||||
| from .const import KEY_BOARD, KEY_ESP8266, KEY_PIN_INITIAL_STATES, esp8266_ns | from .const import KEY_BOARD, KEY_ESP8266, KEY_PIN_INITIAL_STATES, esp8266_ns | ||||||
| @@ -188,7 +188,7 @@ async def esp8266_pin_to_code(config): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(-999.0) | @coroutine_with_priority(CoroPriority.WORKAROUNDS) | ||||||
| async def add_pin_initial_states_array(): | async def add_pin_initial_states_array(): | ||||||
|     # Add includes at the very end, so that they override everything |     # Add includes at the very end, so that they override everything | ||||||
|     initial_states: list[PinInitialState] = CORE.data[KEY_ESP8266][ |     initial_states: list[PinInitialState] = CORE.data[KEY_ESP8266][ | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ from esphome.const import ( | |||||||
|     CONF_SAFE_MODE, |     CONF_SAFE_MODE, | ||||||
|     CONF_VERSION, |     CONF_VERSION, | ||||||
| ) | ) | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import CoroPriority, coroutine_with_priority | ||||||
| import esphome.final_validate as fv | import esphome.final_validate as fv | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
| @@ -121,7 +121,7 @@ CONFIG_SCHEMA = ( | |||||||
| FINAL_VALIDATE_SCHEMA = ota_esphome_final_validate | FINAL_VALIDATE_SCHEMA = ota_esphome_final_validate | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(52.0) | @coroutine_with_priority(CoroPriority.COMMUNICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     cg.add(var.set_port(config[CONF_PORT])) |     cg.add(var.set_port(config[CONF_PORT])) | ||||||
|   | |||||||
| @@ -38,7 +38,12 @@ from esphome.const import ( | |||||||
|     KEY_CORE, |     KEY_CORE, | ||||||
|     KEY_FRAMEWORK_VERSION, |     KEY_FRAMEWORK_VERSION, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, TimePeriodMilliseconds, coroutine_with_priority | from esphome.core import ( | ||||||
|  |     CORE, | ||||||
|  |     CoroPriority, | ||||||
|  |     TimePeriodMilliseconds, | ||||||
|  |     coroutine_with_priority, | ||||||
|  | ) | ||||||
| import esphome.final_validate as fv | import esphome.final_validate as fv | ||||||
|  |  | ||||||
| CONFLICTS_WITH = ["wifi"] | CONFLICTS_WITH = ["wifi"] | ||||||
| @@ -289,7 +294,7 @@ def phy_register(address: int, value: int, page: int): | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(60.0) | @coroutine_with_priority(CoroPriority.COMMUNICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     await cg.register_component(var, config) |     await cg.register_component(var, config) | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_EMPTY, |     DEVICE_CLASS_EMPTY, | ||||||
|     DEVICE_CLASS_MOTION, |     DEVICE_CLASS_MOTION, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -143,6 +143,6 @@ async def event_fire_to_code(config, action_id, template_arg, args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(event_ns.using) |     cg.add_global(event_ns.using) | ||||||
|   | |||||||
| @@ -13,11 +13,11 @@ namespace event { | |||||||
| #define LOG_EVENT(prefix, type, obj) \ | #define LOG_EVENT(prefix, type, obj) \ | ||||||
|   if ((obj) != nullptr) { \ |   if ((obj) != nullptr) { \ | ||||||
|     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ |     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ | ||||||
|     if (!(obj)->get_icon().empty()) { \ |     if (!(obj)->get_icon_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|     if (!(obj)->get_device_class().empty()) { \ |     if (!(obj)->get_device_class_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ from esphome.const import ( | |||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     CONF_WEB_SERVER, |     CONF_WEB_SERVER, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
|  |  | ||||||
| IS_PLATFORM_COMPONENT = True | IS_PLATFORM_COMPONENT = True | ||||||
| @@ -398,6 +398,6 @@ async def fan_is_on_off_to_code(config, condition_id, template_arg, args): | |||||||
|     return cg.new_Pvariable(condition_id, template_arg, paren) |     return cg.new_Pvariable(condition_id, template_arg, paren) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(fan_ns.using) |     cg.add_global(fan_ns.using) | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ from esphome.const import ( | |||||||
|     CONF_TYPE, |     CONF_TYPE, | ||||||
|     CONF_VALUE, |     CONF_VALUE, | ||||||
| ) | ) | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| globals_ns = cg.esphome_ns.namespace("globals") | globals_ns = cg.esphome_ns.namespace("globals") | ||||||
| @@ -35,7 +35,7 @@ CONFIG_SCHEMA = cv.Schema( | |||||||
|  |  | ||||||
|  |  | ||||||
| # Run with low priority so that namespaces are registered first | # Run with low priority so that namespaces are registered first | ||||||
| @coroutine_with_priority(-100.0) | @coroutine_with_priority(CoroPriority.LATE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     type_ = cg.RawExpression(config[CONF_TYPE]) |     type_ = cg.RawExpression(config[CONF_TYPE]) | ||||||
|     restore = config[CONF_RESTORE_VALUE] |     restore = config[CONF_RESTORE_VALUE] | ||||||
|   | |||||||
| @@ -42,9 +42,10 @@ class HostPreferences : public ESPPreferences { | |||||||
|     if (len > 255) |     if (len > 255) | ||||||
|       return false; |       return false; | ||||||
|     this->setup_(); |     this->setup_(); | ||||||
|     if (this->data.count(key) == 0) |     auto it = this->data.find(key); | ||||||
|  |     if (it == this->data.end()) | ||||||
|       return false; |       return false; | ||||||
|     auto vec = this->data[key]; |     const auto &vec = it->second; | ||||||
|     if (vec.size() != len) |     if (vec.size() != len) | ||||||
|       return false; |       return false; | ||||||
|     memcpy(data, vec.data(), len); |     memcpy(data, vec.data(), len); | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import esphome.codegen as cg | |||||||
| from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code | from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ID, CONF_PASSWORD, CONF_URL, CONF_USERNAME | from esphome.const import CONF_ID, CONF_PASSWORD, CONF_URL, CONF_USERNAME | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| from .. import CONF_HTTP_REQUEST_ID, HttpRequestComponent, http_request_ns | from .. import CONF_HTTP_REQUEST_ID, HttpRequestComponent, http_request_ns | ||||||
|  |  | ||||||
| @@ -40,7 +40,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(52.0) | @coroutine_with_priority(CoroPriority.COMMUNICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     await ota_to_code(var, config) |     await ota_to_code(var, config) | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_RP2040, |     PLATFORM_RP2040, | ||||||
|     PlatformFramework, |     PlatformFramework, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| import esphome.final_validate as fv | import esphome.final_validate as fv | ||||||
|  |  | ||||||
| LOGGER = logging.getLogger(__name__) | LOGGER = logging.getLogger(__name__) | ||||||
| @@ -74,7 +74,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(1.0) | @coroutine_with_priority(CoroPriority.BUS) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(i2c_ns.using) |     cg.add_global(i2c_ns.using) | ||||||
|     cg.add_define("USE_I2C") |     cg.add_define("USE_I2C") | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| json_ns = cg.esphome_ns.namespace("json") | json_ns = cg.esphome_ns.namespace("json") | ||||||
| @@ -10,7 +10,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(1.0) | @coroutine_with_priority(CoroPriority.BUS) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_library("bblanchon/ArduinoJson", "7.4.2") |     cg.add_library("bblanchon/ArduinoJson", "7.4.2") | ||||||
|     cg.add_define("USE_JSON") |     cg.add_define("USE_JSON") | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ from esphome.const import ( | |||||||
|     CONF_WEB_SERVER, |     CONF_WEB_SERVER, | ||||||
|     CONF_WHITE, |     CONF_WHITE, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -283,6 +283,6 @@ async def new_light(config, *args): | |||||||
|     return output_var |     return output_var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(light_ns.using) |     cg.add_global(light_ns.using) | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ from esphome.const import ( | |||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     CONF_WEB_SERVER, |     CONF_WEB_SERVER, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -155,6 +155,6 @@ async def lock_is_off_to_code(config, condition_id, template_arg, args): | |||||||
|     return cg.new_Pvariable(condition_id, template_arg, paren, False) |     return cg.new_Pvariable(condition_id, template_arg, paren, False) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(lock_ns.using) |     cg.add_global(lock_ns.using) | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ class Lock; | |||||||
| #define LOG_LOCK(prefix, type, obj) \ | #define LOG_LOCK(prefix, type, obj) \ | ||||||
|   if ((obj) != nullptr) { \ |   if ((obj) != nullptr) { \ | ||||||
|     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ |     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ | ||||||
|     if (!(obj)->get_icon().empty()) { \ |     if (!(obj)->get_icon_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|     if ((obj)->traits.get_assumed_state()) { \ |     if ((obj)->traits.get_assumed_state()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Assumed State: YES", prefix); \ |       ESP_LOGCONFIG(TAG, "%s  Assumed State: YES", prefix); \ | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_RTL87XX, |     PLATFORM_RTL87XX, | ||||||
|     PlatformFramework, |     PlatformFramework, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, Lambda, coroutine_with_priority | from esphome.core import CORE, CoroPriority, Lambda, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| logger_ns = cg.esphome_ns.namespace("logger") | logger_ns = cg.esphome_ns.namespace("logger") | ||||||
| @@ -275,7 +275,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(90.0) | @coroutine_with_priority(CoroPriority.DIAGNOSTICS) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     baud_rate = config[CONF_BAUD_RATE] |     baud_rate = config[CONF_BAUD_RATE] | ||||||
|     level = config[CONF_LEVEL] |     level = config[CONF_LEVEL] | ||||||
|   | |||||||
| @@ -122,7 +122,7 @@ uint8_t Mcp4461Component::get_status_register_() { | |||||||
|   uint8_t addr = static_cast<uint8_t>(Mcp4461Addresses::MCP4461_STATUS); |   uint8_t addr = static_cast<uint8_t>(Mcp4461Addresses::MCP4461_STATUS); | ||||||
|   uint8_t reg = addr | static_cast<uint8_t>(Mcp4461Commands::READ); |   uint8_t reg = addr | static_cast<uint8_t>(Mcp4461Commands::READ); | ||||||
|   uint16_t buf; |   uint16_t buf; | ||||||
|   if (!this->read_byte_16(reg, &buf)) { |   if (!this->read_16_(reg, &buf)) { | ||||||
|     this->error_code_ = MCP4461_STATUS_REGISTER_ERROR; |     this->error_code_ = MCP4461_STATUS_REGISTER_ERROR; | ||||||
|     this->mark_failed(); |     this->mark_failed(); | ||||||
|     return 0; |     return 0; | ||||||
| @@ -148,6 +148,20 @@ void Mcp4461Component::read_status_register_to_log() { | |||||||
|            ((status_register_value >> 3) & 0x01), ((status_register_value >> 2) & 0x01), |            ((status_register_value >> 3) & 0x01), ((status_register_value >> 2) & 0x01), | ||||||
|            ((status_register_value >> 1) & 0x01), ((status_register_value >> 0) & 0x01)); |            ((status_register_value >> 1) & 0x01), ((status_register_value >> 0) & 0x01)); | ||||||
| } | } | ||||||
|  | bool Mcp4461Component::read_16_(uint8_t address, uint16_t *buf) { | ||||||
|  |   // read 16 bits and convert from big endian to host, | ||||||
|  |   // Do this as two separate operations to ensure a stop condition between the write and read | ||||||
|  |   i2c::ErrorCode err = this->write(&address, 1); | ||||||
|  |   if (err != i2c::ERROR_OK) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |   err = this->read(reinterpret_cast<uint8_t *>(buf), 2); | ||||||
|  |   if (err != i2c::ERROR_OK) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |   *buf = convert_big_endian(*buf); | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
| uint8_t Mcp4461Component::get_wiper_address_(uint8_t wiper) { | uint8_t Mcp4461Component::get_wiper_address_(uint8_t wiper) { | ||||||
|   uint8_t addr; |   uint8_t addr; | ||||||
| @@ -205,7 +219,7 @@ uint16_t Mcp4461Component::read_wiper_level_(uint8_t wiper_idx) { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   uint16_t buf = 0; |   uint16_t buf = 0; | ||||||
|   if (!(this->read_byte_16(reg, &buf))) { |   if (!(this->read_16_(reg, &buf))) { | ||||||
|     this->error_code_ = MCP4461_STATUS_I2C_ERROR; |     this->error_code_ = MCP4461_STATUS_I2C_ERROR; | ||||||
|     this->status_set_warning(); |     this->status_set_warning(); | ||||||
|     ESP_LOGW(TAG, "Error fetching %swiper %u value", (wiper_idx > 3) ? "nonvolatile " : "", wiper_idx); |     ESP_LOGW(TAG, "Error fetching %swiper %u value", (wiper_idx > 3) ? "nonvolatile " : "", wiper_idx); | ||||||
| @@ -392,7 +406,7 @@ uint8_t Mcp4461Component::get_terminal_register_(Mcp4461TerminalIdx terminal_con | |||||||
|                                                               : static_cast<uint8_t>(Mcp4461Addresses::MCP4461_TCON1); |                                                               : static_cast<uint8_t>(Mcp4461Addresses::MCP4461_TCON1); | ||||||
|   reg |= static_cast<uint8_t>(Mcp4461Commands::READ); |   reg |= static_cast<uint8_t>(Mcp4461Commands::READ); | ||||||
|   uint16_t buf; |   uint16_t buf; | ||||||
|   if (this->read_byte_16(reg, &buf)) { |   if (this->read_16_(reg, &buf)) { | ||||||
|     return static_cast<uint8_t>(buf & 0x00ff); |     return static_cast<uint8_t>(buf & 0x00ff); | ||||||
|   } else { |   } else { | ||||||
|     this->error_code_ = MCP4461_STATUS_I2C_ERROR; |     this->error_code_ = MCP4461_STATUS_I2C_ERROR; | ||||||
| @@ -517,7 +531,7 @@ uint16_t Mcp4461Component::get_eeprom_value(Mcp4461EepromLocation location) { | |||||||
|   if (!this->is_eeprom_ready_for_writing_(true)) { |   if (!this->is_eeprom_ready_for_writing_(true)) { | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|   if (!this->read_byte_16(reg, &buf)) { |   if (!this->read_16_(reg, &buf)) { | ||||||
|     this->error_code_ = MCP4461_STATUS_I2C_ERROR; |     this->error_code_ = MCP4461_STATUS_I2C_ERROR; | ||||||
|     this->status_set_warning(); |     this->status_set_warning(); | ||||||
|     ESP_LOGW(TAG, "Error fetching EEPROM location value"); |     ESP_LOGW(TAG, "Error fetching EEPROM location value"); | ||||||
|   | |||||||
| @@ -96,6 +96,7 @@ class Mcp4461Component : public Component, public i2c::I2CDevice { | |||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   friend class Mcp4461Wiper; |   friend class Mcp4461Wiper; | ||||||
|  |   bool read_16_(uint8_t address, uint16_t *buf); | ||||||
|   void update_write_protection_status_(); |   void update_write_protection_status_(); | ||||||
|   uint8_t get_wiper_address_(uint8_t wiper); |   uint8_t get_wiper_address_(uint8_t wiper); | ||||||
|   uint16_t read_wiper_level_(uint8_t wiper); |   uint16_t read_wiper_level_(uint8_t wiper); | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ from esphome.const import ( | |||||||
|     CONF_SERVICES, |     CONF_SERVICES, | ||||||
|     PlatformFramework, |     PlatformFramework, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| DEPENDENCIES = ["network"] | DEPENDENCIES = ["network"] | ||||||
| @@ -72,7 +72,7 @@ def mdns_service( | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(55.0) | @coroutine_with_priority(CoroPriority.COMMUNICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     if config[CONF_DISABLED] is True: |     if config[CONF_DISABLED] is True: | ||||||
|         return |         return | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ from esphome.const import ( | |||||||
| ) | ) | ||||||
| from esphome.core import CORE | from esphome.core import CORE | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.coroutine import coroutine_with_priority | from esphome.coroutine import CoroPriority, coroutine_with_priority | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| CODEOWNERS = ["@jesserockz"] | CODEOWNERS = ["@jesserockz"] | ||||||
| @@ -303,7 +303,7 @@ async def media_player_volume_set_action(config, action_id, template_arg, args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(media_player_ns.using) |     cg.add_global(media_player_ns.using) | ||||||
|     cg.add_define("USE_MEDIA_PLAYER") |     cg.add_define("USE_MEDIA_PLAYER") | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ from esphome.const import ( | |||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE | from esphome.core import CORE | ||||||
| from esphome.coroutine import coroutine_with_priority | from esphome.coroutine import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| AUTO_LOAD = ["audio"] | AUTO_LOAD = ["audio"] | ||||||
| CODEOWNERS = ["@jesserockz", "@kahrendt"] | CODEOWNERS = ["@jesserockz", "@kahrendt"] | ||||||
| @@ -213,7 +213,7 @@ automation.register_condition( | |||||||
| )(microphone_action) | )(microphone_action) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(microphone_ns.using) |     cg.add_global(microphone_ns.using) | ||||||
|     cg.add_define("USE_MICROPHONE") |     cg.add_define("USE_MICROPHONE") | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| # Various configuration constants for MIPI displays | # Various configuration constants for MIPI displays | ||||||
| # Various utility functions for MIPI DBI configuration | # Various utility functions for MIPI DBI configuration | ||||||
|  |  | ||||||
| from typing import Any | from typing import Any, Self | ||||||
|  |  | ||||||
| from esphome.components.const import CONF_COLOR_DEPTH | from esphome.components.const import CONF_COLOR_DEPTH | ||||||
| from esphome.components.display import CONF_SHOW_TEST_CARD, display_ns | from esphome.components.display import CONF_SHOW_TEST_CARD, display_ns | ||||||
| @@ -222,7 +222,7 @@ def delay(ms): | |||||||
|  |  | ||||||
|  |  | ||||||
| class DriverChip: | class DriverChip: | ||||||
|     models = {} |     models: dict[str, Self] = {} | ||||||
|  |  | ||||||
|     def __init__( |     def __init__( | ||||||
|         self, |         self, | ||||||
|   | |||||||
| @@ -16,7 +16,6 @@ DriverChip( | |||||||
|     lane_bit_rate="750Mbps", |     lane_bit_rate="750Mbps", | ||||||
|     swap_xy=cv.UNDEFINED, |     swap_xy=cv.UNDEFINED, | ||||||
|     color_order="RGB", |     color_order="RGB", | ||||||
|     reset_pin=27, |  | ||||||
|     initsequence=[ |     initsequence=[ | ||||||
|         (0x30, 0x00), (0xF7, 0x49, 0x61, 0x02, 0x00), (0x30, 0x01), (0x04, 0x0C), (0x05, 0x00), (0x06, 0x00), |         (0x30, 0x00), (0xF7, 0x49, 0x61, 0x02, 0x00), (0x30, 0x01), (0x04, 0x0C), (0x05, 0x00), (0x06, 0x00), | ||||||
|         (0x0B, 0x11), (0x17, 0x00), (0x20, 0x04), (0x1F, 0x05), (0x23, 0x00), (0x25, 0x19), (0x28, 0x18), (0x29, 0x04), (0x2A, 0x01), |         (0x0B, 0x11), (0x17, 0x00), (0x20, 0x04), (0x1F, 0x05), (0x23, 0x00), (0x25, 0x19), (0x28, 0x18), (0x29, 0x04), (0x2A, 0x01), | ||||||
|   | |||||||
| @@ -57,7 +57,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_ESP8266, |     PLATFORM_ESP8266, | ||||||
|     PlatformFramework, |     PlatformFramework, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| DEPENDENCIES = ["network"] | DEPENDENCIES = ["network"] | ||||||
|  |  | ||||||
| @@ -321,7 +321,7 @@ def exp_mqtt_message(config): | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(40.0) | @coroutine_with_priority(CoroPriority.WEB) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     await cg.register_component(var, config) |     await cg.register_component(var, config) | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import esphome.codegen as cg | |||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option | from esphome.components.esp32 import add_idf_sdkconfig_option | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT | from esphome.const import CONF_ENABLE_IPV6, CONF_MIN_IPV6_ADDR_COUNT | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| AUTO_LOAD = ["mdns"] | AUTO_LOAD = ["mdns"] | ||||||
| @@ -36,7 +36,7 @@ CONFIG_SCHEMA = cv.Schema( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(201.0) | @coroutine_with_priority(CoroPriority.NETWORK) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_define("USE_NETWORK") |     cg.add_define("USE_NETWORK") | ||||||
|     if CORE.using_arduino and CORE.is_esp32: |     if CORE.using_arduino and CORE.is_esp32: | ||||||
|   | |||||||
| @@ -2,10 +2,13 @@ from __future__ import annotations | |||||||
|  |  | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  |  | ||||||
|  | from esphome import pins | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| from esphome.components.zephyr import ( | from esphome.components.zephyr import ( | ||||||
|     copy_files as zephyr_copy_files, |     copy_files as zephyr_copy_files, | ||||||
|     zephyr_add_pm_static, |     zephyr_add_pm_static, | ||||||
|  |     zephyr_add_prj_conf, | ||||||
|  |     zephyr_data, | ||||||
|     zephyr_set_core_data, |     zephyr_set_core_data, | ||||||
|     zephyr_to_code, |     zephyr_to_code, | ||||||
| ) | ) | ||||||
| @@ -18,6 +21,8 @@ import esphome.config_validation as cv | |||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_BOARD, |     CONF_BOARD, | ||||||
|     CONF_FRAMEWORK, |     CONF_FRAMEWORK, | ||||||
|  |     CONF_ID, | ||||||
|  |     CONF_RESET_PIN, | ||||||
|     KEY_CORE, |     KEY_CORE, | ||||||
|     KEY_FRAMEWORK_VERSION, |     KEY_FRAMEWORK_VERSION, | ||||||
|     KEY_TARGET_FRAMEWORK, |     KEY_TARGET_FRAMEWORK, | ||||||
| @@ -25,7 +30,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_NRF52, |     PLATFORM_NRF52, | ||||||
|     ThreadModel, |     ThreadModel, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, EsphomeError, coroutine_with_priority | from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority | ||||||
| from esphome.storage_json import StorageJSON | from esphome.storage_json import StorageJSON | ||||||
| from esphome.types import ConfigType | from esphome.types import ConfigType | ||||||
|  |  | ||||||
| @@ -90,19 +95,44 @@ def _detect_bootloader(config: ConfigType) -> ConfigType: | |||||||
|     return config |     return config | ||||||
|  |  | ||||||
|  |  | ||||||
|  | nrf52_ns = cg.esphome_ns.namespace("nrf52") | ||||||
|  | DeviceFirmwareUpdate = nrf52_ns.class_("DeviceFirmwareUpdate", cg.Component) | ||||||
|  |  | ||||||
|  | CONF_DFU = "dfu" | ||||||
|  |  | ||||||
| CONFIG_SCHEMA = cv.All( | CONFIG_SCHEMA = cv.All( | ||||||
|  |     _detect_bootloader, | ||||||
|  |     set_core_data, | ||||||
|     cv.Schema( |     cv.Schema( | ||||||
|         { |         { | ||||||
|             cv.Required(CONF_BOARD): cv.string_strict, |             cv.Required(CONF_BOARD): cv.string_strict, | ||||||
|             cv.Optional(KEY_BOOTLOADER): cv.one_of(*BOOTLOADERS, lower=True), |             cv.Optional(KEY_BOOTLOADER): cv.one_of(*BOOTLOADERS, lower=True), | ||||||
|  |             cv.Optional(CONF_DFU): cv.Schema( | ||||||
|  |                 { | ||||||
|  |                     cv.GenerateID(): cv.declare_id(DeviceFirmwareUpdate), | ||||||
|  |                     cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema, | ||||||
|  |                 } | ||||||
|  |             ), | ||||||
|         } |         } | ||||||
|     ), |     ), | ||||||
|     _detect_bootloader, |  | ||||||
|     set_core_data, |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(1000) | def _validate_mcumgr(config): | ||||||
|  |     bootloader = zephyr_data()[KEY_BOOTLOADER] | ||||||
|  |     if bootloader == BOOTLOADER_MCUBOOT: | ||||||
|  |         raise cv.Invalid(f"'{bootloader}' bootloader does not support DFU") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _final_validate(config): | ||||||
|  |     if CONF_DFU in config: | ||||||
|  |         _validate_mcumgr(config) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | FINAL_VALIDATE_SCHEMA = _final_validate | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @coroutine_with_priority(CoroPriority.PLATFORM) | ||||||
| async def to_code(config: ConfigType) -> None: | async def to_code(config: ConfigType) -> None: | ||||||
|     """Convert the configuration to code.""" |     """Convert the configuration to code.""" | ||||||
|     cg.add_platformio_option("board", config[CONF_BOARD]) |     cg.add_platformio_option("board", config[CONF_BOARD]) | ||||||
| @@ -136,6 +166,19 @@ async def to_code(config: ConfigType) -> None: | |||||||
|  |  | ||||||
|     zephyr_to_code(config) |     zephyr_to_code(config) | ||||||
|  |  | ||||||
|  |     if dfu_config := config.get(CONF_DFU): | ||||||
|  |         CORE.add_job(_dfu_to_code, dfu_config) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @coroutine_with_priority(CoroPriority.DIAGNOSTICS) | ||||||
|  | async def _dfu_to_code(dfu_config): | ||||||
|  |     cg.add_define("USE_NRF52_DFU") | ||||||
|  |     var = cg.new_Pvariable(dfu_config[CONF_ID]) | ||||||
|  |     pin = await cg.gpio_pin_expression(dfu_config[CONF_RESET_PIN]) | ||||||
|  |     cg.add(var.set_reset_pin(pin)) | ||||||
|  |     zephyr_add_prj_conf("CDC_ACM_DTE_RATE_CALLBACK_SUPPORT", True) | ||||||
|  |     await cg.register_component(var, dfu_config) | ||||||
|  |  | ||||||
|  |  | ||||||
| def copy_files() -> None: | def copy_files() -> None: | ||||||
|     """Copy files to the build directory.""" |     """Copy files to the build directory.""" | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ BOOTLOADER_ADAFRUIT = "adafruit" | |||||||
| BOOTLOADER_ADAFRUIT_NRF52_SD132 = "adafruit_nrf52_sd132" | BOOTLOADER_ADAFRUIT_NRF52_SD132 = "adafruit_nrf52_sd132" | ||||||
| BOOTLOADER_ADAFRUIT_NRF52_SD140_V6 = "adafruit_nrf52_sd140_v6" | BOOTLOADER_ADAFRUIT_NRF52_SD140_V6 = "adafruit_nrf52_sd140_v6" | ||||||
| BOOTLOADER_ADAFRUIT_NRF52_SD140_V7 = "adafruit_nrf52_sd140_v7" | BOOTLOADER_ADAFRUIT_NRF52_SD140_V7 = "adafruit_nrf52_sd140_v7" | ||||||
|  |  | ||||||
| EXTRA_ADC = [ | EXTRA_ADC = [ | ||||||
|     "VDD", |     "VDD", | ||||||
|     "VDDHDIV5", |     "VDDHDIV5", | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								esphome/components/nrf52/dfu.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								esphome/components/nrf52/dfu.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | #include "dfu.h" | ||||||
|  |  | ||||||
|  | #ifdef USE_NRF52_DFU | ||||||
|  |  | ||||||
|  | #include <zephyr/device.h> | ||||||
|  | #include <zephyr/drivers/uart.h> | ||||||
|  | #include <zephyr/drivers/uart/cdc_acm.h> | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace nrf52 { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "dfu"; | ||||||
|  |  | ||||||
|  | volatile bool goto_dfu = false;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) | ||||||
|  |  | ||||||
|  | static const uint32_t DFU_DBL_RESET_MAGIC = 0x5A1AD5;  // SALADS | ||||||
|  |  | ||||||
|  | #define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id), | ||||||
|  |  | ||||||
|  | static void cdc_dte_rate_callback(const struct device * /*unused*/, uint32_t rate) { | ||||||
|  |   if (rate == 1200) { | ||||||
|  |     goto_dfu = true; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | void DeviceFirmwareUpdate::setup() { | ||||||
|  |   this->reset_pin_->setup(); | ||||||
|  |   const struct device *cdc_dev[] = {DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA)}; | ||||||
|  |   for (auto &idx : cdc_dev) { | ||||||
|  |     cdc_acm_dte_rate_callback_set(idx, cdc_dte_rate_callback); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void DeviceFirmwareUpdate::loop() { | ||||||
|  |   if (goto_dfu) { | ||||||
|  |     goto_dfu = false; | ||||||
|  |     volatile uint32_t *dbl_reset_mem = (volatile uint32_t *) 0x20007F7C; | ||||||
|  |     (*dbl_reset_mem) = DFU_DBL_RESET_MAGIC; | ||||||
|  |     this->reset_pin_->digital_write(true); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void DeviceFirmwareUpdate::dump_config() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "DFU:"); | ||||||
|  |   LOG_PIN("  RESET Pin: ", this->reset_pin_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace nrf52 | ||||||
|  | }  // namespace esphome | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										24
									
								
								esphome/components/nrf52/dfu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								esphome/components/nrf52/dfu.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/core/defines.h" | ||||||
|  | #ifdef USE_NRF52_DFU | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/core/gpio.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace nrf52 { | ||||||
|  | class DeviceFirmwareUpdate : public Component { | ||||||
|  |  public: | ||||||
|  |   void setup() override; | ||||||
|  |   void loop() override; | ||||||
|  |   void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; } | ||||||
|  |   void dump_config() override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   GPIOPin *reset_pin_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace nrf52 | ||||||
|  | }  // namespace esphome | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -76,7 +76,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_WIND_DIRECTION, |     DEVICE_CLASS_WIND_DIRECTION, | ||||||
|     DEVICE_CLASS_WIND_SPEED, |     DEVICE_CLASS_WIND_SPEED, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -321,7 +321,7 @@ async def number_in_range_to_code(config, condition_id, template_arg, args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(number_ns.using) |     cg.add_global(number_ns.using) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,16 +14,16 @@ void log_number(const char *tag, const char *prefix, const char *type, Number *o | |||||||
|  |  | ||||||
|   ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); |   ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); | ||||||
|  |  | ||||||
|   if (!obj->get_icon().empty()) { |   if (!obj->get_icon_ref().empty()) { | ||||||
|     ESP_LOGCONFIG(tag, "%s  Icon: '%s'", prefix, obj->get_icon().c_str()); |     ESP_LOGCONFIG(tag, "%s  Icon: '%s'", prefix, obj->get_icon_ref().c_str()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (!obj->traits.get_unit_of_measurement().empty()) { |   if (!obj->traits.get_unit_of_measurement().empty()) { | ||||||
|     ESP_LOGCONFIG(tag, "%s  Unit of Measurement: '%s'", prefix, obj->traits.get_unit_of_measurement().c_str()); |     ESP_LOGCONFIG(tag, "%s  Unit of Measurement: '%s'", prefix, obj->traits.get_unit_of_measurement().c_str()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (!obj->traits.get_device_class().empty()) { |   if (!obj->traits.get_device_class_ref().empty()) { | ||||||
|     ESP_LOGCONFIG(tag, "%s  Device Class: '%s'", prefix, obj->traits.get_device_class().c_str()); |     ESP_LOGCONFIG(tag, "%s  Device Class: '%s'", prefix, obj->traits.get_device_class_ref().c_str()); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ from esphome.const import ( | |||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     PlatformFramework, |     PlatformFramework, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| AUTO_LOAD = ["md5", "safe_mode"] | AUTO_LOAD = ["md5", "safe_mode"] | ||||||
| @@ -82,7 +82,7 @@ BASE_OTA_SCHEMA = cv.Schema( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(54.0) | @coroutine_with_priority(CoroPriority.COMMUNICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_define("USE_OTA") |     cg.add_define("USE_OTA") | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_RP2040, |     PLATFORM_RP2040, | ||||||
|     ThreadModel, |     ThreadModel, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, EsphomeError, coroutine_with_priority | from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority | ||||||
| from esphome.helpers import copy_file_if_changed, mkdir_p, read_file, write_file | from esphome.helpers import copy_file_if_changed, mkdir_p, read_file, write_file | ||||||
|  |  | ||||||
| from .const import KEY_BOARD, KEY_PIO_FILES, KEY_RP2040, rp2040_ns | from .const import KEY_BOARD, KEY_PIO_FILES, KEY_RP2040, rp2040_ns | ||||||
| @@ -159,7 +159,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(1000) | @coroutine_with_priority(CoroPriority.PLATFORM) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add(rp2040_ns.setup_preferences()) |     cg.add(rp2040_ns.setup_preferences()) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ from esphome.const import ( | |||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     KEY_PAST_SAFE_MODE, |     KEY_PAST_SAFE_MODE, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.cpp_generator import RawExpression | from esphome.cpp_generator import RawExpression | ||||||
|  |  | ||||||
| CODEOWNERS = ["@paulmonigatti", "@jsuanet", "@kbx81"] | CODEOWNERS = ["@paulmonigatti", "@jsuanet", "@kbx81"] | ||||||
| @@ -53,7 +53,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(50.0) | @coroutine_with_priority(CoroPriority.APPLICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     if not config[CONF_DISABLED]: |     if not config[CONF_DISABLED]: | ||||||
|         var = cg.new_Pvariable(config[CONF_ID]) |         var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ from esphome.const import ( | |||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     CONF_WEB_SERVER, |     CONF_WEB_SERVER, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -124,7 +124,7 @@ async def new_select(config, *args, options: list[str]): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(select_ns.using) |     cg.add_global(select_ns.using) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,8 +12,8 @@ namespace select { | |||||||
| #define LOG_SELECT(prefix, type, obj) \ | #define LOG_SELECT(prefix, type, obj) \ | ||||||
|   if ((obj) != nullptr) { \ |   if ((obj) != nullptr) { \ | ||||||
|     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ |     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ | ||||||
|     if (!(obj)->get_icon().empty()) { \ |     if (!(obj)->get_icon_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -101,7 +101,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_WIND_SPEED, |     DEVICE_CLASS_WIND_SPEED, | ||||||
|     ENTITY_CATEGORY_CONFIG, |     ENTITY_CATEGORY_CONFIG, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
| from esphome.util import Registry | from esphome.util import Registry | ||||||
| @@ -1142,6 +1142,6 @@ def _lstsq(a, b): | |||||||
|     return _mat_dot(_mat_dot(x, a_t), b) |     return _mat_dot(_mat_dot(x, a_t), b) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(sensor_ns.using) |     cg.add_global(sensor_ns.using) | ||||||
|   | |||||||
| @@ -17,15 +17,15 @@ void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *o | |||||||
|                 "%s  State Class: '%s'\n" |                 "%s  State Class: '%s'\n" | ||||||
|                 "%s  Unit of Measurement: '%s'\n" |                 "%s  Unit of Measurement: '%s'\n" | ||||||
|                 "%s  Accuracy Decimals: %d", |                 "%s  Accuracy Decimals: %d", | ||||||
|                 prefix, type, obj->get_name().c_str(), prefix, state_class_to_string(obj->get_state_class()).c_str(), |                 prefix, type, obj->get_name().c_str(), prefix, state_class_to_string(obj->get_state_class()), prefix, | ||||||
|                 prefix, obj->get_unit_of_measurement().c_str(), prefix, obj->get_accuracy_decimals()); |                 obj->get_unit_of_measurement().c_str(), prefix, obj->get_accuracy_decimals()); | ||||||
|  |  | ||||||
|   if (!obj->get_device_class().empty()) { |   if (!obj->get_device_class_ref().empty()) { | ||||||
|     ESP_LOGCONFIG(tag, "%s  Device Class: '%s'", prefix, obj->get_device_class().c_str()); |     ESP_LOGCONFIG(tag, "%s  Device Class: '%s'", prefix, obj->get_device_class_ref().c_str()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (!obj->get_icon().empty()) { |   if (!obj->get_icon_ref().empty()) { | ||||||
|     ESP_LOGCONFIG(tag, "%s  Icon: '%s'", prefix, obj->get_icon().c_str()); |     ESP_LOGCONFIG(tag, "%s  Icon: '%s'", prefix, obj->get_icon_ref().c_str()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (obj->get_force_update()) { |   if (obj->get_force_update()) { | ||||||
| @@ -33,7 +33,7 @@ void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *o | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| std::string state_class_to_string(StateClass state_class) { | const char *state_class_to_string(StateClass state_class) { | ||||||
|   switch (state_class) { |   switch (state_class) { | ||||||
|     case STATE_CLASS_MEASUREMENT: |     case STATE_CLASS_MEASUREMENT: | ||||||
|       return "measurement"; |       return "measurement"; | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ enum StateClass : uint8_t { | |||||||
|   STATE_CLASS_TOTAL = 3, |   STATE_CLASS_TOTAL = 3, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| std::string state_class_to_string(StateClass state_class); | const char *state_class_to_string(StateClass state_class); | ||||||
|  |  | ||||||
| /** Base-class for all sensors. | /** Base-class for all sensors. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -14,8 +14,13 @@ namespace sntp { | |||||||
|  |  | ||||||
| static const char *const TAG = "sntp"; | static const char *const TAG = "sntp"; | ||||||
|  |  | ||||||
|  | #if defined(USE_ESP32) | ||||||
|  | SNTPComponent *SNTPComponent::instance = nullptr;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| void SNTPComponent::setup() { | void SNTPComponent::setup() { | ||||||
| #if defined(USE_ESP32) | #if defined(USE_ESP32) | ||||||
|  |   SNTPComponent::instance = this; | ||||||
|   if (esp_sntp_enabled()) { |   if (esp_sntp_enabled()) { | ||||||
|     esp_sntp_stop(); |     esp_sntp_stop(); | ||||||
|   } |   } | ||||||
| @@ -25,6 +30,11 @@ void SNTPComponent::setup() { | |||||||
|     esp_sntp_setservername(i++, server.c_str()); |     esp_sntp_setservername(i++, server.c_str()); | ||||||
|   } |   } | ||||||
|   esp_sntp_set_sync_interval(this->get_update_interval()); |   esp_sntp_set_sync_interval(this->get_update_interval()); | ||||||
|  |   esp_sntp_set_time_sync_notification_cb([](struct timeval *tv) { | ||||||
|  |     if (SNTPComponent::instance != nullptr) { | ||||||
|  |       SNTPComponent::instance->defer([]() { SNTPComponent::instance->time_synced(); }); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|   esp_sntp_init(); |   esp_sntp_init(); | ||||||
| #else | #else | ||||||
|   sntp_stop(); |   sntp_stop(); | ||||||
| @@ -34,6 +44,14 @@ void SNTPComponent::setup() { | |||||||
|   for (auto &server : this->servers_) { |   for (auto &server : this->servers_) { | ||||||
|     sntp_setservername(i++, server.c_str()); |     sntp_setservername(i++, server.c_str()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | #if defined(USE_ESP8266) | ||||||
|  |   settimeofday_cb([this](bool from_sntp) { | ||||||
|  |     if (from_sntp) | ||||||
|  |       this->time_synced(); | ||||||
|  |   }); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   sntp_init(); |   sntp_init(); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| @@ -46,7 +64,8 @@ void SNTPComponent::dump_config() { | |||||||
| } | } | ||||||
| void SNTPComponent::update() { | void SNTPComponent::update() { | ||||||
| #if !defined(USE_ESP32) | #if !defined(USE_ESP32) | ||||||
|   // force resync |   // Some platforms currently cannot set the sync interval at runtime so we need | ||||||
|  |   // to do the re-sync by hand for now. | ||||||
|   if (sntp_enabled()) { |   if (sntp_enabled()) { | ||||||
|     sntp_stop(); |     sntp_stop(); | ||||||
|     this->has_time_ = false; |     this->has_time_ = false; | ||||||
| @@ -55,23 +74,31 @@ void SNTPComponent::update() { | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
| void SNTPComponent::loop() { | void SNTPComponent::loop() { | ||||||
|  | // The loop is used to infer whether we have valid time on platforms where we | ||||||
|  | // cannot tell whether SNTP has succeeded. | ||||||
|  | // One limitation of this approach is that we cannot tell if it was the SNTP | ||||||
|  | // component that set the time. | ||||||
|  | // ESP-IDF and ESP8266 use callbacks from the SNTP task to trigger the | ||||||
|  | // `on_time_sync` trigger on successful sync events. | ||||||
|  | #if defined(USE_ESP32) || defined(USE_ESP8266) | ||||||
|  |   this->disable_loop(); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   if (this->has_time_) |   if (this->has_time_) | ||||||
|     return; |     return; | ||||||
|  |  | ||||||
|  |   this->time_synced(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void SNTPComponent::time_synced() { | ||||||
|   auto time = this->now(); |   auto time = this->now(); | ||||||
|   if (!time.is_valid()) |   this->has_time_ = time.is_valid(); | ||||||
|  |   if (!this->has_time_) | ||||||
|     return; |     return; | ||||||
|  |  | ||||||
|   ESP_LOGD(TAG, "Synchronized time: %04d-%02d-%02d %02d:%02d:%02d", time.year, time.month, time.day_of_month, time.hour, |   ESP_LOGD(TAG, "Synchronized time: %04d-%02d-%02d %02d:%02d:%02d", time.year, time.month, time.day_of_month, time.hour, | ||||||
|            time.minute, time.second); |            time.minute, time.second); | ||||||
|   this->time_sync_callback_.call(); |   this->time_sync_callback_.call(); | ||||||
|   this->has_time_ = true; |  | ||||||
|  |  | ||||||
| #ifdef USE_ESP_IDF |  | ||||||
|   // On ESP-IDF, time sync is permanent and update() doesn't force resync |  | ||||||
|   // Time is now synchronized, no need to check anymore |  | ||||||
|   this->disable_loop(); |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace sntp | }  // namespace sntp | ||||||
|   | |||||||
| @@ -26,9 +26,16 @@ class SNTPComponent : public time::RealTimeClock { | |||||||
|   void update() override; |   void update() override; | ||||||
|   void loop() override; |   void loop() override; | ||||||
|  |  | ||||||
|  |   void time_synced(); | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   std::vector<std::string> servers_; |   std::vector<std::string> servers_; | ||||||
|   bool has_time_{false}; |   bool has_time_{false}; | ||||||
|  |  | ||||||
|  | #if defined(USE_ESP32) | ||||||
|  |  private: | ||||||
|  |   static SNTPComponent *instance; | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace sntp | }  // namespace sntp | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ from esphome.components import audio, audio_dac | |||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_DATA, CONF_ID, CONF_VOLUME | from esphome.const import CONF_DATA, CONF_ID, CONF_VOLUME | ||||||
| from esphome.core import CORE | from esphome.core import CORE | ||||||
| from esphome.coroutine import coroutine_with_priority | from esphome.coroutine import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| AUTO_LOAD = ["audio"] | AUTO_LOAD = ["audio"] | ||||||
| CODEOWNERS = ["@jesserockz", "@kahrendt"] | CODEOWNERS = ["@jesserockz", "@kahrendt"] | ||||||
| @@ -138,7 +138,7 @@ async def speaker_mute_action_to_code(config, action_id, template_arg, args): | |||||||
|     return cg.new_Pvariable(action_id, template_arg, paren) |     return cg.new_Pvariable(action_id, template_arg, paren) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(speaker_ns.using) |     cg.add_global(speaker_ns.using) | ||||||
|     cg.add_define("USE_SPEAKER") |     cg.add_define("USE_SPEAKER") | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_RP2040, |     PLATFORM_RP2040, | ||||||
|     PlatformFramework, |     PlatformFramework, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| import esphome.final_validate as fv | import esphome.final_validate as fv | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core", "@clydebarrow"] | CODEOWNERS = ["@esphome/core", "@clydebarrow"] | ||||||
| @@ -351,7 +351,7 @@ CONFIG_SCHEMA = cv.All( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(1.0) | @coroutine_with_priority(CoroPriority.BUS) | ||||||
| async def to_code(configs): | async def to_code(configs): | ||||||
|     cg.add_define("USE_SPI") |     cg.add_define("USE_SPI") | ||||||
|     cg.add_global(spi_ns.using) |     cg.add_global(spi_ns.using) | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ from esphome import pins | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ID, CONF_PIN | from esphome.const import CONF_ID, CONF_PIN | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| status_led_ns = cg.esphome_ns.namespace("status_led") | status_led_ns = cg.esphome_ns.namespace("status_led") | ||||||
| StatusLED = status_led_ns.class_("StatusLED", cg.Component) | StatusLED = status_led_ns.class_("StatusLED", cg.Component) | ||||||
| @@ -15,7 +15,7 @@ CONFIG_SCHEMA = cv.Schema( | |||||||
| ).extend(cv.COMPONENT_SCHEMA) | ).extend(cv.COMPONENT_SCHEMA) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(80.0) | @coroutine_with_priority(CoroPriority.STATUS) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     pin = await cg.gpio_pin_expression(config[CONF_PIN]) |     pin = await cg.gpio_pin_expression(config[CONF_PIN]) | ||||||
|     rhs = StatusLED.new(pin) |     rhs = StatusLED.new(pin) | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ from esphome.const import ( | |||||||
|     CONF_SPEED, |     CONF_SPEED, | ||||||
|     CONF_TARGET, |     CONF_TARGET, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| IS_PLATFORM_COMPONENT = True | IS_PLATFORM_COMPONENT = True | ||||||
|  |  | ||||||
| @@ -178,6 +178,6 @@ async def stepper_set_deceleration_to_code(config, action_id, template_arg, args | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(stepper_ns.using) |     cg.add_global(stepper_ns.using) | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_OUTLET, |     DEVICE_CLASS_OUTLET, | ||||||
|     DEVICE_CLASS_SWITCH, |     DEVICE_CLASS_SWITCH, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -230,6 +230,6 @@ async def switch_is_off_to_code(config, condition_id, template_arg, args): | |||||||
|     return cg.new_Pvariable(condition_id, template_arg, paren, False) |     return cg.new_Pvariable(condition_id, template_arg, paren, False) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(switch_ns.using) |     cg.add_global(switch_ns.using) | ||||||
|   | |||||||
| @@ -91,8 +91,8 @@ void log_switch(const char *tag, const char *prefix, const char *type, Switch *o | |||||||
|                   LOG_STR_ARG(onoff)); |                   LOG_STR_ARG(onoff)); | ||||||
|  |  | ||||||
|     // Add optional fields separately |     // Add optional fields separately | ||||||
|     if (!obj->get_icon().empty()) { |     if (!obj->get_icon_ref().empty()) { | ||||||
|       ESP_LOGCONFIG(tag, "%s  Icon: '%s'", prefix, obj->get_icon().c_str()); |       ESP_LOGCONFIG(tag, "%s  Icon: '%s'", prefix, obj->get_icon_ref().c_str()); | ||||||
|     } |     } | ||||||
|     if (obj->assumed_state()) { |     if (obj->assumed_state()) { | ||||||
|       ESP_LOGCONFIG(tag, "%s  Assumed State: YES", prefix); |       ESP_LOGCONFIG(tag, "%s  Assumed State: YES", prefix); | ||||||
| @@ -100,8 +100,8 @@ void log_switch(const char *tag, const char *prefix, const char *type, Switch *o | |||||||
|     if (obj->is_inverted()) { |     if (obj->is_inverted()) { | ||||||
|       ESP_LOGCONFIG(tag, "%s  Inverted: YES", prefix); |       ESP_LOGCONFIG(tag, "%s  Inverted: YES", prefix); | ||||||
|     } |     } | ||||||
|     if (!obj->get_device_class().empty()) { |     if (!obj->get_device_class_ref().empty()) { | ||||||
|       ESP_LOGCONFIG(tag, "%s  Device Class: '%s'", prefix, obj->get_device_class().c_str()); |       ESP_LOGCONFIG(tag, "%s  Device Class: '%s'", prefix, obj->get_device_class_ref().c_str()); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ from esphome.const import ( | |||||||
|     CONF_VALUE, |     CONF_VALUE, | ||||||
|     CONF_WEB_SERVER, |     CONF_WEB_SERVER, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -149,7 +149,7 @@ async def new_text( | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(text_ns.using) |     cg.add_global(text_ns.using) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,8 +12,8 @@ namespace text { | |||||||
| #define LOG_TEXT(prefix, type, obj) \ | #define LOG_TEXT(prefix, type, obj) \ | ||||||
|   if ((obj) != nullptr) { \ |   if ((obj) != nullptr) { \ | ||||||
|     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ |     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ | ||||||
|     if (!(obj)->get_icon().empty()) { \ |     if (!(obj)->get_icon_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_EMPTY, |     DEVICE_CLASS_EMPTY, | ||||||
|     DEVICE_CLASS_TIMESTAMP, |     DEVICE_CLASS_TIMESTAMP, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
| from esphome.util import Registry | from esphome.util import Registry | ||||||
| @@ -230,7 +230,7 @@ async def new_text_sensor(config, *args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(text_sensor_ns.using) |     cg.add_global(text_sensor_ns.using) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,11 +14,11 @@ namespace text_sensor { | |||||||
| #define LOG_TEXT_SENSOR(prefix, type, obj) \ | #define LOG_TEXT_SENSOR(prefix, type, obj) \ | ||||||
|   if ((obj) != nullptr) { \ |   if ((obj) != nullptr) { \ | ||||||
|     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ |     ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ | ||||||
|     if (!(obj)->get_device_class().empty()) { \ |     if (!(obj)->get_device_class_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|     if (!(obj)->get_icon().empty()) { \ |     if (!(obj)->get_icon_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ from esphome.const import ( | |||||||
|     CONF_TIMEZONE, |     CONF_TIMEZONE, | ||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -340,7 +340,7 @@ async def register_time(time_var, config): | |||||||
|     await setup_time_core_(time_var, config) |     await setup_time_core_(time_var, config) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     if CORE.using_zephyr: |     if CORE.using_zephyr: | ||||||
|         zephyr_add_prj_conf("POSIX_CLOCK", True) |         zephyr_add_prj_conf("POSIX_CLOCK", True) | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ from esphome.const import ( | |||||||
|     CONF_SWAP_XY, |     CONF_SWAP_XY, | ||||||
|     CONF_TRANSFORM, |     CONF_TRANSFORM, | ||||||
| ) | ) | ||||||
| from esphome.core import coroutine_with_priority | from esphome.core import CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@jesserockz", "@nielsnl68"] | CODEOWNERS = ["@jesserockz", "@nielsnl68"] | ||||||
| DEPENDENCIES = ["display"] | DEPENDENCIES = ["display"] | ||||||
| @@ -152,7 +152,7 @@ async def register_touchscreen(var, config): | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(touchscreen_ns.using) |     cg.add_global(touchscreen_ns.using) | ||||||
|     cg.add_define("USE_TOUCHSCREEN") |     cg.add_define("USE_TOUCHSCREEN") | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_FIRMWARE, |     DEVICE_CLASS_FIRMWARE, | ||||||
|     ENTITY_CATEGORY_CONFIG, |     ENTITY_CATEGORY_CONFIG, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -124,7 +124,7 @@ async def new_update(config): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(update_ns.using) |     cg.add_global(update_ns.using) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ from esphome.const import ( | |||||||
|     DEVICE_CLASS_GAS, |     DEVICE_CLASS_GAS, | ||||||
|     DEVICE_CLASS_WATER, |     DEVICE_CLASS_WATER, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity | ||||||
| from esphome.cpp_generator import MockObjClass | from esphome.cpp_generator import MockObjClass | ||||||
|  |  | ||||||
| @@ -233,6 +233,6 @@ async def valve_control_to_code(config, action_id, template_arg, args): | |||||||
|     return var |     return var | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     cg.add_global(valve_ns.using) |     cg.add_global(valve_ns.using) | ||||||
|   | |||||||
| @@ -19,8 +19,8 @@ const extern float VALVE_CLOSED; | |||||||
|     if (traits_.get_is_assumed_state()) { \ |     if (traits_.get_is_assumed_state()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Assumed State: YES", prefix); \ |       ESP_LOGCONFIG(TAG, "%s  Assumed State: YES", prefix); \ | ||||||
|     } \ |     } \ | ||||||
|     if (!(obj)->get_device_class().empty()) { \ |     if (!(obj)->get_device_class_ref().empty()) { \ | ||||||
|       ESP_LOGCONFIG(TAG, "%s  Device Class: '%s'", prefix, (obj)->get_device_class().c_str()); \ |       ESP_LOGCONFIG(TAG, "%s  Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \ | ||||||
|     } \ |     } \ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ from esphome.const import ( | |||||||
|     PLATFORM_LN882X, |     PLATFORM_LN882X, | ||||||
|     PLATFORM_RTL87XX, |     PLATFORM_RTL87XX, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| import esphome.final_validate as fv | import esphome.final_validate as fv | ||||||
| from esphome.types import ConfigType | from esphome.types import ConfigType | ||||||
|  |  | ||||||
| @@ -269,7 +269,7 @@ def add_resource_as_progmem( | |||||||
|     cg.add_global(cg.RawExpression(size_t)) |     cg.add_global(cg.RawExpression(size_t)) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(40.0) | @coroutine_with_priority(CoroPriority.WEB) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     paren = await cg.get_variable(config[CONF_WEB_SERVER_BASE_ID]) |     paren = await cg.get_variable(config[CONF_WEB_SERVER_BASE_ID]) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ from esphome.components.esp32 import add_idf_component | |||||||
| from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code | from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ID | from esphome.const import CONF_ID | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| DEPENDENCIES = ["network", "web_server_base"] | DEPENDENCIES = ["network", "web_server_base"] | ||||||
| @@ -22,7 +22,7 @@ CONFIG_SCHEMA = ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(52.0) | @coroutine_with_priority(CoroPriority.COMMUNICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     await ota_to_code(var, config) |     await ota_to_code(var, config) | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import CONF_ID | from esphome.const import CONF_ID | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
|  |  | ||||||
| CODEOWNERS = ["@esphome/core"] | CODEOWNERS = ["@esphome/core"] | ||||||
| DEPENDENCIES = ["network"] | DEPENDENCIES = ["network"] | ||||||
| @@ -26,7 +26,7 @@ CONFIG_SCHEMA = cv.Schema( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(65.0) | @coroutine_with_priority(CoroPriority.COMMUNICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     await cg.register_component(var, config) |     await cg.register_component(var, config) | ||||||
|   | |||||||
| @@ -44,7 +44,7 @@ from esphome.const import ( | |||||||
|     CONF_USERNAME, |     CONF_USERNAME, | ||||||
|     PlatformFramework, |     PlatformFramework, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, HexInt, coroutine_with_priority | from esphome.core import CORE, CoroPriority, HexInt, coroutine_with_priority | ||||||
| import esphome.final_validate as fv | import esphome.final_validate as fv | ||||||
|  |  | ||||||
| from . import wpa2_eap | from . import wpa2_eap | ||||||
| @@ -370,7 +370,7 @@ def wifi_network(config, ap, static_ip): | |||||||
|     return ap |     return ap | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(60.0) | @coroutine_with_priority(CoroPriority.COMMUNICATION) | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     cg.add(var.set_use_address(config[CONF_USE_ADDRESS])) |     cg.add(var.set_use_address(config[CONF_USE_ADDRESS])) | ||||||
|   | |||||||
| @@ -654,12 +654,14 @@ const char *get_disconnect_reason_str(uint8_t reason) { | |||||||
|       return "Association comeback time too long"; |       return "Association comeback time too long"; | ||||||
|     case WIFI_REASON_SA_QUERY_TIMEOUT: |     case WIFI_REASON_SA_QUERY_TIMEOUT: | ||||||
|       return "SA query timeout"; |       return "SA query timeout"; | ||||||
|  | #if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 2) | ||||||
|     case WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY: |     case WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY: | ||||||
|       return "No AP found with compatible security"; |       return "No AP found with compatible security"; | ||||||
|     case WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD: |     case WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD: | ||||||
|       return "No AP found in auth mode threshold"; |       return "No AP found in auth mode threshold"; | ||||||
|     case WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD: |     case WIFI_REASON_NO_AP_FOUND_IN_RSSI_THRESHOLD: | ||||||
|       return "No AP found in RSSI threshold"; |       return "No AP found in RSSI threshold"; | ||||||
|  | #endif | ||||||
|     case WIFI_REASON_UNSPECIFIED: |     case WIFI_REASON_UNSPECIFIED: | ||||||
|     default: |     default: | ||||||
|       return "Unspecified"; |       return "Unspecified"; | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ from esphome.const import ( | |||||||
|  |  | ||||||
| # pylint: disable=unused-import | # pylint: disable=unused-import | ||||||
| from esphome.coroutine import (  # noqa: F401 | from esphome.coroutine import (  # noqa: F401 | ||||||
|  |     CoroPriority, | ||||||
|     FakeAwaitable as _FakeAwaitable, |     FakeAwaitable as _FakeAwaitable, | ||||||
|     FakeEventLoop as _FakeEventLoop, |     FakeEventLoop as _FakeEventLoop, | ||||||
|     coroutine, |     coroutine, | ||||||
|   | |||||||
| @@ -39,7 +39,7 @@ from esphome.const import ( | |||||||
|     PlatformFramework, |     PlatformFramework, | ||||||
|     __version__ as ESPHOME_VERSION, |     __version__ as ESPHOME_VERSION, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | from esphome.core import CORE, CoroPriority, coroutine_with_priority | ||||||
| from esphome.helpers import ( | from esphome.helpers import ( | ||||||
|     copy_file_if_changed, |     copy_file_if_changed, | ||||||
|     fnv1a_32bit_hash, |     fnv1a_32bit_hash, | ||||||
| @@ -359,7 +359,7 @@ ARDUINO_GLUE_CODE = """\ | |||||||
| """ | """ | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(-999.0) | @coroutine_with_priority(CoroPriority.WORKAROUNDS) | ||||||
| async def add_arduino_global_workaround(): | async def add_arduino_global_workaround(): | ||||||
|     # The Arduino framework defined these itself in the global |     # The Arduino framework defined these itself in the global | ||||||
|     # namespace. For the esphome codebase that is not a problem, |     # namespace. For the esphome codebase that is not a problem, | ||||||
| @@ -376,7 +376,7 @@ async def add_arduino_global_workaround(): | |||||||
|         cg.add_global(cg.RawStatement(line)) |         cg.add_global(cg.RawStatement(line)) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(-1000.0) | @coroutine_with_priority(CoroPriority.FINAL) | ||||||
| async def add_includes(includes): | async def add_includes(includes): | ||||||
|     # Add includes at the very end, so that the included files can access global variables |     # Add includes at the very end, so that the included files can access global variables | ||||||
|     for include in includes: |     for include in includes: | ||||||
| @@ -392,7 +392,7 @@ async def add_includes(includes): | |||||||
|             include_file(path, basename) |             include_file(path, basename) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(-1000.0) | @coroutine_with_priority(CoroPriority.FINAL) | ||||||
| async def _add_platformio_options(pio_options): | async def _add_platformio_options(pio_options): | ||||||
|     # Add includes at the very end, so that they override everything |     # Add includes at the very end, so that they override everything | ||||||
|     for key, val in pio_options.items(): |     for key, val in pio_options.items(): | ||||||
| @@ -401,7 +401,7 @@ async def _add_platformio_options(pio_options): | |||||||
|         cg.add_platformio_option(key, val) |         cg.add_platformio_option(key, val) | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(30.0) | @coroutine_with_priority(CoroPriority.AUTOMATION) | ||||||
| async def _add_automations(config): | async def _add_automations(config): | ||||||
|     for conf in config.get(CONF_ON_BOOT, []): |     for conf in config.get(CONF_ON_BOOT, []): | ||||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], conf.get(CONF_PRIORITY)) |         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], conf.get(CONF_PRIORITY)) | ||||||
| @@ -423,7 +423,7 @@ async def _add_automations(config): | |||||||
| DATETIME_SUBTYPES = {"date", "time", "datetime"} | DATETIME_SUBTYPES = {"date", "time", "datetime"} | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(-100.0) | @coroutine_with_priority(CoroPriority.FINAL) | ||||||
| async def _add_platform_defines() -> None: | async def _add_platform_defines() -> None: | ||||||
|     # Generate compile-time defines for platforms that have actual entities |     # Generate compile-time defines for platforms that have actual entities | ||||||
|     # Only add USE_* and count defines when there are entities |     # Only add USE_* and count defines when there are entities | ||||||
| @@ -442,7 +442,7 @@ async def _add_platform_defines() -> None: | |||||||
|             cg.add_define(f"USE_{platform_name.upper()}") |             cg.add_define(f"USE_{platform_name.upper()}") | ||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @coroutine_with_priority(CoroPriority.CORE) | ||||||
| async def to_code(config: ConfigType) -> None: | async def to_code(config: ConfigType) -> None: | ||||||
|     cg.add_global(cg.global_ns.namespace("esphome").using) |     cg.add_global(cg.global_ns.namespace("esphome").using) | ||||||
|     # These can be used by user lambdas, put them to default scope |     # These can be used by user lambdas, put them to default scope | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user