esphome 2025.4.1__py3-none-any.whl → 2025.5.0b2__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/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 +77 -10
- esphome/components/api/api_connection.h +6 -1
- esphome/components/api/api_frame_helper.cpp +98 -130
- esphome/components/api/api_frame_helper.h +12 -2
- 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 +38 -9
- esphome/components/as3935_i2c/as3935_i2c.h +0 -3
- esphome/components/as7341/as7341.h +1 -1
- 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/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/binary_sensor/binary_sensor.cpp +6 -10
- esphome/components/binary_sensor/binary_sensor.h +1 -1
- esphome/components/binary_sensor/filter.cpp +21 -21
- esphome/components/binary_sensor/filter.h +10 -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 +135 -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/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/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/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/debug/debug_component.cpp +5 -0
- esphome/components/debug/debug_component.h +6 -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/emmeti/climate.py +2 -9
- esphome/components/endstop/cover.py +17 -16
- 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.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_can/esp32_can.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/esp8266/gpio.cpp +69 -8
- 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/fujitsu_general/climate.py +2 -9
- 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 +11 -2
- esphome/components/gps/gps.cpp +11 -8
- esphome/components/gps/gps.h +9 -6
- 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/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/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/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/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 +21 -0
- esphome/components/logger/logger.cpp +125 -95
- esphome/components/logger/logger.h +160 -35
- 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/max7219digit/max7219digit.cpp +27 -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/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/mqtt/__init__.py +1 -1
- esphome/components/mqtt/mqtt_client.cpp +5 -1
- 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/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 +193 -229
- 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/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/scd30/sensor.py +2 -3
- esphome/components/scd4x/sensor.py +4 -5
- esphome/components/sdp3x/sensor.py +2 -1
- esphome/components/select/__init__.py +19 -20
- esphome/components/sen5x/sensor.py +1 -1
- esphome/components/sensor/__init__.py +158 -14
- esphome/components/sensor/filter.cpp +23 -0
- esphome/components/sensor/filter.h +22 -0
- esphome/components/sgp4x/sensor.py +1 -1
- esphome/components/sht4x/sht4x.cpp +43 -22
- esphome/components/sht4x/sht4x.h +1 -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/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/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/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/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/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/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_validation.py +38 -58
- esphome/const.py +15 -1
- esphome/core/__init__.py +2 -0
- esphome/core/application.cpp +1 -0
- esphome/core/application.h +4 -0
- esphome/core/automation.h +4 -3
- esphome/core/component.cpp +19 -3
- esphome/core/component.h +5 -0
- esphome/core/defines.h +23 -17
- esphome/core/macros.h +4 -0
- esphome/core/scheduler.cpp +3 -0
- esphome/cpp_generator.py +6 -2
- esphome/dashboard/web_server.py +3 -3
- esphome/helpers.py +39 -0
- esphome/loader.py +4 -0
- esphome/mqtt.py +21 -8
- esphome/platformio_api.py +1 -1
- esphome/schema_extractors.py +0 -1
- esphome/vscode.py +15 -0
- esphome/wizard.py +2 -2
- esphome/zeroconf.py +7 -3
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/METADATA +10 -11
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/RECORD +411 -352
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/WHEEL +1 -1
- esphome/components/esp32_ble/const_esp32c6.h +0 -74
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/entry_points.txt +0 -0
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/top_level.txt +0 -0
@@ -2,12 +2,19 @@
|
|
2
2
|
|
3
3
|
#include <cstdarg>
|
4
4
|
#include <map>
|
5
|
+
#ifdef USE_ESP32
|
6
|
+
#include <atomic>
|
7
|
+
#endif
|
5
8
|
#include "esphome/core/automation.h"
|
6
9
|
#include "esphome/core/component.h"
|
7
10
|
#include "esphome/core/defines.h"
|
8
11
|
#include "esphome/core/helpers.h"
|
9
12
|
#include "esphome/core/log.h"
|
10
13
|
|
14
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
15
|
+
#include "task_log_buffer.h"
|
16
|
+
#endif
|
17
|
+
|
11
18
|
#ifdef USE_ARDUINO
|
12
19
|
#if defined(USE_ESP8266) || defined(USE_ESP32)
|
13
20
|
#include <HardwareSerial.h>
|
@@ -26,6 +33,29 @@ namespace esphome {
|
|
26
33
|
|
27
34
|
namespace logger {
|
28
35
|
|
36
|
+
// Color and letter constants for log levels
|
37
|
+
static const char *const LOG_LEVEL_COLORS[] = {
|
38
|
+
"", // NONE
|
39
|
+
ESPHOME_LOG_BOLD(ESPHOME_LOG_COLOR_RED), // ERROR
|
40
|
+
ESPHOME_LOG_COLOR(ESPHOME_LOG_COLOR_YELLOW), // WARNING
|
41
|
+
ESPHOME_LOG_COLOR(ESPHOME_LOG_COLOR_GREEN), // INFO
|
42
|
+
ESPHOME_LOG_COLOR(ESPHOME_LOG_COLOR_MAGENTA), // CONFIG
|
43
|
+
ESPHOME_LOG_COLOR(ESPHOME_LOG_COLOR_CYAN), // DEBUG
|
44
|
+
ESPHOME_LOG_COLOR(ESPHOME_LOG_COLOR_GRAY), // VERBOSE
|
45
|
+
ESPHOME_LOG_COLOR(ESPHOME_LOG_COLOR_WHITE), // VERY_VERBOSE
|
46
|
+
};
|
47
|
+
|
48
|
+
static const char *const LOG_LEVEL_LETTERS[] = {
|
49
|
+
"", // NONE
|
50
|
+
"E", // ERROR
|
51
|
+
"W", // WARNING
|
52
|
+
"I", // INFO
|
53
|
+
"C", // CONFIG
|
54
|
+
"D", // DEBUG
|
55
|
+
"V", // VERBOSE
|
56
|
+
"VV", // VERY_VERBOSE
|
57
|
+
};
|
58
|
+
|
29
59
|
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY)
|
30
60
|
/** Enum for logging UART selection
|
31
61
|
*
|
@@ -57,7 +87,10 @@ enum UARTSelection {
|
|
57
87
|
class Logger : public Component {
|
58
88
|
public:
|
59
89
|
explicit Logger(uint32_t baud_rate, size_t tx_buffer_size);
|
60
|
-
#ifdef
|
90
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
91
|
+
void init_log_buffer(size_t total_buffer_size);
|
92
|
+
#endif
|
93
|
+
#if defined(USE_LOGGER_USB_CDC) || defined(USE_ESP32)
|
61
94
|
void loop() override;
|
62
95
|
#endif
|
63
96
|
/// Manually set the baud rate for serial, set to 0 to disable.
|
@@ -87,7 +120,7 @@ class Logger : public Component {
|
|
87
120
|
void pre_setup();
|
88
121
|
void dump_config() override;
|
89
122
|
|
90
|
-
int level_for(const char *tag);
|
123
|
+
inline int level_for(const char *tag);
|
91
124
|
|
92
125
|
/// Register a callback that will be called for every log message sent
|
93
126
|
void add_on_log_callback(std::function<void(int, const char *, const char *)> &&callback);
|
@@ -103,46 +136,66 @@ class Logger : public Component {
|
|
103
136
|
#endif
|
104
137
|
|
105
138
|
protected:
|
106
|
-
void
|
107
|
-
void write_footer_();
|
108
|
-
void log_message_(int level, const char *tag, int offset = 0);
|
139
|
+
void call_log_callbacks_(int level, const char *tag, const char *msg);
|
109
140
|
void write_msg_(const char *msg);
|
110
141
|
|
111
|
-
|
112
|
-
|
113
|
-
inline void
|
114
|
-
|
115
|
-
|
116
|
-
this->
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
142
|
+
// Format a log message with printf-style arguments and write it to a buffer with header, footer, and null terminator
|
143
|
+
// It's the caller's responsibility to initialize buffer_at (typically to 0)
|
144
|
+
inline void HOT format_log_to_buffer_with_terminator_(int level, const char *tag, int line, const char *format,
|
145
|
+
va_list args, char *buffer, int *buffer_at, int buffer_size) {
|
146
|
+
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
147
|
+
this->write_header_to_buffer_(level, tag, line, this->get_thread_name_(), buffer, buffer_at, buffer_size);
|
148
|
+
#else
|
149
|
+
this->write_header_to_buffer_(level, tag, line, nullptr, buffer, buffer_at, buffer_size);
|
150
|
+
#endif
|
151
|
+
this->format_body_to_buffer_(buffer, buffer_at, buffer_size, format, args);
|
152
|
+
this->write_footer_to_buffer_(buffer, buffer_at, buffer_size);
|
153
|
+
|
154
|
+
// Always ensure the buffer has a null terminator, even if we need to
|
155
|
+
// overwrite the last character of the actual content
|
156
|
+
if (*buffer_at >= buffer_size) {
|
157
|
+
buffer[buffer_size - 1] = '\0'; // Truncate and ensure null termination
|
158
|
+
} else {
|
159
|
+
buffer[*buffer_at] = '\0'; // Normal case, append null terminator
|
160
|
+
}
|
121
161
|
}
|
122
|
-
|
123
|
-
|
124
|
-
|
162
|
+
|
163
|
+
// Helper to format and send a log message to both console and callbacks
|
164
|
+
inline void HOT log_message_to_buffer_and_send_(int level, const char *tag, int line, const char *format,
|
165
|
+
va_list args) {
|
166
|
+
// Format to tx_buffer and prepare for output
|
167
|
+
this->tx_buffer_at_ = 0; // Initialize buffer position
|
168
|
+
this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, this->tx_buffer_, &this->tx_buffer_at_,
|
169
|
+
this->tx_buffer_size_);
|
170
|
+
|
171
|
+
if (this->baud_rate_ > 0) {
|
172
|
+
this->write_msg_(this->tx_buffer_); // If logging is enabled, write to console
|
125
173
|
}
|
174
|
+
this->call_log_callbacks_(level, tag, this->tx_buffer_);
|
126
175
|
}
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
int
|
132
|
-
if (
|
133
|
-
// Encoding error, do not increment buffer_at
|
176
|
+
|
177
|
+
// Write the body of the log message to the buffer
|
178
|
+
inline void write_body_to_buffer_(const char *value, size_t length, char *buffer, int *buffer_at, int buffer_size) {
|
179
|
+
// Calculate available space
|
180
|
+
const int available = buffer_size - *buffer_at;
|
181
|
+
if (available <= 0)
|
134
182
|
return;
|
183
|
+
|
184
|
+
// Determine copy length (minimum of remaining capacity and string length)
|
185
|
+
const size_t copy_len = (length < static_cast<size_t>(available)) ? length : available;
|
186
|
+
|
187
|
+
// Copy the data
|
188
|
+
if (copy_len > 0) {
|
189
|
+
memcpy(buffer + *buffer_at, value, copy_len);
|
190
|
+
*buffer_at += copy_len;
|
135
191
|
}
|
136
|
-
if (ret >= remaining) {
|
137
|
-
// output was too long, truncated
|
138
|
-
ret = remaining;
|
139
|
-
}
|
140
|
-
this->tx_buffer_at_ += ret;
|
141
192
|
}
|
142
|
-
|
193
|
+
|
194
|
+
// Format string to explicit buffer with varargs
|
195
|
+
inline void printf_to_buffer_(const char *format, char *buffer, int *buffer_at, int buffer_size, ...) {
|
143
196
|
va_list arg;
|
144
|
-
va_start(arg,
|
145
|
-
this->
|
197
|
+
va_start(arg, buffer_size);
|
198
|
+
this->format_body_to_buffer_(buffer, buffer_at, buffer_size, format, arg);
|
146
199
|
va_end(arg);
|
147
200
|
}
|
148
201
|
|
@@ -169,10 +222,82 @@ class Logger : public Component {
|
|
169
222
|
std::map<std::string, int> log_levels_{};
|
170
223
|
CallbackManager<void(int, const char *, const char *)> log_callback_{};
|
171
224
|
int current_level_{ESPHOME_LOG_LEVEL_VERY_VERBOSE};
|
172
|
-
|
173
|
-
bool recursion_guard_
|
225
|
+
#ifdef USE_ESP32
|
226
|
+
std::atomic<bool> recursion_guard_{false};
|
227
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
228
|
+
std::unique_ptr<logger::TaskLogBuffer> log_buffer_; // Will be initialized with init_log_buffer
|
229
|
+
#endif
|
230
|
+
#else
|
231
|
+
bool recursion_guard_{false};
|
232
|
+
#endif
|
174
233
|
void *main_task_ = nullptr;
|
175
234
|
CallbackManager<void(int)> level_callback_{};
|
235
|
+
|
236
|
+
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
237
|
+
const char *HOT get_thread_name_() {
|
238
|
+
TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
|
239
|
+
if (current_task == main_task_) {
|
240
|
+
return nullptr; // Main task
|
241
|
+
} else {
|
242
|
+
#if defined(USE_ESP32)
|
243
|
+
return pcTaskGetName(current_task);
|
244
|
+
#elif defined(USE_LIBRETINY)
|
245
|
+
return pcTaskGetTaskName(current_task);
|
246
|
+
#endif
|
247
|
+
}
|
248
|
+
}
|
249
|
+
#endif
|
250
|
+
|
251
|
+
inline void HOT write_header_to_buffer_(int level, const char *tag, int line, const char *thread_name, char *buffer,
|
252
|
+
int *buffer_at, int buffer_size) {
|
253
|
+
// Format header
|
254
|
+
if (level < 0)
|
255
|
+
level = 0;
|
256
|
+
if (level > 7)
|
257
|
+
level = 7;
|
258
|
+
|
259
|
+
const char *color = esphome::logger::LOG_LEVEL_COLORS[level];
|
260
|
+
const char *letter = esphome::logger::LOG_LEVEL_LETTERS[level];
|
261
|
+
|
262
|
+
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
263
|
+
if (thread_name != nullptr) {
|
264
|
+
// Non-main task with thread name
|
265
|
+
this->printf_to_buffer_("%s[%s][%s:%03u]%s[%s]%s: ", buffer, buffer_at, buffer_size, color, letter, tag, line,
|
266
|
+
ESPHOME_LOG_BOLD(ESPHOME_LOG_COLOR_RED), thread_name, color);
|
267
|
+
return;
|
268
|
+
}
|
269
|
+
#endif
|
270
|
+
// Main task or non ESP32/LibreTiny platform
|
271
|
+
this->printf_to_buffer_("%s[%s][%s:%03u]: ", buffer, buffer_at, buffer_size, color, letter, tag, line);
|
272
|
+
}
|
273
|
+
|
274
|
+
inline void HOT format_body_to_buffer_(char *buffer, int *buffer_at, int buffer_size, const char *format,
|
275
|
+
va_list args) {
|
276
|
+
// Get remaining capacity in the buffer
|
277
|
+
const int remaining = buffer_size - *buffer_at;
|
278
|
+
if (remaining <= 0)
|
279
|
+
return;
|
280
|
+
|
281
|
+
const int ret = vsnprintf(buffer + *buffer_at, remaining, format, args);
|
282
|
+
|
283
|
+
if (ret < 0) {
|
284
|
+
return; // Encoding error, do not increment buffer_at
|
285
|
+
}
|
286
|
+
|
287
|
+
// Update buffer_at with the formatted length (handle truncation)
|
288
|
+
int formatted_len = (ret >= remaining) ? remaining : ret;
|
289
|
+
*buffer_at += formatted_len;
|
290
|
+
|
291
|
+
// Remove all trailing newlines right after formatting
|
292
|
+
while (*buffer_at > 0 && buffer[*buffer_at - 1] == '\n') {
|
293
|
+
(*buffer_at)--;
|
294
|
+
}
|
295
|
+
}
|
296
|
+
|
297
|
+
inline void HOT write_footer_to_buffer_(char *buffer, int *buffer_at, int buffer_size) {
|
298
|
+
static const int RESET_COLOR_LEN = strlen(ESPHOME_LOG_RESET_COLOR);
|
299
|
+
this->write_body_to_buffer_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN, buffer, buffer_at, buffer_size);
|
300
|
+
}
|
176
301
|
};
|
177
302
|
extern Logger *global_logger; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
178
303
|
|
@@ -0,0 +1,138 @@
|
|
1
|
+
|
2
|
+
#include "task_log_buffer.h"
|
3
|
+
#include "esphome/core/helpers.h"
|
4
|
+
#include "esphome/core/log.h"
|
5
|
+
|
6
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
7
|
+
|
8
|
+
namespace esphome {
|
9
|
+
namespace logger {
|
10
|
+
|
11
|
+
TaskLogBuffer::TaskLogBuffer(size_t total_buffer_size) {
|
12
|
+
// Store the buffer size
|
13
|
+
this->size_ = total_buffer_size;
|
14
|
+
// Allocate memory for the ring buffer using ESPHome's RAM allocator
|
15
|
+
RAMAllocator<uint8_t> allocator;
|
16
|
+
this->storage_ = allocator.allocate(this->size_);
|
17
|
+
// Create a static ring buffer with RINGBUF_TYPE_NOSPLIT for message integrity
|
18
|
+
this->ring_buffer_ = xRingbufferCreateStatic(this->size_, RINGBUF_TYPE_NOSPLIT, this->storage_, &this->structure_);
|
19
|
+
}
|
20
|
+
|
21
|
+
TaskLogBuffer::~TaskLogBuffer() {
|
22
|
+
if (this->ring_buffer_ != nullptr) {
|
23
|
+
// Delete the ring buffer
|
24
|
+
vRingbufferDelete(this->ring_buffer_);
|
25
|
+
this->ring_buffer_ = nullptr;
|
26
|
+
|
27
|
+
// Free the allocated memory
|
28
|
+
RAMAllocator<uint8_t> allocator;
|
29
|
+
allocator.deallocate(this->storage_, this->size_);
|
30
|
+
this->storage_ = nullptr;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
bool TaskLogBuffer::borrow_message_main_loop(LogMessage **message, const char **text, void **received_token) {
|
35
|
+
if (message == nullptr || text == nullptr || received_token == nullptr) {
|
36
|
+
return false;
|
37
|
+
}
|
38
|
+
|
39
|
+
size_t item_size = 0;
|
40
|
+
void *received_item = xRingbufferReceive(ring_buffer_, &item_size, 0);
|
41
|
+
if (received_item == nullptr) {
|
42
|
+
return false;
|
43
|
+
}
|
44
|
+
|
45
|
+
LogMessage *msg = static_cast<LogMessage *>(received_item);
|
46
|
+
*message = msg;
|
47
|
+
*text = msg->text_data();
|
48
|
+
*received_token = received_item;
|
49
|
+
|
50
|
+
return true;
|
51
|
+
}
|
52
|
+
|
53
|
+
void TaskLogBuffer::release_message_main_loop(void *token) {
|
54
|
+
if (token == nullptr) {
|
55
|
+
return;
|
56
|
+
}
|
57
|
+
vRingbufferReturnItem(ring_buffer_, token);
|
58
|
+
// Update counter to mark all messages as processed
|
59
|
+
last_processed_counter_ = message_counter_.load(std::memory_order_relaxed);
|
60
|
+
}
|
61
|
+
|
62
|
+
bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, TaskHandle_t task_handle,
|
63
|
+
const char *format, va_list args) {
|
64
|
+
// First, calculate the exact length needed using a null buffer (no actual writing)
|
65
|
+
va_list args_copy;
|
66
|
+
va_copy(args_copy, args);
|
67
|
+
int ret = vsnprintf(nullptr, 0, format, args_copy);
|
68
|
+
va_end(args_copy);
|
69
|
+
|
70
|
+
if (ret <= 0) {
|
71
|
+
return false; // Formatting error or empty message
|
72
|
+
}
|
73
|
+
|
74
|
+
// Calculate actual text length (capped to maximum size)
|
75
|
+
static constexpr size_t MAX_TEXT_SIZE = 255;
|
76
|
+
size_t text_length = (static_cast<size_t>(ret) > MAX_TEXT_SIZE) ? MAX_TEXT_SIZE : ret;
|
77
|
+
|
78
|
+
// Calculate total size needed (header + text length + null terminator)
|
79
|
+
size_t total_size = sizeof(LogMessage) + text_length + 1;
|
80
|
+
|
81
|
+
// Acquire memory directly from the ring buffer
|
82
|
+
void *acquired_memory = nullptr;
|
83
|
+
BaseType_t result = xRingbufferSendAcquire(ring_buffer_, &acquired_memory, total_size, 0);
|
84
|
+
|
85
|
+
if (result != pdTRUE || acquired_memory == nullptr) {
|
86
|
+
return false; // Failed to acquire memory
|
87
|
+
}
|
88
|
+
|
89
|
+
// Set up the message header in the acquired memory
|
90
|
+
LogMessage *msg = static_cast<LogMessage *>(acquired_memory);
|
91
|
+
msg->level = level;
|
92
|
+
msg->tag = tag;
|
93
|
+
msg->line = line;
|
94
|
+
|
95
|
+
// Store the thread name now instead of waiting until main loop processing
|
96
|
+
// This avoids crashes if the task completes or is deleted between when this message
|
97
|
+
// is enqueued and when it's processed by the main loop
|
98
|
+
const char *thread_name = pcTaskGetName(task_handle);
|
99
|
+
if (thread_name != nullptr) {
|
100
|
+
strncpy(msg->thread_name, thread_name, sizeof(msg->thread_name) - 1);
|
101
|
+
msg->thread_name[sizeof(msg->thread_name) - 1] = '\0'; // Ensure null termination
|
102
|
+
} else {
|
103
|
+
msg->thread_name[0] = '\0'; // Empty string if no thread name
|
104
|
+
}
|
105
|
+
|
106
|
+
// Format the message text directly into the acquired memory
|
107
|
+
// We add 1 to text_length to ensure space for null terminator during formatting
|
108
|
+
char *text_area = msg->text_data();
|
109
|
+
ret = vsnprintf(text_area, text_length + 1, format, args);
|
110
|
+
|
111
|
+
// Handle unexpected formatting error
|
112
|
+
if (ret <= 0) {
|
113
|
+
vRingbufferReturnItem(ring_buffer_, acquired_memory);
|
114
|
+
return false;
|
115
|
+
}
|
116
|
+
|
117
|
+
// Remove trailing newlines
|
118
|
+
while (text_length > 0 && text_area[text_length - 1] == '\n') {
|
119
|
+
text_length--;
|
120
|
+
}
|
121
|
+
|
122
|
+
msg->text_length = text_length;
|
123
|
+
// Complete the send operation with the acquired memory
|
124
|
+
result = xRingbufferSendComplete(ring_buffer_, acquired_memory);
|
125
|
+
|
126
|
+
if (result != pdTRUE) {
|
127
|
+
return false; // Failed to complete the message send
|
128
|
+
}
|
129
|
+
|
130
|
+
// Message sent successfully, increment the counter
|
131
|
+
message_counter_.fetch_add(1, std::memory_order_relaxed);
|
132
|
+
return true;
|
133
|
+
}
|
134
|
+
|
135
|
+
} // namespace logger
|
136
|
+
} // namespace esphome
|
137
|
+
|
138
|
+
#endif // USE_ESPHOME_TASK_LOG_BUFFER
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "esphome/core/defines.h"
|
4
|
+
#include "esphome/core/helpers.h"
|
5
|
+
|
6
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
7
|
+
#include <cstddef>
|
8
|
+
#include <cstring>
|
9
|
+
#include <memory>
|
10
|
+
#include <atomic>
|
11
|
+
#include <freertos/FreeRTOS.h>
|
12
|
+
#include <freertos/ringbuf.h>
|
13
|
+
|
14
|
+
namespace esphome {
|
15
|
+
namespace logger {
|
16
|
+
|
17
|
+
class TaskLogBuffer {
|
18
|
+
public:
|
19
|
+
// Structure for a log message header (text data follows immediately after)
|
20
|
+
struct LogMessage {
|
21
|
+
const char *tag; // We store the pointer, assuming tags are static
|
22
|
+
char thread_name[16]; // Store thread name directly (only used for non-main threads)
|
23
|
+
uint16_t text_length; // Length of the message text (up to ~64KB)
|
24
|
+
uint16_t line; // Source code line number
|
25
|
+
uint8_t level; // Log level (0-7)
|
26
|
+
|
27
|
+
// Methods for accessing message contents
|
28
|
+
inline char *text_data() { return reinterpret_cast<char *>(this) + sizeof(LogMessage); }
|
29
|
+
|
30
|
+
inline const char *text_data() const { return reinterpret_cast<const char *>(this) + sizeof(LogMessage); }
|
31
|
+
};
|
32
|
+
|
33
|
+
// Constructor that takes a total buffer size
|
34
|
+
explicit TaskLogBuffer(size_t total_buffer_size);
|
35
|
+
~TaskLogBuffer();
|
36
|
+
|
37
|
+
// NOT thread-safe - borrow a message from the ring buffer, only call from main loop
|
38
|
+
bool borrow_message_main_loop(LogMessage **message, const char **text, void **received_token);
|
39
|
+
|
40
|
+
// NOT thread-safe - release a message buffer and update the counter, only call from main loop
|
41
|
+
void release_message_main_loop(void *token);
|
42
|
+
|
43
|
+
// Thread-safe - send a message to the ring buffer from any thread
|
44
|
+
bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, TaskHandle_t task_handle,
|
45
|
+
const char *format, va_list args);
|
46
|
+
|
47
|
+
// Check if there are messages ready to be processed using an atomic counter for performance
|
48
|
+
inline bool HOT has_messages() const {
|
49
|
+
return message_counter_.load(std::memory_order_relaxed) != last_processed_counter_;
|
50
|
+
}
|
51
|
+
|
52
|
+
// Get the total buffer size in bytes
|
53
|
+
inline size_t size() const { return size_; }
|
54
|
+
|
55
|
+
private:
|
56
|
+
RingbufHandle_t ring_buffer_{nullptr}; // FreeRTOS ring buffer handle
|
57
|
+
StaticRingbuffer_t structure_; // Static structure for the ring buffer
|
58
|
+
uint8_t *storage_{nullptr}; // Pointer to allocated memory
|
59
|
+
size_t size_{0}; // Size of allocated memory
|
60
|
+
|
61
|
+
// Atomic counter for message tracking (only differences matter)
|
62
|
+
std::atomic<uint16_t> message_counter_{0}; // Incremented when messages are committed
|
63
|
+
mutable uint16_t last_processed_counter_{0}; // Tracks last processed message
|
64
|
+
};
|
65
|
+
|
66
|
+
} // namespace logger
|
67
|
+
} // namespace esphome
|
68
|
+
|
69
|
+
#endif // USE_ESPHOME_TASK_LOG_BUFFER
|
@@ -2,6 +2,7 @@ import logging
|
|
2
2
|
|
3
3
|
from esphome.automation import build_automation, register_action, validate_automation
|
4
4
|
import esphome.codegen as cg
|
5
|
+
from esphome.components.const import CONF_DRAW_ROUNDING
|
5
6
|
from esphome.components.display import Display
|
6
7
|
import esphome.config_validation as cv
|
7
8
|
from esphome.const import (
|
@@ -17,14 +18,14 @@ from esphome.const import (
|
|
17
18
|
CONF_TRIGGER_ID,
|
18
19
|
CONF_TYPE,
|
19
20
|
)
|
20
|
-
from esphome.core import CORE, ID
|
21
|
+
from esphome.core import CORE, ID, Lambda
|
21
22
|
from esphome.cpp_generator import MockObj
|
22
23
|
from esphome.final_validate import full_config
|
23
24
|
from esphome.helpers import write_file_if_changed
|
24
25
|
|
25
26
|
from . import defines as df, helpers, lv_validation as lvalid
|
26
|
-
from .automation import disp_update, focused_widgets, update_to_code
|
27
|
-
from .defines import
|
27
|
+
from .automation import disp_update, focused_widgets, refreshed_widgets, update_to_code
|
28
|
+
from .defines import add_define
|
28
29
|
from .encoders import (
|
29
30
|
ENCODERS_CONFIG,
|
30
31
|
encoders_to_code,
|
@@ -239,6 +240,13 @@ def final_validation(configs):
|
|
239
240
|
"A non adjustable arc may not be focused",
|
240
241
|
path,
|
241
242
|
)
|
243
|
+
for w in refreshed_widgets:
|
244
|
+
path = global_config.get_path_for_id(w)
|
245
|
+
widget_conf = global_config.get_config_for_path(path[:-1])
|
246
|
+
if not any(isinstance(v, Lambda) for v in widget_conf.values()):
|
247
|
+
raise cv.Invalid(
|
248
|
+
f"Widget '{w}' does not have any templated properties to refresh",
|
249
|
+
)
|
242
250
|
|
243
251
|
|
244
252
|
async def to_code(configs):
|
@@ -323,7 +331,7 @@ async def to_code(configs):
|
|
323
331
|
displays,
|
324
332
|
frac,
|
325
333
|
config[df.CONF_FULL_REFRESH],
|
326
|
-
config[
|
334
|
+
config[CONF_DRAW_ROUNDING],
|
327
335
|
config[df.CONF_RESUME_ON_INPUT],
|
328
336
|
)
|
329
337
|
await cg.register_component(lv_component, config)
|
@@ -413,7 +421,7 @@ LVGL_SCHEMA = cv.All(
|
|
413
421
|
df.CONF_DEFAULT_FONT, default="montserrat_14"
|
414
422
|
): lvalid.lv_font,
|
415
423
|
cv.Optional(df.CONF_FULL_REFRESH, default=False): cv.boolean,
|
416
|
-
cv.Optional(
|
424
|
+
cv.Optional(CONF_DRAW_ROUNDING, default=2): cv.positive_int,
|
417
425
|
cv.Optional(CONF_BUFFER_SIZE, default="100%"): cv.percentage,
|
418
426
|
cv.Optional(df.CONF_LOG_LEVEL, default="WARN"): cv.one_of(
|
419
427
|
*df.LV_LOG_LEVELS, upper=True
|
@@ -35,7 +35,13 @@ from .lvcode import (
|
|
35
35
|
lv_obj,
|
36
36
|
lvgl_comp,
|
37
37
|
)
|
38
|
-
from .schemas import
|
38
|
+
from .schemas import (
|
39
|
+
ALL_STYLES,
|
40
|
+
DISP_BG_SCHEMA,
|
41
|
+
LIST_ACTION_SCHEMA,
|
42
|
+
LVGL_SCHEMA,
|
43
|
+
base_update_schema,
|
44
|
+
)
|
39
45
|
from .types import (
|
40
46
|
LV_STATE,
|
41
47
|
LvglAction,
|
@@ -57,6 +63,7 @@ from .widgets import (
|
|
57
63
|
|
58
64
|
# Record widgets that are used in a focused action here
|
59
65
|
focused_widgets = set()
|
66
|
+
refreshed_widgets = set()
|
60
67
|
|
61
68
|
|
62
69
|
async def action_to_code(
|
@@ -361,3 +368,45 @@ async def obj_update_to_code(config, action_id, template_arg, args):
|
|
361
368
|
return await action_to_code(
|
362
369
|
widgets, do_update, action_id, template_arg, args, config
|
363
370
|
)
|
371
|
+
|
372
|
+
|
373
|
+
def validate_refresh_config(config):
|
374
|
+
for w in config:
|
375
|
+
refreshed_widgets.add(w[CONF_ID])
|
376
|
+
return config
|
377
|
+
|
378
|
+
|
379
|
+
@automation.register_action(
|
380
|
+
"lvgl.widget.refresh",
|
381
|
+
ObjUpdateAction,
|
382
|
+
cv.All(
|
383
|
+
cv.ensure_list(
|
384
|
+
cv.maybe_simple_value(
|
385
|
+
{
|
386
|
+
cv.Required(CONF_ID): cv.use_id(lv_obj_t),
|
387
|
+
},
|
388
|
+
key=CONF_ID,
|
389
|
+
)
|
390
|
+
),
|
391
|
+
validate_refresh_config,
|
392
|
+
),
|
393
|
+
)
|
394
|
+
async def obj_refresh_to_code(config, action_id, template_arg, args):
|
395
|
+
widget = await get_widgets(config)
|
396
|
+
|
397
|
+
async def do_refresh(widget: Widget):
|
398
|
+
# only update style properties that might have changed, i.e. are templated
|
399
|
+
config = {k: v for k, v in widget.config.items() if isinstance(v, Lambda)}
|
400
|
+
await set_obj_properties(widget, config)
|
401
|
+
# must pass all widget-specific options here, even if not templated, but only do so if at least one is
|
402
|
+
# templated. First filter out common style properties.
|
403
|
+
config = {k: v for k, v in widget.config.items() if k not in ALL_STYLES}
|
404
|
+
if any(isinstance(v, Lambda) for v in config.values()):
|
405
|
+
await widget.type.to_code(widget, config)
|
406
|
+
if (
|
407
|
+
widget.type.w_type.value_property is not None
|
408
|
+
and widget.type.w_type.value_property in config
|
409
|
+
):
|
410
|
+
lv.event_send(widget.obj, UPDATE_EVENT, nullptr)
|
411
|
+
|
412
|
+
return await action_to_code(widget, do_refresh, action_id, template_arg, args)
|
@@ -424,7 +424,6 @@ CONF_DEFAULT_FONT = "default_font"
|
|
424
424
|
CONF_DEFAULT_GROUP = "default_group"
|
425
425
|
CONF_DIR = "dir"
|
426
426
|
CONF_DISPLAYS = "displays"
|
427
|
-
CONF_DRAW_ROUNDING = "draw_rounding"
|
428
427
|
CONF_EDITING = "editing"
|
429
428
|
CONF_ENCODERS = "encoders"
|
430
429
|
CONF_END_ANGLE = "end_angle"
|
@@ -16,7 +16,7 @@ from esphome.const import (
|
|
16
16
|
)
|
17
17
|
from esphome.core import CORE, ID, Lambda
|
18
18
|
from esphome.cpp_generator import MockObj
|
19
|
-
from esphome.cpp_types import ESPTime, uint32
|
19
|
+
from esphome.cpp_types import ESPTime, int32, uint32
|
20
20
|
from esphome.helpers import cpp_string_escape
|
21
21
|
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
22
22
|
|
@@ -263,6 +263,15 @@ def pixels_validator(value):
|
|
263
263
|
pixels = LValidator(pixels_validator, uint32, retmapper=literal)
|
264
264
|
|
265
265
|
|
266
|
+
def padding_validator(value):
|
267
|
+
if isinstance(value, str) and value.lower().endswith("px"):
|
268
|
+
value = value[:-2]
|
269
|
+
return cv.int_(value)
|
270
|
+
|
271
|
+
|
272
|
+
padding = LValidator(padding_validator, int32, retmapper=literal)
|
273
|
+
|
274
|
+
|
266
275
|
def zoom_validator(value):
|
267
276
|
value = cv.float_range(0.1, 10.0)(value)
|
268
277
|
return value
|
@@ -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");
|