esphome 2025.9.2__py3-none-any.whl → 2025.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +103 -37
- esphome/address_cache.py +142 -0
- esphome/automation.py +130 -32
- esphome/build_gen/platformio.py +1 -3
- esphome/codegen.py +1 -0
- esphome/components/animation/animation.cpp +2 -2
- esphome/components/api/__init__.py +167 -3
- esphome/components/api/api_connection.cpp +84 -41
- esphome/components/api/api_connection.h +22 -16
- esphome/components/api/api_frame_helper.cpp +33 -19
- esphome/components/api/api_frame_helper.h +19 -4
- esphome/components/api/api_frame_helper_noise.cpp +41 -53
- esphome/components/api/api_frame_helper_noise.h +1 -1
- esphome/components/api/api_frame_helper_plaintext.cpp +22 -31
- esphome/components/api/api_frame_helper_plaintext.h +1 -1
- esphome/components/api/api_pb2.cpp +189 -15
- esphome/components/api/api_pb2.h +132 -20
- esphome/components/api/api_pb2_dump.cpp +97 -9
- esphome/components/api/api_pb2_service.cpp +118 -160
- esphome/components/api/api_pb2_service.h +31 -3
- esphome/components/api/api_server.cpp +78 -11
- esphome/components/api/api_server.h +32 -4
- esphome/components/api/custom_api_device.h +8 -8
- esphome/components/api/homeassistant_service.h +123 -6
- esphome/components/api/proto.h +6 -2
- esphome/components/api/user_services.h +2 -2
- esphome/components/as7341/sensor.py +1 -1
- esphome/components/audio/__init__.py +1 -1
- esphome/components/audio/audio.cpp +1 -1
- esphome/components/audio/audio_decoder.cpp +9 -9
- esphome/components/bl0906/bl0906.cpp +2 -2
- esphome/components/bl0942/bl0942.cpp +2 -2
- esphome/components/ble_client/__init__.py +1 -1
- esphome/components/bluetooth_proxy/__init__.py +4 -30
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +11 -4
- esphome/components/bluetooth_proxy/bluetooth_connection.h +2 -2
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -2
- esphome/components/camera_encoder/__init__.py +2 -4
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +4 -2
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +3 -1
- esphome/components/canbus/canbus.cpp +7 -5
- esphome/components/canbus/canbus.h +7 -7
- esphome/components/captive_portal/__init__.py +18 -1
- esphome/components/captive_portal/captive_portal.cpp +40 -46
- esphome/components/captive_portal/captive_portal.h +20 -22
- esphome/components/captive_portal/dns_server_esp32_idf.cpp +205 -0
- esphome/components/captive_portal/dns_server_esp32_idf.h +27 -0
- esphome/components/ccs811/ccs811.cpp +1 -1
- esphome/components/climate/climate.cpp +10 -7
- esphome/components/cm1106/cm1106.cpp +1 -1
- esphome/components/copy/lock/copy_lock.cpp +1 -1
- esphome/components/cover/cover.cpp +1 -0
- esphome/components/daikin_arc/daikin_arc.cpp +19 -12
- esphome/components/dashboard_import/dashboard_import.cpp +1 -1
- esphome/components/dashboard_import/dashboard_import.h +1 -1
- esphome/components/deep_sleep/__init__.py +9 -2
- esphome/components/deep_sleep/deep_sleep_component.h +11 -9
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
- esphome/components/ektf2232/touchscreen/__init__.py +8 -5
- esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
- esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
- esphome/components/epaper_spi/__init__.py +1 -0
- esphome/components/epaper_spi/display.py +80 -0
- esphome/components/epaper_spi/epaper_spi.cpp +227 -0
- esphome/components/epaper_spi/epaper_spi.h +93 -0
- esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
- esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
- esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
- esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
- esphome/components/es7210/es7210.cpp +3 -3
- esphome/components/esp32/__init__.py +256 -340
- esphome/components/esp32/boards.py +81 -0
- esphome/components/esp32/preferences.cpp +23 -17
- esphome/components/esp32_ble/__init__.py +167 -44
- esphome/components/esp32_ble/ble.cpp +47 -3
- esphome/components/esp32_ble/ble.h +18 -0
- esphome/components/esp32_ble/ble_advertising.cpp +7 -3
- esphome/components/esp32_ble/ble_advertising.h +4 -0
- esphome/components/esp32_ble/ble_uuid.cpp +16 -42
- esphome/components/esp32_ble_beacon/__init__.py +3 -4
- esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +0 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
- esphome/components/esp32_ble_server/__init__.py +28 -14
- esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
- esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
- esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
- esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
- esphome/components/esp32_ble_server/ble_server.cpp +59 -24
- esphome/components/esp32_ble_server/ble_server.h +38 -20
- esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
- esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
- esphome/components/esp32_ble_tracker/__init__.py +25 -80
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -8
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
- esphome/components/esp32_camera/__init__.py +1 -3
- esphome/components/esp32_can/esp32_can.cpp +22 -4
- esphome/components/esp32_can/esp32_can.h +3 -0
- esphome/components/esp32_hosted/__init__.py +2 -1
- esphome/components/esp32_improv/esp32_improv_component.cpp +135 -65
- esphome/components/esp32_improv/esp32_improv_component.h +7 -1
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
- esphome/components/esp8266/__init__.py +3 -3
- esphome/components/esphome/ota/__init__.py +21 -2
- esphome/components/esphome/ota/ota_esphome.cpp +456 -146
- esphome/components/esphome/ota/ota_esphome.h +49 -2
- esphome/components/ethernet/__init__.py +39 -22
- esphome/components/ethernet/ethernet_component.cpp +28 -5
- esphome/components/ethernet/ethernet_component.h +5 -1
- esphome/components/external_components/__init__.py +8 -6
- esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
- esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
- esphome/components/font/__init__.py +5 -5
- esphome/components/graph/graph.cpp +1 -1
- esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
- esphome/components/haier/hon_climate.cpp +2 -2
- esphome/components/haier/hon_climate.h +1 -1
- esphome/components/hdc1080/hdc1080.cpp +42 -34
- esphome/components/hdc1080/hdc1080.h +1 -3
- esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
- esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
- esphome/components/http_request/__init__.py +3 -3
- esphome/components/htu21d/htu21d.cpp +13 -18
- esphome/components/htu21d/htu21d.h +1 -1
- esphome/components/i2s_audio/__init__.py +1 -2
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
- esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
- esphome/components/improv_serial/improv_serial_component.cpp +12 -15
- esphome/components/improv_serial/improv_serial_component.h +6 -8
- esphome/components/json/json_util.cpp +42 -44
- esphome/components/json/json_util.h +57 -0
- esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
- esphome/components/key_collector/key_collector.h +4 -4
- esphome/components/libretiny/__init__.py +6 -6
- esphome/components/libretiny/preferences.cpp +23 -16
- esphome/components/light/light_call.cpp +98 -120
- esphome/components/light/light_call.h +17 -7
- esphome/components/lm75b/__init__.py +0 -0
- esphome/components/lm75b/lm75b.cpp +39 -0
- esphome/components/lm75b/lm75b.h +19 -0
- esphome/components/lm75b/sensor.py +34 -0
- esphome/components/lock/lock.h +12 -6
- esphome/components/logger/__init__.py +15 -27
- esphome/components/logger/logger.cpp +10 -20
- esphome/components/logger/logger.h +105 -62
- esphome/components/logger/logger_esp32.cpp +0 -48
- esphome/components/logger/logger_zephyr.cpp +2 -3
- esphome/components/logger/select/logger_level_select.cpp +6 -7
- esphome/components/logger/select/logger_level_select.h +7 -0
- esphome/components/ltr501/ltr501.cpp +7 -6
- esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
- esphome/components/matrix_keypad/matrix_keypad.h +4 -4
- esphome/components/max7219digit/max7219digit.cpp +1 -1
- esphome/components/mcp23xxx_base/mcp23xxx_base.h +3 -3
- esphome/components/mcp2515/mcp2515.cpp +31 -3
- esphome/components/mcp2515/mcp2515_defs.h +3 -1
- esphome/components/md5/md5.cpp +0 -26
- esphome/components/md5/md5.h +10 -20
- esphome/components/mdns/__init__.py +93 -19
- esphome/components/mdns/mdns_component.cpp +57 -94
- esphome/components/mdns/mdns_component.h +35 -11
- esphome/components/mdns/mdns_esp32.cpp +7 -13
- esphome/components/mdns/mdns_esp8266.cpp +7 -7
- esphome/components/mdns/mdns_libretiny.cpp +3 -4
- esphome/components/mdns/mdns_rp2040.cpp +3 -4
- esphome/components/mipi/__init__.py +1 -5
- esphome/components/mipi_dsi/models/waveshare.py +27 -36
- esphome/components/mipi_spi/display.py +24 -8
- esphome/components/mipi_spi/mipi_spi.h +3 -3
- esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
- esphome/components/mmc5603/mmc5603.cpp +3 -3
- esphome/components/modbus/modbus.cpp +27 -13
- esphome/components/modbus/modbus.h +5 -3
- esphome/components/modbus/modbus_definitions.h +86 -0
- esphome/components/modbus_controller/__init__.py +29 -1
- esphome/components/modbus_controller/const.py +4 -0
- esphome/components/modbus_controller/modbus_controller.cpp +38 -13
- esphome/components/modbus_controller/modbus_controller.h +18 -29
- esphome/components/mpr121/mpr121.cpp +41 -42
- esphome/components/mpr121/mpr121.h +0 -1
- esphome/components/nau7802/nau7802.cpp +2 -2
- esphome/components/network/__init__.py +7 -3
- esphome/components/nextion/display.py +4 -4
- esphome/components/nextion/nextion.cpp +8 -8
- esphome/components/number/__init__.py +2 -0
- esphome/components/number/number_call.cpp +23 -12
- esphome/components/number/number_call.h +5 -0
- esphome/components/online_image/bmp_image.cpp +2 -1
- esphome/components/online_image/jpeg_image.cpp +4 -2
- esphome/components/opentherm/opentherm.cpp +5 -5
- esphome/components/opentherm/opentherm.h +3 -3
- esphome/components/openthread/openthread.cpp +11 -10
- esphome/components/openthread/openthread.h +0 -1
- esphome/components/ota/ota_backend.h +1 -0
- esphome/components/packages/__init__.py +10 -8
- esphome/components/packet_transport/packet_transport.cpp +2 -0
- esphome/components/pid/pid_controller.cpp +1 -1
- esphome/components/prometheus/prometheus_handler.cpp +239 -239
- esphome/components/psram/__init__.py +32 -28
- esphome/components/qmc5883l/qmc5883l.cpp +15 -0
- esphome/components/qmc5883l/qmc5883l.h +3 -0
- esphome/components/qmc5883l/sensor.py +31 -12
- esphome/components/remote_base/gobox_protocol.cpp +3 -3
- esphome/components/remote_receiver/__init__.py +14 -2
- esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
- esphome/components/remote_receiver/remote_receiver.h +4 -0
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
- esphome/components/remote_transmitter/__init__.py +2 -2
- esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
- esphome/components/rp2040/__init__.py +11 -11
- esphome/components/rtttl/rtttl.cpp +2 -2
- esphome/components/scd30/sensor.py +1 -1
- esphome/components/script/__init__.py +1 -1
- esphome/components/script/script.h +7 -7
- esphome/components/select/select.cpp +5 -4
- esphome/components/select/select_call.cpp +1 -1
- esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
- esphome/components/sensor/__init__.py +2 -0
- esphome/components/sha256/__init__.py +22 -0
- esphome/components/sha256/sha256.cpp +116 -0
- esphome/components/sha256/sha256.h +60 -0
- esphome/components/sim800l/sim800l.cpp +8 -4
- esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
- esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
- esphome/components/speaker/media_player/__init__.py +16 -3
- esphome/components/spi/__init__.py +0 -3
- esphome/components/split_buffer/__init__.py +5 -0
- esphome/components/split_buffer/split_buffer.cpp +133 -0
- esphome/components/split_buffer/split_buffer.h +40 -0
- esphome/components/sps30/sps30.cpp +14 -10
- esphome/components/sps30/sps30.h +2 -0
- esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
- esphome/components/st7789v/st7789v.cpp +3 -2
- esphome/components/statsd/statsd.cpp +1 -1
- esphome/components/substitutions/__init__.py +3 -1
- esphome/components/substitutions/jinja.py +13 -3
- esphome/components/sx126x/__init__.py +16 -0
- esphome/components/sx126x/sx126x.cpp +15 -1
- esphome/components/sx126x/sx126x.h +9 -1
- esphome/components/sx126x/sx126x_reg.h +2 -0
- esphome/components/text_sensor/text_sensor.cpp +16 -0
- esphome/components/text_sensor/text_sensor.h +3 -10
- esphome/components/tormatic/tormatic_cover.cpp +1 -1
- esphome/components/tuya/select/tuya_select.cpp +1 -1
- esphome/components/tuya/tuya.cpp +29 -4
- esphome/components/uart/__init__.py +37 -27
- esphome/components/uart/uart.h +6 -0
- esphome/components/uart/uart_component.cpp +8 -0
- esphome/components/uart/uart_component.h +28 -0
- esphome/components/uart/uart_component_esp_idf.cpp +64 -10
- esphome/components/uart/uart_component_esp_idf.h +5 -2
- esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
- esphome/components/usb_host/__init__.py +12 -2
- esphome/components/usb_host/usb_host.h +89 -14
- esphome/components/usb_host/usb_host_client.cpp +157 -22
- esphome/components/usb_host/usb_host_component.cpp +1 -1
- esphome/components/usb_uart/__init__.py +0 -1
- esphome/components/usb_uart/ch34x.cpp +4 -4
- esphome/components/usb_uart/cp210x.cpp +3 -3
- esphome/components/usb_uart/usb_uart.cpp +88 -32
- esphome/components/usb_uart/usb_uart.h +30 -6
- esphome/components/valve/valve.cpp +1 -0
- esphome/components/veml7700/veml7700.cpp +7 -6
- esphome/components/version/version_text_sensor.cpp +2 -1
- esphome/components/voice_assistant/voice_assistant.cpp +3 -3
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
- esphome/components/web_server/list_entities.cpp +3 -4
- esphome/components/web_server/list_entities.h +8 -10
- esphome/components/web_server/ota/__init__.py +1 -1
- esphome/components/web_server/ota/ota_web_server.cpp +9 -3
- esphome/components/web_server/web_server.cpp +509 -404
- esphome/components/web_server/web_server.h +5 -6
- esphome/components/web_server/web_server_v1.cpp +21 -19
- esphome/components/web_server_base/__init__.py +5 -2
- esphome/components/web_server_base/web_server_base.h +27 -7
- esphome/components/web_server_idf/__init__.py +1 -1
- esphome/components/web_server_idf/multipart.cpp +2 -2
- esphome/components/web_server_idf/multipart.h +2 -2
- esphome/components/web_server_idf/utils.cpp +2 -2
- esphome/components/web_server_idf/utils.h +2 -2
- esphome/components/web_server_idf/web_server_idf.cpp +118 -26
- esphome/components/web_server_idf/web_server_idf.h +12 -10
- esphome/components/wifi/__init__.py +13 -11
- esphome/components/wifi/wifi_component.cpp +74 -56
- esphome/components/wifi/wifi_component.h +4 -4
- esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
- esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
- esphome/components/wireguard/__init__.py +1 -1
- esphome/components/wts01/__init__.py +0 -0
- esphome/components/wts01/sensor.py +41 -0
- esphome/components/wts01/wts01.cpp +91 -0
- esphome/components/wts01/wts01.h +27 -0
- esphome/components/zephyr/__init__.py +5 -5
- esphome/components/zwave_proxy/__init__.py +43 -0
- esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
- esphome/components/zwave_proxy/zwave_proxy.h +93 -0
- esphome/config.py +79 -24
- esphome/config_validation.py +13 -15
- esphome/const.py +9 -2
- esphome/core/__init__.py +33 -22
- esphome/core/component.cpp +28 -18
- esphome/core/component_iterator.h +2 -1
- esphome/core/config.py +15 -15
- esphome/core/defines.h +21 -0
- esphome/core/entity_helpers.py +9 -6
- esphome/core/hash_base.h +56 -0
- esphome/core/helpers.cpp +19 -3
- esphome/core/helpers.h +26 -0
- esphome/core/scheduler.cpp +5 -21
- esphome/core/scheduler.h +19 -8
- esphome/core/string_ref.h +1 -1
- esphome/core/time.cpp +5 -5
- esphome/cpp_generator.py +4 -29
- esphome/dashboard/const.py +21 -4
- esphome/dashboard/core.py +10 -8
- esphome/dashboard/dns.py +15 -0
- esphome/dashboard/entries.py +15 -21
- esphome/dashboard/models.py +76 -0
- esphome/dashboard/settings.py +7 -7
- esphome/dashboard/status/mdns.py +46 -2
- esphome/dashboard/web_server.py +367 -93
- esphome/espota2.py +112 -32
- esphome/external_files.py +6 -7
- esphome/git.py +8 -0
- esphome/helpers.py +124 -77
- esphome/loader.py +8 -9
- esphome/pins.py +2 -2
- esphome/platformio_api.py +56 -18
- esphome/storage_json.py +26 -21
- esphome/types.py +30 -2
- esphome/util.py +32 -16
- esphome/vscode.py +8 -8
- esphome/wizard.py +10 -10
- esphome/writer.py +57 -15
- esphome/yaml_util.py +37 -31
- esphome/zeroconf.py +12 -3
- {esphome-2025.9.2.dist-info → esphome-2025.10.0.dist-info}/METADATA +12 -12
- {esphome-2025.9.2.dist-info → esphome-2025.10.0.dist-info}/RECORD +343 -323
- esphome/components/event_emitter/__init__.py +0 -5
- esphome/components/event_emitter/event_emitter.cpp +0 -14
- esphome/components/event_emitter/event_emitter.h +0 -63
- esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
- esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
- esphome/components/uart/uart_component_esp32_arduino.h +0 -60
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
- esphome/core/string_ref.cpp +0 -12
- esphome/dashboard/util/file.py +0 -63
- {esphome-2025.9.2.dist-info → esphome-2025.10.0.dist-info}/WHEEL +0 -0
- {esphome-2025.9.2.dist-info → esphome-2025.10.0.dist-info}/entry_points.txt +0 -0
- {esphome-2025.9.2.dist-info → esphome-2025.10.0.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.9.2.dist-info → esphome-2025.10.0.dist-info}/top_level.txt +0 -0
esphome/writer.py
CHANGED
|
@@ -15,6 +15,8 @@ from esphome.const import (
|
|
|
15
15
|
from esphome.core import CORE, EsphomeError
|
|
16
16
|
from esphome.helpers import (
|
|
17
17
|
copy_file_if_changed,
|
|
18
|
+
get_str_env,
|
|
19
|
+
is_ha_addon,
|
|
18
20
|
read_file,
|
|
19
21
|
walk_files,
|
|
20
22
|
write_file_if_changed,
|
|
@@ -266,7 +268,7 @@ def generate_version_h():
|
|
|
266
268
|
|
|
267
269
|
def write_cpp(code_s):
|
|
268
270
|
path = CORE.relative_src_path("main.cpp")
|
|
269
|
-
if
|
|
271
|
+
if path.is_file():
|
|
270
272
|
text = read_file(path)
|
|
271
273
|
code_format = find_begin_end(
|
|
272
274
|
text, CPP_AUTO_GENERATE_BEGIN, CPP_AUTO_GENERATE_END
|
|
@@ -292,43 +294,84 @@ def write_cpp(code_s):
|
|
|
292
294
|
|
|
293
295
|
def clean_cmake_cache():
|
|
294
296
|
pioenvs = CORE.relative_pioenvs_path()
|
|
295
|
-
if
|
|
296
|
-
pioenvs_cmake_path = CORE.
|
|
297
|
-
if
|
|
297
|
+
if pioenvs.is_dir():
|
|
298
|
+
pioenvs_cmake_path = pioenvs / CORE.name / "CMakeCache.txt"
|
|
299
|
+
if pioenvs_cmake_path.is_file():
|
|
298
300
|
_LOGGER.info("Deleting %s", pioenvs_cmake_path)
|
|
299
|
-
|
|
301
|
+
pioenvs_cmake_path.unlink()
|
|
300
302
|
|
|
301
303
|
|
|
302
304
|
def clean_build():
|
|
303
305
|
import shutil
|
|
304
306
|
|
|
307
|
+
# Allow skipping cache cleaning for integration tests
|
|
308
|
+
if os.environ.get("ESPHOME_SKIP_CLEAN_BUILD"):
|
|
309
|
+
_LOGGER.warning("Skipping build cleaning (ESPHOME_SKIP_CLEAN_BUILD set)")
|
|
310
|
+
return
|
|
311
|
+
|
|
305
312
|
pioenvs = CORE.relative_pioenvs_path()
|
|
306
|
-
if
|
|
313
|
+
if pioenvs.is_dir():
|
|
307
314
|
_LOGGER.info("Deleting %s", pioenvs)
|
|
308
315
|
shutil.rmtree(pioenvs)
|
|
309
316
|
piolibdeps = CORE.relative_piolibdeps_path()
|
|
310
|
-
if
|
|
317
|
+
if piolibdeps.is_dir():
|
|
311
318
|
_LOGGER.info("Deleting %s", piolibdeps)
|
|
312
319
|
shutil.rmtree(piolibdeps)
|
|
313
320
|
dependencies_lock = CORE.relative_build_path("dependencies.lock")
|
|
314
|
-
if
|
|
321
|
+
if dependencies_lock.is_file():
|
|
315
322
|
_LOGGER.info("Deleting %s", dependencies_lock)
|
|
316
|
-
|
|
323
|
+
dependencies_lock.unlink()
|
|
317
324
|
|
|
318
325
|
# Clean PlatformIO cache to resolve CMake compiler detection issues
|
|
319
326
|
# This helps when toolchain paths change or get corrupted
|
|
320
327
|
try:
|
|
321
|
-
from platformio.project.
|
|
328
|
+
from platformio.project.config import ProjectConfig
|
|
322
329
|
except ImportError:
|
|
323
330
|
# PlatformIO is not available, skip cache cleaning
|
|
324
331
|
pass
|
|
325
332
|
else:
|
|
326
|
-
|
|
327
|
-
|
|
333
|
+
config = ProjectConfig.get_instance()
|
|
334
|
+
cache_dir = Path(config.get("platformio", "cache_dir"))
|
|
335
|
+
if cache_dir.is_dir():
|
|
328
336
|
_LOGGER.info("Deleting PlatformIO cache %s", cache_dir)
|
|
329
337
|
shutil.rmtree(cache_dir)
|
|
330
338
|
|
|
331
339
|
|
|
340
|
+
def clean_all(configuration: list[str]):
|
|
341
|
+
import shutil
|
|
342
|
+
|
|
343
|
+
data_dirs = [Path(dir) / ".esphome" for dir in configuration]
|
|
344
|
+
if is_ha_addon():
|
|
345
|
+
data_dirs.append(Path("/data"))
|
|
346
|
+
if "ESPHOME_DATA_DIR" in os.environ:
|
|
347
|
+
data_dirs.append(Path(get_str_env("ESPHOME_DATA_DIR", None)))
|
|
348
|
+
|
|
349
|
+
# Clean build dir
|
|
350
|
+
for dir in data_dirs:
|
|
351
|
+
if dir.is_dir():
|
|
352
|
+
_LOGGER.info("Cleaning %s", dir)
|
|
353
|
+
# Don't remove storage or .json files which are needed by the dashboard
|
|
354
|
+
for item in dir.iterdir():
|
|
355
|
+
if item.is_file() and not item.name.endswith(".json"):
|
|
356
|
+
item.unlink()
|
|
357
|
+
elif item.is_dir() and item.name != "storage":
|
|
358
|
+
shutil.rmtree(item)
|
|
359
|
+
|
|
360
|
+
# Clean PlatformIO project files
|
|
361
|
+
try:
|
|
362
|
+
from platformio.project.config import ProjectConfig
|
|
363
|
+
except ImportError:
|
|
364
|
+
# PlatformIO is not available, skip cleaning
|
|
365
|
+
pass
|
|
366
|
+
else:
|
|
367
|
+
config = ProjectConfig.get_instance()
|
|
368
|
+
for pio_dir in ["cache_dir", "packages_dir", "platforms_dir", "core_dir"]:
|
|
369
|
+
path = Path(config.get("platformio", pio_dir))
|
|
370
|
+
if path.is_dir():
|
|
371
|
+
_LOGGER.info("Deleting PlatformIO %s %s", pio_dir, path)
|
|
372
|
+
shutil.rmtree(path)
|
|
373
|
+
|
|
374
|
+
|
|
332
375
|
GITIGNORE_CONTENT = """# Gitignore settings for ESPHome
|
|
333
376
|
# This is an example and may include too much for your use-case.
|
|
334
377
|
# You can modify this file to suit your needs.
|
|
@@ -339,6 +382,5 @@ GITIGNORE_CONTENT = """# Gitignore settings for ESPHome
|
|
|
339
382
|
|
|
340
383
|
def write_gitignore():
|
|
341
384
|
path = CORE.relative_config_path(".gitignore")
|
|
342
|
-
if not
|
|
343
|
-
|
|
344
|
-
f.write(GITIGNORE_CONTENT)
|
|
385
|
+
if not path.is_file():
|
|
386
|
+
path.write_text(GITIGNORE_CONTENT, encoding="utf-8")
|
esphome/yaml_util.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from collections.abc import Callable
|
|
4
|
-
import fnmatch
|
|
5
4
|
import functools
|
|
6
5
|
import inspect
|
|
7
6
|
from io import BytesIO, TextIOBase, TextIOWrapper
|
|
@@ -9,6 +8,7 @@ from ipaddress import _BaseAddress, _BaseNetwork
|
|
|
9
8
|
import logging
|
|
10
9
|
import math
|
|
11
10
|
import os
|
|
11
|
+
from pathlib import Path
|
|
12
12
|
from typing import Any
|
|
13
13
|
import uuid
|
|
14
14
|
|
|
@@ -69,7 +69,7 @@ class ESPHomeDataBase:
|
|
|
69
69
|
self._content_offset = database.content_offset
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
class
|
|
72
|
+
class ESPLiteralValue:
|
|
73
73
|
pass
|
|
74
74
|
|
|
75
75
|
|
|
@@ -109,7 +109,9 @@ def _add_data_ref(fn):
|
|
|
109
109
|
class ESPHomeLoaderMixin:
|
|
110
110
|
"""Loader class that keeps track of line numbers."""
|
|
111
111
|
|
|
112
|
-
def __init__(
|
|
112
|
+
def __init__(
|
|
113
|
+
self, name: Path, yaml_loader: Callable[[Path], dict[str, Any]]
|
|
114
|
+
) -> None:
|
|
113
115
|
"""Initialize the loader."""
|
|
114
116
|
self.name = name
|
|
115
117
|
self.yaml_loader = yaml_loader
|
|
@@ -254,12 +256,8 @@ class ESPHomeLoaderMixin:
|
|
|
254
256
|
f"Environment variable '{node.value}' not defined", node.start_mark
|
|
255
257
|
)
|
|
256
258
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
return os.path.dirname(self.name)
|
|
260
|
-
|
|
261
|
-
def _rel_path(self, *args: str) -> str:
|
|
262
|
-
return os.path.join(self._directory, *args)
|
|
259
|
+
def _rel_path(self, *args: str) -> Path:
|
|
260
|
+
return self.name.parent / Path(*args)
|
|
263
261
|
|
|
264
262
|
@_add_data_ref
|
|
265
263
|
def construct_secret(self, node: yaml.Node) -> str:
|
|
@@ -269,8 +267,8 @@ class ESPHomeLoaderMixin:
|
|
|
269
267
|
if self.name == CORE.config_path:
|
|
270
268
|
raise e
|
|
271
269
|
try:
|
|
272
|
-
main_config_dir =
|
|
273
|
-
main_secret_yml =
|
|
270
|
+
main_config_dir = CORE.config_path.parent
|
|
271
|
+
main_secret_yml = main_config_dir / SECRET_YAML
|
|
274
272
|
secrets = self.yaml_loader(main_secret_yml)
|
|
275
273
|
except EsphomeError as er:
|
|
276
274
|
raise EsphomeError(f"{e}\n{er}") from er
|
|
@@ -329,7 +327,7 @@ class ESPHomeLoaderMixin:
|
|
|
329
327
|
files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml"))
|
|
330
328
|
mapping = OrderedDict()
|
|
331
329
|
for fname in files:
|
|
332
|
-
filename =
|
|
330
|
+
filename = fname.stem
|
|
333
331
|
mapping[filename] = self.yaml_loader(fname)
|
|
334
332
|
return mapping
|
|
335
333
|
|
|
@@ -350,9 +348,15 @@ class ESPHomeLoaderMixin:
|
|
|
350
348
|
return Lambda(str(node.value))
|
|
351
349
|
|
|
352
350
|
@_add_data_ref
|
|
353
|
-
def
|
|
354
|
-
obj =
|
|
355
|
-
|
|
351
|
+
def construct_literal(self, node: yaml.Node) -> ESPLiteralValue:
|
|
352
|
+
obj = None
|
|
353
|
+
if isinstance(node, yaml.ScalarNode):
|
|
354
|
+
obj = self.construct_scalar(node)
|
|
355
|
+
elif isinstance(node, yaml.SequenceNode):
|
|
356
|
+
obj = self.construct_sequence(node)
|
|
357
|
+
elif isinstance(node, yaml.MappingNode):
|
|
358
|
+
obj = self.construct_mapping(node)
|
|
359
|
+
return add_class_to_obj(obj, ESPLiteralValue)
|
|
356
360
|
|
|
357
361
|
@_add_data_ref
|
|
358
362
|
def construct_extend(self, node: yaml.Node) -> Extend:
|
|
@@ -369,8 +373,8 @@ class ESPHomeLoader(ESPHomeLoaderMixin, FastestAvailableSafeLoader):
|
|
|
369
373
|
def __init__(
|
|
370
374
|
self,
|
|
371
375
|
stream: TextIOBase | BytesIO,
|
|
372
|
-
name:
|
|
373
|
-
yaml_loader: Callable[[
|
|
376
|
+
name: Path,
|
|
377
|
+
yaml_loader: Callable[[Path], dict[str, Any]],
|
|
374
378
|
) -> None:
|
|
375
379
|
FastestAvailableSafeLoader.__init__(self, stream)
|
|
376
380
|
ESPHomeLoaderMixin.__init__(self, name, yaml_loader)
|
|
@@ -382,8 +386,8 @@ class ESPHomePurePythonLoader(ESPHomeLoaderMixin, PurePythonLoader):
|
|
|
382
386
|
def __init__(
|
|
383
387
|
self,
|
|
384
388
|
stream: TextIOBase | BytesIO,
|
|
385
|
-
name:
|
|
386
|
-
yaml_loader: Callable[[
|
|
389
|
+
name: Path,
|
|
390
|
+
yaml_loader: Callable[[Path], dict[str, Any]],
|
|
387
391
|
) -> None:
|
|
388
392
|
PurePythonLoader.__init__(self, stream)
|
|
389
393
|
ESPHomeLoaderMixin.__init__(self, name, yaml_loader)
|
|
@@ -409,29 +413,29 @@ for _loader in (ESPHomeLoader, ESPHomePurePythonLoader):
|
|
|
409
413
|
"!include_dir_merge_named", _loader.construct_include_dir_merge_named
|
|
410
414
|
)
|
|
411
415
|
_loader.add_constructor("!lambda", _loader.construct_lambda)
|
|
412
|
-
_loader.add_constructor("!
|
|
416
|
+
_loader.add_constructor("!literal", _loader.construct_literal)
|
|
413
417
|
_loader.add_constructor("!extend", _loader.construct_extend)
|
|
414
418
|
_loader.add_constructor("!remove", _loader.construct_remove)
|
|
415
419
|
|
|
416
420
|
|
|
417
|
-
def load_yaml(fname:
|
|
421
|
+
def load_yaml(fname: Path, clear_secrets: bool = True) -> Any:
|
|
418
422
|
if clear_secrets:
|
|
419
423
|
_SECRET_VALUES.clear()
|
|
420
424
|
_SECRET_CACHE.clear()
|
|
421
425
|
return _load_yaml_internal(fname)
|
|
422
426
|
|
|
423
427
|
|
|
424
|
-
def _load_yaml_internal(fname:
|
|
428
|
+
def _load_yaml_internal(fname: Path) -> Any:
|
|
425
429
|
"""Load a YAML file."""
|
|
426
430
|
try:
|
|
427
|
-
with open(
|
|
431
|
+
with fname.open(encoding="utf-8") as f_handle:
|
|
428
432
|
return parse_yaml(fname, f_handle)
|
|
429
433
|
except (UnicodeDecodeError, OSError) as err:
|
|
430
434
|
raise EsphomeError(f"Error reading file {fname}: {err}") from err
|
|
431
435
|
|
|
432
436
|
|
|
433
437
|
def parse_yaml(
|
|
434
|
-
file_name:
|
|
438
|
+
file_name: Path, file_handle: TextIOWrapper, yaml_loader=_load_yaml_internal
|
|
435
439
|
) -> Any:
|
|
436
440
|
"""Parse a YAML file."""
|
|
437
441
|
try:
|
|
@@ -483,9 +487,9 @@ def substitute_vars(config, vars):
|
|
|
483
487
|
|
|
484
488
|
def _load_yaml_internal_with_type(
|
|
485
489
|
loader_type: type[ESPHomeLoader] | type[ESPHomePurePythonLoader],
|
|
486
|
-
fname:
|
|
490
|
+
fname: Path,
|
|
487
491
|
content: TextIOWrapper,
|
|
488
|
-
yaml_loader: Any,
|
|
492
|
+
yaml_loader: Callable[[Path], dict[str, Any]],
|
|
489
493
|
) -> Any:
|
|
490
494
|
"""Load a YAML file."""
|
|
491
495
|
loader = loader_type(content, fname, yaml_loader)
|
|
@@ -512,13 +516,14 @@ def _is_file_valid(name: str) -> bool:
|
|
|
512
516
|
return not name.startswith(".")
|
|
513
517
|
|
|
514
518
|
|
|
515
|
-
def _find_files(directory, pattern):
|
|
519
|
+
def _find_files(directory: Path, pattern):
|
|
516
520
|
"""Recursively load files in a directory."""
|
|
517
|
-
for root, dirs, files in os.walk(directory
|
|
521
|
+
for root, dirs, files in os.walk(directory):
|
|
518
522
|
dirs[:] = [d for d in dirs if _is_file_valid(d)]
|
|
519
|
-
for
|
|
520
|
-
|
|
521
|
-
|
|
523
|
+
for f in files:
|
|
524
|
+
filename = Path(f)
|
|
525
|
+
if _is_file_valid(f) and filename.match(pattern):
|
|
526
|
+
filename = Path(root) / filename
|
|
522
527
|
yield filename
|
|
523
528
|
|
|
524
529
|
|
|
@@ -627,3 +632,4 @@ ESPHomeDumper.add_multi_representer(TimePeriod, ESPHomeDumper.represent_stringif
|
|
|
627
632
|
ESPHomeDumper.add_multi_representer(Lambda, ESPHomeDumper.represent_lambda)
|
|
628
633
|
ESPHomeDumper.add_multi_representer(core.ID, ESPHomeDumper.represent_id)
|
|
629
634
|
ESPHomeDumper.add_multi_representer(uuid.UUID, ESPHomeDumper.represent_stringify)
|
|
635
|
+
ESPHomeDumper.add_multi_representer(Path, ESPHomeDumper.represent_stringify)
|
esphome/zeroconf.py
CHANGED
|
@@ -68,8 +68,11 @@ class DashboardBrowser(AsyncServiceBrowser):
|
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
class DashboardImportDiscovery:
|
|
71
|
-
def __init__(
|
|
71
|
+
def __init__(
|
|
72
|
+
self, on_update: Callable[[str, DiscoveredImport | None], None] | None = None
|
|
73
|
+
) -> None:
|
|
72
74
|
self.import_state: dict[str, DiscoveredImport] = {}
|
|
75
|
+
self.on_update = on_update
|
|
73
76
|
|
|
74
77
|
def browser_callback(
|
|
75
78
|
self,
|
|
@@ -85,7 +88,9 @@ class DashboardImportDiscovery:
|
|
|
85
88
|
state_change,
|
|
86
89
|
)
|
|
87
90
|
if state_change == ServiceStateChange.Removed:
|
|
88
|
-
self.import_state.pop(name, None)
|
|
91
|
+
removed = self.import_state.pop(name, None)
|
|
92
|
+
if removed and self.on_update:
|
|
93
|
+
self.on_update(name, None)
|
|
89
94
|
return
|
|
90
95
|
|
|
91
96
|
if state_change == ServiceStateChange.Updated and name not in self.import_state:
|
|
@@ -139,7 +144,7 @@ class DashboardImportDiscovery:
|
|
|
139
144
|
if friendly_name is not None:
|
|
140
145
|
friendly_name = friendly_name.decode()
|
|
141
146
|
|
|
142
|
-
|
|
147
|
+
discovered = DiscoveredImport(
|
|
143
148
|
friendly_name=friendly_name,
|
|
144
149
|
device_name=node_name,
|
|
145
150
|
package_import_url=import_url,
|
|
@@ -147,6 +152,10 @@ class DashboardImportDiscovery:
|
|
|
147
152
|
project_version=project_version,
|
|
148
153
|
network=network,
|
|
149
154
|
)
|
|
155
|
+
is_new = name not in self.import_state
|
|
156
|
+
self.import_state[name] = discovered
|
|
157
|
+
if is_new and self.on_update:
|
|
158
|
+
self.on_update(name, discovered)
|
|
150
159
|
|
|
151
160
|
def update_device_mdns(self, node_name: str, version: str):
|
|
152
161
|
storage_path = ext_storage_path(node_name + ".yaml")
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: esphome
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.10.0
|
|
4
4
|
Summary: ESPHome is a system to configure your microcontrollers by simple yet powerful configuration files and control them remotely through Home Automation systems.
|
|
5
5
|
Author-email: The ESPHome Authors <esphome@openhomefoundation.org>
|
|
6
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Documentation, https://esphome.io
|
|
8
8
|
Project-URL: Source Code, https://github.com/esphome/esphome
|
|
9
9
|
Project-URL: Bug Tracker, https://github.com/esphome/esphome/issues
|
|
@@ -16,7 +16,6 @@ Platform: any
|
|
|
16
16
|
Classifier: Environment :: Console
|
|
17
17
|
Classifier: Intended Audience :: Developers
|
|
18
18
|
Classifier: Intended Audience :: End Users/Desktop
|
|
19
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
20
19
|
Classifier: Programming Language :: C++
|
|
21
20
|
Classifier: Programming Language :: Python :: 3
|
|
22
21
|
Classifier: Topic :: Home Automation
|
|
@@ -25,7 +24,7 @@ Description-Content-Type: text/markdown
|
|
|
25
24
|
License-File: LICENSE
|
|
26
25
|
Requires-Dist: cryptography==45.0.1
|
|
27
26
|
Requires-Dist: voluptuous==0.15.2
|
|
28
|
-
Requires-Dist: PyYAML==6.0.
|
|
27
|
+
Requires-Dist: PyYAML==6.0.3
|
|
29
28
|
Requires-Dist: paho-mqtt==1.6.1
|
|
30
29
|
Requires-Dist: colorama==0.4.6
|
|
31
30
|
Requires-Dist: icmplib==3.0.4
|
|
@@ -34,13 +33,14 @@ Requires-Dist: tzlocal==5.3.1
|
|
|
34
33
|
Requires-Dist: tzdata>=2021.1
|
|
35
34
|
Requires-Dist: pyserial==3.5
|
|
36
35
|
Requires-Dist: platformio==6.1.18
|
|
37
|
-
Requires-Dist: esptool==5.0
|
|
36
|
+
Requires-Dist: esptool==5.1.0
|
|
38
37
|
Requires-Dist: click==8.1.7
|
|
39
|
-
Requires-Dist: esphome-dashboard==
|
|
40
|
-
Requires-Dist: aioesphomeapi==
|
|
41
|
-
Requires-Dist: zeroconf==0.
|
|
38
|
+
Requires-Dist: esphome-dashboard==20251013.0
|
|
39
|
+
Requires-Dist: aioesphomeapi==41.16.1
|
|
40
|
+
Requires-Dist: zeroconf==0.148.0
|
|
42
41
|
Requires-Dist: puremagic==1.30
|
|
43
42
|
Requires-Dist: ruamel.yaml==0.18.15
|
|
43
|
+
Requires-Dist: ruamel.yaml.clib==0.2.12
|
|
44
44
|
Requires-Dist: esphome-glyphsets==0.2.0
|
|
45
45
|
Requires-Dist: pillow==10.4.0
|
|
46
46
|
Requires-Dist: cairosvg==2.8.2
|
|
@@ -54,15 +54,15 @@ Requires-Dist: clang-format==13.0.1; extra == "dev"
|
|
|
54
54
|
Requires-Dist: clang-tidy==18.1.8; extra == "dev"
|
|
55
55
|
Requires-Dist: yamllint==1.37.1; extra == "dev"
|
|
56
56
|
Provides-Extra: test
|
|
57
|
-
Requires-Dist: pylint==3.3.
|
|
57
|
+
Requires-Dist: pylint==3.3.9; extra == "test"
|
|
58
58
|
Requires-Dist: flake8==7.3.0; extra == "test"
|
|
59
|
-
Requires-Dist: ruff==0.
|
|
59
|
+
Requires-Dist: ruff==0.14.0; extra == "test"
|
|
60
60
|
Requires-Dist: pyupgrade==3.20.0; extra == "test"
|
|
61
61
|
Requires-Dist: pre-commit; extra == "test"
|
|
62
62
|
Requires-Dist: pytest==8.4.2; extra == "test"
|
|
63
63
|
Requires-Dist: pytest-cov==7.0.0; extra == "test"
|
|
64
|
-
Requires-Dist: pytest-mock==3.15.
|
|
65
|
-
Requires-Dist: pytest-asyncio==1.
|
|
64
|
+
Requires-Dist: pytest-mock==3.15.1; extra == "test"
|
|
65
|
+
Requires-Dist: pytest-asyncio==1.2.0; extra == "test"
|
|
66
66
|
Requires-Dist: pytest-xdist==3.8.0; extra == "test"
|
|
67
67
|
Requires-Dist: asyncmock==0.4.2; extra == "test"
|
|
68
68
|
Requires-Dist: hypothesis==6.92.1; extra == "test"
|