esphome 2025.4.1__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/as3935_i2c/as3935_i2c.h +0 -3
- 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/display/rect.cpp +4 -9
- esphome/components/display/rect.h +1 -1
- 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 -8
- 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/hlw8012/hlw8012.cpp +1 -1
- 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/lv_validation.py +10 -1
- esphome/components/lvgl/lvgl_esphome.cpp +5 -1
- esphome/components/lvgl/schemas.py +14 -14
- esphome/components/lvgl/text/__init__.py +1 -2
- esphome/components/lvgl/widgets/arc.py +7 -6
- esphome/components/lvgl/widgets/buttonmatrix.py +3 -3
- esphome/components/lvgl/widgets/checkbox.py +2 -2
- esphome/components/lvgl/widgets/dropdown.py +2 -1
- esphome/components/lvgl/widgets/img.py +15 -12
- 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 +40 -6
- 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/tt21100/touchscreen/tt21100.cpp +1 -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.1.dist-info → esphome-2025.5.0.dist-info}/METADATA +10 -11
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/RECORD +456 -396
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/WHEEL +1 -1
- esphome/components/esp32_ble/const_esp32c6.h +0 -74
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/entry_points.txt +0 -0
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/top_level.txt +0 -0
@@ -434,7 +434,11 @@ void LvglComponent::setup() {
|
|
434
434
|
auto height = display->get_height();
|
435
435
|
size_t buffer_pixels = width * height / this->buffer_frac_;
|
436
436
|
auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8;
|
437
|
-
|
437
|
+
void *buffer = nullptr;
|
438
|
+
if (this->buffer_frac_ >= 4)
|
439
|
+
buffer = malloc(buf_bytes); // NOLINT
|
440
|
+
if (buffer == nullptr)
|
441
|
+
buffer = lv_custom_mem_alloc(buf_bytes); // NOLINT
|
438
442
|
if (buffer == nullptr) {
|
439
443
|
this->mark_failed();
|
440
444
|
this->status_set_error("Memory allocation failure");
|
@@ -156,13 +156,13 @@ STYLE_PROPS = {
|
|
156
156
|
"opa_layered": lvalid.opacity,
|
157
157
|
"outline_color": lvalid.lv_color,
|
158
158
|
"outline_opa": lvalid.opacity,
|
159
|
-
"outline_pad": lvalid.
|
159
|
+
"outline_pad": lvalid.padding,
|
160
160
|
"outline_width": lvalid.pixels,
|
161
|
-
"pad_all": lvalid.
|
162
|
-
"pad_bottom": lvalid.
|
163
|
-
"pad_left": lvalid.
|
164
|
-
"pad_right": lvalid.
|
165
|
-
"pad_top": lvalid.
|
161
|
+
"pad_all": lvalid.padding,
|
162
|
+
"pad_bottom": lvalid.padding,
|
163
|
+
"pad_left": lvalid.padding,
|
164
|
+
"pad_right": lvalid.padding,
|
165
|
+
"pad_top": lvalid.padding,
|
166
166
|
"shadow_color": lvalid.lv_color,
|
167
167
|
"shadow_ofs_x": lvalid.lv_int,
|
168
168
|
"shadow_ofs_y": lvalid.lv_int,
|
@@ -226,8 +226,8 @@ FULL_STYLE_SCHEMA = STYLE_SCHEMA.extend(
|
|
226
226
|
{
|
227
227
|
cv.Optional(df.CONF_GRID_CELL_X_ALIGN): grid_alignments,
|
228
228
|
cv.Optional(df.CONF_GRID_CELL_Y_ALIGN): grid_alignments,
|
229
|
-
cv.Optional(df.CONF_PAD_ROW): lvalid.
|
230
|
-
cv.Optional(df.CONF_PAD_COLUMN): lvalid.
|
229
|
+
cv.Optional(df.CONF_PAD_ROW): lvalid.padding,
|
230
|
+
cv.Optional(df.CONF_PAD_COLUMN): lvalid.padding,
|
231
231
|
}
|
232
232
|
)
|
233
233
|
|
@@ -370,8 +370,8 @@ LAYOUT_SCHEMA = {
|
|
370
370
|
cv.Required(df.CONF_GRID_COLUMNS): [grid_spec],
|
371
371
|
cv.Optional(df.CONF_GRID_COLUMN_ALIGN): grid_alignments,
|
372
372
|
cv.Optional(df.CONF_GRID_ROW_ALIGN): grid_alignments,
|
373
|
-
cv.Optional(df.CONF_PAD_ROW): lvalid.
|
374
|
-
cv.Optional(df.CONF_PAD_COLUMN): lvalid.
|
373
|
+
cv.Optional(df.CONF_PAD_ROW): lvalid.padding,
|
374
|
+
cv.Optional(df.CONF_PAD_COLUMN): lvalid.padding,
|
375
375
|
},
|
376
376
|
df.TYPE_FLEX: {
|
377
377
|
cv.Optional(
|
@@ -380,8 +380,8 @@ LAYOUT_SCHEMA = {
|
|
380
380
|
cv.Optional(df.CONF_FLEX_ALIGN_MAIN, default="start"): flex_alignments,
|
381
381
|
cv.Optional(df.CONF_FLEX_ALIGN_CROSS, default="start"): flex_alignments,
|
382
382
|
cv.Optional(df.CONF_FLEX_ALIGN_TRACK, default="start"): flex_alignments,
|
383
|
-
cv.Optional(df.CONF_PAD_ROW): lvalid.
|
384
|
-
cv.Optional(df.CONF_PAD_COLUMN): lvalid.
|
383
|
+
cv.Optional(df.CONF_PAD_ROW): lvalid.padding,
|
384
|
+
cv.Optional(df.CONF_PAD_COLUMN): lvalid.padding,
|
385
385
|
},
|
386
386
|
},
|
387
387
|
lower=True,
|
@@ -427,8 +427,8 @@ ALL_STYLES = {
|
|
427
427
|
**STYLE_PROPS,
|
428
428
|
**GRID_CELL_SCHEMA,
|
429
429
|
**FLEX_OBJ_SCHEMA,
|
430
|
-
cv.Optional(df.CONF_PAD_ROW): lvalid.
|
431
|
-
cv.Optional(df.CONF_PAD_COLUMN): lvalid.
|
430
|
+
cv.Optional(df.CONF_PAD_ROW): lvalid.padding,
|
431
|
+
cv.Optional(df.CONF_PAD_COLUMN): lvalid.padding,
|
432
432
|
}
|
433
433
|
|
434
434
|
|
@@ -19,9 +19,8 @@ from ..widgets import get_widgets, wait_for_widgets
|
|
19
19
|
|
20
20
|
LVGLText = lvgl_ns.class_("LVGLText", text.Text)
|
21
21
|
|
22
|
-
CONFIG_SCHEMA = text.
|
22
|
+
CONFIG_SCHEMA = text.text_schema(LVGLText).extend(
|
23
23
|
{
|
24
|
-
cv.GenerateID(): cv.declare_id(LVGLText),
|
25
24
|
cv.Required(CONF_WIDGET): cv.use_id(LvText),
|
26
25
|
}
|
27
26
|
)
|
@@ -67,12 +67,13 @@ class ArcType(NumberType):
|
|
67
67
|
lv.arc_set_mode(w.obj, literal(config[CONF_MODE]))
|
68
68
|
lv.arc_set_change_rate(w.obj, config[CONF_CHANGE_RATE])
|
69
69
|
|
70
|
-
if
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
70
|
+
if CONF_ADJUSTABLE in config:
|
71
|
+
if not config[CONF_ADJUSTABLE]:
|
72
|
+
lv_obj.remove_style(w.obj, nullptr, literal("LV_PART_KNOB"))
|
73
|
+
w.clear_flag("LV_OBJ_FLAG_CLICKABLE")
|
74
|
+
elif CONF_GROUP not in config:
|
75
|
+
# For some reason arc does not get automatically added to the default group
|
76
|
+
lv.group_add_obj(lv_expr.group_get_default(), w.obj)
|
76
77
|
|
77
78
|
value = await get_start_value(config)
|
78
79
|
if value is not None:
|
@@ -19,7 +19,7 @@ from ..defines import (
|
|
19
19
|
CONF_SELECTED,
|
20
20
|
)
|
21
21
|
from ..helpers import lvgl_components_required
|
22
|
-
from ..lv_validation import key_code, lv_bool,
|
22
|
+
from ..lv_validation import key_code, lv_bool, padding
|
23
23
|
from ..lvcode import lv, lv_add, lv_expr
|
24
24
|
from ..schemas import automation_schema
|
25
25
|
from ..types import (
|
@@ -59,8 +59,8 @@ BUTTONMATRIX_BUTTON_SCHEMA = cv.Schema(
|
|
59
59
|
BUTTONMATRIX_SCHEMA = cv.Schema(
|
60
60
|
{
|
61
61
|
cv.Optional(CONF_ONE_CHECKED, default=False): lv_bool,
|
62
|
-
cv.Optional(CONF_PAD_ROW):
|
63
|
-
cv.Optional(CONF_PAD_COLUMN):
|
62
|
+
cv.Optional(CONF_PAD_ROW): padding,
|
63
|
+
cv.Optional(CONF_PAD_COLUMN): padding,
|
64
64
|
cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr),
|
65
65
|
cv.Required(CONF_ROWS): cv.ensure_list(
|
66
66
|
cv.Schema(
|
@@ -2,7 +2,7 @@ from esphome.config_validation import Optional
|
|
2
2
|
from esphome.const import CONF_TEXT
|
3
3
|
|
4
4
|
from ..defines import CONF_INDICATOR, CONF_MAIN, CONF_PAD_COLUMN
|
5
|
-
from ..lv_validation import lv_text,
|
5
|
+
from ..lv_validation import lv_text, padding
|
6
6
|
from ..lvcode import lv
|
7
7
|
from ..schemas import TEXT_SCHEMA
|
8
8
|
from ..types import LvBoolean
|
@@ -19,7 +19,7 @@ class CheckboxType(WidgetType):
|
|
19
19
|
(CONF_MAIN, CONF_INDICATOR),
|
20
20
|
TEXT_SCHEMA.extend(
|
21
21
|
{
|
22
|
-
Optional(CONF_PAD_COLUMN):
|
22
|
+
Optional(CONF_PAD_COLUMN): padding,
|
23
23
|
}
|
24
24
|
),
|
25
25
|
)
|
@@ -36,7 +36,6 @@ DROPDOWN_BASE_SCHEMA = cv.Schema(
|
|
36
36
|
cv.Optional(CONF_SYMBOL): lv_text,
|
37
37
|
cv.Exclusive(CONF_SELECTED_INDEX, CONF_SELECTED_TEXT): lv_int,
|
38
38
|
cv.Exclusive(CONF_SELECTED_TEXT, CONF_SELECTED_TEXT): lv_text,
|
39
|
-
cv.Optional(CONF_DIR, default="BOTTOM"): DIRECTIONS.one_of,
|
40
39
|
cv.Optional(CONF_DROPDOWN_LIST): part_schema(dropdown_list_spec.parts),
|
41
40
|
}
|
42
41
|
)
|
@@ -44,12 +43,14 @@ DROPDOWN_BASE_SCHEMA = cv.Schema(
|
|
44
43
|
DROPDOWN_SCHEMA = DROPDOWN_BASE_SCHEMA.extend(
|
45
44
|
{
|
46
45
|
cv.Required(CONF_OPTIONS): cv.ensure_list(option_string),
|
46
|
+
cv.Optional(CONF_DIR, default="BOTTOM"): DIRECTIONS.one_of,
|
47
47
|
}
|
48
48
|
)
|
49
49
|
|
50
50
|
DROPDOWN_UPDATE_SCHEMA = DROPDOWN_BASE_SCHEMA.extend(
|
51
51
|
{
|
52
52
|
cv.Optional(CONF_OPTIONS): cv.ensure_list(option_string),
|
53
|
+
cv.Optional(CONF_DIR): DIRECTIONS.one_of,
|
53
54
|
}
|
54
55
|
)
|
55
56
|
|
@@ -10,7 +10,7 @@ from ..defines import (
|
|
10
10
|
CONF_ZOOM,
|
11
11
|
LvConstant,
|
12
12
|
)
|
13
|
-
from ..lv_validation import
|
13
|
+
from ..lv_validation import lv_angle, lv_bool, lv_image, size, zoom
|
14
14
|
from ..lvcode import lv
|
15
15
|
from ..types import lv_img_t
|
16
16
|
from . import Widget, WidgetType
|
@@ -20,9 +20,9 @@ CONF_IMAGE = "image"
|
|
20
20
|
|
21
21
|
BASE_IMG_SCHEMA = cv.Schema(
|
22
22
|
{
|
23
|
-
cv.Optional(CONF_PIVOT_X
|
24
|
-
cv.Optional(CONF_PIVOT_Y
|
25
|
-
cv.Optional(CONF_ANGLE):
|
23
|
+
cv.Optional(CONF_PIVOT_X): size,
|
24
|
+
cv.Optional(CONF_PIVOT_Y): size,
|
25
|
+
cv.Optional(CONF_ANGLE): lv_angle,
|
26
26
|
cv.Optional(CONF_ZOOM): zoom,
|
27
27
|
cv.Optional(CONF_OFFSET_X): size,
|
28
28
|
cv.Optional(CONF_OFFSET_Y): size,
|
@@ -63,19 +63,22 @@ class ImgType(WidgetType):
|
|
63
63
|
async def to_code(self, w: Widget, config):
|
64
64
|
if src := config.get(CONF_SRC):
|
65
65
|
lv.img_set_src(w.obj, await lv_image.process(src))
|
66
|
+
if (pivot_x := config.get(CONF_PIVOT_X)) and (
|
67
|
+
pivot_y := config.get(CONF_PIVOT_Y)
|
68
|
+
):
|
69
|
+
lv.img_set_pivot(
|
70
|
+
w.obj, await size.process(pivot_x), await size.process(pivot_y)
|
71
|
+
)
|
66
72
|
if (cf_angle := config.get(CONF_ANGLE)) is not None:
|
67
|
-
|
68
|
-
pivot_y = config[CONF_PIVOT_Y]
|
69
|
-
lv.img_set_pivot(w.obj, pivot_x, pivot_y)
|
70
|
-
lv.img_set_angle(w.obj, cf_angle)
|
73
|
+
lv.img_set_angle(w.obj, await lv_angle.process(cf_angle))
|
71
74
|
if (img_zoom := config.get(CONF_ZOOM)) is not None:
|
72
|
-
lv.img_set_zoom(w.obj, img_zoom)
|
75
|
+
lv.img_set_zoom(w.obj, await zoom.process(img_zoom))
|
73
76
|
if (offset := config.get(CONF_OFFSET_X)) is not None:
|
74
|
-
lv.img_set_offset_x(w.obj, offset)
|
77
|
+
lv.img_set_offset_x(w.obj, await size.process(offset))
|
75
78
|
if (offset := config.get(CONF_OFFSET_Y)) is not None:
|
76
|
-
lv.img_set_offset_y(w.obj, offset)
|
79
|
+
lv.img_set_offset_y(w.obj, await size.process(offset))
|
77
80
|
if CONF_ANTIALIAS in config:
|
78
|
-
lv.img_set_antialias(w.obj, config[CONF_ANTIALIAS])
|
81
|
+
lv.img_set_antialias(w.obj, await lv_bool.process(config[CONF_ANTIALIAS]))
|
79
82
|
if mode := config.get(CONF_MODE):
|
80
83
|
await w.set_property("size_mode", mode)
|
81
84
|
|
@@ -0,0 +1,134 @@
|
|
1
|
+
import difflib
|
2
|
+
|
3
|
+
import esphome.codegen as cg
|
4
|
+
import esphome.config_validation as cv
|
5
|
+
from esphome.const import CONF_FROM, CONF_ID, CONF_TO
|
6
|
+
from esphome.core import CORE
|
7
|
+
from esphome.cpp_generator import MockObj, VariableDeclarationExpression, add_global
|
8
|
+
from esphome.loader import get_component
|
9
|
+
|
10
|
+
CODEOWNERS = ["@clydebarrow"]
|
11
|
+
MULTI_CONF = True
|
12
|
+
|
13
|
+
map_ = cg.std_ns.class_("map")
|
14
|
+
|
15
|
+
CONF_ENTRIES = "entries"
|
16
|
+
CONF_CLASS = "class"
|
17
|
+
|
18
|
+
|
19
|
+
class IndexType:
|
20
|
+
"""
|
21
|
+
Represents a type of index in a map.
|
22
|
+
"""
|
23
|
+
|
24
|
+
def __init__(self, validator, data_type, conversion):
|
25
|
+
self.validator = validator
|
26
|
+
self.data_type = data_type
|
27
|
+
self.conversion = conversion
|
28
|
+
|
29
|
+
|
30
|
+
INDEX_TYPES = {
|
31
|
+
"int": IndexType(cv.int_, cg.int_, int),
|
32
|
+
"string": IndexType(cv.string, cg.std_string, str),
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
def to_schema(value):
|
37
|
+
"""
|
38
|
+
Generate a schema for the 'to' field of a map. This can be either one of the index types or a class name.
|
39
|
+
:param value:
|
40
|
+
:return:
|
41
|
+
"""
|
42
|
+
return cv.Any(
|
43
|
+
cv.one_of(*INDEX_TYPES, lower=True),
|
44
|
+
cv.one_of(*CORE.id_classes.keys()),
|
45
|
+
)(value)
|
46
|
+
|
47
|
+
|
48
|
+
BASE_SCHEMA = cv.Schema(
|
49
|
+
{
|
50
|
+
cv.Required(CONF_ID): cv.declare_id(map_),
|
51
|
+
cv.Required(CONF_FROM): cv.one_of(*INDEX_TYPES, lower=True),
|
52
|
+
cv.Required(CONF_TO): cv.string,
|
53
|
+
},
|
54
|
+
extra=cv.ALLOW_EXTRA,
|
55
|
+
)
|
56
|
+
|
57
|
+
|
58
|
+
def get_object_type(to_):
|
59
|
+
"""
|
60
|
+
Get the object type from a string. Possible formats:
|
61
|
+
xxx The name of a component which defines INSTANCE_TYPE
|
62
|
+
esphome::xxx::yyy A C++ class name defined in a component
|
63
|
+
xxx::yyy A C++ class name defined in a component
|
64
|
+
yyy A C++ class name defined in the core
|
65
|
+
"""
|
66
|
+
|
67
|
+
if cls := CORE.id_classes.get(to_):
|
68
|
+
return cls
|
69
|
+
if cls := CORE.id_classes.get(to_.removeprefix("esphome::")):
|
70
|
+
return cls
|
71
|
+
# get_component will throw a wobbly if we don't check this first.
|
72
|
+
if "." in to_:
|
73
|
+
return None
|
74
|
+
if component := get_component(to_):
|
75
|
+
return component.instance_type
|
76
|
+
return None
|
77
|
+
|
78
|
+
|
79
|
+
def map_schema(config):
|
80
|
+
config = BASE_SCHEMA(config)
|
81
|
+
if CONF_ENTRIES not in config or not isinstance(config[CONF_ENTRIES], dict):
|
82
|
+
raise cv.Invalid("an entries list is required for a map")
|
83
|
+
entries = config[CONF_ENTRIES]
|
84
|
+
if len(entries) == 0:
|
85
|
+
raise cv.Invalid("Map must have at least one entry")
|
86
|
+
to_ = config[CONF_TO]
|
87
|
+
if to_ in INDEX_TYPES:
|
88
|
+
value_type = INDEX_TYPES[to_].validator
|
89
|
+
else:
|
90
|
+
value_type = get_object_type(to_)
|
91
|
+
if value_type is None:
|
92
|
+
matches = difflib.get_close_matches(to_, CORE.id_classes)
|
93
|
+
raise cv.Invalid(
|
94
|
+
f"No known mappable class name matches '{to_}'; did you mean one of {', '.join(matches)}?"
|
95
|
+
)
|
96
|
+
value_type = cv.use_id(value_type)
|
97
|
+
config[CONF_ENTRIES] = {k: value_type(v) for k, v in entries.items()}
|
98
|
+
return config
|
99
|
+
|
100
|
+
|
101
|
+
CONFIG_SCHEMA = map_schema
|
102
|
+
|
103
|
+
|
104
|
+
async def to_code(config):
|
105
|
+
entries = config[CONF_ENTRIES]
|
106
|
+
from_ = config[CONF_FROM]
|
107
|
+
to_ = config[CONF_TO]
|
108
|
+
index_conversion = INDEX_TYPES[from_].conversion
|
109
|
+
index_type = INDEX_TYPES[from_].data_type
|
110
|
+
if to_ in INDEX_TYPES:
|
111
|
+
value_conversion = INDEX_TYPES[to_].conversion
|
112
|
+
value_type = INDEX_TYPES[to_].data_type
|
113
|
+
entries = {
|
114
|
+
index_conversion(key): value_conversion(value)
|
115
|
+
for key, value in entries.items()
|
116
|
+
}
|
117
|
+
else:
|
118
|
+
entries = {
|
119
|
+
index_conversion(key): await cg.get_variable(value)
|
120
|
+
for key, value in entries.items()
|
121
|
+
}
|
122
|
+
value_type = get_object_type(to_)
|
123
|
+
if list(entries.values())[0].op != ".":
|
124
|
+
value_type = value_type.operator("ptr")
|
125
|
+
varid = config[CONF_ID]
|
126
|
+
varid.type = map_.template(index_type, value_type)
|
127
|
+
var = MockObj(varid, ".")
|
128
|
+
decl = VariableDeclarationExpression(varid.type, "", varid)
|
129
|
+
add_global(decl)
|
130
|
+
CORE.register_variable(varid, var)
|
131
|
+
|
132
|
+
for key, value in entries.items():
|
133
|
+
cg.add(var.insert((key, value)))
|
134
|
+
return var
|
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "matrix_keypad.h"
|
2
2
|
#include "esphome/core/log.h"
|
3
|
+
#include "esphome/core/application.h"
|
3
4
|
|
4
5
|
namespace esphome {
|
5
6
|
namespace matrix_keypad {
|
@@ -28,7 +29,7 @@ void MatrixKeypad::setup() {
|
|
28
29
|
void MatrixKeypad::loop() {
|
29
30
|
static uint32_t active_start = 0;
|
30
31
|
static int active_key = -1;
|
31
|
-
uint32_t now =
|
32
|
+
uint32_t now = App.get_loop_component_start_time();
|
32
33
|
int key = -1;
|
33
34
|
bool error = false;
|
34
35
|
int pos = 0, row, col;
|
@@ -2,8 +2,11 @@
|
|
2
2
|
#include "esphome/core/log.h"
|
3
3
|
#include "esphome/core/helpers.h"
|
4
4
|
#include "esphome/core/hal.h"
|
5
|
+
#include "esphome/core/application.h"
|
5
6
|
#include "max7219font.h"
|
6
7
|
|
8
|
+
#include <algorithm>
|
9
|
+
|
7
10
|
namespace esphome {
|
8
11
|
namespace max7219digit {
|
9
12
|
|
@@ -61,45 +64,42 @@ void MAX7219Component::dump_config() {
|
|
61
64
|
}
|
62
65
|
|
63
66
|
void MAX7219Component::loop() {
|
64
|
-
uint32_t now =
|
65
|
-
|
67
|
+
const uint32_t now = App.get_loop_component_start_time();
|
68
|
+
const uint32_t millis_since_last_scroll = now - this->last_scroll_;
|
69
|
+
const size_t first_line_size = this->max_displaybuffer_[0].size();
|
66
70
|
// check if the buffer has shrunk past the current position since last update
|
67
|
-
if ((this->
|
68
|
-
|
71
|
+
if ((first_line_size >= this->old_buffer_size_ + 3) || (first_line_size <= this->old_buffer_size_ - 3)) {
|
72
|
+
ESP_LOGV(TAG, "Buffer size changed %d to %d", this->old_buffer_size_, first_line_size);
|
69
73
|
this->stepsleft_ = 0;
|
70
74
|
this->display();
|
71
|
-
this->old_buffer_size_ =
|
75
|
+
this->old_buffer_size_ = first_line_size;
|
72
76
|
}
|
73
77
|
|
74
|
-
|
75
|
-
|
76
|
-
this->stepsleft_ = 0;
|
77
|
-
|
78
|
-
// Return if there is no need to scroll or scroll is off
|
79
|
-
if (!this->scroll_ || (this->max_displaybuffer_[0].size() <= (size_t) get_width_internal())) {
|
78
|
+
if (!this->scroll_ || (first_line_size <= (size_t) get_width_internal())) {
|
79
|
+
ESP_LOGVV(TAG, "Return if there is no need to scroll or scroll is off.");
|
80
80
|
this->display();
|
81
81
|
return;
|
82
82
|
}
|
83
83
|
|
84
|
-
if ((this->stepsleft_ == 0) && (
|
84
|
+
if ((this->stepsleft_ == 0) && (millis_since_last_scroll < this->scroll_delay_)) {
|
85
|
+
ESP_LOGVV(TAG, "At first step. Waiting for scroll delay");
|
85
86
|
this->display();
|
86
87
|
return;
|
87
88
|
}
|
88
89
|
|
89
|
-
// Dwell time at end of string in case of stop at end
|
90
90
|
if (this->scroll_mode_ == ScrollMode::STOP) {
|
91
|
-
if (this->stepsleft_
|
92
|
-
if (
|
93
|
-
|
94
|
-
|
95
|
-
|
91
|
+
if (this->stepsleft_ + get_width_internal() == first_line_size + 1) {
|
92
|
+
if (millis_since_last_scroll < this->scroll_dwell_) {
|
93
|
+
ESP_LOGVV(TAG, "Dwell time at end of string in case of stop at end. Step %d, since last scroll %d, dwell %d.",
|
94
|
+
this->stepsleft_, millis_since_last_scroll, this->scroll_dwell_);
|
95
|
+
return;
|
96
96
|
}
|
97
|
-
|
97
|
+
ESP_LOGV(TAG, "Dwell time passed. Continue scrolling.");
|
98
98
|
}
|
99
99
|
}
|
100
100
|
|
101
|
-
|
102
|
-
|
101
|
+
if (millis_since_last_scroll >= this->scroll_speed_) {
|
102
|
+
ESP_LOGVV(TAG, "Call to scroll left action");
|
103
103
|
this->last_scroll_ = now;
|
104
104
|
this->scroll_left();
|
105
105
|
this->display();
|
@@ -227,19 +227,20 @@ void MAX7219Component::scroll(bool on_off) { this->set_scroll(on_off); }
|
|
227
227
|
|
228
228
|
void MAX7219Component::scroll_left() {
|
229
229
|
for (int chip_line = 0; chip_line < this->num_chip_lines_; chip_line++) {
|
230
|
+
auto scroll = [&](std::vector<uint8_t> &line, uint16_t steps) {
|
231
|
+
std::rotate(line.begin(), std::next(line.begin(), steps), line.end());
|
232
|
+
};
|
230
233
|
if (this->update_) {
|
231
234
|
this->max_displaybuffer_[chip_line].push_back(this->bckgrnd_);
|
232
|
-
|
233
|
-
|
234
|
-
this->max_displaybuffer_[chip_line].erase(this->max_displaybuffer_[chip_line].begin());
|
235
|
-
}
|
235
|
+
scroll(this->max_displaybuffer_[chip_line],
|
236
|
+
(this->stepsleft_ + 1) % (this->max_displaybuffer_[chip_line].size()));
|
236
237
|
} else {
|
237
|
-
|
238
|
-
this->max_displaybuffer_[chip_line].erase(this->max_displaybuffer_[chip_line].begin());
|
238
|
+
scroll(this->max_displaybuffer_[chip_line], 1);
|
239
239
|
}
|
240
240
|
}
|
241
241
|
this->update_ = false;
|
242
242
|
this->stepsleft_++;
|
243
|
+
this->stepsleft_ %= this->max_displaybuffer_[0].size();
|
243
244
|
}
|
244
245
|
|
245
246
|
void MAX7219Component::send_char(uint8_t chip, uint8_t data) {
|
@@ -35,8 +35,8 @@ SERVICE_SCHEMA = cv.Schema(
|
|
35
35
|
{
|
36
36
|
cv.Required(CONF_SERVICE): cv.string,
|
37
37
|
cv.Required(CONF_PROTOCOL): cv.string,
|
38
|
-
cv.Optional(CONF_PORT, default=0): cv.Any(0, cv.port),
|
39
|
-
cv.Optional(CONF_TXT, default={}): {cv.string: cv.string},
|
38
|
+
cv.Optional(CONF_PORT, default=0): cv.templatable(cv.Any(0, cv.port)),
|
39
|
+
cv.Optional(CONF_TXT, default={}): {cv.string: cv.templatable(cv.string)},
|
40
40
|
}
|
41
41
|
)
|
42
42
|
|
@@ -102,12 +102,18 @@ async def to_code(config):
|
|
102
102
|
|
103
103
|
for service in config[CONF_SERVICES]:
|
104
104
|
txt = [
|
105
|
-
|
105
|
+
cg.StructInitializer(
|
106
|
+
MDNSTXTRecord,
|
107
|
+
("key", txt_key),
|
108
|
+
("value", await cg.templatable(txt_value, [], cg.std_string)),
|
109
|
+
)
|
106
110
|
for txt_key, txt_value in service[CONF_TXT].items()
|
107
111
|
]
|
108
|
-
|
109
112
|
exp = mdns_service(
|
110
|
-
service[CONF_SERVICE],
|
113
|
+
service[CONF_SERVICE],
|
114
|
+
service[CONF_PROTOCOL],
|
115
|
+
await cg.templatable(service[CONF_PORT], [], cg.uint16),
|
116
|
+
txt,
|
111
117
|
)
|
112
118
|
|
113
119
|
cg.add(var.add_extra_service(exp))
|
@@ -1,9 +1,9 @@
|
|
1
1
|
#include "esphome/core/defines.h"
|
2
2
|
#ifdef USE_MDNS
|
3
|
-
#include "mdns_component.h"
|
4
|
-
#include "esphome/core/version.h"
|
5
3
|
#include "esphome/core/application.h"
|
6
4
|
#include "esphome/core/log.h"
|
5
|
+
#include "esphome/core/version.h"
|
6
|
+
#include "mdns_component.h"
|
7
7
|
|
8
8
|
#ifdef USE_API
|
9
9
|
#include "esphome/components/api/api_server.h"
|
@@ -62,7 +62,11 @@ void MDNSComponent::compile_records_() {
|
|
62
62
|
#endif
|
63
63
|
|
64
64
|
#ifdef USE_API_NOISE
|
65
|
-
|
65
|
+
if (api::global_api_server->get_noise_ctx()->has_psk()) {
|
66
|
+
service.txt_records.push_back({"api_encryption", "Noise_NNpsk0_25519_ChaChaPoly_SHA256"});
|
67
|
+
} else {
|
68
|
+
service.txt_records.push_back({"api_encryption_supported", "Noise_NNpsk0_25519_ChaChaPoly_SHA256"});
|
69
|
+
}
|
66
70
|
#endif
|
67
71
|
|
68
72
|
#ifdef ESPHOME_PROJECT_NAME
|
@@ -117,9 +121,11 @@ void MDNSComponent::dump_config() {
|
|
117
121
|
ESP_LOGCONFIG(TAG, " Hostname: %s", this->hostname_.c_str());
|
118
122
|
ESP_LOGV(TAG, " Services:");
|
119
123
|
for (const auto &service : this->services_) {
|
120
|
-
ESP_LOGV(TAG, " - %s, %s, %d", service.service_type.c_str(), service.proto.c_str(),
|
124
|
+
ESP_LOGV(TAG, " - %s, %s, %d", service.service_type.c_str(), service.proto.c_str(),
|
125
|
+
const_cast<TemplatableValue<uint16_t> &>(service.port).value());
|
121
126
|
for (const auto &record : service.txt_records) {
|
122
|
-
ESP_LOGV(TAG, " TXT: %s = %s", record.key.c_str(),
|
127
|
+
ESP_LOGV(TAG, " TXT: %s = %s", record.key.c_str(),
|
128
|
+
const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
|
123
129
|
}
|
124
130
|
}
|
125
131
|
}
|
@@ -3,6 +3,7 @@
|
|
3
3
|
#ifdef USE_MDNS
|
4
4
|
#include <string>
|
5
5
|
#include <vector>
|
6
|
+
#include "esphome/core/automation.h"
|
6
7
|
#include "esphome/core/component.h"
|
7
8
|
|
8
9
|
namespace esphome {
|
@@ -10,7 +11,7 @@ namespace mdns {
|
|
10
11
|
|
11
12
|
struct MDNSTXTRecord {
|
12
13
|
std::string key;
|
13
|
-
std::string value;
|
14
|
+
TemplatableValue<std::string> value;
|
14
15
|
};
|
15
16
|
|
16
17
|
struct MDNSService {
|
@@ -20,7 +21,7 @@ struct MDNSService {
|
|
20
21
|
// second label indicating protocol _including_ underscore character prefix
|
21
22
|
// as defined in RFC6763 Section 7, like "_tcp" or "_udp"
|
22
23
|
std::string proto;
|
23
|
-
uint16_t port;
|
24
|
+
TemplatableValue<uint16_t> port;
|
24
25
|
std::vector<MDNSTXTRecord> txt_records;
|
25
26
|
};
|
26
27
|
|
@@ -31,11 +31,12 @@ void MDNSComponent::setup() {
|
|
31
31
|
mdns_txt_item_t it{};
|
32
32
|
// dup strings to ensure the pointer is valid even after the record loop
|
33
33
|
it.key = strdup(record.key.c_str());
|
34
|
-
it.value = strdup(record.value.c_str());
|
34
|
+
it.value = strdup(const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
|
35
35
|
txt_records.push_back(it);
|
36
36
|
}
|
37
|
-
|
38
|
-
|
37
|
+
uint16_t port = const_cast<TemplatableValue<uint16_t> &>(service.port).value();
|
38
|
+
err = mdns_service_add(nullptr, service.service_type.c_str(), service.proto.c_str(), port, txt_records.data(),
|
39
|
+
txt_records.size());
|
39
40
|
|
40
41
|
// free records
|
41
42
|
for (const auto &it : txt_records) {
|
@@ -29,9 +29,11 @@ void MDNSComponent::setup() {
|
|
29
29
|
while (*service_type == '_') {
|
30
30
|
service_type++;
|
31
31
|
}
|
32
|
-
|
32
|
+
uint16_t port = const_cast<TemplatableValue<uint16_t> &>(service.port).value();
|
33
|
+
MDNS.addService(service_type, proto, port);
|
33
34
|
for (const auto &record : service.txt_records) {
|
34
|
-
MDNS.addServiceTxt(service_type, proto, record.key.c_str(),
|
35
|
+
MDNS.addServiceTxt(service_type, proto, record.key.c_str(),
|
36
|
+
const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
|
35
37
|
}
|
36
38
|
}
|
37
39
|
}
|
@@ -29,9 +29,11 @@ void MDNSComponent::setup() {
|
|
29
29
|
while (*service_type == '_') {
|
30
30
|
service_type++;
|
31
31
|
}
|
32
|
-
|
32
|
+
uint16_t port_ = const_cast<TemplatableValue<uint16_t> &>(service.port).value();
|
33
|
+
MDNS.addService(service_type, proto, port_);
|
33
34
|
for (const auto &record : service.txt_records) {
|
34
|
-
MDNS.addServiceTxt(service_type, proto, record.key.c_str(),
|
35
|
+
MDNS.addServiceTxt(service_type, proto, record.key.c_str(),
|
36
|
+
const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
|
35
37
|
}
|
36
38
|
}
|
37
39
|
}
|
@@ -29,9 +29,11 @@ void MDNSComponent::setup() {
|
|
29
29
|
while (*service_type == '_') {
|
30
30
|
service_type++;
|
31
31
|
}
|
32
|
-
|
32
|
+
uint16_t port = const_cast<TemplatableValue<uint16_t> &>(service.port).value();
|
33
|
+
MDNS.addService(service_type, proto, port);
|
33
34
|
for (const auto &record : service.txt_records) {
|
34
|
-
MDNS.addServiceTxt(service_type, proto, record.key.c_str(),
|
35
|
+
MDNS.addServiceTxt(service_type, proto, record.key.c_str(),
|
36
|
+
const_cast<TemplatableValue<std::string> &>(record.value).value().c_str());
|
35
37
|
}
|
36
38
|
}
|
37
39
|
}
|