esphome 2025.4.2__py3-none-any.whl → 2025.5.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 +16 -14
- esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
- esphome/components/adc/__init__.py +51 -34
- esphome/components/airthings_wave_base/__init__.py +1 -1
- esphome/components/alarm_control_panel/__init__.py +37 -2
- esphome/components/am43/cover/__init__.py +4 -5
- esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
- esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
- esphome/components/analog_threshold/binary_sensor.py +10 -8
- esphome/components/anova/climate.py +4 -5
- esphome/components/api/__init__.py +25 -8
- esphome/components/api/api_connection.cpp +416 -662
- esphome/components/api/api_connection.h +256 -57
- esphome/components/api/api_frame_helper.cpp +232 -177
- esphome/components/api/api_frame_helper.h +61 -8
- esphome/components/api/api_noise_context.h +13 -4
- esphome/components/api/api_pb2.cpp +1422 -1
- esphome/components/api/api_pb2.h +255 -1
- esphome/components/api/api_pb2_service.cpp +162 -49
- esphome/components/api/api_pb2_service.h +90 -51
- esphome/components/api/api_pb2_size.h +361 -0
- esphome/components/api/api_server.cpp +110 -34
- esphome/components/api/api_server.h +8 -0
- esphome/components/api/proto.h +86 -17
- esphome/components/as7341/as7341.h +1 -1
- esphome/components/at581x/at581x.h +4 -4
- esphome/components/atm90e32/__init__.py +1 -0
- esphome/components/atm90e32/atm90e32.cpp +576 -199
- esphome/components/atm90e32/atm90e32.h +128 -31
- esphome/components/atm90e32/atm90e32_reg.h +4 -2
- esphome/components/atm90e32/button/__init__.py +62 -10
- esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
- esphome/components/atm90e32/button/atm90e32_button.h +36 -4
- esphome/components/atm90e32/number/__init__.py +130 -0
- esphome/components/atm90e32/number/atm90e32_number.h +16 -0
- esphome/components/atm90e32/sensor.py +21 -4
- esphome/components/atm90e32/text_sensor/__init__.py +48 -0
- esphome/components/audio/__init__.py +96 -49
- esphome/components/audio/audio.h +48 -0
- esphome/components/audio/audio_decoder.cpp +1 -1
- esphome/components/audio/audio_resampler.cpp +2 -0
- esphome/components/audio/audio_resampler.h +1 -0
- esphome/components/ballu/climate.py +2 -9
- esphome/components/bang_bang/climate.py +5 -6
- esphome/components/bedjet/bedjet_hub.cpp +1 -0
- esphome/components/bedjet/climate/__init__.py +3 -8
- esphome/components/bedjet/fan/__init__.py +2 -11
- esphome/components/binary/fan/__init__.py +13 -16
- esphome/components/binary_sensor/__init__.py +13 -10
- esphome/components/bl0906/constants.h +16 -16
- esphome/components/ble_client/text_sensor/__init__.py +3 -5
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +136 -21
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
- esphome/components/button/__init__.py +11 -8
- esphome/components/canbus/canbus.cpp +3 -0
- esphome/components/canbus/canbus.h +16 -0
- esphome/components/ccs811/sensor.py +9 -6
- esphome/components/climate/__init__.py +35 -2
- esphome/components/climate/climate_mode.h +1 -1
- esphome/components/climate/climate_traits.h +63 -57
- esphome/components/climate_ir/__init__.py +57 -17
- esphome/components/climate_ir_lg/climate.py +2 -5
- esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
- esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
- esphome/components/color/__init__.py +2 -0
- esphome/components/const/__init__.py +5 -0
- esphome/components/coolix/climate.py +2 -9
- esphome/components/copy/cover/__init__.py +10 -9
- esphome/components/copy/fan/__init__.py +11 -9
- esphome/components/copy/lock/__init__.py +11 -9
- esphome/components/copy/text/__init__.py +9 -6
- esphome/components/cover/__init__.py +37 -2
- esphome/components/cse7766/cse7766.cpp +2 -1
- esphome/components/cst226/binary_sensor/__init__.py +28 -0
- esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
- esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
- esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
- esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
- esphome/components/current_based/cover.py +37 -36
- esphome/components/current_based/current_based_cover.cpp +2 -1
- esphome/components/daikin/climate.py +2 -9
- esphome/components/daikin/daikin.cpp +15 -9
- esphome/components/daikin/daikin.h +5 -5
- esphome/components/daikin_arc/climate.py +2 -7
- esphome/components/daikin_brc/climate.py +3 -5
- esphome/components/dallas_temp/dallas_temp.cpp +17 -24
- esphome/components/dallas_temp/dallas_temp.h +0 -1
- esphome/components/daly_bms/daly_bms.cpp +2 -1
- esphome/components/debug/debug_component.cpp +6 -1
- esphome/components/debug/debug_component.h +8 -0
- esphome/components/debug/debug_esp32.cpp +109 -254
- esphome/components/debug/sensor.py +14 -0
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
- esphome/components/delonghi/climate.py +2 -9
- esphome/components/demo/__init__.py +18 -20
- esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
- esphome/components/dps310/sensor.py +6 -6
- esphome/components/ee895/sensor.py +9 -9
- esphome/components/emmeti/climate.py +2 -9
- esphome/components/endstop/cover.py +17 -16
- esphome/components/endstop/endstop_cover.cpp +2 -1
- esphome/components/ens160_base/__init__.py +12 -9
- esphome/components/esp32/__init__.py +60 -3
- esphome/components/esp32/core.cpp +11 -5
- esphome/components/esp32/gpio.cpp +86 -24
- esphome/components/esp32/gpio.py +15 -16
- esphome/components/esp32/gpio_esp32.py +1 -2
- esphome/components/esp32/gpio_esp32_c2.py +1 -1
- esphome/components/esp32/gpio_esp32_c3.py +1 -1
- esphome/components/esp32/gpio_esp32_c6.py +1 -1
- esphome/components/esp32/gpio_esp32_h2.py +1 -1
- esphome/components/esp32_ble/ble.cpp +1 -0
- esphome/components/esp32_ble/ble.h +5 -3
- esphome/components/esp32_ble/ble_advertising.cpp +2 -1
- esphome/components/esp32_ble/ble_advertising.h +1 -0
- esphome/components/esp32_ble_server/__init__.py +3 -0
- esphome/components/esp32_ble_tracker/__init__.py +7 -1
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
- esphome/components/esp32_camera/__init__.py +1 -1
- esphome/components/esp32_camera/esp32_camera.cpp +2 -10
- esphome/components/esp32_camera/esp32_camera.h +1 -1
- esphome/components/esp32_can/esp32_can.cpp +1 -1
- esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
- esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
- esphome/components/esp32_rmt_led_strip/light.py +9 -1
- esphome/components/esp32_touch/esp32_touch.cpp +1 -1
- esphome/components/esp8266/gpio.cpp +69 -8
- esphome/components/ethernet/ethernet_component.cpp +1 -1
- esphome/components/event/__init__.py +13 -10
- esphome/components/factory_reset/switch/__init__.py +7 -21
- esphome/components/fan/__init__.py +52 -5
- esphome/components/fastled_base/__init__.py +1 -4
- esphome/components/fastled_base/fastled_light.cpp +1 -1
- esphome/components/feedback/cover.py +38 -33
- esphome/components/feedback/feedback_cover.cpp +2 -1
- esphome/components/fujitsu_general/climate.py +2 -9
- esphome/components/gcja5/gcja5.cpp +2 -1
- esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
- esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
- esphome/components/gpio_expander/cached_gpio.h +22 -7
- esphome/components/gps/__init__.py +47 -17
- esphome/components/gps/gps.cpp +42 -23
- esphome/components/gps/gps.h +17 -13
- esphome/components/graph/__init__.py +1 -2
- esphome/components/gree/climate.py +4 -6
- esphome/components/gree/gree.cpp +16 -2
- esphome/components/gree/gree.h +2 -2
- esphome/components/growatt_solar/growatt_solar.cpp +2 -1
- esphome/components/haier/climate.py +37 -34
- esphome/components/hbridge/fan/__init__.py +19 -17
- esphome/components/he60r/cover.py +4 -5
- esphome/components/heatpumpir/climate.py +3 -6
- esphome/components/hitachi_ac344/climate.py +2 -9
- esphome/components/hitachi_ac424/climate.py +2 -9
- esphome/components/hm3301/hm3301.h +1 -1
- esphome/components/hte501/sensor.py +6 -6
- esphome/components/http_request/__init__.py +39 -6
- esphome/components/http_request/http_request.cpp +20 -0
- esphome/components/http_request/http_request.h +57 -15
- esphome/components/http_request/http_request_arduino.cpp +22 -6
- esphome/components/http_request/http_request_arduino.h +4 -3
- esphome/components/http_request/http_request_host.cpp +141 -0
- esphome/components/http_request/http_request_host.h +37 -0
- esphome/components/http_request/http_request_idf.cpp +35 -3
- esphome/components/http_request/http_request_idf.h +10 -3
- esphome/components/http_request/httplib.h +9691 -0
- esphome/components/http_request/update/__init__.py +11 -8
- esphome/components/hyt271/sensor.py +6 -6
- esphome/components/i2c/i2c.h +4 -0
- esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
- esphome/components/i2s_audio/__init__.py +131 -22
- esphome/components/i2s_audio/i2s_audio.h +44 -4
- esphome/components/i2s_audio/media_player/__init__.py +19 -9
- esphome/components/i2s_audio/microphone/__init__.py +63 -5
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
- esphome/components/i2s_audio/speaker/__init__.py +31 -5
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
- esphome/components/ili9xxx/ili9xxx_init.h +1 -1
- esphome/components/image/__init__.py +37 -17
- esphome/components/image/image.cpp +25 -8
- esphome/components/internal_temperature/internal_temperature.cpp +6 -4
- esphome/components/key_collector/__init__.py +35 -0
- esphome/components/key_collector/key_collector.cpp +8 -0
- esphome/components/key_collector/key_collector.h +10 -0
- esphome/components/kuntze/kuntze.cpp +2 -1
- esphome/components/ld2410/ld2410.h +1 -1
- esphome/components/ld2450/ld2450.h +1 -1
- esphome/components/light/__init__.py +57 -0
- esphome/components/lock/__init__.py +51 -4
- esphome/components/lock/automation.h +2 -13
- esphome/components/logger/__init__.py +22 -0
- esphome/components/logger/logger.cpp +154 -103
- esphome/components/logger/logger.h +211 -36
- esphome/components/logger/task_log_buffer.cpp +138 -0
- esphome/components/logger/task_log_buffer.h +69 -0
- esphome/components/lvgl/__init__.py +13 -5
- esphome/components/lvgl/automation.py +50 -1
- esphome/components/lvgl/defines.py +0 -1
- esphome/components/lvgl/lvgl_esphome.cpp +5 -1
- esphome/components/lvgl/text/__init__.py +1 -2
- esphome/components/mapping/__init__.py +134 -0
- esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
- esphome/components/max7219digit/max7219digit.cpp +28 -27
- esphome/components/mdns/__init__.py +11 -5
- esphome/components/mdns/mdns_component.cpp +11 -5
- esphome/components/mdns/mdns_component.h +3 -2
- esphome/components/mdns/mdns_esp32.cpp +4 -3
- esphome/components/mdns/mdns_esp8266.cpp +4 -2
- esphome/components/mdns/mdns_libretiny.cpp +4 -2
- esphome/components/mdns/mdns_rp2040.cpp +4 -2
- esphome/components/media_player/__init__.py +33 -1
- esphome/components/mhz19/sensor.py +11 -7
- esphome/components/micro_wake_word/__init__.py +99 -31
- esphome/components/micro_wake_word/automation.h +54 -0
- esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
- esphome/components/micro_wake_word/micro_wake_word.h +58 -105
- esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
- esphome/components/micro_wake_word/streaming_model.cpp +158 -41
- esphome/components/micro_wake_word/streaming_model.h +85 -13
- esphome/components/microphone/__init__.py +139 -9
- esphome/components/microphone/automation.h +14 -2
- esphome/components/microphone/microphone.cpp +21 -0
- esphome/components/microphone/microphone.h +14 -5
- esphome/components/microphone/microphone_source.cpp +95 -0
- esphome/components/microphone/microphone_source.h +80 -0
- esphome/components/mics_4514/sensor.py +25 -14
- esphome/components/midea/climate.py +3 -4
- esphome/components/midea_ir/climate.py +3 -5
- esphome/components/mipi_spi/__init__.py +15 -0
- esphome/components/mipi_spi/display.py +474 -0
- esphome/components/mipi_spi/mipi_spi.cpp +481 -0
- esphome/components/mipi_spi/mipi_spi.h +171 -0
- esphome/components/mipi_spi/models/__init__.py +65 -0
- esphome/components/mipi_spi/models/amoled.py +72 -0
- esphome/components/mipi_spi/models/commands.py +82 -0
- esphome/components/mipi_spi/models/cyd.py +10 -0
- esphome/components/mipi_spi/models/ili.py +749 -0
- esphome/components/mipi_spi/models/jc.py +260 -0
- esphome/components/mipi_spi/models/lanbon.py +15 -0
- esphome/components/mipi_spi/models/lilygo.py +60 -0
- esphome/components/mipi_spi/models/waveshare.py +139 -0
- esphome/components/mitsubishi/climate.py +2 -5
- esphome/components/mitsubishi/mitsubishi.cpp +9 -9
- esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
- esphome/components/mixer/speaker/mixer_speaker.h +1 -3
- esphome/components/mlx90393/sensor.py +5 -0
- esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
- esphome/components/mlx90393/sensor_mlx90393.h +21 -4
- esphome/components/modbus/modbus.cpp +2 -1
- esphome/components/mqtt/__init__.py +1 -1
- esphome/components/mqtt/mqtt_client.cpp +6 -2
- esphome/components/mqtt/mqtt_const.h +4 -0
- esphome/components/mqtt/mqtt_fan.cpp +39 -0
- esphome/components/mqtt/mqtt_fan.h +2 -0
- esphome/components/ms5611/sensor.py +6 -6
- esphome/components/ms8607/sensor.py +3 -3
- esphome/components/network/__init__.py +1 -1
- esphome/components/nextion/base_component.py +17 -16
- esphome/components/nextion/display.py +11 -2
- esphome/components/nextion/nextion.cpp +39 -1
- esphome/components/nextion/nextion.h +50 -0
- esphome/components/noblex/climate.py +2 -9
- esphome/components/number/__init__.py +12 -9
- esphome/components/one_wire/one_wire_bus.cpp +14 -10
- esphome/components/one_wire/one_wire_bus.h +14 -8
- esphome/components/online_image/bmp_image.cpp +48 -11
- esphome/components/online_image/bmp_image.h +2 -0
- esphome/components/opentherm/binary_sensor/__init__.py +2 -4
- esphome/components/opentherm/number/__init__.py +11 -20
- esphome/components/opentherm/sensor/__init__.py +3 -3
- esphome/components/opentherm/switch/__init__.py +3 -5
- esphome/components/output/lock/__init__.py +11 -9
- esphome/components/packages/__init__.py +33 -31
- esphome/components/packet_transport/__init__.py +201 -0
- esphome/components/packet_transport/binary_sensor.py +19 -0
- esphome/components/packet_transport/packet_transport.cpp +534 -0
- esphome/components/packet_transport/packet_transport.h +154 -0
- esphome/components/packet_transport/sensor.py +19 -0
- esphome/components/pca9685/pca9685_output.cpp +2 -1
- esphome/components/pid/climate.py +2 -4
- esphome/components/pm2005/__init__.py +1 -0
- esphome/components/pm2005/pm2005.cpp +123 -0
- esphome/components/pm2005/pm2005.h +46 -0
- esphome/components/pm2005/sensor.py +86 -0
- esphome/components/pmsa003i/pmsa003i.cpp +43 -16
- esphome/components/pmsa003i/pmsa003i.h +25 -25
- esphome/components/pmsx003/pmsx003.cpp +195 -230
- esphome/components/pmsx003/pmsx003.h +51 -33
- esphome/components/pmsx003/sensor.py +21 -11
- esphome/components/pn7150/pn7150.h +2 -2
- esphome/components/pn7160/pn7160.h +2 -2
- esphome/components/prometheus/prometheus_handler.cpp +174 -0
- esphome/components/prometheus/prometheus_handler.h +17 -0
- esphome/components/psram/__init__.py +7 -5
- esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
- esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
- esphome/components/pzem004t/pzem004t.cpp +2 -1
- esphome/components/qspi_dbi/__init__.py +0 -1
- esphome/components/qspi_dbi/display.py +2 -1
- esphome/components/qspi_dbi/models.py +1 -2
- esphome/components/remote_base/__init__.py +91 -0
- esphome/components/remote_base/beo4_protocol.cpp +153 -0
- esphome/components/remote_base/beo4_protocol.h +43 -0
- esphome/components/remote_base/gobox_protocol.cpp +131 -0
- esphome/components/remote_base/gobox_protocol.h +54 -0
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
- esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
- esphome/components/resampler/speaker/resampler_speaker.h +1 -1
- esphome/components/rf_bridge/rf_bridge.cpp +2 -1
- esphome/components/scd30/sensor.py +2 -3
- esphome/components/scd4x/sensor.py +4 -5
- esphome/components/sdp3x/sensor.py +2 -1
- esphome/components/sds011/sds011.cpp +2 -1
- esphome/components/select/__init__.py +19 -20
- esphome/components/sen5x/sen5x.cpp +55 -36
- esphome/components/sen5x/sensor.py +1 -1
- esphome/components/senseair/sensor.py +3 -3
- esphome/components/sensor/__init__.py +158 -14
- esphome/components/sensor/filter.cpp +23 -0
- esphome/components/sensor/filter.h +22 -0
- esphome/components/sgp30/sensor.py +14 -16
- esphome/components/sgp4x/sensor.py +1 -1
- esphome/components/sht4x/sht4x.cpp +43 -22
- esphome/components/sht4x/sht4x.h +1 -1
- esphome/components/shtcx/sensor.py +6 -6
- esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
- esphome/components/sml/text_sensor/__init__.py +4 -6
- esphome/components/sound_level/__init__.py +0 -0
- esphome/components/sound_level/sensor.py +97 -0
- esphome/components/sound_level/sound_level.cpp +194 -0
- esphome/components/sound_level/sound_level.h +73 -0
- esphome/components/speaker/media_player/__init__.py +4 -8
- esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
- esphome/components/speaker/media_player/speaker_media_player.h +0 -11
- esphome/components/speaker/speaker.h +4 -7
- esphome/components/speed/fan/__init__.py +17 -16
- esphome/components/spi/spi.h +11 -1
- esphome/components/sprinkler/__init__.py +18 -19
- esphome/components/sprinkler/sprinkler.cpp +6 -5
- esphome/components/switch/__init__.py +32 -42
- esphome/components/syslog/__init__.py +41 -0
- esphome/components/syslog/esphome_syslog.cpp +49 -0
- esphome/components/syslog/esphome_syslog.h +27 -0
- esphome/components/t6615/sensor.py +3 -3
- esphome/components/t6615/t6615.cpp +2 -1
- esphome/components/tca9555/tca9555.cpp +11 -6
- esphome/components/tcl112/climate.py +2 -9
- esphome/components/template/alarm_control_panel/__init__.py +7 -6
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
- esphome/components/template/cover/__init__.py +27 -21
- esphome/components/template/fan/__init__.py +14 -12
- esphome/components/template/lock/__init__.py +20 -25
- esphome/components/template/lock/automation.h +18 -0
- esphome/components/template/text/__init__.py +4 -3
- esphome/components/template/valve/__init__.py +32 -21
- esphome/components/template/valve/automation.h +24 -0
- esphome/components/text/__init__.py +32 -1
- esphome/components/text_sensor/__init__.py +24 -29
- esphome/components/thermostat/climate.py +5 -5
- esphome/components/time_based/cover.py +17 -16
- esphome/components/time_based/time_based_cover.cpp +2 -1
- esphome/components/tm1638/switch/__init__.py +10 -7
- esphome/components/tormatic/cover.py +4 -5
- esphome/components/toshiba/climate.py +3 -5
- esphome/components/touchscreen/touchscreen.cpp +3 -1
- esphome/components/tuya/climate/__init__.py +5 -6
- esphome/components/tuya/cover/__init__.py +6 -11
- esphome/components/tuya/select/__init__.py +15 -5
- esphome/components/tuya/select/tuya_select.cpp +6 -1
- esphome/components/tuya/select/tuya_select.h +5 -1
- esphome/components/uart/packet_transport/__init__.py +20 -0
- esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
- esphome/components/uart/packet_transport/uart_transport.h +41 -0
- esphome/components/uart/switch/uart_switch.cpp +2 -1
- esphome/components/udp/__init__.py +126 -128
- esphome/components/udp/automation.h +40 -0
- esphome/components/udp/binary_sensor.py +3 -25
- esphome/components/udp/packet_transport/__init__.py +29 -0
- esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
- esphome/components/udp/packet_transport/udp_transport.h +28 -0
- esphome/components/udp/sensor.py +3 -25
- esphome/components/udp/udp_component.cpp +26 -470
- esphome/components/udp/udp_component.h +21 -128
- esphome/components/update/__init__.py +31 -1
- esphome/components/uponor_smatrix/climate/__init__.py +4 -9
- esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
- esphome/components/uptime/text_sensor/__init__.py +47 -7
- esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
- esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
- esphome/components/valve/__init__.py +34 -3
- esphome/components/valve/automation.h +1 -19
- esphome/components/vl53l0x/sensor.py +11 -0
- esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
- esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
- esphome/components/voice_assistant/__init__.py +36 -10
- esphome/components/voice_assistant/voice_assistant.cpp +170 -144
- esphome/components/voice_assistant/voice_assistant.h +26 -25
- esphome/components/waveshare_epaper/display.py +6 -0
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
- esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
- esphome/components/weikai/weikai.cpp +0 -52
- esphome/components/whirlpool/climate.py +3 -5
- esphome/components/whynter/climate.py +3 -5
- esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
- esphome/components/yashima/climate.py +6 -6
- esphome/components/zhlt01/climate.py +2 -7
- esphome/config.py +13 -13
- esphome/config_validation.py +38 -58
- esphome/const.py +15 -1
- esphome/core/__init__.py +2 -0
- esphome/core/application.cpp +27 -10
- esphome/core/application.h +9 -1
- esphome/core/automation.h +4 -3
- esphome/core/component.cpp +28 -7
- esphome/core/component.h +10 -1
- esphome/core/defines.h +23 -17
- esphome/core/doxygen.h +13 -0
- esphome/core/macros.h +4 -0
- esphome/core/scheduler.cpp +7 -1
- esphome/cpp_generator.py +6 -2
- esphome/dashboard/web_server.py +3 -3
- esphome/helpers.py +39 -0
- esphome/loader.py +4 -0
- esphome/log.py +15 -19
- esphome/mqtt.py +23 -10
- esphome/platformio_api.py +1 -1
- esphome/schema_extractors.py +0 -1
- esphome/voluptuous_schema.py +3 -1
- esphome/vscode.py +15 -0
- esphome/wizard.py +47 -37
- esphome/zeroconf.py +7 -3
- {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/METADATA +10 -11
- {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/RECORD +444 -383
- {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/WHEEL +1 -1
- {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/entry_points.txt +0 -0
- {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.4.2.dist-info → esphome-2025.5.0.dist-info}/top_level.txt +0 -0
@@ -35,8 +35,54 @@ using nextion_writer_t = std::function<void(Nextion &)>;
|
|
35
35
|
|
36
36
|
static const std::string COMMAND_DELIMITER{static_cast<char>(255), static_cast<char>(255), static_cast<char>(255)};
|
37
37
|
|
38
|
+
#ifdef USE_NEXTION_COMMAND_SPACING
|
39
|
+
class NextionCommandPacer {
|
40
|
+
public:
|
41
|
+
/**
|
42
|
+
* @brief Creates command pacer with initial spacing
|
43
|
+
* @param initial_spacing Initial time between commands in milliseconds
|
44
|
+
*/
|
45
|
+
explicit NextionCommandPacer(uint8_t initial_spacing = 0) : spacing_ms_(initial_spacing) {}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* @brief Set the minimum time between commands
|
49
|
+
* @param spacing_ms Spacing in milliseconds
|
50
|
+
*/
|
51
|
+
void set_spacing(uint8_t spacing_ms) { spacing_ms_ = spacing_ms; }
|
52
|
+
|
53
|
+
/**
|
54
|
+
* @brief Get current command spacing
|
55
|
+
* @return Current spacing in milliseconds
|
56
|
+
*/
|
57
|
+
uint8_t get_spacing() const { return spacing_ms_; }
|
58
|
+
|
59
|
+
/**
|
60
|
+
* @brief Check if enough time has passed to send next command
|
61
|
+
* @return true if enough time has passed since last command
|
62
|
+
*/
|
63
|
+
bool can_send() const { return (millis() - last_command_time_) >= spacing_ms_; }
|
64
|
+
|
65
|
+
/**
|
66
|
+
* @brief Mark a command as sent, updating the timing
|
67
|
+
*/
|
68
|
+
void mark_sent() { last_command_time_ = millis(); }
|
69
|
+
|
70
|
+
private:
|
71
|
+
uint8_t spacing_ms_;
|
72
|
+
uint32_t last_command_time_{0};
|
73
|
+
};
|
74
|
+
#endif // USE_NEXTION_COMMAND_SPACING
|
75
|
+
|
38
76
|
class Nextion : public NextionBase, public PollingComponent, public uart::UARTDevice {
|
39
77
|
public:
|
78
|
+
#ifdef USE_NEXTION_COMMAND_SPACING
|
79
|
+
/**
|
80
|
+
* @brief Set the command spacing for the display
|
81
|
+
* @param spacing_ms Time in milliseconds between commands
|
82
|
+
*/
|
83
|
+
void set_command_spacing(uint32_t spacing_ms) { this->command_pacer_.set_spacing(spacing_ms); }
|
84
|
+
#endif // USE_NEXTION_COMMAND_SPACING
|
85
|
+
|
40
86
|
/**
|
41
87
|
* Set the text of a component to a static string.
|
42
88
|
* @param component The component name.
|
@@ -1227,6 +1273,9 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|
1227
1273
|
bool is_connected() { return this->is_connected_; }
|
1228
1274
|
|
1229
1275
|
protected:
|
1276
|
+
#ifdef USE_NEXTION_COMMAND_SPACING
|
1277
|
+
NextionCommandPacer command_pacer_{0};
|
1278
|
+
#endif // USE_NEXTION_COMMAND_SPACING
|
1230
1279
|
std::deque<NextionQueue *> nextion_queue_;
|
1231
1280
|
std::deque<NextionQueue *> waveform_queue_;
|
1232
1281
|
uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag);
|
@@ -1360,5 +1409,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|
1360
1409
|
uint32_t started_ms_ = 0;
|
1361
1410
|
bool sent_setup_commands_ = false;
|
1362
1411
|
};
|
1412
|
+
|
1363
1413
|
} // namespace nextion
|
1364
1414
|
} // namespace esphome
|
@@ -1,20 +1,13 @@
|
|
1
1
|
import esphome.codegen as cg
|
2
2
|
from esphome.components import climate_ir
|
3
|
-
import esphome.config_validation as cv
|
4
|
-
from esphome.const import CONF_ID
|
5
3
|
|
6
4
|
AUTO_LOAD = ["climate_ir"]
|
7
5
|
|
8
6
|
noblex_ns = cg.esphome_ns.namespace("noblex")
|
9
7
|
NoblexClimate = noblex_ns.class_("NoblexClimate", climate_ir.ClimateIR)
|
10
8
|
|
11
|
-
CONFIG_SCHEMA = climate_ir.
|
12
|
-
{
|
13
|
-
cv.GenerateID(): cv.declare_id(NoblexClimate),
|
14
|
-
}
|
15
|
-
)
|
9
|
+
CONFIG_SCHEMA = climate_ir.climate_ir_with_receiver_schema(NoblexClimate)
|
16
10
|
|
17
11
|
|
18
12
|
async def to_code(config):
|
19
|
-
|
20
|
-
await climate_ir.register_climate_ir(var, config)
|
13
|
+
await climate_ir.new_climate_ir(config)
|
@@ -170,7 +170,7 @@ NUMBER_OPERATION_OPTIONS = {
|
|
170
170
|
validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
|
171
171
|
validate_unit_of_measurement = cv.string_strict
|
172
172
|
|
173
|
-
|
173
|
+
_NUMBER_SCHEMA = (
|
174
174
|
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
|
175
175
|
.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
|
176
176
|
.extend(
|
@@ -196,16 +196,14 @@ NUMBER_SCHEMA = (
|
|
196
196
|
)
|
197
197
|
)
|
198
198
|
|
199
|
-
_UNDEF = object()
|
200
|
-
|
201
199
|
|
202
200
|
def number_schema(
|
203
201
|
class_: MockObjClass,
|
204
202
|
*,
|
205
|
-
icon: str =
|
206
|
-
entity_category: str =
|
207
|
-
device_class: str =
|
208
|
-
unit_of_measurement: str =
|
203
|
+
icon: str = cv.UNDEFINED,
|
204
|
+
entity_category: str = cv.UNDEFINED,
|
205
|
+
device_class: str = cv.UNDEFINED,
|
206
|
+
unit_of_measurement: str = cv.UNDEFINED,
|
209
207
|
) -> cv.Schema:
|
210
208
|
schema = {cv.GenerateID(): cv.declare_id(class_)}
|
211
209
|
|
@@ -215,10 +213,15 @@ def number_schema(
|
|
215
213
|
(CONF_DEVICE_CLASS, device_class, validate_device_class),
|
216
214
|
(CONF_UNIT_OF_MEASUREMENT, unit_of_measurement, validate_unit_of_measurement),
|
217
215
|
]:
|
218
|
-
if default is not
|
216
|
+
if default is not cv.UNDEFINED:
|
219
217
|
schema[cv.Optional(key, default=default)] = validator
|
220
218
|
|
221
|
-
return
|
219
|
+
return _NUMBER_SCHEMA.extend(schema)
|
220
|
+
|
221
|
+
|
222
|
+
# Remove before 2025.11.0
|
223
|
+
NUMBER_SCHEMA = number_schema(Number)
|
224
|
+
NUMBER_SCHEMA.add_extra(cv.deprecated_schema_constant("number"))
|
222
225
|
|
223
226
|
|
224
227
|
async def setup_number_core_(
|
@@ -17,8 +17,15 @@ const uint8_t ONE_WIRE_ROM_SEARCH = 0xF0;
|
|
17
17
|
|
18
18
|
const std::vector<uint64_t> &OneWireBus::get_devices() { return this->devices_; }
|
19
19
|
|
20
|
+
bool OneWireBus::reset_() {
|
21
|
+
int res = this->reset_int();
|
22
|
+
if (res == -1)
|
23
|
+
ESP_LOGE(TAG, "1-wire bus is held low");
|
24
|
+
return res == 1;
|
25
|
+
}
|
26
|
+
|
20
27
|
bool IRAM_ATTR OneWireBus::select(uint64_t address) {
|
21
|
-
if (!this->
|
28
|
+
if (!this->reset_())
|
22
29
|
return false;
|
23
30
|
this->write8(ONE_WIRE_ROM_SELECT);
|
24
31
|
this->write64(address);
|
@@ -31,16 +38,13 @@ void OneWireBus::search() {
|
|
31
38
|
this->reset_search();
|
32
39
|
uint64_t address;
|
33
40
|
while (true) {
|
34
|
-
{
|
35
|
-
|
36
|
-
|
37
|
-
// Reset failed or no devices present
|
38
|
-
return;
|
39
|
-
}
|
40
|
-
|
41
|
-
this->write8(ONE_WIRE_ROM_SEARCH);
|
42
|
-
address = this->search_int();
|
41
|
+
if (!this->reset_()) {
|
42
|
+
// Reset failed or no devices present
|
43
|
+
return;
|
43
44
|
}
|
45
|
+
|
46
|
+
this->write8(ONE_WIRE_ROM_SEARCH);
|
47
|
+
address = this->search_int();
|
44
48
|
if (address == 0)
|
45
49
|
break;
|
46
50
|
auto *address8 = reinterpret_cast<uint8_t *>(&address);
|
@@ -9,14 +9,6 @@ namespace one_wire {
|
|
9
9
|
|
10
10
|
class OneWireBus {
|
11
11
|
public:
|
12
|
-
/** Reset the bus, should be done before all write operations.
|
13
|
-
*
|
14
|
-
* Takes approximately 1ms.
|
15
|
-
*
|
16
|
-
* @return Whether the operation was successful.
|
17
|
-
*/
|
18
|
-
virtual bool reset() = 0;
|
19
|
-
|
20
12
|
/// Write a word to the bus. LSB first.
|
21
13
|
virtual void write8(uint8_t val) = 0;
|
22
14
|
|
@@ -50,6 +42,20 @@ class OneWireBus {
|
|
50
42
|
/// log the found devices
|
51
43
|
void dump_devices_(const char *tag);
|
52
44
|
|
45
|
+
/** Reset the bus, should be done before all write operations.
|
46
|
+
*
|
47
|
+
* Takes approximately 1ms.
|
48
|
+
*
|
49
|
+
* @return Whether the operation was successful.
|
50
|
+
*/
|
51
|
+
bool reset_();
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Bus Reset
|
55
|
+
* @return -1: signal fail, 0: no device detected, 1: device detected
|
56
|
+
*/
|
57
|
+
virtual int reset_int() = 0;
|
58
|
+
|
53
59
|
/// Reset the device search.
|
54
60
|
virtual void reset_search() = 0;
|
55
61
|
|
@@ -62,6 +62,13 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) {
|
|
62
62
|
case 1:
|
63
63
|
this->width_bytes_ = (this->width_ % 8 == 0) ? (this->width_ / 8) : (this->width_ / 8 + 1);
|
64
64
|
break;
|
65
|
+
case 24:
|
66
|
+
this->width_bytes_ = this->width_ * 3;
|
67
|
+
if (this->width_bytes_ % 4 != 0) {
|
68
|
+
this->padding_bytes_ = 4 - (this->width_bytes_ % 4);
|
69
|
+
this->width_bytes_ += this->padding_bytes_;
|
70
|
+
}
|
71
|
+
break;
|
65
72
|
default:
|
66
73
|
ESP_LOGE(TAG, "Unsupported bits per pixel: %d", this->bits_per_pixel_);
|
67
74
|
return DECODE_ERROR_UNSUPPORTED_FORMAT;
|
@@ -78,18 +85,48 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) {
|
|
78
85
|
this->current_index_ = this->data_offset_;
|
79
86
|
index = this->data_offset_;
|
80
87
|
}
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
88
|
+
switch (this->bits_per_pixel_) {
|
89
|
+
case 1: {
|
90
|
+
while (index < size) {
|
91
|
+
uint8_t current_byte = buffer[index];
|
92
|
+
for (uint8_t i = 0; i < 8; i++) {
|
93
|
+
size_t x = (this->paint_index_ % this->width_) + i;
|
94
|
+
size_t y = (this->height_ - 1) - (this->paint_index_ / this->width_);
|
95
|
+
Color c = (current_byte & (1 << (7 - i))) ? display::COLOR_ON : display::COLOR_OFF;
|
96
|
+
this->draw(x, y, 1, 1, c);
|
97
|
+
}
|
98
|
+
this->paint_index_ += 8;
|
99
|
+
this->current_index_++;
|
100
|
+
index++;
|
101
|
+
}
|
102
|
+
break;
|
90
103
|
}
|
91
|
-
|
92
|
-
|
104
|
+
case 24: {
|
105
|
+
while (index < size) {
|
106
|
+
if (index + 2 >= size) {
|
107
|
+
this->decoded_bytes_ += index;
|
108
|
+
return index;
|
109
|
+
}
|
110
|
+
uint8_t b = buffer[index];
|
111
|
+
uint8_t g = buffer[index + 1];
|
112
|
+
uint8_t r = buffer[index + 2];
|
113
|
+
size_t x = this->paint_index_ % this->width_;
|
114
|
+
size_t y = (this->height_ - 1) - (this->paint_index_ / this->width_);
|
115
|
+
Color c = Color(r, g, b);
|
116
|
+
this->draw(x, y, 1, 1, c);
|
117
|
+
this->paint_index_++;
|
118
|
+
this->current_index_ += 3;
|
119
|
+
index += 3;
|
120
|
+
if (x == this->width_ - 1 && this->padding_bytes_ > 0) {
|
121
|
+
index += this->padding_bytes_;
|
122
|
+
this->current_index_ += this->padding_bytes_;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
break;
|
126
|
+
}
|
127
|
+
default:
|
128
|
+
ESP_LOGE(TAG, "Unsupported bits per pixel: %d", this->bits_per_pixel_);
|
129
|
+
return DECODE_ERROR_UNSUPPORTED_FORMAT;
|
93
130
|
}
|
94
131
|
this->decoded_bytes_ += size;
|
95
132
|
return size;
|
@@ -24,6 +24,7 @@ class BmpDecoder : public ImageDecoder {
|
|
24
24
|
|
25
25
|
protected:
|
26
26
|
size_t current_index_{0};
|
27
|
+
size_t paint_index_{0};
|
27
28
|
ssize_t width_{0};
|
28
29
|
ssize_t height_{0};
|
29
30
|
uint16_t bits_per_pixel_{0};
|
@@ -32,6 +33,7 @@ class BmpDecoder : public ImageDecoder {
|
|
32
33
|
uint32_t color_table_entries_{0};
|
33
34
|
size_t width_bytes_{0};
|
34
35
|
size_t data_offset_{0};
|
36
|
+
uint8_t padding_bytes_{0};
|
35
37
|
};
|
36
38
|
|
37
39
|
} // namespace online_image
|
@@ -11,10 +11,8 @@ COMPONENT_TYPE = const.BINARY_SENSOR
|
|
11
11
|
|
12
12
|
def get_entity_validation_schema(entity: schema.BinarySensorSchema) -> cv.Schema:
|
13
13
|
return binary_sensor.binary_sensor_schema(
|
14
|
-
device_class=(
|
15
|
-
|
16
|
-
),
|
17
|
-
icon=(entity.icon or binary_sensor._UNDEF), # pylint: disable=protected-access
|
14
|
+
device_class=(entity.device_class or cv.UNDEFINED),
|
15
|
+
icon=(entity.icon or cv.UNDEFINED),
|
18
16
|
)
|
19
17
|
|
20
18
|
|
@@ -3,13 +3,7 @@ from typing import Any
|
|
3
3
|
import esphome.codegen as cg
|
4
4
|
from esphome.components import number
|
5
5
|
import esphome.config_validation as cv
|
6
|
-
from esphome.const import
|
7
|
-
CONF_ID,
|
8
|
-
CONF_INITIAL_VALUE,
|
9
|
-
CONF_RESTORE_VALUE,
|
10
|
-
CONF_STEP,
|
11
|
-
CONF_UNIT_OF_MEASUREMENT,
|
12
|
-
)
|
6
|
+
from esphome.const import CONF_INITIAL_VALUE, CONF_RESTORE_VALUE, CONF_STEP
|
13
7
|
|
14
8
|
from .. import const, generate, input, schema, validate
|
15
9
|
|
@@ -22,33 +16,30 @@ OpenthermNumber = generate.opentherm_ns.class_(
|
|
22
16
|
|
23
17
|
|
24
18
|
async def new_openthermnumber(config: dict[str, Any]) -> cg.Pvariable:
|
25
|
-
var =
|
26
|
-
await cg.register_component(var, config)
|
27
|
-
await number.register_number(
|
28
|
-
var,
|
19
|
+
var = await number.new_number(
|
29
20
|
config,
|
30
21
|
min_value=config[input.CONF_min_value],
|
31
22
|
max_value=config[input.CONF_max_value],
|
32
23
|
step=config[input.CONF_step],
|
33
24
|
)
|
25
|
+
await cg.register_component(var, config)
|
34
26
|
input.generate_setters(var, config)
|
35
27
|
|
36
|
-
if CONF_INITIAL_VALUE
|
37
|
-
cg.add(var.set_initial_value(
|
38
|
-
if CONF_RESTORE_VALUE
|
39
|
-
cg.add(var.set_restore_value(
|
28
|
+
if (initial_value := config.get(CONF_INITIAL_VALUE, None)) is not None:
|
29
|
+
cg.add(var.set_initial_value(initial_value))
|
30
|
+
if (restore_value := config.get(CONF_RESTORE_VALUE, None)) is not None:
|
31
|
+
cg.add(var.set_restore_value(restore_value))
|
40
32
|
|
41
33
|
return var
|
42
34
|
|
43
35
|
|
44
36
|
def get_entity_validation_schema(entity: schema.InputSchema) -> cv.Schema:
|
45
37
|
return (
|
46
|
-
number.
|
38
|
+
number.number_schema(
|
39
|
+
OpenthermNumber, unit_of_measurement=entity.unit_of_measurement
|
40
|
+
)
|
41
|
+
.extend(
|
47
42
|
{
|
48
|
-
cv.GenerateID(): cv.declare_id(OpenthermNumber),
|
49
|
-
cv.Optional(
|
50
|
-
CONF_UNIT_OF_MEASUREMENT, entity.unit_of_measurement
|
51
|
-
): cv.string_strict,
|
52
43
|
cv.Optional(CONF_STEP, entity.step): cv.float_,
|
53
44
|
cv.Optional(CONF_INITIAL_VALUE): cv.float_,
|
54
45
|
cv.Optional(CONF_RESTORE_VALUE): cv.boolean,
|
@@ -23,10 +23,10 @@ MSG_DATA_TYPES = {
|
|
23
23
|
|
24
24
|
def get_entity_validation_schema(entity: schema.SensorSchema) -> cv.Schema:
|
25
25
|
return sensor.sensor_schema(
|
26
|
-
unit_of_measurement=entity.unit_of_measurement or
|
26
|
+
unit_of_measurement=entity.unit_of_measurement or cv.UNDEFINED, # pylint: disable=protected-access
|
27
27
|
accuracy_decimals=entity.accuracy_decimals,
|
28
|
-
device_class=entity.device_class or
|
29
|
-
icon=entity.icon or
|
28
|
+
device_class=entity.device_class or cv.UNDEFINED, # pylint: disable=protected-access
|
29
|
+
icon=entity.icon or cv.UNDEFINED, # pylint: disable=protected-access
|
30
30
|
state_class=entity.state_class,
|
31
31
|
).extend(
|
32
32
|
{
|
@@ -3,7 +3,6 @@ from typing import Any
|
|
3
3
|
import esphome.codegen as cg
|
4
4
|
from esphome.components import switch
|
5
5
|
import esphome.config_validation as cv
|
6
|
-
from esphome.const import CONF_ID
|
7
6
|
|
8
7
|
from .. import const, generate, schema, validate
|
9
8
|
|
@@ -16,15 +15,14 @@ OpenthermSwitch = generate.opentherm_ns.class_(
|
|
16
15
|
|
17
16
|
|
18
17
|
async def new_openthermswitch(config: dict[str, Any]) -> cg.Pvariable:
|
19
|
-
var =
|
18
|
+
var = await switch.new_switch(config)
|
20
19
|
await cg.register_component(var, config)
|
21
|
-
await switch.register_switch(var, config)
|
22
20
|
return var
|
23
21
|
|
24
22
|
|
25
23
|
def get_entity_validation_schema(entity: schema.SwitchSchema) -> cv.Schema:
|
26
|
-
return switch.
|
27
|
-
|
24
|
+
return switch.switch_schema(
|
25
|
+
OpenthermSwitch, default_restore_mode=entity.default_mode
|
28
26
|
).extend(cv.COMPONENT_SCHEMA)
|
29
27
|
|
30
28
|
|
@@ -1,24 +1,26 @@
|
|
1
1
|
import esphome.codegen as cg
|
2
2
|
from esphome.components import lock, output
|
3
3
|
import esphome.config_validation as cv
|
4
|
-
from esphome.const import
|
4
|
+
from esphome.const import CONF_OUTPUT
|
5
5
|
|
6
6
|
from .. import output_ns
|
7
7
|
|
8
8
|
OutputLock = output_ns.class_("OutputLock", lock.Lock, cg.Component)
|
9
9
|
|
10
|
-
CONFIG_SCHEMA =
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
CONFIG_SCHEMA = (
|
11
|
+
lock.lock_schema(OutputLock)
|
12
|
+
.extend(
|
13
|
+
{
|
14
|
+
cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput),
|
15
|
+
}
|
16
|
+
)
|
17
|
+
.extend(cv.COMPONENT_SCHEMA)
|
18
|
+
)
|
16
19
|
|
17
20
|
|
18
21
|
async def to_code(config):
|
19
|
-
var =
|
22
|
+
var = await lock.new_lock(config)
|
20
23
|
await cg.register_component(var, config)
|
21
|
-
await lock.register_lock(var, config)
|
22
24
|
|
23
25
|
output_ = await cg.get_variable(config[CONF_OUTPUT])
|
24
26
|
cg.add(var.set_output(output_))
|
@@ -24,22 +24,13 @@ DOMAIN = CONF_PACKAGES
|
|
24
24
|
|
25
25
|
|
26
26
|
def validate_git_package(config: dict):
|
27
|
+
if CONF_URL not in config:
|
28
|
+
return config
|
29
|
+
config = BASE_SCHEMA(config)
|
27
30
|
new_config = config
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
conf = BASE_SCHEMA(conf)
|
32
|
-
if CONF_FILE in conf:
|
33
|
-
new_config[key][CONF_FILES] = [conf[CONF_FILE]]
|
34
|
-
del new_config[key][CONF_FILE]
|
35
|
-
except cv.MultipleInvalid as e:
|
36
|
-
with cv.prepend_path([key]):
|
37
|
-
raise e
|
38
|
-
except cv.Invalid as e:
|
39
|
-
raise cv.Invalid(
|
40
|
-
"Extra keys not allowed in git based package",
|
41
|
-
path=[key] + e.path,
|
42
|
-
) from e
|
31
|
+
if CONF_FILE in config:
|
32
|
+
new_config[CONF_FILES] = [config[CONF_FILE]]
|
33
|
+
del new_config[CONF_FILE]
|
43
34
|
return new_config
|
44
35
|
|
45
36
|
|
@@ -74,8 +65,8 @@ BASE_SCHEMA = cv.All(
|
|
74
65
|
cv.Required(CONF_URL): cv.url,
|
75
66
|
cv.Optional(CONF_USERNAME): cv.string,
|
76
67
|
cv.Optional(CONF_PASSWORD): cv.string,
|
77
|
-
cv.Exclusive(CONF_FILE,
|
78
|
-
cv.Exclusive(CONF_FILES,
|
68
|
+
cv.Exclusive(CONF_FILE, CONF_FILES): validate_yaml_filename,
|
69
|
+
cv.Exclusive(CONF_FILES, CONF_FILES): cv.All(
|
79
70
|
cv.ensure_list(
|
80
71
|
cv.Any(
|
81
72
|
validate_yaml_filename,
|
@@ -100,14 +91,17 @@ BASE_SCHEMA = cv.All(
|
|
100
91
|
cv.has_at_least_one_key(CONF_FILE, CONF_FILES),
|
101
92
|
)
|
102
93
|
|
94
|
+
PACKAGE_SCHEMA = cv.All(
|
95
|
+
cv.Any(validate_source_shorthand, BASE_SCHEMA, dict), validate_git_package
|
96
|
+
)
|
103
97
|
|
104
|
-
CONFIG_SCHEMA = cv.
|
98
|
+
CONFIG_SCHEMA = cv.Any(
|
105
99
|
cv.Schema(
|
106
100
|
{
|
107
|
-
str:
|
101
|
+
str: PACKAGE_SCHEMA,
|
108
102
|
}
|
109
103
|
),
|
110
|
-
|
104
|
+
cv.ensure_list(PACKAGE_SCHEMA),
|
111
105
|
)
|
112
106
|
|
113
107
|
|
@@ -183,25 +177,33 @@ def _process_base_package(config: dict) -> dict:
|
|
183
177
|
return {"packages": packages}
|
184
178
|
|
185
179
|
|
180
|
+
def _process_package(package_config, config):
|
181
|
+
recursive_package = package_config
|
182
|
+
if CONF_URL in package_config:
|
183
|
+
package_config = _process_base_package(package_config)
|
184
|
+
if isinstance(package_config, dict):
|
185
|
+
recursive_package = do_packages_pass(package_config)
|
186
|
+
config = merge_config(recursive_package, config)
|
187
|
+
return config
|
188
|
+
|
189
|
+
|
186
190
|
def do_packages_pass(config: dict):
|
187
191
|
if CONF_PACKAGES not in config:
|
188
192
|
return config
|
189
193
|
packages = config[CONF_PACKAGES]
|
190
194
|
with cv.prepend_path(CONF_PACKAGES):
|
191
195
|
packages = CONFIG_SCHEMA(packages)
|
192
|
-
if
|
196
|
+
if isinstance(packages, dict):
|
197
|
+
for package_name, package_config in reversed(packages.items()):
|
198
|
+
with cv.prepend_path(package_name):
|
199
|
+
config = _process_package(package_config, config)
|
200
|
+
elif isinstance(packages, list):
|
201
|
+
for package_config in reversed(packages):
|
202
|
+
config = _process_package(package_config, config)
|
203
|
+
else:
|
193
204
|
raise cv.Invalid(
|
194
|
-
f"Packages must be a key to value mapping, got {type(packages)} instead"
|
205
|
+
f"Packages must be a key to value mapping or list, got {type(packages)} instead"
|
195
206
|
)
|
196
207
|
|
197
|
-
for package_name, package_config in reversed(packages.items()):
|
198
|
-
with cv.prepend_path(package_name):
|
199
|
-
recursive_package = package_config
|
200
|
-
if CONF_URL in package_config:
|
201
|
-
package_config = _process_base_package(package_config)
|
202
|
-
if isinstance(package_config, dict):
|
203
|
-
recursive_package = do_packages_pass(package_config)
|
204
|
-
config = merge_config(recursive_package, config)
|
205
|
-
|
206
208
|
del config[CONF_PACKAGES]
|
207
209
|
return config
|