esphome 2025.4.2__py3-none-any.whl → 2025.5.0b3__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 +81 -13
- esphome/components/api/api_connection.h +13 -1
- esphome/components/api/api_frame_helper.cpp +232 -177
- esphome/components/api/api_frame_helper.h +61 -8
- esphome/components/api/api_noise_context.h +13 -4
- esphome/components/api/api_pb2.cpp +1422 -1
- esphome/components/api/api_pb2.h +255 -1
- esphome/components/api/api_pb2_service.cpp +162 -49
- esphome/components/api/api_pb2_service.h +90 -51
- esphome/components/api/api_pb2_size.h +361 -0
- esphome/components/api/api_server.cpp +110 -34
- esphome/components/api/api_server.h +8 -0
- esphome/components/api/proto.h +86 -17
- esphome/components/as7341/as7341.h +1 -1
- esphome/components/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 +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/dps310/sensor.py +6 -6
- esphome/components/ee895/sensor.py +9 -9
- esphome/components/emmeti/climate.py +2 -9
- esphome/components/endstop/cover.py +17 -16
- esphome/components/endstop/endstop_cover.cpp +2 -1
- esphome/components/ens160_base/__init__.py +12 -9
- esphome/components/esp32/__init__.py +60 -3
- esphome/components/esp32/core.cpp +11 -5
- esphome/components/esp32/gpio.cpp +86 -24
- esphome/components/esp32/gpio.py +15 -16
- esphome/components/esp32/gpio_esp32.py +1 -2
- esphome/components/esp32/gpio_esp32_c2.py +1 -1
- esphome/components/esp32/gpio_esp32_c3.py +1 -1
- esphome/components/esp32/gpio_esp32_c6.py +1 -1
- esphome/components/esp32/gpio_esp32_h2.py +1 -1
- esphome/components/esp32_ble/ble.cpp +1 -0
- esphome/components/esp32_ble/ble.h +5 -3
- esphome/components/esp32_ble/ble_advertising.cpp +2 -1
- esphome/components/esp32_ble/ble_advertising.h +1 -0
- esphome/components/esp32_ble_server/__init__.py +3 -0
- esphome/components/esp32_ble_tracker/__init__.py +7 -1
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
- esphome/components/esp32_camera/esp32_camera.cpp +2 -1
- esphome/components/esp32_camera/esp32_camera.h +1 -1
- esphome/components/esp32_can/esp32_can.cpp +1 -1
- esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
- esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
- esphome/components/esp32_rmt_led_strip/light.py +9 -1
- esphome/components/esp32_touch/esp32_touch.cpp +1 -1
- esphome/components/esp8266/gpio.cpp +69 -8
- esphome/components/ethernet/ethernet_component.cpp +1 -1
- esphome/components/event/__init__.py +13 -10
- esphome/components/factory_reset/switch/__init__.py +7 -21
- esphome/components/fan/__init__.py +52 -5
- esphome/components/fastled_base/__init__.py +1 -4
- esphome/components/fastled_base/fastled_light.cpp +1 -1
- esphome/components/feedback/cover.py +38 -33
- esphome/components/feedback/feedback_cover.cpp +2 -1
- esphome/components/fujitsu_general/climate.py +2 -9
- esphome/components/gcja5/gcja5.cpp +2 -1
- esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
- esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
- esphome/components/gpio_expander/cached_gpio.h +22 -7
- esphome/components/gps/__init__.py +47 -17
- esphome/components/gps/gps.cpp +42 -23
- esphome/components/gps/gps.h +17 -13
- esphome/components/graph/__init__.py +1 -2
- esphome/components/gree/climate.py +4 -6
- esphome/components/gree/gree.cpp +16 -2
- esphome/components/gree/gree.h +2 -2
- esphome/components/growatt_solar/growatt_solar.cpp +2 -1
- esphome/components/haier/climate.py +37 -34
- esphome/components/hbridge/fan/__init__.py +19 -17
- esphome/components/he60r/cover.py +4 -5
- esphome/components/heatpumpir/climate.py +3 -6
- esphome/components/hitachi_ac344/climate.py +2 -9
- esphome/components/hitachi_ac424/climate.py +2 -9
- esphome/components/hm3301/hm3301.h +1 -1
- esphome/components/hte501/sensor.py +6 -6
- esphome/components/http_request/__init__.py +39 -6
- esphome/components/http_request/http_request.cpp +20 -0
- esphome/components/http_request/http_request.h +57 -15
- esphome/components/http_request/http_request_arduino.cpp +22 -6
- esphome/components/http_request/http_request_arduino.h +4 -3
- esphome/components/http_request/http_request_host.cpp +141 -0
- esphome/components/http_request/http_request_host.h +37 -0
- esphome/components/http_request/http_request_idf.cpp +35 -3
- esphome/components/http_request/http_request_idf.h +10 -3
- esphome/components/http_request/httplib.h +9691 -0
- esphome/components/http_request/update/__init__.py +11 -8
- esphome/components/hyt271/sensor.py +6 -6
- esphome/components/i2c/i2c.h +4 -0
- esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
- esphome/components/i2s_audio/__init__.py +131 -22
- esphome/components/i2s_audio/i2s_audio.h +44 -4
- esphome/components/i2s_audio/media_player/__init__.py +19 -9
- esphome/components/i2s_audio/microphone/__init__.py +63 -5
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
- esphome/components/i2s_audio/speaker/__init__.py +31 -5
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
- esphome/components/ili9xxx/ili9xxx_init.h +1 -1
- esphome/components/image/__init__.py +37 -17
- esphome/components/image/image.cpp +25 -8
- esphome/components/internal_temperature/internal_temperature.cpp +6 -4
- esphome/components/key_collector/__init__.py +35 -0
- esphome/components/key_collector/key_collector.cpp +8 -0
- esphome/components/key_collector/key_collector.h +10 -0
- esphome/components/kuntze/kuntze.cpp +2 -1
- esphome/components/ld2410/ld2410.h +1 -1
- esphome/components/ld2450/ld2450.h +1 -1
- esphome/components/light/__init__.py +57 -0
- esphome/components/lock/__init__.py +51 -4
- esphome/components/lock/automation.h +2 -13
- esphome/components/logger/__init__.py +22 -0
- esphome/components/logger/logger.cpp +154 -103
- esphome/components/logger/logger.h +211 -36
- esphome/components/logger/task_log_buffer.cpp +138 -0
- esphome/components/logger/task_log_buffer.h +69 -0
- esphome/components/lvgl/__init__.py +13 -5
- esphome/components/lvgl/automation.py +50 -1
- esphome/components/lvgl/defines.py +0 -1
- esphome/components/lvgl/lvgl_esphome.cpp +5 -1
- esphome/components/lvgl/text/__init__.py +1 -2
- esphome/components/mapping/__init__.py +134 -0
- esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
- esphome/components/max7219digit/max7219digit.cpp +28 -27
- esphome/components/mdns/__init__.py +11 -5
- esphome/components/mdns/mdns_component.cpp +11 -5
- esphome/components/mdns/mdns_component.h +3 -2
- esphome/components/mdns/mdns_esp32.cpp +4 -3
- esphome/components/mdns/mdns_esp8266.cpp +4 -2
- esphome/components/mdns/mdns_libretiny.cpp +4 -2
- esphome/components/mdns/mdns_rp2040.cpp +4 -2
- esphome/components/media_player/__init__.py +33 -1
- esphome/components/mhz19/sensor.py +11 -7
- esphome/components/micro_wake_word/__init__.py +99 -31
- esphome/components/micro_wake_word/automation.h +54 -0
- esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
- esphome/components/micro_wake_word/micro_wake_word.h +58 -105
- esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
- esphome/components/micro_wake_word/streaming_model.cpp +158 -41
- esphome/components/micro_wake_word/streaming_model.h +85 -13
- esphome/components/microphone/__init__.py +139 -9
- esphome/components/microphone/automation.h +14 -2
- esphome/components/microphone/microphone.cpp +21 -0
- esphome/components/microphone/microphone.h +14 -5
- esphome/components/microphone/microphone_source.cpp +95 -0
- esphome/components/microphone/microphone_source.h +80 -0
- esphome/components/mics_4514/sensor.py +25 -14
- esphome/components/midea/climate.py +3 -4
- esphome/components/midea_ir/climate.py +3 -5
- esphome/components/mipi_spi/__init__.py +15 -0
- esphome/components/mipi_spi/display.py +474 -0
- esphome/components/mipi_spi/mipi_spi.cpp +481 -0
- esphome/components/mipi_spi/mipi_spi.h +171 -0
- esphome/components/mipi_spi/models/__init__.py +65 -0
- esphome/components/mipi_spi/models/amoled.py +72 -0
- esphome/components/mipi_spi/models/commands.py +82 -0
- esphome/components/mipi_spi/models/cyd.py +10 -0
- esphome/components/mipi_spi/models/ili.py +749 -0
- esphome/components/mipi_spi/models/jc.py +260 -0
- esphome/components/mipi_spi/models/lanbon.py +15 -0
- esphome/components/mipi_spi/models/lilygo.py +60 -0
- esphome/components/mipi_spi/models/waveshare.py +139 -0
- esphome/components/mitsubishi/climate.py +2 -5
- esphome/components/mitsubishi/mitsubishi.cpp +9 -9
- esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
- esphome/components/mixer/speaker/mixer_speaker.h +1 -3
- esphome/components/mlx90393/sensor.py +5 -0
- esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
- esphome/components/mlx90393/sensor_mlx90393.h +21 -4
- esphome/components/modbus/modbus.cpp +2 -1
- esphome/components/mqtt/__init__.py +1 -1
- esphome/components/mqtt/mqtt_client.cpp +6 -2
- esphome/components/mqtt/mqtt_const.h +4 -0
- esphome/components/mqtt/mqtt_fan.cpp +39 -0
- esphome/components/mqtt/mqtt_fan.h +2 -0
- esphome/components/ms5611/sensor.py +6 -6
- esphome/components/ms8607/sensor.py +3 -3
- esphome/components/network/__init__.py +1 -1
- esphome/components/nextion/base_component.py +17 -16
- esphome/components/nextion/display.py +11 -2
- esphome/components/nextion/nextion.cpp +39 -1
- esphome/components/nextion/nextion.h +50 -0
- esphome/components/noblex/climate.py +2 -9
- esphome/components/number/__init__.py +12 -9
- esphome/components/one_wire/one_wire_bus.cpp +14 -10
- esphome/components/one_wire/one_wire_bus.h +14 -8
- esphome/components/online_image/bmp_image.cpp +48 -11
- esphome/components/online_image/bmp_image.h +2 -0
- esphome/components/opentherm/binary_sensor/__init__.py +2 -4
- esphome/components/opentherm/number/__init__.py +11 -20
- esphome/components/opentherm/sensor/__init__.py +3 -3
- esphome/components/opentherm/switch/__init__.py +3 -5
- esphome/components/output/lock/__init__.py +11 -9
- esphome/components/packages/__init__.py +33 -31
- esphome/components/packet_transport/__init__.py +201 -0
- esphome/components/packet_transport/binary_sensor.py +19 -0
- esphome/components/packet_transport/packet_transport.cpp +534 -0
- esphome/components/packet_transport/packet_transport.h +154 -0
- esphome/components/packet_transport/sensor.py +19 -0
- esphome/components/pca9685/pca9685_output.cpp +2 -1
- esphome/components/pid/climate.py +2 -4
- esphome/components/pm2005/__init__.py +1 -0
- esphome/components/pm2005/pm2005.cpp +123 -0
- esphome/components/pm2005/pm2005.h +46 -0
- esphome/components/pm2005/sensor.py +86 -0
- esphome/components/pmsa003i/pmsa003i.cpp +43 -16
- esphome/components/pmsa003i/pmsa003i.h +25 -25
- esphome/components/pmsx003/pmsx003.cpp +195 -230
- esphome/components/pmsx003/pmsx003.h +51 -33
- esphome/components/pmsx003/sensor.py +21 -11
- esphome/components/pn7150/pn7150.h +2 -2
- esphome/components/pn7160/pn7160.h +2 -2
- esphome/components/prometheus/prometheus_handler.cpp +174 -0
- esphome/components/prometheus/prometheus_handler.h +17 -0
- esphome/components/psram/__init__.py +7 -5
- esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
- esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
- esphome/components/pzem004t/pzem004t.cpp +2 -1
- esphome/components/qspi_dbi/__init__.py +0 -1
- esphome/components/qspi_dbi/display.py +2 -1
- esphome/components/qspi_dbi/models.py +1 -2
- esphome/components/remote_base/__init__.py +91 -0
- esphome/components/remote_base/beo4_protocol.cpp +153 -0
- esphome/components/remote_base/beo4_protocol.h +43 -0
- esphome/components/remote_base/gobox_protocol.cpp +131 -0
- esphome/components/remote_base/gobox_protocol.h +54 -0
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
- esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
- esphome/components/resampler/speaker/resampler_speaker.h +1 -1
- esphome/components/rf_bridge/rf_bridge.cpp +2 -1
- esphome/components/scd30/sensor.py +2 -3
- esphome/components/scd4x/sensor.py +4 -5
- esphome/components/sdp3x/sensor.py +2 -1
- esphome/components/sds011/sds011.cpp +2 -1
- esphome/components/select/__init__.py +19 -20
- esphome/components/sen5x/sen5x.cpp +55 -36
- esphome/components/sen5x/sensor.py +1 -1
- esphome/components/senseair/sensor.py +3 -3
- esphome/components/sensor/__init__.py +158 -14
- esphome/components/sensor/filter.cpp +23 -0
- esphome/components/sensor/filter.h +22 -0
- esphome/components/sgp30/sensor.py +14 -16
- esphome/components/sgp4x/sensor.py +1 -1
- esphome/components/sht4x/sht4x.cpp +43 -22
- esphome/components/sht4x/sht4x.h +1 -1
- esphome/components/shtcx/sensor.py +6 -6
- esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
- esphome/components/sml/text_sensor/__init__.py +4 -6
- esphome/components/sound_level/__init__.py +0 -0
- esphome/components/sound_level/sensor.py +97 -0
- esphome/components/sound_level/sound_level.cpp +194 -0
- esphome/components/sound_level/sound_level.h +73 -0
- esphome/components/speaker/media_player/__init__.py +4 -8
- esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
- esphome/components/speaker/media_player/speaker_media_player.h +0 -11
- esphome/components/speaker/speaker.h +4 -7
- esphome/components/speed/fan/__init__.py +17 -16
- esphome/components/spi/spi.h +11 -1
- esphome/components/sprinkler/__init__.py +18 -19
- esphome/components/sprinkler/sprinkler.cpp +6 -5
- esphome/components/switch/__init__.py +32 -42
- esphome/components/syslog/__init__.py +41 -0
- esphome/components/syslog/esphome_syslog.cpp +49 -0
- esphome/components/syslog/esphome_syslog.h +27 -0
- esphome/components/t6615/sensor.py +3 -3
- esphome/components/t6615/t6615.cpp +2 -1
- esphome/components/tca9555/tca9555.cpp +11 -6
- esphome/components/tcl112/climate.py +2 -9
- esphome/components/template/alarm_control_panel/__init__.py +7 -6
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
- esphome/components/template/cover/__init__.py +27 -21
- esphome/components/template/fan/__init__.py +14 -12
- esphome/components/template/lock/__init__.py +20 -25
- esphome/components/template/lock/automation.h +18 -0
- esphome/components/template/text/__init__.py +4 -3
- esphome/components/template/valve/__init__.py +32 -21
- esphome/components/template/valve/automation.h +24 -0
- esphome/components/text/__init__.py +32 -1
- esphome/components/text_sensor/__init__.py +24 -29
- esphome/components/thermostat/climate.py +5 -5
- esphome/components/time_based/cover.py +17 -16
- esphome/components/time_based/time_based_cover.cpp +2 -1
- esphome/components/tm1638/switch/__init__.py +10 -7
- esphome/components/tormatic/cover.py +4 -5
- esphome/components/toshiba/climate.py +3 -5
- esphome/components/touchscreen/touchscreen.cpp +3 -1
- esphome/components/tuya/climate/__init__.py +5 -6
- esphome/components/tuya/cover/__init__.py +6 -11
- esphome/components/tuya/select/__init__.py +15 -5
- esphome/components/tuya/select/tuya_select.cpp +6 -1
- esphome/components/tuya/select/tuya_select.h +5 -1
- esphome/components/uart/packet_transport/__init__.py +20 -0
- esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
- esphome/components/uart/packet_transport/uart_transport.h +41 -0
- esphome/components/uart/switch/uart_switch.cpp +2 -1
- esphome/components/udp/__init__.py +126 -128
- esphome/components/udp/automation.h +40 -0
- esphome/components/udp/binary_sensor.py +3 -25
- esphome/components/udp/packet_transport/__init__.py +29 -0
- esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
- esphome/components/udp/packet_transport/udp_transport.h +28 -0
- esphome/components/udp/sensor.py +3 -25
- esphome/components/udp/udp_component.cpp +26 -470
- esphome/components/udp/udp_component.h +21 -128
- esphome/components/update/__init__.py +31 -1
- esphome/components/uponor_smatrix/climate/__init__.py +4 -9
- esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
- esphome/components/uptime/text_sensor/__init__.py +47 -7
- esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
- esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
- esphome/components/valve/__init__.py +34 -3
- esphome/components/valve/automation.h +1 -19
- esphome/components/vl53l0x/sensor.py +11 -0
- esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
- esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
- esphome/components/voice_assistant/__init__.py +36 -10
- esphome/components/voice_assistant/voice_assistant.cpp +170 -144
- esphome/components/voice_assistant/voice_assistant.h +26 -25
- esphome/components/waveshare_epaper/display.py +6 -0
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
- esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
- esphome/components/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 +23 -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/macros.h +4 -0
- esphome/core/scheduler.cpp +7 -1
- esphome/cpp_generator.py +6 -2
- esphome/dashboard/web_server.py +3 -3
- esphome/helpers.py +39 -0
- esphome/loader.py +4 -0
- esphome/log.py +15 -19
- esphome/mqtt.py +23 -10
- esphome/platformio_api.py +1 -1
- esphome/schema_extractors.py +0 -1
- esphome/voluptuous_schema.py +3 -1
- esphome/vscode.py +15 -0
- esphome/wizard.py +47 -37
- esphome/zeroconf.py +7 -3
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/METADATA +10 -11
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/RECORD +440 -380
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/WHEEL +1 -1
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/entry_points.txt +0 -0
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/top_level.txt +0 -0
@@ -129,7 +129,7 @@ enum PeriodicDataStructure : uint8_t {
|
|
129
129
|
LIGHT_SENSOR = 37,
|
130
130
|
OUT_PIN_SENSOR = 38,
|
131
131
|
};
|
132
|
-
enum PeriodicDataValue : uint8_t { HEAD =
|
132
|
+
enum PeriodicDataValue : uint8_t { HEAD = 0xAA, END = 0x55, CHECK = 0x00 };
|
133
133
|
|
134
134
|
enum AckDataStructure : uint8_t { COMMAND = 6, COMMAND_STATUS = 7 };
|
135
135
|
|
@@ -105,7 +105,7 @@ enum PeriodicDataStructure : uint8_t {
|
|
105
105
|
TARGET_RESOLUTION = 10,
|
106
106
|
};
|
107
107
|
|
108
|
-
enum PeriodicDataValue : uint8_t { HEAD =
|
108
|
+
enum PeriodicDataValue : uint8_t { HEAD = 0xAA, END = 0x55, CHECK = 0x00 };
|
109
109
|
|
110
110
|
enum AckDataStructure : uint8_t { COMMAND = 6, COMMAND_STATUS = 7 };
|
111
111
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import enum
|
2
|
+
|
1
3
|
import esphome.automation as auto
|
2
4
|
import esphome.codegen as cg
|
3
5
|
from esphome.components import mqtt, power_supply, web_server
|
@@ -13,15 +15,18 @@ from esphome.const import (
|
|
13
15
|
CONF_COLOR_TEMPERATURE,
|
14
16
|
CONF_DEFAULT_TRANSITION_LENGTH,
|
15
17
|
CONF_EFFECTS,
|
18
|
+
CONF_ENTITY_CATEGORY,
|
16
19
|
CONF_FLASH_TRANSITION_LENGTH,
|
17
20
|
CONF_GAMMA_CORRECT,
|
18
21
|
CONF_GREEN,
|
22
|
+
CONF_ICON,
|
19
23
|
CONF_ID,
|
20
24
|
CONF_INITIAL_STATE,
|
21
25
|
CONF_MQTT_ID,
|
22
26
|
CONF_ON_STATE,
|
23
27
|
CONF_ON_TURN_OFF,
|
24
28
|
CONF_ON_TURN_ON,
|
29
|
+
CONF_OUTPUT_ID,
|
25
30
|
CONF_POWER_SUPPLY,
|
26
31
|
CONF_RED,
|
27
32
|
CONF_RESTORE_MODE,
|
@@ -33,6 +38,7 @@ from esphome.const import (
|
|
33
38
|
CONF_WHITE,
|
34
39
|
)
|
35
40
|
from esphome.core import coroutine_with_priority
|
41
|
+
from esphome.cpp_generator import MockObjClass
|
36
42
|
from esphome.cpp_helpers import setup_entity
|
37
43
|
|
38
44
|
from .automation import LIGHT_STATE_SCHEMA
|
@@ -141,6 +147,51 @@ ADDRESSABLE_LIGHT_SCHEMA = RGB_LIGHT_SCHEMA.extend(
|
|
141
147
|
)
|
142
148
|
|
143
149
|
|
150
|
+
class LightType(enum.IntEnum):
|
151
|
+
"""Light type enum."""
|
152
|
+
|
153
|
+
BINARY = 0
|
154
|
+
BRIGHTNESS_ONLY = 1
|
155
|
+
RGB = 2
|
156
|
+
ADDRESSABLE = 3
|
157
|
+
|
158
|
+
|
159
|
+
def light_schema(
|
160
|
+
class_: MockObjClass,
|
161
|
+
type_: LightType,
|
162
|
+
*,
|
163
|
+
entity_category: str = cv.UNDEFINED,
|
164
|
+
icon: str = cv.UNDEFINED,
|
165
|
+
default_restore_mode: str = cv.UNDEFINED,
|
166
|
+
) -> cv.Schema:
|
167
|
+
schema = {
|
168
|
+
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(class_),
|
169
|
+
}
|
170
|
+
|
171
|
+
for key, default, validator in [
|
172
|
+
(CONF_ENTITY_CATEGORY, entity_category, cv.entity_category),
|
173
|
+
(CONF_ICON, icon, cv.icon),
|
174
|
+
(
|
175
|
+
CONF_RESTORE_MODE,
|
176
|
+
default_restore_mode,
|
177
|
+
cv.enum(RESTORE_MODES, upper=True, space="_"),
|
178
|
+
),
|
179
|
+
]:
|
180
|
+
if default is not cv.UNDEFINED:
|
181
|
+
schema[cv.Optional(key, default=default)] = validator
|
182
|
+
|
183
|
+
if type_ == LightType.BINARY:
|
184
|
+
return BINARY_LIGHT_SCHEMA.extend(schema)
|
185
|
+
if type_ == LightType.BRIGHTNESS_ONLY:
|
186
|
+
return BRIGHTNESS_ONLY_LIGHT_SCHEMA.extend(schema)
|
187
|
+
if type_ == LightType.RGB:
|
188
|
+
return RGB_LIGHT_SCHEMA.extend(schema)
|
189
|
+
if type_ == LightType.ADDRESSABLE:
|
190
|
+
return ADDRESSABLE_LIGHT_SCHEMA.extend(schema)
|
191
|
+
|
192
|
+
raise ValueError(f"Invalid light type: {type_}")
|
193
|
+
|
194
|
+
|
144
195
|
def validate_color_temperature_channels(value):
|
145
196
|
if (
|
146
197
|
CONF_COLD_WHITE_COLOR_TEMPERATURE in value
|
@@ -223,6 +274,12 @@ async def register_light(output_var, config):
|
|
223
274
|
await setup_light_core_(light_var, output_var, config)
|
224
275
|
|
225
276
|
|
277
|
+
async def new_light(config, *args):
|
278
|
+
output_var = cg.new_Pvariable(config[CONF_OUTPUT_ID], *args)
|
279
|
+
await register_light(output_var, config)
|
280
|
+
return output_var
|
281
|
+
|
282
|
+
|
226
283
|
@coroutine_with_priority(100.0)
|
227
284
|
async def to_code(config):
|
228
285
|
cg.add_define("USE_LIGHT")
|
@@ -4,6 +4,8 @@ import esphome.codegen as cg
|
|
4
4
|
from esphome.components import mqtt, web_server
|
5
5
|
import esphome.config_validation as cv
|
6
6
|
from esphome.const import (
|
7
|
+
CONF_ENTITY_CATEGORY,
|
8
|
+
CONF_ICON,
|
7
9
|
CONF_ID,
|
8
10
|
CONF_MQTT_ID,
|
9
11
|
CONF_ON_LOCK,
|
@@ -12,6 +14,7 @@ from esphome.const import (
|
|
12
14
|
CONF_WEB_SERVER,
|
13
15
|
)
|
14
16
|
from esphome.core import CORE, coroutine_with_priority
|
17
|
+
from esphome.cpp_generator import MockObjClass
|
15
18
|
from esphome.cpp_helpers import setup_entity
|
16
19
|
|
17
20
|
CODEOWNERS = ["@esphome/core"]
|
@@ -31,7 +34,19 @@ LockCondition = lock_ns.class_("LockCondition", Condition)
|
|
31
34
|
LockLockTrigger = lock_ns.class_("LockLockTrigger", automation.Trigger.template())
|
32
35
|
LockUnlockTrigger = lock_ns.class_("LockUnlockTrigger", automation.Trigger.template())
|
33
36
|
|
34
|
-
|
37
|
+
LockState = lock_ns.enum("LockState")
|
38
|
+
|
39
|
+
LOCK_STATES = {
|
40
|
+
"LOCKED": LockState.LOCK_STATE_LOCKED,
|
41
|
+
"UNLOCKED": LockState.LOCK_STATE_UNLOCKED,
|
42
|
+
"JAMMED": LockState.LOCK_STATE_JAMMED,
|
43
|
+
"LOCKING": LockState.LOCK_STATE_LOCKING,
|
44
|
+
"UNLOCKING": LockState.LOCK_STATE_UNLOCKING,
|
45
|
+
}
|
46
|
+
|
47
|
+
validate_lock_state = cv.enum(LOCK_STATES, upper=True)
|
48
|
+
|
49
|
+
_LOCK_SCHEMA = (
|
35
50
|
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
|
36
51
|
.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
|
37
52
|
.extend(
|
@@ -52,7 +67,33 @@ LOCK_SCHEMA = (
|
|
52
67
|
)
|
53
68
|
|
54
69
|
|
55
|
-
|
70
|
+
def lock_schema(
|
71
|
+
class_: MockObjClass = cv.UNDEFINED,
|
72
|
+
*,
|
73
|
+
icon: str = cv.UNDEFINED,
|
74
|
+
entity_category: str = cv.UNDEFINED,
|
75
|
+
) -> cv.Schema:
|
76
|
+
schema = {}
|
77
|
+
|
78
|
+
if class_ is not cv.UNDEFINED:
|
79
|
+
schema[cv.GenerateID()] = cv.declare_id(class_)
|
80
|
+
|
81
|
+
for key, default, validator in [
|
82
|
+
(CONF_ICON, icon, cv.icon),
|
83
|
+
(CONF_ENTITY_CATEGORY, entity_category, cv.entity_category),
|
84
|
+
]:
|
85
|
+
if default is not cv.UNDEFINED:
|
86
|
+
schema[cv.Optional(key, default=default)] = validator
|
87
|
+
|
88
|
+
return _LOCK_SCHEMA.extend(schema)
|
89
|
+
|
90
|
+
|
91
|
+
# Remove before 2025.11.0
|
92
|
+
LOCK_SCHEMA = lock_schema()
|
93
|
+
LOCK_SCHEMA.add_extra(cv.deprecated_schema_constant("lock"))
|
94
|
+
|
95
|
+
|
96
|
+
async def _setup_lock_core(var, config):
|
56
97
|
await setup_entity(var, config)
|
57
98
|
|
58
99
|
for conf in config.get(CONF_ON_LOCK, []):
|
@@ -74,12 +115,18 @@ async def register_lock(var, config):
|
|
74
115
|
if not CORE.has_id(config[CONF_ID]):
|
75
116
|
var = cg.Pvariable(config[CONF_ID], var)
|
76
117
|
cg.add(cg.App.register_lock(var))
|
77
|
-
await
|
118
|
+
await _setup_lock_core(var, config)
|
119
|
+
|
120
|
+
|
121
|
+
async def new_lock(config, *args):
|
122
|
+
var = cg.new_Pvariable(config[CONF_ID], *args)
|
123
|
+
await register_lock(var, config)
|
124
|
+
return var
|
78
125
|
|
79
126
|
|
80
127
|
LOCK_ACTION_SCHEMA = maybe_simple_id(
|
81
128
|
{
|
82
|
-
cv.
|
129
|
+
cv.GenerateID(CONF_ID): cv.use_id(Lock),
|
83
130
|
}
|
84
131
|
)
|
85
132
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#pragma once
|
2
2
|
|
3
|
-
#include "esphome/core/component.h"
|
4
|
-
#include "esphome/core/automation.h"
|
5
3
|
#include "esphome/components/lock/lock.h"
|
4
|
+
#include "esphome/core/automation.h"
|
5
|
+
#include "esphome/core/component.h"
|
6
6
|
|
7
7
|
namespace esphome {
|
8
8
|
namespace lock {
|
@@ -72,16 +72,5 @@ class LockUnlockTrigger : public Trigger<> {
|
|
72
72
|
}
|
73
73
|
};
|
74
74
|
|
75
|
-
template<typename... Ts> class LockPublishAction : public Action<Ts...> {
|
76
|
-
public:
|
77
|
-
LockPublishAction(Lock *a_lock) : lock_(a_lock) {}
|
78
|
-
TEMPLATABLE_VALUE(LockState, state)
|
79
|
-
|
80
|
-
void play(Ts... x) override { this->lock_->publish_state(this->state_.value(x...)); }
|
81
|
-
|
82
|
-
protected:
|
83
|
-
Lock *lock_;
|
84
|
-
};
|
85
|
-
|
86
75
|
} // namespace lock
|
87
76
|
} // namespace esphome
|
@@ -79,6 +79,7 @@ DEFAULT = "DEFAULT"
|
|
79
79
|
|
80
80
|
CONF_INITIAL_LEVEL = "initial_level"
|
81
81
|
CONF_LOGGER_ID = "logger_id"
|
82
|
+
CONF_TASK_LOG_BUFFER_SIZE = "task_log_buffer_size"
|
82
83
|
|
83
84
|
UART_SELECTION_ESP32 = {
|
84
85
|
VARIANT_ESP32: [UART0, UART1, UART2],
|
@@ -180,6 +181,20 @@ CONFIG_SCHEMA = cv.All(
|
|
180
181
|
cv.Optional(CONF_BAUD_RATE, default=115200): cv.positive_int,
|
181
182
|
cv.Optional(CONF_TX_BUFFER_SIZE, default=512): cv.validate_bytes,
|
182
183
|
cv.Optional(CONF_DEASSERT_RTS_DTR, default=False): cv.boolean,
|
184
|
+
cv.SplitDefault(
|
185
|
+
CONF_TASK_LOG_BUFFER_SIZE,
|
186
|
+
esp32=768, # Default: 768 bytes (~5-6 messages with 70-byte text plus thread names)
|
187
|
+
): cv.All(
|
188
|
+
cv.only_on_esp32,
|
189
|
+
cv.validate_bytes,
|
190
|
+
cv.Any(
|
191
|
+
cv.int_(0), # Disabled
|
192
|
+
cv.int_range(
|
193
|
+
min=640, # Min: ~4-5 messages with 70-byte text plus thread names
|
194
|
+
max=32768, # Max: Depends on message sizes, typically ~300 messages with default size
|
195
|
+
),
|
196
|
+
),
|
197
|
+
),
|
183
198
|
cv.SplitDefault(
|
184
199
|
CONF_HARDWARE_UART,
|
185
200
|
esp8266=UART0,
|
@@ -238,6 +253,13 @@ async def to_code(config):
|
|
238
253
|
baud_rate,
|
239
254
|
config[CONF_TX_BUFFER_SIZE],
|
240
255
|
)
|
256
|
+
if CORE.is_esp32:
|
257
|
+
cg.add(log.create_pthread_key())
|
258
|
+
task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE]
|
259
|
+
if task_log_buffer_size > 0:
|
260
|
+
cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER")
|
261
|
+
cg.add(log.init_log_buffer(task_log_buffer_size))
|
262
|
+
|
241
263
|
cg.add(log.set_log_level(initial_level))
|
242
264
|
if CONF_HARDWARE_UART in config:
|
243
265
|
cg.add(
|
@@ -1,5 +1,8 @@
|
|
1
1
|
#include "logger.h"
|
2
2
|
#include <cinttypes>
|
3
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
4
|
+
#include <memory> // For unique_ptr
|
5
|
+
#endif
|
3
6
|
|
4
7
|
#include "esphome/core/hal.h"
|
5
8
|
#include "esphome/core/log.h"
|
@@ -10,127 +13,132 @@ namespace logger {
|
|
10
13
|
|
11
14
|
static const char *const TAG = "logger";
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
"C", // CONFIG
|
29
|
-
"D", // DEBUG
|
30
|
-
"V", // VERBOSE
|
31
|
-
"VV", // VERY_VERBOSE
|
32
|
-
};
|
33
|
-
|
34
|
-
void Logger::write_header_(int level, const char *tag, int line) {
|
35
|
-
if (level < 0)
|
36
|
-
level = 0;
|
37
|
-
if (level > 7)
|
38
|
-
level = 7;
|
39
|
-
|
40
|
-
const char *color = LOG_LEVEL_COLORS[level];
|
41
|
-
const char *letter = LOG_LEVEL_LETTERS[level];
|
42
|
-
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
16
|
+
#ifdef USE_ESP32
|
17
|
+
// Implementation for ESP32 (multi-task platform with task-specific tracking)
|
18
|
+
// Main task always uses direct buffer access for console output and callbacks
|
19
|
+
//
|
20
|
+
// For non-main tasks:
|
21
|
+
// - WITH task log buffer: Prefer sending to ring buffer for async processing
|
22
|
+
// - Avoids allocating stack memory for console output in normal operation
|
23
|
+
// - Prevents console corruption from concurrent writes by multiple tasks
|
24
|
+
// - Messages are serialized through main loop for proper console output
|
25
|
+
// - Fallback to emergency console logging only if ring buffer is full
|
26
|
+
// - WITHOUT task log buffer: Only emergency console output, no callbacks
|
27
|
+
void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *format, va_list args) { // NOLINT
|
28
|
+
if (level > this->level_for(tag))
|
29
|
+
return;
|
30
|
+
|
43
31
|
TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
if (
|
48
|
-
|
49
|
-
} else {
|
50
|
-
const char *thread_name = ""; // NOLINT(clang-analyzer-deadcode.DeadStores)
|
51
|
-
#if defined(USE_ESP32)
|
52
|
-
thread_name = pcTaskGetName(current_task);
|
53
|
-
#elif defined(USE_LIBRETINY)
|
54
|
-
thread_name = pcTaskGetTaskName(current_task);
|
55
|
-
#endif
|
56
|
-
this->printf_to_buffer_("%s[%s][%s:%03u]%s[%s]%s: ", color, letter, tag, line,
|
57
|
-
ESPHOME_LOG_BOLD(ESPHOME_LOG_COLOR_RED), thread_name, color);
|
32
|
+
bool is_main_task = (current_task == main_task_);
|
33
|
+
|
34
|
+
// Check and set recursion guard - uses pthread TLS for per-task state
|
35
|
+
if (this->check_and_set_task_log_recursion_(is_main_task)) {
|
36
|
+
return; // Recursion detected
|
58
37
|
}
|
59
|
-
}
|
60
38
|
|
39
|
+
// Main task uses the shared buffer for efficiency
|
40
|
+
if (is_main_task) {
|
41
|
+
this->log_message_to_buffer_and_send_(level, tag, line, format, args);
|
42
|
+
this->reset_task_log_recursion_(is_main_task);
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
|
46
|
+
bool message_sent = false;
|
47
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
48
|
+
// For non-main tasks, queue the message for callbacks - but only if we have any callbacks registered
|
49
|
+
message_sent = this->log_buffer_->send_message_thread_safe(static_cast<uint8_t>(level), tag,
|
50
|
+
static_cast<uint16_t>(line), current_task, format, args);
|
51
|
+
#endif // USE_ESPHOME_TASK_LOG_BUFFER
|
52
|
+
|
53
|
+
// Emergency console logging for non-main tasks when ring buffer is full or disabled
|
54
|
+
// This is a fallback mechanism to ensure critical log messages are visible
|
55
|
+
// Note: This may cause interleaved/corrupted console output if multiple tasks
|
56
|
+
// log simultaneously, but it's better than losing important messages entirely
|
57
|
+
if (!message_sent && this->baud_rate_ > 0) { // If logging is enabled, write to console
|
58
|
+
// Maximum size for console log messages (includes null terminator)
|
59
|
+
static const size_t MAX_CONSOLE_LOG_MSG_SIZE = 144;
|
60
|
+
char console_buffer[MAX_CONSOLE_LOG_MSG_SIZE]; // MUST be stack allocated for thread safety
|
61
|
+
int buffer_at = 0; // Initialize buffer position
|
62
|
+
this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, console_buffer, &buffer_at,
|
63
|
+
MAX_CONSOLE_LOG_MSG_SIZE);
|
64
|
+
this->write_msg_(console_buffer);
|
65
|
+
}
|
66
|
+
|
67
|
+
// Reset the recursion guard for this task
|
68
|
+
this->reset_task_log_recursion_(is_main_task);
|
69
|
+
}
|
70
|
+
#else
|
71
|
+
// Implementation for all other platforms
|
61
72
|
void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *format, va_list args) { // NOLINT
|
62
|
-
if (level > this->level_for(tag) ||
|
73
|
+
if (level > this->level_for(tag) || global_recursion_guard_)
|
63
74
|
return;
|
64
75
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
this->
|
69
|
-
|
70
|
-
|
71
|
-
recursion_guard_ = false;
|
76
|
+
global_recursion_guard_ = true;
|
77
|
+
|
78
|
+
// Format and send to both console and callbacks
|
79
|
+
this->log_message_to_buffer_and_send_(level, tag, line, format, args);
|
80
|
+
|
81
|
+
global_recursion_guard_ = false;
|
72
82
|
}
|
83
|
+
#endif // !USE_ESP32
|
84
|
+
|
73
85
|
#ifdef USE_STORE_LOG_STR_IN_FLASH
|
86
|
+
// Implementation for ESP8266 with flash string support.
|
87
|
+
// Note: USE_STORE_LOG_STR_IN_FLASH is only defined for ESP8266.
|
74
88
|
void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStringHelper *format,
|
75
89
|
va_list args) { // NOLINT
|
76
|
-
if (level > this->level_for(tag) ||
|
90
|
+
if (level > this->level_for(tag) || global_recursion_guard_)
|
77
91
|
return;
|
78
92
|
|
79
|
-
|
80
|
-
this->
|
81
|
-
|
93
|
+
global_recursion_guard_ = true;
|
94
|
+
this->tx_buffer_at_ = 0;
|
95
|
+
|
96
|
+
// Copy format string from progmem
|
82
97
|
auto *format_pgm_p = reinterpret_cast<const uint8_t *>(format);
|
83
|
-
size_t len = 0;
|
84
98
|
char ch = '.';
|
85
|
-
while (
|
99
|
+
while (this->tx_buffer_at_ < this->tx_buffer_size_ && ch != '\0') {
|
86
100
|
this->tx_buffer_[this->tx_buffer_at_++] = ch = (char) progmem_read_byte(format_pgm_p++);
|
87
101
|
}
|
88
|
-
|
89
|
-
|
102
|
+
|
103
|
+
// Buffer full from copying format
|
104
|
+
if (this->tx_buffer_at_ >= this->tx_buffer_size_) {
|
105
|
+
global_recursion_guard_ = false; // Make sure to reset the recursion guard before returning
|
90
106
|
return;
|
107
|
+
}
|
108
|
+
|
109
|
+
// Save the offset before calling format_log_to_buffer_with_terminator_
|
110
|
+
// since it will increment tx_buffer_at_ to the end of the formatted string
|
111
|
+
uint32_t msg_start = this->tx_buffer_at_;
|
112
|
+
this->format_log_to_buffer_with_terminator_(level, tag, line, this->tx_buffer_, args, this->tx_buffer_,
|
113
|
+
&this->tx_buffer_at_, this->tx_buffer_size_);
|
91
114
|
|
92
|
-
//
|
93
|
-
|
115
|
+
// Write to console and send callback starting at the msg_start
|
116
|
+
if (this->baud_rate_ > 0) {
|
117
|
+
this->write_msg_(this->tx_buffer_ + msg_start);
|
118
|
+
}
|
119
|
+
this->call_log_callbacks_(level, tag, this->tx_buffer_ + msg_start);
|
94
120
|
|
95
|
-
|
96
|
-
this->write_header_(level, tag, line);
|
97
|
-
this->vprintf_to_buffer_(this->tx_buffer_, args);
|
98
|
-
this->write_footer_();
|
99
|
-
this->log_message_(level, tag, offset);
|
100
|
-
recursion_guard_ = false;
|
121
|
+
global_recursion_guard_ = false;
|
101
122
|
}
|
102
|
-
#endif
|
123
|
+
#endif // USE_STORE_LOG_STR_IN_FLASH
|
103
124
|
|
104
|
-
int
|
105
|
-
|
106
|
-
|
125
|
+
inline int Logger::level_for(const char *tag) {
|
126
|
+
auto it = this->log_levels_.find(tag);
|
127
|
+
if (it != this->log_levels_.end())
|
128
|
+
return it->second;
|
107
129
|
return this->current_level_;
|
108
130
|
}
|
109
131
|
|
110
|
-
void HOT Logger::
|
111
|
-
// remove trailing newline
|
112
|
-
if (this->tx_buffer_[this->tx_buffer_at_ - 1] == '\n') {
|
113
|
-
this->tx_buffer_at_--;
|
114
|
-
}
|
115
|
-
// make sure null terminator is present
|
116
|
-
this->set_null_terminator_();
|
117
|
-
|
118
|
-
const char *msg = this->tx_buffer_ + offset;
|
119
|
-
|
120
|
-
if (this->baud_rate_ > 0) {
|
121
|
-
this->write_msg_(msg);
|
122
|
-
}
|
123
|
-
|
132
|
+
void HOT Logger::call_log_callbacks_(int level, const char *tag, const char *msg) {
|
124
133
|
#ifdef USE_ESP32
|
125
|
-
// Suppress network-logging if memory constrained
|
126
|
-
//
|
134
|
+
// Suppress network-logging if memory constrained
|
135
|
+
// In some configurations (eg BLE enabled) there may be some transient
|
127
136
|
// memory exhaustion, and trying to log when OOM can lead to a crash. Skipping
|
128
137
|
// here usually allows the stack to recover instead.
|
129
138
|
// See issue #1234 for analysis.
|
130
139
|
if (xPortGetFreeHeapSize() < 2048)
|
131
140
|
return;
|
132
141
|
#endif
|
133
|
-
|
134
142
|
this->log_callback_.call(level, tag, msg);
|
135
143
|
}
|
136
144
|
|
@@ -141,21 +149,60 @@ Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate
|
|
141
149
|
this->main_task_ = xTaskGetCurrentTaskHandle();
|
142
150
|
#endif
|
143
151
|
}
|
152
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
153
|
+
void Logger::init_log_buffer(size_t total_buffer_size) {
|
154
|
+
this->log_buffer_ = esphome::make_unique<logger::TaskLogBuffer>(total_buffer_size);
|
155
|
+
}
|
156
|
+
#endif
|
144
157
|
|
145
|
-
#
|
158
|
+
#if defined(USE_LOGGER_USB_CDC) || defined(USE_ESP32)
|
146
159
|
void Logger::loop() {
|
147
|
-
#
|
148
|
-
if (this->uart_
|
149
|
-
|
160
|
+
#if defined(USE_LOGGER_USB_CDC) && defined(USE_ARDUINO)
|
161
|
+
if (this->uart_ == UART_SELECTION_USB_CDC) {
|
162
|
+
static bool opened = false;
|
163
|
+
if (opened == Serial) {
|
164
|
+
return;
|
165
|
+
}
|
166
|
+
if (false == opened) {
|
167
|
+
App.schedule_dump_config();
|
168
|
+
}
|
169
|
+
opened = !opened;
|
150
170
|
}
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
if (
|
156
|
-
|
171
|
+
#endif
|
172
|
+
|
173
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
174
|
+
// Process any buffered messages when available
|
175
|
+
if (this->log_buffer_->has_messages()) {
|
176
|
+
logger::TaskLogBuffer::LogMessage *message;
|
177
|
+
const char *text;
|
178
|
+
void *received_token;
|
179
|
+
|
180
|
+
// Process messages from the buffer
|
181
|
+
while (this->log_buffer_->borrow_message_main_loop(&message, &text, &received_token)) {
|
182
|
+
this->tx_buffer_at_ = 0;
|
183
|
+
// Use the thread name that was stored when the message was created
|
184
|
+
// This avoids potential crashes if the task no longer exists
|
185
|
+
const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr;
|
186
|
+
this->write_header_to_buffer_(message->level, message->tag, message->line, thread_name, this->tx_buffer_,
|
187
|
+
&this->tx_buffer_at_, this->tx_buffer_size_);
|
188
|
+
this->write_body_to_buffer_(text, message->text_length, this->tx_buffer_, &this->tx_buffer_at_,
|
189
|
+
this->tx_buffer_size_);
|
190
|
+
this->write_footer_to_buffer_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_);
|
191
|
+
this->tx_buffer_[this->tx_buffer_at_] = '\0';
|
192
|
+
this->call_log_callbacks_(message->level, message->tag, this->tx_buffer_);
|
193
|
+
// At this point all the data we need from message has been transferred to the tx_buffer
|
194
|
+
// so we can release the message to allow other tasks to use it as soon as possible.
|
195
|
+
this->log_buffer_->release_message_main_loop(received_token);
|
196
|
+
|
197
|
+
// Write to console from the main loop to prevent corruption from concurrent writes
|
198
|
+
// This ensures all log messages appear on the console in a clean, serialized manner
|
199
|
+
// Note: Messages may appear slightly out of order due to async processing, but
|
200
|
+
// this is preferred over corrupted/interleaved console output
|
201
|
+
if (this->baud_rate_ > 0) {
|
202
|
+
this->write_msg_(this->tx_buffer_);
|
203
|
+
}
|
204
|
+
}
|
157
205
|
}
|
158
|
-
opened = !opened;
|
159
206
|
#endif
|
160
207
|
}
|
161
208
|
#endif
|
@@ -171,7 +218,7 @@ void Logger::add_on_log_callback(std::function<void(int, const char *, const cha
|
|
171
218
|
this->log_callback_.add(std::move(callback));
|
172
219
|
}
|
173
220
|
float Logger::get_setup_priority() const { return setup_priority::BUS + 500.0f; }
|
174
|
-
const char *const LOG_LEVELS[] = {"NONE", "ERROR", "WARN", "INFO", "CONFIG", "DEBUG", "VERBOSE", "VERY_VERBOSE"};
|
221
|
+
static const char *const LOG_LEVELS[] = {"NONE", "ERROR", "WARN", "INFO", "CONFIG", "DEBUG", "VERBOSE", "VERY_VERBOSE"};
|
175
222
|
|
176
223
|
void Logger::dump_config() {
|
177
224
|
ESP_LOGCONFIG(TAG, "Logger:");
|
@@ -181,12 +228,16 @@ void Logger::dump_config() {
|
|
181
228
|
ESP_LOGCONFIG(TAG, " Log Baud Rate: %" PRIu32, this->baud_rate_);
|
182
229
|
ESP_LOGCONFIG(TAG, " Hardware UART: %s", get_uart_selection_());
|
183
230
|
#endif
|
231
|
+
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
232
|
+
if (this->log_buffer_) {
|
233
|
+
ESP_LOGCONFIG(TAG, " Task Log Buffer Size: %u", this->log_buffer_->size());
|
234
|
+
}
|
235
|
+
#endif
|
184
236
|
|
185
237
|
for (auto &it : this->log_levels_) {
|
186
238
|
ESP_LOGCONFIG(TAG, " Level for '%s': %s", it.first.c_str(), LOG_LEVELS[it.second]);
|
187
239
|
}
|
188
240
|
}
|
189
|
-
void Logger::write_footer_() { this->write_to_buffer_(ESPHOME_LOG_RESET_COLOR, strlen(ESPHOME_LOG_RESET_COLOR)); }
|
190
241
|
|
191
242
|
void Logger::set_log_level(int level) {
|
192
243
|
if (level > ESPHOME_LOG_LEVEL) {
|