esphome 2025.7.5__py3-none-any.whl → 2025.8.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 +190 -83
- esphome/automation.py +2 -4
- esphome/build_gen/__init__.py +0 -0
- esphome/build_gen/platformio.py +102 -0
- esphome/components/a4988/a4988.cpp +0 -1
- esphome/components/absolute_humidity/absolute_humidity.cpp +0 -2
- esphome/components/absolute_humidity/sensor.py +2 -2
- esphome/components/adc/__init__.py +123 -85
- esphome/components/adc/adc_sensor.h +98 -35
- esphome/components/adc/adc_sensor_common.cpp +10 -4
- esphome/components/adc/adc_sensor_esp32.cpp +291 -123
- esphome/components/adc/adc_sensor_esp8266.cpp +1 -4
- esphome/components/adc/adc_sensor_libretiny.cpp +1 -2
- esphome/components/adc/adc_sensor_rp2040.cpp +1 -2
- esphome/components/adc/adc_sensor_zephyr.cpp +207 -0
- esphome/components/adc/sensor.py +61 -27
- esphome/components/adc128s102/adc128s102.cpp +1 -4
- esphome/components/ade7880/sensor.py +75 -49
- esphome/components/ads1115/ads1115.cpp +0 -1
- esphome/components/ads1118/ads1118.cpp +0 -1
- esphome/components/ags10/ags10.cpp +0 -4
- esphome/components/aht10/aht10.cpp +0 -4
- esphome/components/aic3204/aic3204.cpp +0 -2
- esphome/components/airthings_wave_plus/__init__.py +1 -1
- esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +22 -4
- esphome/components/airthings_wave_plus/airthings_wave_plus.h +10 -1
- esphome/components/airthings_wave_plus/sensor.py +55 -28
- esphome/components/alarm_control_panel/__init__.py +4 -9
- esphome/components/am2315c/am2315c.cpp +0 -2
- esphome/components/am2320/am2320.cpp +0 -1
- esphome/components/animation/__init__.py +14 -11
- esphome/components/apds9306/apds9306.cpp +0 -4
- esphome/components/apds9960/apds9960.cpp +0 -1
- esphome/components/api/__init__.py +29 -4
- esphome/components/api/api_connection.cpp +378 -401
- esphome/components/api/api_connection.h +102 -52
- esphome/components/api/api_frame_helper.cpp +69 -896
- esphome/components/api/api_frame_helper.h +31 -126
- esphome/components/api/api_frame_helper_noise.cpp +583 -0
- esphome/components/api/api_frame_helper_noise.h +68 -0
- esphome/components/api/api_frame_helper_plaintext.cpp +290 -0
- esphome/components/api/api_frame_helper_plaintext.h +53 -0
- esphome/components/api/api_noise_context.h +2 -4
- esphome/components/api/api_pb2.cpp +1601 -1808
- esphome/components/api/api_pb2.h +367 -323
- esphome/components/api/api_pb2_dump.cpp +1137 -3466
- esphome/components/api/api_pb2_includes.h +34 -0
- esphome/components/api/api_pb2_service.cpp +94 -105
- esphome/components/api/api_pb2_service.h +27 -16
- esphome/components/api/api_server.cpp +18 -17
- esphome/components/api/api_server.h +8 -5
- esphome/components/api/client.py +16 -8
- esphome/components/api/custom_api_device.h +68 -14
- esphome/components/api/homeassistant_service.h +24 -19
- esphome/components/api/list_entities.cpp +3 -5
- esphome/components/api/list_entities.h +2 -4
- esphome/components/api/proto.cpp +3 -5
- esphome/components/api/proto.h +239 -274
- esphome/components/api/subscribe_state.cpp +2 -4
- esphome/components/api/subscribe_state.h +2 -4
- esphome/components/api/user_services.cpp +2 -4
- esphome/components/api/user_services.h +8 -8
- esphome/components/as3935/as3935.cpp +0 -2
- esphome/components/as3935_spi/as3935_spi.cpp +0 -2
- esphome/components/as5600/__init__.py +1 -1
- esphome/components/as5600/as5600.cpp +0 -2
- esphome/components/as5600/sensor/__init__.py +0 -1
- esphome/components/as7341/as7341.cpp +0 -1
- esphome/components/async_tcp/__init__.py +1 -1
- esphome/components/at581x/at581x.cpp +1 -1
- esphome/components/atm90e26/atm90e26.cpp +0 -1
- esphome/components/atm90e32/atm90e32.cpp +475 -116
- esphome/components/atm90e32/atm90e32.h +43 -5
- esphome/components/audio/audio.h +2 -2
- esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +0 -2
- esphome/components/beken_spi_led_strip/led_strip.cpp +0 -2
- esphome/components/bh1750/bh1750.cpp +0 -1
- esphome/components/binary_sensor/__init__.py +14 -12
- esphome/components/ble_client/__init__.py +4 -7
- esphome/components/bluetooth_proxy/__init__.py +40 -3
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +392 -81
- esphome/components/bluetooth_proxy/bluetooth_connection.h +16 -5
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +102 -311
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +30 -14
- esphome/components/bme280_base/bme280_base.cpp +15 -16
- esphome/components/bme680/bme680.cpp +2 -3
- esphome/components/bme680_bsec/bme680_bsec.cpp +0 -2
- esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +0 -2
- esphome/components/bmi160/bmi160.cpp +0 -1
- esphome/components/bmp085/bmp085.cpp +0 -1
- esphome/components/bmp280_base/bmp280_base.cpp +13 -14
- esphome/components/bmp3xx_base/bmp3xx_base.cpp +0 -1
- esphome/components/bmp581/bmp581.cpp +0 -2
- esphome/components/bp1658cj/bp1658cj.cpp +0 -1
- esphome/components/bp5758d/bp5758d.cpp +0 -1
- esphome/components/button/__init__.py +0 -1
- esphome/components/canbus/__init__.py +2 -3
- esphome/components/canbus/canbus.cpp +0 -1
- esphome/components/cap1188/cap1188.cpp +0 -2
- esphome/components/captive_portal/__init__.py +1 -1
- esphome/components/cd74hc4067/cd74hc4067.cpp +0 -2
- esphome/components/ch422g/ch422g.cpp +0 -1
- esphome/components/chsc6x/chsc6x_touchscreen.cpp +0 -3
- esphome/components/climate/__init__.py +0 -1
- esphome/components/climate/climate_traits.h +24 -0
- esphome/components/cm1106/cm1106.cpp +0 -1
- esphome/components/const/__init__.py +6 -0
- esphome/components/cover/__init__.py +0 -1
- esphome/components/cover/cover.cpp +9 -13
- esphome/components/cs5460a/cs5460a.cpp +0 -2
- esphome/components/cse7761/cse7761.cpp +0 -1
- esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +0 -2
- esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +0 -2
- esphome/components/dac7678/dac7678_output.cpp +0 -2
- esphome/components/dallas_temp/dallas_temp.cpp +0 -1
- esphome/components/datetime/__init__.py +0 -2
- esphome/components/debug/__init__.py +15 -1
- esphome/components/debug/debug_zephyr.cpp +281 -0
- esphome/components/debug/sensor.py +2 -1
- esphome/components/deep_sleep/deep_sleep_component.cpp +0 -1
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +20 -1
- esphome/components/dfrobot_sen0395/__init__.py +1 -2
- esphome/components/dht/dht.cpp +0 -1
- esphome/components/dht12/dht12.cpp +0 -1
- esphome/components/display/__init__.py +16 -3
- esphome/components/display_menu_base/__init__.py +1 -1
- esphome/components/dps310/dps310.cpp +0 -2
- esphome/components/ds1307/ds1307.cpp +0 -1
- esphome/components/ds2484/ds2484.cpp +0 -1
- esphome/components/duty_cycle/duty_cycle_sensor.cpp +0 -1
- esphome/components/ee895/ee895.cpp +0 -1
- esphome/components/ektf2232/touchscreen/ektf2232.cpp +0 -1
- esphome/components/emc2101/emc2101.cpp +0 -2
- esphome/components/ens160_base/ens160_base.cpp +0 -2
- esphome/components/ens210/ens210.cpp +0 -1
- esphome/components/es7210/es7210.cpp +0 -2
- esphome/components/es7243e/es7243e.cpp +0 -2
- esphome/components/es8156/es8156.cpp +0 -2
- esphome/components/es8311/es8311.cpp +0 -2
- esphome/components/es8388/es8388.cpp +0 -2
- esphome/components/esp32/__init__.py +203 -60
- esphome/components/esp32/boards.py +17 -0
- esphome/components/esp32/gpio.cpp +0 -1
- esphome/components/esp32/gpio.py +1 -2
- esphome/components/esp32/gpio_esp32_h2.py +2 -7
- esphome/components/esp32/gpio_esp32_p4.py +2 -7
- esphome/components/esp32/post_build.py.script +112 -61
- esphome/components/esp32_ble/__init__.py +41 -2
- esphome/components/esp32_ble/ble.cpp +14 -10
- esphome/components/esp32_ble/ble.h +18 -18
- esphome/components/esp32_ble/ble_advertising.cpp +5 -5
- esphome/components/esp32_ble/ble_advertising.h +7 -5
- esphome/components/esp32_ble/ble_event.h +139 -73
- esphome/components/esp32_ble/ble_scan_result.h +2 -4
- esphome/components/esp32_ble/ble_uuid.cpp +5 -5
- esphome/components/esp32_ble/ble_uuid.h +6 -5
- esphome/components/esp32_ble_beacon/__init__.py +4 -0
- esphome/components/esp32_ble_client/__init__.py +1 -1
- esphome/components/esp32_ble_client/ble_characteristic.cpp +4 -4
- esphome/components/esp32_ble_client/ble_characteristic.h +6 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +155 -104
- esphome/components/esp32_ble_client/ble_client_base.h +17 -6
- esphome/components/esp32_ble_client/ble_descriptor.h +6 -4
- esphome/components/esp32_ble_client/ble_service.cpp +4 -4
- esphome/components/esp32_ble_client/ble_service.h +6 -4
- esphome/components/esp32_ble_server/__init__.py +15 -12
- esphome/components/esp32_ble_tracker/__init__.py +79 -11
- esphome/components/esp32_ble_tracker/automation.h +4 -4
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +264 -261
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +103 -37
- esphome/components/esp32_camera/__init__.py +13 -1
- esphome/components/esp32_camera/esp32_camera.cpp +7 -2
- esphome/components/esp32_camera/esp32_camera.h +1 -0
- esphome/components/esp32_dac/esp32_dac.cpp +3 -19
- esphome/components/esp32_dac/esp32_dac.h +4 -8
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -6
- esphome/components/esp32_rmt_led_strip/light.py +1 -1
- esphome/components/esp32_touch/__init__.py +2 -3
- esphome/components/esp32_touch/esp32_touch.h +9 -6
- esphome/components/esp32_touch/esp32_touch_common.cpp +2 -0
- esphome/components/esp32_touch/esp32_touch_v1.cpp +7 -9
- esphome/components/esp32_touch/esp32_touch_v2.cpp +10 -6
- esphome/components/esp8266/__init__.py +3 -1
- esphome/components/esp8266_pwm/esp8266_pwm.cpp +0 -1
- esphome/components/esphome/ota/__init__.py +1 -2
- esphome/components/esphome/ota/ota_esphome.cpp +150 -77
- esphome/components/esphome/ota/ota_esphome.h +8 -1
- esphome/components/espnow/__init__.py +309 -0
- esphome/components/espnow/automation.h +175 -0
- esphome/components/espnow/espnow_component.cpp +468 -0
- esphome/components/espnow/espnow_component.h +183 -0
- esphome/components/espnow/espnow_err.h +19 -0
- esphome/components/espnow/espnow_packet.h +166 -0
- esphome/components/ethernet/__init__.py +7 -1
- esphome/components/ethernet/esp_eth_phy_jl1101.c +5 -0
- esphome/components/ethernet/ethernet_component.cpp +0 -1
- esphome/components/ethernet/ethernet_component.h +4 -0
- esphome/components/ethernet_info/ethernet_info_text_sensor.h +0 -3
- esphome/components/event/__init__.py +0 -1
- esphome/components/factory_reset/__init__.py +92 -0
- esphome/components/factory_reset/factory_reset.cpp +76 -0
- esphome/components/factory_reset/factory_reset.h +43 -0
- esphome/components/fan/__init__.py +0 -1
- esphome/components/fan/fan_traits.h +16 -0
- esphome/components/fastled_base/fastled_light.cpp +0 -1
- esphome/components/fastled_spi/light.py +1 -3
- esphome/components/fingerprint_grow/fingerprint_grow.cpp +0 -2
- esphome/components/fs3000/fs3000.cpp +0 -2
- esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp +0 -2
- esphome/components/ft63x6/ft63x6.cpp +0 -1
- esphome/components/gdk101/gdk101.cpp +0 -1
- esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +0 -1
- esphome/components/gl_r01_i2c/sensor.py +1 -1
- esphome/components/gpio/one_wire/gpio_one_wire.cpp +0 -1
- esphome/components/gpio/switch/gpio_switch.cpp +0 -2
- esphome/components/gpio_expander/cached_gpio.h +24 -15
- esphome/components/gps/__init__.py +6 -2
- esphome/components/gps/gps.cpp +50 -49
- esphome/components/gps/gps.h +4 -8
- esphome/components/gps/time/gps_time.cpp +3 -9
- esphome/components/gps/time/gps_time.h +4 -7
- esphome/components/graph/__init__.py +1 -1
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +0 -1
- esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +0 -1
- esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +21 -12
- esphome/components/gt911/touchscreen/gt911_touchscreen.h +26 -2
- esphome/components/haier/climate.py +5 -10
- esphome/components/haier/haier_base.cpp +0 -1
- esphome/components/hbridge/switch/hbridge_switch.cpp +0 -2
- esphome/components/hdc1080/hdc1080.cpp +0 -2
- esphome/components/heatpumpir/climate.py +2 -2
- esphome/components/hlw8012/hlw8012.cpp +0 -1
- esphome/components/hm3301/hm3301.cpp +0 -1
- esphome/components/hmc5883l/hmc5883l.cpp +0 -1
- esphome/components/homeassistant/__init__.py +1 -0
- esphome/components/homeassistant/number/__init__.py +1 -0
- esphome/components/homeassistant/number/homeassistant_number.cpp +11 -7
- esphome/components/homeassistant/switch/__init__.py +1 -0
- esphome/components/homeassistant/switch/homeassistant_switch.cpp +9 -5
- esphome/components/honeywellabp/honeywellabp.cpp +1 -4
- esphome/components/host/__init__.py +2 -0
- esphome/components/hte501/hte501.cpp +0 -1
- esphome/components/http_request/__init__.py +2 -3
- esphome/components/http_request/http_request_idf.cpp +2 -2
- esphome/components/htu21d/htu21d.cpp +0 -2
- esphome/components/htu31d/htu31d.cpp +0 -2
- esphome/components/hx711/hx711.cpp +0 -1
- esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +0 -1
- esphome/components/hydreon_rgxx/sensor.py +4 -5
- esphome/components/i2c/i2c_bus.h +1 -1
- esphome/components/i2c/i2c_bus_arduino.cpp +1 -2
- esphome/components/i2c/i2c_bus_esp_idf.cpp +192 -17
- esphome/components/i2c/i2c_bus_esp_idf.h +11 -1
- esphome/components/i2s_audio/__init__.py +6 -5
- esphome/components/i2s_audio/i2s_audio.cpp +0 -2
- esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +1 -4
- esphome/components/i2s_audio/microphone/__init__.py +4 -6
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +0 -1
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +2 -2
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +273 -269
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +19 -34
- esphome/components/ili9xxx/display.py +4 -3
- esphome/components/ili9xxx/ili9xxx_display.cpp +0 -2
- esphome/components/image/__init__.py +123 -92
- esphome/components/improv_serial/__init__.py +7 -8
- esphome/components/ina219/ina219.cpp +0 -1
- esphome/components/ina226/ina226.cpp +0 -2
- esphome/components/ina260/ina260.cpp +0 -2
- esphome/components/ina2xx_base/__init__.py +2 -5
- esphome/components/ina2xx_base/ina2xx_base.cpp +0 -2
- esphome/components/ina3221/ina3221.cpp +0 -1
- esphome/components/internal_temperature/internal_temperature.cpp +0 -2
- esphome/components/interval/interval.h +5 -9
- esphome/components/json/__init__.py +1 -1
- esphome/components/kmeteriso/kmeteriso.cpp +0 -2
- esphome/components/lc709203f/lc709203f.cpp +0 -2
- esphome/components/lcd_gpio/display.py +1 -3
- esphome/components/lcd_gpio/gpio_lcd_display.cpp +0 -1
- esphome/components/lcd_pcf8574/pcf8574_display.cpp +0 -1
- esphome/components/ld2410/__init__.py +4 -6
- esphome/components/ld2410/binary_sensor.py +4 -0
- esphome/components/ld2410/ld2410.cpp +56 -100
- esphome/components/ld2410/ld2410.h +17 -15
- esphome/components/ld2410/sensor.py +24 -10
- esphome/components/ld2412/__init__.py +46 -0
- esphome/components/ld2412/binary_sensor.py +70 -0
- esphome/components/ld2412/button/__init__.py +74 -0
- esphome/components/ld2412/button/factory_reset_button.cpp +9 -0
- esphome/components/ld2412/button/factory_reset_button.h +18 -0
- esphome/components/ld2412/button/query_button.cpp +9 -0
- esphome/components/ld2412/button/query_button.h +18 -0
- esphome/components/ld2412/button/restart_button.cpp +9 -0
- esphome/components/ld2412/button/restart_button.h +18 -0
- esphome/components/ld2412/button/start_dynamic_background_correction_button.cpp +11 -0
- esphome/components/ld2412/button/start_dynamic_background_correction_button.h +18 -0
- esphome/components/ld2412/ld2412.cpp +861 -0
- esphome/components/ld2412/ld2412.h +141 -0
- esphome/components/ld2412/number/__init__.py +126 -0
- esphome/components/ld2412/number/gate_threshold_number.cpp +14 -0
- esphome/components/ld2412/number/gate_threshold_number.h +19 -0
- esphome/components/ld2412/number/light_threshold_number.cpp +12 -0
- esphome/components/ld2412/number/light_threshold_number.h +18 -0
- esphome/components/ld2412/number/max_distance_timeout_number.cpp +12 -0
- esphome/components/ld2412/number/max_distance_timeout_number.h +18 -0
- esphome/components/ld2412/select/__init__.py +82 -0
- esphome/components/ld2412/select/baud_rate_select.cpp +12 -0
- esphome/components/ld2412/select/baud_rate_select.h +18 -0
- esphome/components/ld2412/select/distance_resolution_select.cpp +12 -0
- esphome/components/ld2412/select/distance_resolution_select.h +18 -0
- esphome/components/ld2412/select/light_out_control_select.cpp +12 -0
- esphome/components/ld2412/select/light_out_control_select.h +18 -0
- esphome/components/ld2412/sensor.py +124 -0
- esphome/components/ld2412/switch/__init__.py +45 -0
- esphome/components/ld2412/switch/bluetooth_switch.cpp +12 -0
- esphome/components/ld2412/switch/bluetooth_switch.h +18 -0
- esphome/components/ld2412/switch/engineering_mode_switch.cpp +12 -0
- esphome/components/ld2412/switch/engineering_mode_switch.h +18 -0
- esphome/components/ld2412/text_sensor.py +34 -0
- esphome/components/ld2420/ld2420.cpp +0 -1
- esphome/components/ld2450/__init__.py +3 -4
- esphome/components/ld2450/binary_sensor.py +3 -0
- esphome/components/ld2450/ld2450.cpp +77 -165
- esphome/components/ld2450/ld2450.h +26 -54
- esphome/components/ld2450/sensor.py +120 -6
- esphome/components/ld2450/text_sensor.py +5 -4
- esphome/components/ld24xx/__init__.py +1 -0
- esphome/components/ld24xx/ld24xx.h +65 -0
- esphome/components/ledc/ledc_output.cpp +0 -1
- esphome/components/libretiny/__init__.py +2 -0
- esphome/components/light/__init__.py +0 -1
- esphome/components/light/effects.py +70 -45
- esphome/components/light/light_call.cpp +101 -66
- esphome/components/light/light_color_values.h +16 -11
- esphome/components/light/light_json_schema.cpp +46 -44
- esphome/components/light/light_state.cpp +8 -11
- esphome/components/light/light_traits.h +17 -0
- esphome/components/lightwaverf/lightwaverf.cpp +0 -2
- esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +0 -1
- esphome/components/lock/__init__.py +0 -1
- esphome/components/logger/__init__.py +31 -9
- esphome/components/logger/logger.cpp +12 -7
- esphome/components/logger/logger.h +25 -14
- esphome/components/logger/logger_esp32.cpp +2 -7
- esphome/components/logger/logger_esp8266.cpp +2 -4
- esphome/components/logger/logger_host.cpp +2 -4
- esphome/components/logger/logger_libretiny.cpp +2 -4
- esphome/components/logger/logger_rp2040.cpp +2 -4
- esphome/components/logger/logger_zephyr.cpp +86 -0
- esphome/components/logger/select/logger_level_select.cpp +2 -4
- esphome/components/logger/select/logger_level_select.h +2 -4
- esphome/components/logger/task_log_buffer.cpp +2 -4
- esphome/components/logger/task_log_buffer.h +2 -4
- esphome/components/lps22/sensor.py +5 -5
- esphome/components/ltr390/ltr390.cpp +0 -2
- esphome/components/ltr501/ltr501.cpp +0 -1
- esphome/components/ltr_als_ps/ltr_als_ps.cpp +0 -1
- esphome/components/lvgl/__init__.py +14 -13
- esphome/components/lvgl/automation.py +2 -4
- esphome/components/lvgl/defines.py +0 -2
- esphome/components/lvgl/helpers.py +1 -1
- esphome/components/lvgl/lv_validation.py +7 -4
- esphome/components/lvgl/lvgl_esphome.cpp +2 -3
- esphome/components/lvgl/styles.py +2 -2
- esphome/components/lvgl/types.py +1 -1
- esphome/components/lvgl/widgets/__init__.py +2 -2
- esphome/components/lvgl/widgets/arc.py +14 -11
- esphome/components/lvgl/widgets/buttonmatrix.py +1 -1
- esphome/components/lvgl/widgets/qrcode.py +7 -7
- esphome/components/lvgl/widgets/spinner.py +6 -6
- esphome/components/lvgl/widgets/switch.py +2 -2
- esphome/components/lvgl/widgets/tabview.py +3 -3
- esphome/components/m5stack_8angle/m5stack_8angle.cpp +0 -1
- esphome/components/matrix_keypad/__init__.py +4 -3
- esphome/components/max17043/max17043.cpp +0 -2
- esphome/components/max31855/max31855.cpp +1 -4
- esphome/components/max31856/max31856.cpp +0 -4
- esphome/components/max31865/max31865.cpp +0 -1
- esphome/components/max44009/max44009.cpp +0 -1
- esphome/components/max6675/max6675.cpp +1 -4
- esphome/components/max6956/max6956.cpp +0 -1
- esphome/components/max7219/max7219.cpp +0 -1
- esphome/components/max7219digit/display.py +1 -1
- esphome/components/max7219digit/max7219digit.cpp +0 -1
- esphome/components/max9611/max9611.cpp +0 -1
- esphome/components/mcp23008/__init__.py +1 -1
- esphome/components/mcp23008/mcp23008.cpp +0 -1
- esphome/components/mcp23016/mcp23016.cpp +0 -1
- esphome/components/mcp23017/__init__.py +1 -1
- esphome/components/mcp23017/mcp23017.cpp +0 -1
- esphome/components/mcp23s08/__init__.py +1 -1
- esphome/components/mcp23s08/mcp23s08.cpp +0 -1
- esphome/components/mcp23s17/__init__.py +1 -1
- esphome/components/mcp23s17/mcp23s17.cpp +0 -1
- esphome/components/mcp23x08_base/__init__.py +2 -0
- esphome/components/mcp23x08_base/mcp23x08_base.cpp +9 -7
- esphome/components/mcp23x08_base/mcp23x08_base.h +9 -4
- esphome/components/mcp23x17_base/__init__.py +2 -0
- esphome/components/mcp23x17_base/mcp23x17_base.cpp +20 -7
- esphome/components/mcp23x17_base/mcp23x17_base.h +9 -4
- esphome/components/mcp23xxx_base/__init__.py +11 -5
- esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +15 -12
- esphome/components/mcp23xxx_base/mcp23xxx_base.h +8 -7
- esphome/components/mcp3008/mcp3008.cpp +1 -4
- esphome/components/mcp3204/mcp3204.cpp +1 -4
- esphome/components/mcp4461/mcp4461.cpp +0 -1
- esphome/components/mcp4725/mcp4725.cpp +0 -1
- esphome/components/mcp4728/mcp4728.cpp +0 -1
- esphome/components/mcp9600/mcp9600.cpp +0 -2
- esphome/components/mcp9808/mcp9808.cpp +0 -2
- esphome/components/mdns/__init__.py +3 -0
- esphome/components/mdns/mdns_component.cpp +2 -0
- esphome/components/mdns/mdns_component.h +4 -0
- esphome/components/media_player/__init__.py +40 -0
- esphome/components/media_player/automation.h +16 -0
- esphome/components/media_player/media_player.cpp +13 -0
- esphome/components/media_player/media_player.h +50 -3
- esphome/components/micro_wake_word/micro_wake_word.cpp +0 -3
- esphome/components/mics_4514/mics_4514.cpp +1 -6
- esphome/components/midea/ir_transmitter.h +4 -4
- esphome/components/mipi/__init__.py +416 -0
- esphome/components/mipi_dsi/__init__.py +5 -0
- esphome/components/mipi_dsi/display.py +233 -0
- esphome/components/mipi_dsi/mipi_dsi.cpp +379 -0
- esphome/components/mipi_dsi/mipi_dsi.h +123 -0
- esphome/components/mipi_dsi/models/__init__.py +0 -0
- esphome/components/mipi_dsi/models/guition.py +38 -0
- esphome/components/mipi_dsi/models/m5stack.py +57 -0
- esphome/components/mipi_dsi/models/waveshare.py +105 -0
- esphome/components/mipi_rgb/models/lilygo.py +0 -0
- esphome/components/mipi_spi/__init__.py +0 -9
- esphome/components/mipi_spi/display.py +220 -256
- esphome/components/mipi_spi/mipi_spi.cpp +1 -485
- esphome/components/mipi_spi/mipi_spi.h +556 -108
- esphome/components/mipi_spi/models/__init__.py +0 -65
- esphome/components/mipi_spi/models/adafruit.py +30 -0
- esphome/components/mipi_spi/models/amoled.py +41 -5
- esphome/components/mipi_spi/models/ili.py +5 -5
- esphome/components/mipi_spi/models/jc.py +1 -3
- esphome/components/mipi_spi/models/lilygo.py +1 -1
- esphome/components/mipi_spi/models/waveshare.py +16 -1
- esphome/components/mixer/speaker/__init__.py +4 -5
- esphome/components/mlx90393/sensor.py +7 -5
- esphome/components/mlx90393/sensor_mlx90393.cpp +0 -1
- esphome/components/mlx90614/mlx90614.cpp +0 -1
- esphome/components/mmc5603/mmc5603.cpp +0 -1
- esphome/components/mmc5983/mmc5983.cpp +0 -2
- esphome/components/mpl3115a2/mpl3115a2.cpp +0 -2
- esphome/components/mpr121/__init__.py +7 -6
- esphome/components/mpr121/mpr121.cpp +0 -1
- esphome/components/mpu6050/mpu6050.cpp +0 -1
- esphome/components/mpu6886/mpu6886.cpp +0 -1
- esphome/components/mqtt/__init__.py +1 -2
- esphome/components/mqtt/mqtt_button.cpp +1 -1
- esphome/components/mqtt/mqtt_client.cpp +0 -1
- esphome/components/mqtt/mqtt_component.cpp +8 -14
- esphome/components/mqtt/mqtt_component.h +0 -7
- esphome/components/mqtt/mqtt_sensor.cpp +0 -1
- esphome/components/mqtt/mqtt_sensor.h +0 -1
- esphome/components/mqtt/mqtt_text_sensor.cpp +0 -1
- esphome/components/mqtt/mqtt_text_sensor.h +0 -1
- esphome/components/ms5611/ms5611.cpp +0 -1
- esphome/components/ms8607/ms8607.cpp +0 -1
- esphome/components/msa3xx/msa3xx.cpp +0 -2
- esphome/components/my9231/my9231.cpp +0 -2
- esphome/components/nau7802/nau7802.cpp +0 -1
- esphome/components/neopixelbus/light.py +3 -0
- esphome/components/network/util.cpp +29 -0
- esphome/components/nextion/nextion.cpp +2 -2
- esphome/components/nfc/binary_sensor/{binary_sensor.cpp → nfc_binary_sensor.cpp} +1 -1
- esphome/components/npi19/npi19.cpp +0 -2
- esphome/components/nrf52/__init__.py +223 -0
- esphome/components/nrf52/boards.py +34 -0
- esphome/components/nrf52/const.py +18 -0
- esphome/components/nrf52/gpio.py +79 -0
- esphome/components/number/__init__.py +2 -1
- esphome/components/one_wire/__init__.py +1 -2
- esphome/components/one_wire/one_wire.cpp +0 -2
- esphome/components/one_wire/one_wire.h +0 -2
- esphome/components/opentherm/hub.cpp +0 -1
- esphome/components/opentherm/number/__init__.py +2 -2
- esphome/components/openthread/__init__.py +2 -3
- esphome/components/openthread/openthread.cpp +30 -13
- esphome/components/openthread/openthread.h +3 -0
- esphome/components/openthread/openthread_esp.cpp +3 -1
- esphome/components/opt3001/sensor.py +2 -6
- esphome/components/output/__init__.py +38 -0
- esphome/components/output/automation.h +24 -0
- esphome/components/output/switch/output_switch.cpp +0 -2
- esphome/components/packages/__init__.py +1 -2
- esphome/components/packet_transport/__init__.py +4 -3
- esphome/components/pca6416a/pca6416a.cpp +0 -1
- esphome/components/pca9554/pca9554.cpp +0 -1
- esphome/components/pca9685/pca9685_output.cpp +0 -2
- esphome/components/pcf85063/pcf85063.cpp +0 -1
- esphome/components/pcf8563/pcf8563.cpp +0 -1
- esphome/components/pcf8574/pcf8574.cpp +0 -1
- esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +0 -1
- esphome/components/pipsolar/pipsolar.cpp +54 -42
- esphome/components/pipsolar/pipsolar.h +5 -4
- esphome/components/pipsolar/sensor/__init__.py +1 -1
- esphome/components/pm2005/pm2005.cpp +0 -1
- esphome/components/pmsa003i/pmsa003i.cpp +0 -2
- esphome/components/pmwcs3/sensor.py +1 -2
- esphome/components/pn532/pn532.cpp +0 -2
- esphome/components/pn532_spi/pn532_spi.cpp +0 -2
- esphome/components/power_supply/power_supply.cpp +7 -10
- esphome/components/power_supply/power_supply.h +1 -1
- esphome/components/psram/__init__.py +6 -1
- esphome/components/pulse_counter/pulse_counter_sensor.cpp +0 -1
- esphome/components/pulse_counter/sensor.py +9 -6
- esphome/components/pylontech/pylontech.cpp +0 -1
- esphome/components/qmc5883l/qmc5883l.cpp +0 -1
- esphome/components/qmp6988/qmp6988.cpp +0 -2
- esphome/components/qspi_dbi/display.py +2 -3
- esphome/components/qspi_dbi/qspi_dbi.cpp +0 -2
- esphome/components/qwiic_pir/binary_sensor.py +2 -3
- esphome/components/qwiic_pir/qwiic_pir.cpp +0 -2
- esphome/components/rc522/rc522.cpp +9 -31
- esphome/components/rc522_spi/rc522_spi.cpp +0 -1
- esphome/components/remote_base/__init__.py +5 -6
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -1
- esphome/components/remote_receiver/remote_receiver_esp8266.cpp +0 -1
- esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -1
- esphome/components/remote_transmitter/__init__.py +26 -0
- esphome/components/remote_transmitter/automation.h +18 -0
- esphome/components/remote_transmitter/remote_transmitter.h +2 -1
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -1
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
- esphome/components/resampler/speaker/__init__.py +4 -5
- esphome/components/rf_bridge/__init__.py +4 -8
- esphome/components/rotary_encoder/rotary_encoder.cpp +0 -2
- esphome/components/rp2040/__init__.py +3 -1
- esphome/components/rp2040_pio_led_strip/led_strip.cpp +0 -2
- esphome/components/rp2040_pio_led_strip/light.py +1 -2
- esphome/components/rp2040_pwm/rp2040_pwm.cpp +1 -5
- esphome/components/rpi_dpi_rgb/display.py +13 -15
- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -3
- esphome/components/runtime_stats/__init__.py +34 -0
- esphome/components/runtime_stats/runtime_stats.cpp +102 -0
- esphome/components/runtime_stats/runtime_stats.h +132 -0
- esphome/components/scd30/scd30.cpp +0 -2
- esphome/components/scd30/sensor.py +1 -2
- esphome/components/scd4x/scd4x.cpp +0 -1
- esphome/components/scd4x/sensor.py +1 -3
- esphome/components/sdl/display.py +3 -1
- esphome/components/sdl/sdl_esphome.cpp +0 -2
- esphome/components/sdp3x/sdp3x.cpp +0 -2
- esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +0 -2
- esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +0 -3
- esphome/components/select/__init__.py +2 -3
- esphome/components/select/select_traits.cpp +1 -1
- esphome/components/select/select_traits.h +1 -1
- esphome/components/sen0321/sen0321.cpp +0 -1
- esphome/components/sen5x/sen5x.cpp +0 -2
- esphome/components/senseair/senseair.cpp +7 -3
- esphome/components/senseair/senseair.h +11 -0
- esphome/components/sensor/__init__.py +36 -4
- esphome/components/sensor/filter.cpp +49 -10
- esphome/components/sensor/filter.h +22 -7
- esphome/components/sensor/sensor.cpp +0 -1
- esphome/components/sensor/sensor.h +0 -9
- esphome/components/sfa30/sfa30.cpp +0 -4
- esphome/components/sgp30/sgp30.cpp +0 -2
- esphome/components/sgp4x/sensor.py +1 -1
- esphome/components/sgp4x/sgp4x.cpp +0 -2
- esphome/components/shelly_dimmer/shelly_dimmer.cpp +0 -2
- esphome/components/sht3xd/sht3xd.cpp +0 -2
- esphome/components/sht4x/sht4x.cpp +0 -2
- esphome/components/shtcx/shtcx.cpp +0 -1
- esphome/components/sim800l/__init__.py +2 -4
- esphome/components/sm16716/sm16716.cpp +0 -1
- esphome/components/sm2135/sm2135.cpp +0 -1
- esphome/components/sm2235/sm2235.cpp +0 -1
- esphome/components/sm2335/sm2335.cpp +0 -1
- esphome/components/sn74hc165/sn74hc165.cpp +0 -1
- esphome/components/sn74hc595/sn74hc595.cpp +0 -1
- esphome/components/sntp/sntp_component.cpp +0 -1
- esphome/components/sound_level/sensor.py +1 -1
- esphome/components/speaker/media_player/__init__.py +21 -33
- esphome/components/speaker/media_player/audio_pipeline.cpp +4 -7
- esphome/components/spi/__init__.py +29 -13
- esphome/components/spi/spi.cpp +0 -2
- esphome/components/spi_device/spi_device.cpp +1 -4
- esphome/components/sprinkler/__init__.py +4 -4
- esphome/components/sps30/sps30.cpp +0 -1
- esphome/components/ssd1306_base/__init__.py +11 -11
- esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
- esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +0 -1
- esphome/components/ssd1306_spi/ssd1306_spi.cpp +0 -1
- esphome/components/ssd1322_spi/ssd1322_spi.cpp +0 -1
- esphome/components/ssd1325_spi/ssd1325_spi.cpp +0 -1
- esphome/components/ssd1327_i2c/ssd1327_i2c.cpp +0 -1
- esphome/components/ssd1327_spi/ssd1327_spi.cpp +0 -1
- esphome/components/ssd1331_spi/ssd1331_spi.cpp +0 -1
- esphome/components/ssd1351_spi/ssd1351_spi.cpp +0 -1
- esphome/components/st7567_i2c/st7567_i2c.cpp +0 -1
- esphome/components/st7567_spi/st7567_spi.cpp +0 -1
- esphome/components/st7701s/display.py +10 -14
- esphome/components/st7701s/st7701s.cpp +0 -3
- esphome/components/st7735/st7735.cpp +0 -1
- esphome/components/st7789v/st7789v.cpp +0 -1
- esphome/components/st7920/st7920.cpp +0 -1
- esphome/components/status_led/light/status_led_light.cpp +0 -2
- esphome/components/status_led/status_led.cpp +0 -1
- esphome/components/stepper/__init__.py +2 -4
- esphome/components/sts3x/sts3x.cpp +0 -1
- esphome/components/substitutions/__init__.py +10 -16
- esphome/components/substitutions/jinja.py +24 -1
- esphome/components/sun/__init__.py +2 -3
- esphome/components/switch/__init__.py +31 -1
- esphome/components/switch/automation.h +24 -0
- esphome/components/switch/switch.cpp +8 -0
- esphome/components/switch/switch.h +8 -0
- esphome/components/sx126x/sx126x.cpp +0 -2
- esphome/components/sx127x/sx127x.cpp +0 -2
- esphome/components/sx1509/__init__.py +7 -5
- esphome/components/sx1509/output/sx1509_float_output.cpp +1 -1
- esphome/components/sx1509/sx1509.cpp +0 -2
- esphome/components/syslog/esphome_syslog.cpp +1 -1
- esphome/components/tc74/tc74.cpp +0 -1
- esphome/components/tca9548a/tca9548a.cpp +0 -1
- esphome/components/tca9555/tca9555.cpp +0 -1
- esphome/components/tcs34725/tcs34725.cpp +0 -1
- esphome/components/tee501/tee501.cpp +0 -1
- esphome/components/tem3200/tem3200.cpp +0 -2
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +0 -1
- esphome/components/template/cover/template_cover.cpp +0 -1
- esphome/components/template/select/template_select.cpp +0 -1
- esphome/components/template/text/template_text.cpp +0 -2
- esphome/components/template/valve/template_valve.cpp +0 -1
- esphome/components/text/__init__.py +0 -1
- esphome/components/text/text_traits.h +2 -0
- esphome/components/text_sensor/__init__.py +2 -1
- esphome/components/text_sensor/text_sensor.cpp +0 -2
- esphome/components/text_sensor/text_sensor.h +0 -8
- esphome/components/thermostat/climate.py +4 -4
- esphome/components/time/__init__.py +7 -4
- esphome/components/time/real_time_clock.cpp +16 -3
- esphome/components/tlc59208f/tlc59208f_output.cpp +0 -2
- esphome/components/tlc5947/tlc5947.cpp +0 -2
- esphome/components/tlc5971/tlc5971.cpp +0 -2
- esphome/components/tm1621/tm1621.cpp +0 -2
- esphome/components/tm1637/tm1637.cpp +0 -2
- esphome/components/tm1638/tm1638.cpp +0 -2
- esphome/components/tm1651/__init__.py +45 -48
- esphome/components/tm1651/tm1651.cpp +213 -47
- esphome/components/tm1651/tm1651.h +37 -32
- esphome/components/tmp117/tmp117.cpp +0 -2
- esphome/components/tsl2561/tsl2561.cpp +0 -1
- esphome/components/tsl2591/tsl2591.cpp +0 -1
- esphome/components/tt21100/touchscreen/tt21100.cpp +0 -2
- esphome/components/ttp229_bsf/ttp229_bsf.cpp +0 -1
- esphome/components/ttp229_lsf/ttp229_lsf.cpp +0 -1
- esphome/components/tuya/climate/__init__.py +9 -10
- esphome/components/tuya/number/__init__.py +8 -6
- esphome/components/tx20/tx20.cpp +0 -1
- esphome/components/uart/uart_component_esp32_arduino.cpp +0 -1
- esphome/components/uart/uart_component_esp8266.cpp +0 -1
- esphome/components/uart/uart_component_esp_idf.cpp +0 -2
- esphome/components/uart/uart_component_libretiny.cpp +0 -2
- esphome/components/uart/uart_component_rp2040.cpp +0 -2
- esphome/components/udp/__init__.py +1 -1
- esphome/components/ufire_ec/sensor.py +1 -2
- esphome/components/ufire_ec/ufire_ec.cpp +0 -2
- esphome/components/ufire_ise/sensor.py +1 -2
- esphome/components/ufire_ise/ufire_ise.cpp +0 -2
- esphome/components/ultrasonic/ultrasonic_sensor.cpp +0 -1
- esphome/components/update/__init__.py +0 -1
- esphome/components/uptime/sensor/uptime_seconds_sensor.cpp +0 -1
- esphome/components/uptime/sensor/uptime_seconds_sensor.h +0 -2
- esphome/components/usb_host/usb_host_client.cpp +0 -1
- esphome/components/usb_host/usb_host_component.cpp +0 -1
- esphome/components/valve/__init__.py +0 -1
- esphome/components/veml3235/veml3235.cpp +0 -3
- esphome/components/veml7700/veml7700.cpp +0 -2
- esphome/components/version/version_text_sensor.cpp +0 -1
- esphome/components/version/version_text_sensor.h +0 -1
- esphome/components/vl53l0x/vl53l0x_sensor.cpp +0 -4
- esphome/components/voice_assistant/voice_assistant.cpp +9 -8
- esphome/components/web_server/__init__.py +13 -0
- esphome/components/web_server/web_server.cpp +188 -353
- esphome/components/web_server/web_server.h +61 -1
- esphome/components/web_server_base/__init__.py +1 -1
- esphome/components/web_server_base/web_server_base.cpp +2 -0
- esphome/components/web_server_base/web_server_base.h +6 -0
- esphome/components/web_server_idf/web_server_idf.cpp +10 -8
- esphome/components/web_server_idf/web_server_idf.h +2 -0
- esphome/components/weikai_i2c/weikai_i2c.cpp +1 -2
- esphome/components/weikai_spi/weikai_spi.cpp +1 -1
- esphome/components/wifi/__init__.py +17 -43
- esphome/components/wifi/wifi_component.cpp +100 -36
- esphome/components/wifi/wifi_component.h +5 -1
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -0
- esphome/components/wifi/wifi_component_esp_idf.cpp +30 -0
- esphome/components/wifi_info/wifi_info_text_sensor.h +0 -6
- esphome/components/wifi_signal/wifi_signal_sensor.h +0 -1
- esphome/components/wireguard/wireguard.cpp +0 -2
- esphome/components/x9c/x9c.cpp +0 -2
- esphome/components/xgzp68xx/xgzp68xx.cpp +0 -1
- esphome/components/xl9535/xl9535.cpp +0 -2
- esphome/components/zephyr/__init__.py +252 -0
- esphome/components/zephyr/const.py +16 -0
- esphome/components/zephyr/core.cpp +90 -0
- esphome/components/zephyr/gpio.cpp +120 -0
- esphome/components/zephyr/gpio.h +38 -0
- esphome/components/zephyr/pre_build.py.script +4 -0
- esphome/components/zephyr/preferences.cpp +156 -0
- esphome/components/zephyr/preferences.h +13 -0
- esphome/config.py +38 -16
- esphome/config_helpers.py +1 -2
- esphome/config_validation.py +12 -16
- esphome/const.py +26 -1
- esphome/core/__init__.py +92 -51
- esphome/core/application.cpp +75 -21
- esphome/core/application.h +106 -171
- esphome/core/color.h +10 -0
- esphome/core/component.cpp +41 -25
- esphome/core/component.h +9 -6
- esphome/core/component_iterator.cpp +61 -261
- esphome/core/component_iterator.h +15 -0
- esphome/core/config.py +26 -11
- esphome/core/defines.h +40 -2
- esphome/core/entity_base.h +18 -0
- esphome/core/entity_helpers.py +45 -10
- esphome/core/helpers.cpp +8 -15
- esphome/core/helpers.h +60 -6
- esphome/core/lock_free_queue.h +1 -1
- esphome/core/scheduler.cpp +311 -77
- esphome/core/scheduler.h +141 -28
- esphome/cpp_generator.py +2 -6
- esphome/cpp_helpers.py +1 -1
- esphome/dashboard/dashboard.py +2 -3
- esphome/dashboard/dns.py +2 -8
- esphome/dashboard/web_server.py +34 -19
- esphome/espota2.py +1 -4
- esphome/git.py +3 -1
- esphome/helpers.py +23 -4
- esphome/log.py +3 -1
- esphome/mqtt.py +3 -5
- esphome/platformio_api.py +7 -4
- esphome/types.py +12 -0
- esphome/util.py +20 -8
- esphome/voluptuous_schema.py +4 -3
- esphome/vscode.py +1 -2
- esphome/wizard.py +1 -4
- esphome/writer.py +16 -108
- esphome/yaml_util.py +7 -5
- {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/METADATA +13 -14
- {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/RECORD +755 -675
- esphome/components/mipi_spi/models/commands.py +0 -82
- /esphome/components/nfc/binary_sensor/{binary_sensor.h → nfc_binary_sensor.h} +0 -0
- {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/WHEEL +0 -0
- {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/entry_points.txt +0 -0
- {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.7.5.dist-info → esphome-2025.8.0.dist-info}/top_level.txt +0 -0
esphome/core/scheduler.h
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include "esphome/core/defines.h"
|
|
3
4
|
#include <vector>
|
|
4
5
|
#include <memory>
|
|
5
6
|
#include <cstring>
|
|
6
7
|
#include <deque>
|
|
8
|
+
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
|
|
9
|
+
#include <atomic>
|
|
10
|
+
#endif
|
|
7
11
|
|
|
8
12
|
#include "esphome/core/component.h"
|
|
9
13
|
#include "esphome/core/helpers.h"
|
|
@@ -11,8 +15,15 @@
|
|
|
11
15
|
namespace esphome {
|
|
12
16
|
|
|
13
17
|
class Component;
|
|
18
|
+
struct RetryArgs;
|
|
19
|
+
|
|
20
|
+
// Forward declaration of retry_handler - needs to be non-static for friend declaration
|
|
21
|
+
void retry_handler(const std::shared_ptr<RetryArgs> &args);
|
|
14
22
|
|
|
15
23
|
class Scheduler {
|
|
24
|
+
// Allow retry_handler to access protected members
|
|
25
|
+
friend void ::esphome::retry_handler(const std::shared_ptr<RetryArgs> &args);
|
|
26
|
+
|
|
16
27
|
public:
|
|
17
28
|
// Public API - accepts std::string for backward compatibility
|
|
18
29
|
void set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function<void()> func);
|
|
@@ -50,11 +61,21 @@ class Scheduler {
|
|
|
50
61
|
bool cancel_interval(Component *component, const char *name);
|
|
51
62
|
void set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts,
|
|
52
63
|
std::function<RetryResult(uint8_t)> func, float backoff_increase_factor = 1.0f);
|
|
64
|
+
void set_retry(Component *component, const char *name, uint32_t initial_wait_time, uint8_t max_attempts,
|
|
65
|
+
std::function<RetryResult(uint8_t)> func, float backoff_increase_factor = 1.0f);
|
|
53
66
|
bool cancel_retry(Component *component, const std::string &name);
|
|
67
|
+
bool cancel_retry(Component *component, const char *name);
|
|
54
68
|
|
|
55
|
-
|
|
69
|
+
// Calculate when the next scheduled item should run
|
|
70
|
+
// @param now Fresh timestamp from millis() - must not be stale/cached
|
|
71
|
+
// Returns the time in milliseconds until the next scheduled item, or nullopt if no items
|
|
72
|
+
// This method performs cleanup of removed items before checking the schedule
|
|
73
|
+
// IMPORTANT: This method should only be called from the main thread (loop task).
|
|
74
|
+
optional<uint32_t> next_schedule_in(uint32_t now);
|
|
56
75
|
|
|
57
|
-
|
|
76
|
+
// Execute all scheduled items that are ready
|
|
77
|
+
// @param now Fresh timestamp from millis() - must not be stale/cached
|
|
78
|
+
void call(uint32_t now);
|
|
58
79
|
|
|
59
80
|
void process_to_add();
|
|
60
81
|
|
|
@@ -76,15 +97,42 @@ class Scheduler {
|
|
|
76
97
|
|
|
77
98
|
std::function<void()> callback;
|
|
78
99
|
|
|
79
|
-
|
|
100
|
+
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
|
|
101
|
+
// Multi-threaded with atomics: use atomic for lock-free access
|
|
102
|
+
// Place atomic<bool> separately since it can't be packed with bit fields
|
|
103
|
+
std::atomic<bool> remove{false};
|
|
104
|
+
|
|
105
|
+
// Bit-packed fields (3 bits used, 5 bits padding in 1 byte)
|
|
106
|
+
enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1;
|
|
107
|
+
bool name_is_dynamic : 1; // True if name was dynamically allocated (needs delete[])
|
|
108
|
+
bool is_retry : 1; // True if this is a retry timeout
|
|
109
|
+
// 5 bits padding
|
|
110
|
+
#else
|
|
111
|
+
// Single-threaded or multi-threaded without atomics: can pack all fields together
|
|
112
|
+
// Bit-packed fields (4 bits used, 4 bits padding in 1 byte)
|
|
80
113
|
enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1;
|
|
81
114
|
bool remove : 1;
|
|
82
115
|
bool name_is_dynamic : 1; // True if name was dynamically allocated (needs delete[])
|
|
83
|
-
//
|
|
116
|
+
bool is_retry : 1; // True if this is a retry timeout
|
|
117
|
+
// 4 bits padding
|
|
118
|
+
#endif
|
|
84
119
|
|
|
85
120
|
// Constructor
|
|
86
121
|
SchedulerItem()
|
|
87
|
-
: component(nullptr),
|
|
122
|
+
: component(nullptr),
|
|
123
|
+
interval(0),
|
|
124
|
+
next_execution_(0),
|
|
125
|
+
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
|
|
126
|
+
// remove is initialized in the member declaration as std::atomic<bool>{false}
|
|
127
|
+
type(TIMEOUT),
|
|
128
|
+
name_is_dynamic(false),
|
|
129
|
+
is_retry(false) {
|
|
130
|
+
#else
|
|
131
|
+
type(TIMEOUT),
|
|
132
|
+
remove(false),
|
|
133
|
+
name_is_dynamic(false),
|
|
134
|
+
is_retry(false) {
|
|
135
|
+
#endif
|
|
88
136
|
name_.static_name = nullptr;
|
|
89
137
|
}
|
|
90
138
|
|
|
@@ -136,15 +184,22 @@ class Scheduler {
|
|
|
136
184
|
|
|
137
185
|
// Common implementation for both timeout and interval
|
|
138
186
|
void set_timer_common_(Component *component, SchedulerItem::Type type, bool is_static_string, const void *name_ptr,
|
|
139
|
-
uint32_t delay, std::function<void()> func);
|
|
187
|
+
uint32_t delay, std::function<void()> func, bool is_retry = false);
|
|
140
188
|
|
|
141
|
-
|
|
142
|
-
void
|
|
189
|
+
// Common implementation for retry
|
|
190
|
+
void set_retry_common_(Component *component, bool is_static_string, const void *name_ptr, uint32_t initial_wait_time,
|
|
191
|
+
uint8_t max_attempts, std::function<RetryResult(uint8_t)> func, float backoff_increase_factor);
|
|
192
|
+
|
|
193
|
+
uint64_t millis_64_(uint32_t now);
|
|
194
|
+
// Cleanup logically deleted items from the scheduler
|
|
195
|
+
// Returns the number of items remaining after cleanup
|
|
196
|
+
// IMPORTANT: This method should only be called from the main thread (loop task).
|
|
197
|
+
size_t cleanup_();
|
|
143
198
|
void pop_raw_();
|
|
144
199
|
|
|
145
200
|
private:
|
|
146
201
|
// Helper to cancel items by name - must be called with lock held
|
|
147
|
-
bool cancel_item_locked_(Component *component, const char *name, SchedulerItem::Type type);
|
|
202
|
+
bool cancel_item_locked_(Component *component, const char *name, SchedulerItem::Type type, bool match_retry = false);
|
|
148
203
|
|
|
149
204
|
// Helper to extract name as const char* from either static string or std::string
|
|
150
205
|
inline const char *get_name_cstr_(bool is_static_string, const void *name_ptr) {
|
|
@@ -156,8 +211,9 @@ class Scheduler {
|
|
|
156
211
|
|
|
157
212
|
// Helper function to check if item matches criteria for cancellation
|
|
158
213
|
inline bool HOT matches_item_(const std::unique_ptr<SchedulerItem> &item, Component *component, const char *name_cstr,
|
|
159
|
-
SchedulerItem::Type type) {
|
|
160
|
-
if (item->component != component || item->type != type || item->remove)
|
|
214
|
+
SchedulerItem::Type type, bool match_retry, bool skip_removed = true) const {
|
|
215
|
+
if (item->component != component || item->type != type || (skip_removed && item->remove) ||
|
|
216
|
+
(match_retry && !item->is_retry)) {
|
|
161
217
|
return false;
|
|
162
218
|
}
|
|
163
219
|
const char *item_name = item->get_name();
|
|
@@ -176,37 +232,94 @@ class Scheduler {
|
|
|
176
232
|
}
|
|
177
233
|
|
|
178
234
|
// Helper to execute a scheduler item
|
|
179
|
-
void execute_item_(SchedulerItem *item);
|
|
235
|
+
void execute_item_(SchedulerItem *item, uint32_t now);
|
|
180
236
|
|
|
181
237
|
// Helper to check if item should be skipped
|
|
182
238
|
bool should_skip_item_(const SchedulerItem *item) const {
|
|
183
239
|
return item->remove || (item->component != nullptr && item->component->is_failed());
|
|
184
240
|
}
|
|
185
241
|
|
|
186
|
-
//
|
|
187
|
-
//
|
|
188
|
-
//
|
|
189
|
-
//
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
242
|
+
// Helper to check if item is marked for removal (platform-specific)
|
|
243
|
+
// Returns true if item should be skipped, handles platform-specific synchronization
|
|
244
|
+
// For ESPHOME_THREAD_MULTI_NO_ATOMICS platforms, the caller must hold the scheduler lock before calling this
|
|
245
|
+
// function.
|
|
246
|
+
bool is_item_removed_(SchedulerItem *item) const {
|
|
247
|
+
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
|
|
248
|
+
// Multi-threaded with atomics: use atomic load for lock-free access
|
|
249
|
+
return item->remove.load(std::memory_order_acquire);
|
|
250
|
+
#else
|
|
251
|
+
// Single-threaded (ESPHOME_THREAD_SINGLE) or
|
|
252
|
+
// multi-threaded without atomics (ESPHOME_THREAD_MULTI_NO_ATOMICS): direct read
|
|
253
|
+
// For ESPHOME_THREAD_MULTI_NO_ATOMICS, caller MUST hold lock!
|
|
254
|
+
return item->remove;
|
|
255
|
+
#endif
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Helper to mark item for removal (platform-specific)
|
|
259
|
+
// For ESPHOME_THREAD_MULTI_NO_ATOMICS platforms, the caller must hold the scheduler lock before calling this
|
|
260
|
+
// function.
|
|
261
|
+
void mark_item_removed_(SchedulerItem *item) {
|
|
262
|
+
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
|
|
263
|
+
// Multi-threaded with atomics: use atomic store
|
|
264
|
+
item->remove.store(true, std::memory_order_release);
|
|
265
|
+
#else
|
|
266
|
+
// Single-threaded (ESPHOME_THREAD_SINGLE) or
|
|
267
|
+
// multi-threaded without atomics (ESPHOME_THREAD_MULTI_NO_ATOMICS): direct write
|
|
268
|
+
// For ESPHOME_THREAD_MULTI_NO_ATOMICS, caller MUST hold lock!
|
|
269
|
+
item->remove = true;
|
|
270
|
+
#endif
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Template helper to check if any item in a container matches our criteria
|
|
274
|
+
template<typename Container>
|
|
275
|
+
bool has_cancelled_timeout_in_container_(const Container &container, Component *component, const char *name_cstr,
|
|
276
|
+
bool match_retry) const {
|
|
277
|
+
for (const auto &item : container) {
|
|
278
|
+
if (item->remove && this->matches_item_(item, component, name_cstr, SchedulerItem::TIMEOUT, match_retry,
|
|
279
|
+
/* skip_removed= */ false)) {
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return false;
|
|
195
284
|
}
|
|
196
285
|
|
|
197
286
|
Mutex lock_;
|
|
198
287
|
std::vector<std::unique_ptr<SchedulerItem>> items_;
|
|
199
288
|
std::vector<std::unique_ptr<SchedulerItem>> to_add_;
|
|
200
|
-
#
|
|
201
|
-
//
|
|
202
|
-
// ESP8266: Single-core with no preemptive multitasking
|
|
203
|
-
// RP2040: Currently has empty mutex implementation in ESPHome
|
|
204
|
-
// Both platforms save 40 bytes of RAM by excluding this
|
|
289
|
+
#ifndef ESPHOME_THREAD_SINGLE
|
|
290
|
+
// Single-core platforms don't need the defer queue and save 40 bytes of RAM
|
|
205
291
|
std::deque<std::unique_ptr<SchedulerItem>> defer_queue_; // FIFO queue for defer() calls
|
|
206
|
-
#endif
|
|
292
|
+
#endif /* ESPHOME_THREAD_SINGLE */
|
|
293
|
+
uint32_t to_remove_{0};
|
|
294
|
+
|
|
295
|
+
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
|
|
296
|
+
/*
|
|
297
|
+
* Multi-threaded platforms with atomic support: last_millis_ needs atomic for lock-free updates
|
|
298
|
+
*
|
|
299
|
+
* MEMORY-ORDERING NOTE
|
|
300
|
+
* --------------------
|
|
301
|
+
* `last_millis_` and `millis_major_` form a single 64-bit timestamp split in half.
|
|
302
|
+
* Writers publish `last_millis_` with memory_order_release and readers use
|
|
303
|
+
* memory_order_acquire. This ensures that once a reader sees the new low word,
|
|
304
|
+
* it also observes the corresponding increment of `millis_major_`.
|
|
305
|
+
*/
|
|
306
|
+
std::atomic<uint32_t> last_millis_{0};
|
|
307
|
+
#else /* not ESPHOME_THREAD_MULTI_ATOMICS */
|
|
308
|
+
// Platforms without atomic support or single-threaded platforms
|
|
207
309
|
uint32_t last_millis_{0};
|
|
310
|
+
#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */
|
|
311
|
+
|
|
312
|
+
/*
|
|
313
|
+
* Upper 16 bits of the 64-bit millis counter. Incremented only while holding
|
|
314
|
+
* `lock_`; read concurrently. Atomic (relaxed) avoids a formal data race.
|
|
315
|
+
* Ordering relative to `last_millis_` is provided by its release store and the
|
|
316
|
+
* corresponding acquire loads.
|
|
317
|
+
*/
|
|
318
|
+
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
|
|
319
|
+
std::atomic<uint16_t> millis_major_{0};
|
|
320
|
+
#else /* not ESPHOME_THREAD_MULTI_ATOMICS */
|
|
208
321
|
uint16_t millis_major_{0};
|
|
209
|
-
|
|
322
|
+
#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */
|
|
210
323
|
};
|
|
211
324
|
|
|
212
325
|
} // namespace esphome
|
esphome/cpp_generator.py
CHANGED
|
@@ -771,8 +771,7 @@ class MockObj(Expression):
|
|
|
771
771
|
if attr.startswith("P") and self.op not in ["::", ""]:
|
|
772
772
|
attr = attr[1:]
|
|
773
773
|
next_op = "->"
|
|
774
|
-
|
|
775
|
-
attr = attr[1:]
|
|
774
|
+
attr = attr.removeprefix("_")
|
|
776
775
|
return MockObj(f"{self.base}{self.op}{attr}", next_op)
|
|
777
776
|
|
|
778
777
|
def __call__(self, *args: SafeExpType) -> "MockObj":
|
|
@@ -1037,10 +1036,7 @@ class MockObjClass(MockObj):
|
|
|
1037
1036
|
def inherits_from(self, other: "MockObjClass") -> bool:
|
|
1038
1037
|
if str(self) == str(other):
|
|
1039
1038
|
return True
|
|
1040
|
-
for parent in self._parents
|
|
1041
|
-
if str(parent) == str(other):
|
|
1042
|
-
return True
|
|
1043
|
-
return False
|
|
1039
|
+
return any(str(parent) == str(other) for parent in self._parents)
|
|
1044
1040
|
|
|
1045
1041
|
def template(self, *args: SafeExpType) -> "MockObjClass":
|
|
1046
1042
|
if len(args) != 1 or not isinstance(args[0], TemplateArguments):
|
esphome/cpp_helpers.py
CHANGED
esphome/dashboard/dashboard.py
CHANGED
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from asyncio import events
|
|
5
5
|
from concurrent.futures import ThreadPoolExecutor
|
|
6
|
+
import contextlib
|
|
6
7
|
import logging
|
|
7
8
|
import os
|
|
8
9
|
import socket
|
|
@@ -125,10 +126,8 @@ def start_dashboard(args) -> None:
|
|
|
125
126
|
|
|
126
127
|
asyncio.set_event_loop_policy(DashboardEventLoopPolicy(settings.verbose))
|
|
127
128
|
|
|
128
|
-
|
|
129
|
+
with contextlib.suppress(KeyboardInterrupt):
|
|
129
130
|
asyncio.run(async_start(args))
|
|
130
|
-
except KeyboardInterrupt:
|
|
131
|
-
pass
|
|
132
131
|
|
|
133
132
|
|
|
134
133
|
async def async_start(args) -> None:
|
esphome/dashboard/dns.py
CHANGED
|
@@ -3,15 +3,9 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from contextlib import suppress
|
|
5
5
|
from ipaddress import ip_address
|
|
6
|
-
import sys
|
|
7
6
|
|
|
8
7
|
from icmplib import NameLookupError, async_resolve
|
|
9
8
|
|
|
10
|
-
if sys.version_info >= (3, 11):
|
|
11
|
-
from asyncio import timeout as async_timeout
|
|
12
|
-
else:
|
|
13
|
-
from async_timeout import timeout as async_timeout
|
|
14
|
-
|
|
15
9
|
RESOLVE_TIMEOUT = 3.0
|
|
16
10
|
|
|
17
11
|
|
|
@@ -20,9 +14,9 @@ async def _async_resolve_wrapper(hostname: str) -> list[str] | Exception:
|
|
|
20
14
|
with suppress(ValueError):
|
|
21
15
|
return [str(ip_address(hostname))]
|
|
22
16
|
try:
|
|
23
|
-
async with
|
|
17
|
+
async with asyncio.timeout(RESOLVE_TIMEOUT):
|
|
24
18
|
return await async_resolve(hostname)
|
|
25
|
-
except (
|
|
19
|
+
except (TimeoutError, NameLookupError, UnicodeError) as ex:
|
|
26
20
|
return ex
|
|
27
21
|
|
|
28
22
|
|
esphome/dashboard/web_server.py
CHANGED
|
@@ -144,7 +144,7 @@ def websocket_class(cls):
|
|
|
144
144
|
if not hasattr(cls, "_message_handlers"):
|
|
145
145
|
cls._message_handlers = {}
|
|
146
146
|
|
|
147
|
-
for
|
|
147
|
+
for method in cls.__dict__.values():
|
|
148
148
|
if hasattr(method, "_message_handler"):
|
|
149
149
|
cls._message_handlers[method._message_handler] = method
|
|
150
150
|
|
|
@@ -229,6 +229,7 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
|
|
229
229
|
stdin=subprocess.PIPE,
|
|
230
230
|
stdout=subprocess.PIPE,
|
|
231
231
|
stderr=subprocess.STDOUT,
|
|
232
|
+
close_fds=False,
|
|
232
233
|
)
|
|
233
234
|
stdout_thread = threading.Thread(target=self._stdout_thread)
|
|
234
235
|
stdout_thread.daemon = True
|
|
@@ -324,39 +325,53 @@ class EsphomePortCommandWebSocket(EsphomeCommandWebSocket):
|
|
|
324
325
|
configuration = json_message["configuration"]
|
|
325
326
|
config_file = settings.rel_path(configuration)
|
|
326
327
|
port = json_message["port"]
|
|
328
|
+
addresses: list[str] = []
|
|
327
329
|
if (
|
|
328
330
|
port == "OTA" # pylint: disable=too-many-boolean-expressions
|
|
329
331
|
and (entry := entries.get(config_file))
|
|
330
332
|
and entry.loaded_integrations
|
|
331
333
|
and "api" in entry.loaded_integrations
|
|
332
334
|
):
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
# Use the IP address if available but only
|
|
337
|
-
# if the API is loaded and the device is online
|
|
338
|
-
# since MQTT logging will not work otherwise
|
|
339
|
-
port = sort_ip_addresses(address_list)[0]
|
|
340
|
-
elif (
|
|
341
|
-
entry.address
|
|
335
|
+
# First priority: entry.address AKA use_address
|
|
336
|
+
if (
|
|
337
|
+
(use_address := entry.address)
|
|
342
338
|
and (
|
|
343
339
|
address_list := await dashboard.dns_cache.async_resolve(
|
|
344
|
-
|
|
340
|
+
use_address, time.monotonic()
|
|
345
341
|
)
|
|
346
342
|
)
|
|
347
343
|
and not isinstance(address_list, Exception)
|
|
348
344
|
):
|
|
349
|
-
|
|
350
|
-
port = sort_ip_addresses(address_list)[0]
|
|
345
|
+
addresses.extend(sort_ip_addresses(address_list))
|
|
351
346
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
347
|
+
# Second priority: mDNS
|
|
348
|
+
if (
|
|
349
|
+
(mdns := dashboard.mdns_status)
|
|
350
|
+
and (address_list := await mdns.async_resolve_host(entry.name))
|
|
351
|
+
and (
|
|
352
|
+
new_addresses := [
|
|
353
|
+
addr for addr in address_list if addr not in addresses
|
|
354
|
+
]
|
|
355
|
+
)
|
|
356
|
+
):
|
|
357
|
+
# Use the IP address if available but only
|
|
358
|
+
# if the API is loaded and the device is online
|
|
359
|
+
# since MQTT logging will not work otherwise
|
|
360
|
+
addresses.extend(sort_ip_addresses(new_addresses))
|
|
361
|
+
|
|
362
|
+
if not addresses:
|
|
363
|
+
# If no address was found, use the port directly
|
|
364
|
+
# as otherwise they will get the chooser which
|
|
365
|
+
# does not work with the dashboard as there is no
|
|
366
|
+
# interactive way to get keyboard input
|
|
367
|
+
addresses = [port]
|
|
368
|
+
|
|
369
|
+
device_args: list[str] = [
|
|
370
|
+
arg for address in addresses for arg in ("--device", address)
|
|
358
371
|
]
|
|
359
372
|
|
|
373
|
+
return [*DASHBOARD_COMMAND, *args, config_file, *device_args]
|
|
374
|
+
|
|
360
375
|
|
|
361
376
|
class EsphomeLogsHandler(EsphomePortCommandWebSocket):
|
|
362
377
|
async def build_command(self, json_message: dict[str, Any]) -> list[str]:
|
esphome/espota2.py
CHANGED
|
@@ -88,10 +88,7 @@ def recv_decode(sock, amount, decode=True):
|
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
def receive_exactly(sock, amount, msg, expect, decode=True):
|
|
91
|
-
if decode
|
|
92
|
-
data = []
|
|
93
|
-
else:
|
|
94
|
-
data = b""
|
|
91
|
+
data = [] if decode else b""
|
|
95
92
|
|
|
96
93
|
try:
|
|
97
94
|
data += recv_decode(sock, 1, decode=decode)
|
esphome/git.py
CHANGED
|
@@ -17,7 +17,9 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
17
17
|
def run_git_command(cmd, cwd=None) -> str:
|
|
18
18
|
_LOGGER.debug("Running git command: %s", " ".join(cmd))
|
|
19
19
|
try:
|
|
20
|
-
ret = subprocess.run(
|
|
20
|
+
ret = subprocess.run(
|
|
21
|
+
cmd, cwd=cwd, capture_output=True, check=False, close_fds=False
|
|
22
|
+
)
|
|
21
23
|
except FileNotFoundError as err:
|
|
22
24
|
raise cv.Invalid(
|
|
23
25
|
"git is not installed but required for external_components.\n"
|
esphome/helpers.py
CHANGED
|
@@ -9,6 +9,8 @@ import re
|
|
|
9
9
|
import tempfile
|
|
10
10
|
from urllib.parse import urlparse
|
|
11
11
|
|
|
12
|
+
from esphome.const import __version__ as ESPHOME_VERSION
|
|
13
|
+
|
|
12
14
|
_LOGGER = logging.getLogger(__name__)
|
|
13
15
|
|
|
14
16
|
IS_MACOS = platform.system() == "Darwin"
|
|
@@ -96,9 +98,7 @@ def cpp_string_escape(string, encoding="utf-8"):
|
|
|
96
98
|
def _should_escape(byte: int) -> bool:
|
|
97
99
|
if not 32 <= byte < 127:
|
|
98
100
|
return True
|
|
99
|
-
|
|
100
|
-
return True
|
|
101
|
-
return False
|
|
101
|
+
return byte in (ord("\\"), ord('"'))
|
|
102
102
|
|
|
103
103
|
if isinstance(string, str):
|
|
104
104
|
string = string.encode(encoding)
|
|
@@ -114,7 +114,9 @@ def cpp_string_escape(string, encoding="utf-8"):
|
|
|
114
114
|
def run_system_command(*args):
|
|
115
115
|
import subprocess
|
|
116
116
|
|
|
117
|
-
with subprocess.Popen(
|
|
117
|
+
with subprocess.Popen(
|
|
118
|
+
args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=False
|
|
119
|
+
) as p:
|
|
118
120
|
stdout, stderr = p.communicate()
|
|
119
121
|
rc = p.returncode
|
|
120
122
|
return rc, stdout, stderr
|
|
@@ -505,3 +507,20 @@ _DISALLOWED_CHARS = re.compile(r"[^a-zA-Z0-9-_]")
|
|
|
505
507
|
def sanitize(value):
|
|
506
508
|
"""Same behaviour as `helpers.cpp` method `str_sanitize`."""
|
|
507
509
|
return _DISALLOWED_CHARS.sub("_", value)
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
def docs_url(path: str) -> str:
|
|
513
|
+
"""Return the URL to the documentation for a given path."""
|
|
514
|
+
# Local import to avoid circular import
|
|
515
|
+
from esphome.config_validation import Version
|
|
516
|
+
|
|
517
|
+
version = Version.parse(ESPHOME_VERSION)
|
|
518
|
+
if version.is_beta:
|
|
519
|
+
docs_format = "https://beta.esphome.io/{path}"
|
|
520
|
+
elif version.is_dev:
|
|
521
|
+
docs_format = "https://next.esphome.io/{path}"
|
|
522
|
+
else:
|
|
523
|
+
docs_format = "https://esphome.io/{path}"
|
|
524
|
+
|
|
525
|
+
path = path.removeprefix("/")
|
|
526
|
+
return docs_format.format(path=path)
|
esphome/log.py
CHANGED
|
@@ -37,6 +37,8 @@ class AnsiStyle(Enum):
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def color(col: AnsiFore, msg: str, reset: bool = True) -> str:
|
|
40
|
+
if col == AnsiFore.KEEP:
|
|
41
|
+
return msg
|
|
40
42
|
s = col.value + msg
|
|
41
43
|
if reset and col:
|
|
42
44
|
s += AnsiStyle.RESET_ALL.value
|
|
@@ -61,7 +63,7 @@ class ESPHomeLogFormatter(logging.Formatter):
|
|
|
61
63
|
}.get(record.levelname, "")
|
|
62
64
|
message = f"{prefix}{formatted}{AnsiStyle.RESET_ALL.value}"
|
|
63
65
|
if CORE.dashboard:
|
|
64
|
-
try:
|
|
66
|
+
try: # noqa: SIM105
|
|
65
67
|
message = message.replace("\033", "\\033")
|
|
66
68
|
except UnicodeEncodeError:
|
|
67
69
|
pass
|
esphome/mqtt.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import contextlib
|
|
1
2
|
from datetime import datetime
|
|
2
3
|
import hashlib
|
|
3
4
|
import json
|
|
@@ -35,7 +36,7 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
def config_from_env():
|
|
38
|
-
|
|
39
|
+
return {
|
|
39
40
|
CONF_MQTT: {
|
|
40
41
|
CONF_USERNAME: get_str_env("ESPHOME_DASHBOARD_MQTT_USERNAME"),
|
|
41
42
|
CONF_PASSWORD: get_str_env("ESPHOME_DASHBOARD_MQTT_PASSWORD"),
|
|
@@ -43,7 +44,6 @@ def config_from_env():
|
|
|
43
44
|
CONF_PORT: get_int_env("ESPHOME_DASHBOARD_MQTT_PORT", 1883),
|
|
44
45
|
},
|
|
45
46
|
}
|
|
46
|
-
return config
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def initialize(
|
|
@@ -52,10 +52,8 @@ def initialize(
|
|
|
52
52
|
client = prepare(
|
|
53
53
|
config, subscriptions, on_message, on_connect, username, password, client_id
|
|
54
54
|
)
|
|
55
|
-
|
|
55
|
+
with contextlib.suppress(KeyboardInterrupt):
|
|
56
56
|
client.loop_forever()
|
|
57
|
-
except KeyboardInterrupt:
|
|
58
|
-
pass
|
|
59
57
|
return 0
|
|
60
58
|
|
|
61
59
|
|
esphome/platformio_api.py
CHANGED
|
@@ -61,6 +61,7 @@ FILTER_PLATFORMIO_LINES = [
|
|
|
61
61
|
r"Advanced Memory Usage is available via .*",
|
|
62
62
|
r"Merged .* ELF section",
|
|
63
63
|
r"esptool.py v.*",
|
|
64
|
+
r"esptool v.*",
|
|
64
65
|
r"Checking size .*",
|
|
65
66
|
r"Retrieving maximum program size .*",
|
|
66
67
|
r"PLATFORM: .*",
|
|
@@ -131,9 +132,11 @@ def _load_idedata(config):
|
|
|
131
132
|
temp_idedata = Path(CORE.relative_internal_path("idedata", f"{CORE.name}.json"))
|
|
132
133
|
|
|
133
134
|
changed = False
|
|
134
|
-
if
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
if (
|
|
136
|
+
not platformio_ini.is_file()
|
|
137
|
+
or not temp_idedata.is_file()
|
|
138
|
+
or platformio_ini.stat().st_mtime >= temp_idedata.stat().st_mtime
|
|
139
|
+
):
|
|
137
140
|
changed = True
|
|
138
141
|
|
|
139
142
|
if not changed:
|
|
@@ -208,7 +211,7 @@ def _decode_pc(config, addr):
|
|
|
208
211
|
return
|
|
209
212
|
command = [idedata.addr2line_path, "-pfiaC", "-e", idedata.firmware_elf_path, addr]
|
|
210
213
|
try:
|
|
211
|
-
translation = subprocess.check_output(command).decode().strip()
|
|
214
|
+
translation = subprocess.check_output(command, close_fds=False).decode().strip()
|
|
212
215
|
except Exception: # pylint: disable=broad-except
|
|
213
216
|
_LOGGER.debug("Caught exception for command %s", command, exc_info=1)
|
|
214
217
|
return
|
esphome/types.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""This helper module tracks commonly used types in the esphome python codebase."""
|
|
2
2
|
|
|
3
|
+
from typing import TypedDict
|
|
4
|
+
|
|
3
5
|
from esphome.core import ID, EsphomeCore, Lambda
|
|
4
6
|
|
|
5
7
|
ConfigFragmentType = (
|
|
@@ -16,3 +18,13 @@ ConfigFragmentType = (
|
|
|
16
18
|
ConfigType = dict[str, ConfigFragmentType]
|
|
17
19
|
CoreType = EsphomeCore
|
|
18
20
|
ConfigPathType = str | int
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class EntityMetadata(TypedDict):
|
|
24
|
+
"""Metadata stored for each entity to help with duplicate detection."""
|
|
25
|
+
|
|
26
|
+
name: str
|
|
27
|
+
device_id: str
|
|
28
|
+
platform: str
|
|
29
|
+
entity_id: str
|
|
30
|
+
component: str
|