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
@@ -25,6 +25,10 @@ static const uint16_t SEN5X_CMD_TEMPERATURE_COMPENSATION = 0x60B2;
|
|
25
25
|
static const uint16_t SEN5X_CMD_VOC_ALGORITHM_STATE = 0x6181;
|
26
26
|
static const uint16_t SEN5X_CMD_VOC_ALGORITHM_TUNING = 0x60D0;
|
27
27
|
|
28
|
+
static const int8_t SEN5X_INDEX_SCALE_FACTOR = 10; // used for VOC and NOx index values
|
29
|
+
static const int8_t SEN5X_MIN_INDEX_VALUE = 1 * SEN5X_INDEX_SCALE_FACTOR; // must be adjusted by the scale factor
|
30
|
+
static const int16_t SEN5X_MAX_INDEX_VALUE = 500 * SEN5X_INDEX_SCALE_FACTOR; // must be adjusted by the scale factor
|
31
|
+
|
28
32
|
void SEN5XComponent::setup() {
|
29
33
|
ESP_LOGCONFIG(TAG, "Setting up sen5x...");
|
30
34
|
|
@@ -88,8 +92,9 @@ void SEN5XComponent::setup() {
|
|
88
92
|
product_name_.push_back(current_char);
|
89
93
|
// second char
|
90
94
|
current_char = *current_int & 0xFF;
|
91
|
-
if (current_char)
|
95
|
+
if (current_char) {
|
92
96
|
product_name_.push_back(current_char);
|
97
|
+
}
|
93
98
|
}
|
94
99
|
current_int++;
|
95
100
|
} while (current_char && --max);
|
@@ -271,10 +276,10 @@ void SEN5XComponent::dump_config() {
|
|
271
276
|
ESP_LOGCONFIG(TAG, " Low RH/T acceleration mode");
|
272
277
|
break;
|
273
278
|
case MEDIUM_ACCELERATION:
|
274
|
-
ESP_LOGCONFIG(TAG, " Medium RH/T
|
279
|
+
ESP_LOGCONFIG(TAG, " Medium RH/T acceleration mode");
|
275
280
|
break;
|
276
281
|
case HIGH_ACCELERATION:
|
277
|
-
ESP_LOGCONFIG(TAG, " High RH/T
|
282
|
+
ESP_LOGCONFIG(TAG, " High RH/T acceleration mode");
|
278
283
|
break;
|
279
284
|
}
|
280
285
|
}
|
@@ -337,47 +342,61 @@ void SEN5XComponent::update() {
|
|
337
342
|
ESP_LOGD(TAG, "read data error (%d)", this->last_error_);
|
338
343
|
return;
|
339
344
|
}
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
float
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
345
|
+
|
346
|
+
ESP_LOGVV(TAG, "pm_1_0 = 0x%.4x", measurements[0]);
|
347
|
+
float pm_1_0 = measurements[0] == UINT16_MAX ? NAN : measurements[0] / 10.0f;
|
348
|
+
|
349
|
+
ESP_LOGVV(TAG, "pm_2_5 = 0x%.4x", measurements[1]);
|
350
|
+
float pm_2_5 = measurements[1] == UINT16_MAX ? NAN : measurements[1] / 10.0f;
|
351
|
+
|
352
|
+
ESP_LOGVV(TAG, "pm_4_0 = 0x%.4x", measurements[2]);
|
353
|
+
float pm_4_0 = measurements[2] == UINT16_MAX ? NAN : measurements[2] / 10.0f;
|
354
|
+
|
355
|
+
ESP_LOGVV(TAG, "pm_10_0 = 0x%.4x", measurements[3]);
|
356
|
+
float pm_10_0 = measurements[3] == UINT16_MAX ? NAN : measurements[3] / 10.0f;
|
357
|
+
|
358
|
+
ESP_LOGVV(TAG, "humidity = 0x%.4x", measurements[4]);
|
359
|
+
float humidity = measurements[4] == INT16_MAX ? NAN : static_cast<int16_t>(measurements[4]) / 100.0f;
|
360
|
+
|
361
|
+
ESP_LOGVV(TAG, "temperature = 0x%.4x", measurements[5]);
|
362
|
+
float temperature = measurements[5] == INT16_MAX ? NAN : static_cast<int16_t>(measurements[5]) / 200.0f;
|
363
|
+
|
364
|
+
ESP_LOGVV(TAG, "voc = 0x%.4x", measurements[6]);
|
365
|
+
int16_t voc_idx = static_cast<int16_t>(measurements[6]);
|
366
|
+
float voc = (voc_idx < SEN5X_MIN_INDEX_VALUE || voc_idx > SEN5X_MAX_INDEX_VALUE)
|
367
|
+
? NAN
|
368
|
+
: static_cast<float>(voc_idx) / 10.0f;
|
369
|
+
|
370
|
+
ESP_LOGVV(TAG, "nox = 0x%.4x", measurements[7]);
|
371
|
+
int16_t nox_idx = static_cast<int16_t>(measurements[7]);
|
372
|
+
float nox = (nox_idx < SEN5X_MIN_INDEX_VALUE || nox_idx > SEN5X_MAX_INDEX_VALUE)
|
373
|
+
? NAN
|
374
|
+
: static_cast<float>(nox_idx) / 10.0f;
|
375
|
+
|
376
|
+
if (this->pm_1_0_sensor_ != nullptr) {
|
366
377
|
this->pm_1_0_sensor_->publish_state(pm_1_0);
|
367
|
-
|
378
|
+
}
|
379
|
+
if (this->pm_2_5_sensor_ != nullptr) {
|
368
380
|
this->pm_2_5_sensor_->publish_state(pm_2_5);
|
369
|
-
|
381
|
+
}
|
382
|
+
if (this->pm_4_0_sensor_ != nullptr) {
|
370
383
|
this->pm_4_0_sensor_->publish_state(pm_4_0);
|
371
|
-
|
384
|
+
}
|
385
|
+
if (this->pm_10_0_sensor_ != nullptr) {
|
372
386
|
this->pm_10_0_sensor_->publish_state(pm_10_0);
|
373
|
-
|
387
|
+
}
|
388
|
+
if (this->temperature_sensor_ != nullptr) {
|
374
389
|
this->temperature_sensor_->publish_state(temperature);
|
375
|
-
|
390
|
+
}
|
391
|
+
if (this->humidity_sensor_ != nullptr) {
|
376
392
|
this->humidity_sensor_->publish_state(humidity);
|
377
|
-
|
393
|
+
}
|
394
|
+
if (this->voc_sensor_ != nullptr) {
|
378
395
|
this->voc_sensor_->publish_state(voc);
|
379
|
-
|
396
|
+
}
|
397
|
+
if (this->nox_sensor_ != nullptr) {
|
380
398
|
this->nox_sensor_->publish_state(nox);
|
399
|
+
}
|
381
400
|
this->status_clear_warning();
|
382
401
|
});
|
383
402
|
}
|
@@ -4,6 +4,7 @@ import esphome.codegen as cg
|
|
4
4
|
from esphome.components import i2c, sensirion_common, sensor
|
5
5
|
import esphome.config_validation as cv
|
6
6
|
from esphome.const import (
|
7
|
+
CONF_GAIN_FACTOR,
|
7
8
|
CONF_HUMIDITY,
|
8
9
|
CONF_ID,
|
9
10
|
CONF_OFFSET,
|
@@ -43,7 +44,6 @@ RhtAccelerationMode = sen5x_ns.enum("RhtAccelerationMode")
|
|
43
44
|
CONF_ACCELERATION_MODE = "acceleration_mode"
|
44
45
|
CONF_ALGORITHM_TUNING = "algorithm_tuning"
|
45
46
|
CONF_AUTO_CLEANING_INTERVAL = "auto_cleaning_interval"
|
46
|
-
CONF_GAIN_FACTOR = "gain_factor"
|
47
47
|
CONF_GATING_MAX_DURATION_MINUTES = "gating_max_duration_minutes"
|
48
48
|
CONF_INDEX_OFFSET = "index_offset"
|
49
49
|
CONF_LEARNING_TIME_GAIN_HOURS = "learning_time_gain_hours"
|
@@ -38,7 +38,7 @@ CONFIG_SCHEMA = (
|
|
38
38
|
cv.Schema(
|
39
39
|
{
|
40
40
|
cv.GenerateID(): cv.declare_id(SenseAirComponent),
|
41
|
-
cv.
|
41
|
+
cv.Optional(CONF_CO2): sensor.sensor_schema(
|
42
42
|
unit_of_measurement=UNIT_PARTS_PER_MILLION,
|
43
43
|
icon=ICON_MOLECULE_CO2,
|
44
44
|
accuracy_decimals=0,
|
@@ -57,8 +57,8 @@ async def to_code(config):
|
|
57
57
|
await cg.register_component(var, config)
|
58
58
|
await uart.register_uart_device(var, config)
|
59
59
|
|
60
|
-
if
|
61
|
-
sens = await sensor.new_sensor(
|
60
|
+
if co2 := config.get(CONF_CO2):
|
61
|
+
sens = await sensor.new_sensor(co2)
|
62
62
|
cg.add(var.set_co2_sensor(sens))
|
63
63
|
|
64
64
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import logging
|
1
2
|
import math
|
2
3
|
|
3
4
|
from esphome import automation
|
@@ -9,6 +10,7 @@ from esphome.const import (
|
|
9
10
|
CONF_ACCURACY_DECIMALS,
|
10
11
|
CONF_ALPHA,
|
11
12
|
CONF_BELOW,
|
13
|
+
CONF_CALIBRATION,
|
12
14
|
CONF_DEVICE_CLASS,
|
13
15
|
CONF_ENTITY_CATEGORY,
|
14
16
|
CONF_EXPIRE_AFTER,
|
@@ -30,6 +32,7 @@ from esphome.const import (
|
|
30
32
|
CONF_SEND_EVERY,
|
31
33
|
CONF_SEND_FIRST_AT,
|
32
34
|
CONF_STATE_CLASS,
|
35
|
+
CONF_TEMPERATURE,
|
33
36
|
CONF_TIMEOUT,
|
34
37
|
CONF_TO,
|
35
38
|
CONF_TRIGGER_ID,
|
@@ -153,6 +156,8 @@ DEVICE_CLASSES = [
|
|
153
156
|
DEVICE_CLASS_WIND_SPEED,
|
154
157
|
]
|
155
158
|
|
159
|
+
_LOGGER = logging.getLogger(__name__)
|
160
|
+
|
156
161
|
sensor_ns = cg.esphome_ns.namespace("sensor")
|
157
162
|
StateClasses = sensor_ns.enum("StateClass")
|
158
163
|
STATE_CLASSES = {
|
@@ -246,6 +251,8 @@ HeartbeatFilter = sensor_ns.class_("HeartbeatFilter", Filter, cg.Component)
|
|
246
251
|
DeltaFilter = sensor_ns.class_("DeltaFilter", Filter)
|
247
252
|
OrFilter = sensor_ns.class_("OrFilter", Filter)
|
248
253
|
CalibrateLinearFilter = sensor_ns.class_("CalibrateLinearFilter", Filter)
|
254
|
+
ToNTCResistanceFilter = sensor_ns.class_("ToNTCResistanceFilter", Filter)
|
255
|
+
ToNTCTemperatureFilter = sensor_ns.class_("ToNTCTemperatureFilter", Filter)
|
249
256
|
CalibratePolynomialFilter = sensor_ns.class_("CalibratePolynomialFilter", Filter)
|
250
257
|
SensorInRangeCondition = sensor_ns.class_("SensorInRangeCondition", Filter)
|
251
258
|
ClampFilter = sensor_ns.class_("ClampFilter", Filter)
|
@@ -257,7 +264,7 @@ validate_accuracy_decimals = cv.int_
|
|
257
264
|
validate_icon = cv.icon
|
258
265
|
validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
|
259
266
|
|
260
|
-
|
267
|
+
_SENSOR_SCHEMA = (
|
261
268
|
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
|
262
269
|
.extend(cv.MQTT_COMPONENT_SCHEMA)
|
263
270
|
.extend(
|
@@ -302,22 +309,20 @@ SENSOR_SCHEMA = (
|
|
302
309
|
)
|
303
310
|
)
|
304
311
|
|
305
|
-
_UNDEF = object()
|
306
|
-
|
307
312
|
|
308
313
|
def sensor_schema(
|
309
|
-
class_: MockObjClass =
|
314
|
+
class_: MockObjClass = cv.UNDEFINED,
|
310
315
|
*,
|
311
|
-
unit_of_measurement: str =
|
312
|
-
icon: str =
|
313
|
-
accuracy_decimals: int =
|
314
|
-
device_class: str =
|
315
|
-
state_class: str =
|
316
|
-
entity_category: str =
|
316
|
+
unit_of_measurement: str = cv.UNDEFINED,
|
317
|
+
icon: str = cv.UNDEFINED,
|
318
|
+
accuracy_decimals: int = cv.UNDEFINED,
|
319
|
+
device_class: str = cv.UNDEFINED,
|
320
|
+
state_class: str = cv.UNDEFINED,
|
321
|
+
entity_category: str = cv.UNDEFINED,
|
317
322
|
) -> cv.Schema:
|
318
323
|
schema = {}
|
319
324
|
|
320
|
-
if class_ is not
|
325
|
+
if class_ is not cv.UNDEFINED:
|
321
326
|
# Not optional.
|
322
327
|
schema[cv.GenerateID()] = cv.declare_id(class_)
|
323
328
|
|
@@ -329,10 +334,15 @@ def sensor_schema(
|
|
329
334
|
(CONF_STATE_CLASS, state_class, validate_state_class),
|
330
335
|
(CONF_ENTITY_CATEGORY, entity_category, sensor_entity_category),
|
331
336
|
]:
|
332
|
-
if default is not
|
337
|
+
if default is not cv.UNDEFINED:
|
333
338
|
schema[cv.Optional(key, default=default)] = validator
|
334
339
|
|
335
|
-
return
|
340
|
+
return _SENSOR_SCHEMA.extend(schema)
|
341
|
+
|
342
|
+
|
343
|
+
# Remove before 2025.11.0
|
344
|
+
SENSOR_SCHEMA = sensor_schema()
|
345
|
+
SENSOR_SCHEMA.add_extra(cv.deprecated_schema_constant("sensor"))
|
336
346
|
|
337
347
|
|
338
348
|
@FILTER_REGISTRY.register("offset", OffsetFilter, cv.templatable(cv.float_))
|
@@ -804,7 +814,9 @@ async def setup_sensor_core_(var, config):
|
|
804
814
|
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
805
815
|
await mqtt.register_mqtt_component(mqtt_, config)
|
806
816
|
|
807
|
-
if (
|
817
|
+
if (
|
818
|
+
expire_after := config.get(CONF_EXPIRE_AFTER, cv.UNDEFINED)
|
819
|
+
) is not cv.UNDEFINED:
|
808
820
|
if expire_after is None:
|
809
821
|
cg.add(mqtt_.disable_expire_after())
|
810
822
|
else:
|
@@ -852,6 +864,138 @@ async def sensor_in_range_to_code(config, condition_id, template_arg, args):
|
|
852
864
|
return var
|
853
865
|
|
854
866
|
|
867
|
+
def validate_ntc_calibration_parameter(value):
|
868
|
+
if isinstance(value, dict):
|
869
|
+
return cv.Schema(
|
870
|
+
{
|
871
|
+
cv.Required(CONF_TEMPERATURE): cv.temperature,
|
872
|
+
cv.Required(CONF_VALUE): cv.resistance,
|
873
|
+
}
|
874
|
+
)(value)
|
875
|
+
|
876
|
+
value = cv.string(value)
|
877
|
+
parts = value.split("->")
|
878
|
+
if len(parts) != 2:
|
879
|
+
raise cv.Invalid("Calibration parameter must be of form 3000 -> 23°C")
|
880
|
+
resistance = cv.resistance(parts[0].strip())
|
881
|
+
temperature = cv.temperature(parts[1].strip())
|
882
|
+
return validate_ntc_calibration_parameter(
|
883
|
+
{
|
884
|
+
CONF_TEMPERATURE: temperature,
|
885
|
+
CONF_VALUE: resistance,
|
886
|
+
}
|
887
|
+
)
|
888
|
+
|
889
|
+
|
890
|
+
CONF_A = "a"
|
891
|
+
CONF_B = "b"
|
892
|
+
CONF_C = "c"
|
893
|
+
ZERO_POINT = 273.15
|
894
|
+
|
895
|
+
|
896
|
+
def ntc_calc_steinhart_hart(value):
|
897
|
+
r1 = value[0][CONF_VALUE]
|
898
|
+
r2 = value[1][CONF_VALUE]
|
899
|
+
r3 = value[2][CONF_VALUE]
|
900
|
+
t1 = value[0][CONF_TEMPERATURE] + ZERO_POINT
|
901
|
+
t2 = value[1][CONF_TEMPERATURE] + ZERO_POINT
|
902
|
+
t3 = value[2][CONF_TEMPERATURE] + ZERO_POINT
|
903
|
+
|
904
|
+
l1 = math.log(r1)
|
905
|
+
l2 = math.log(r2)
|
906
|
+
l3 = math.log(r3)
|
907
|
+
|
908
|
+
y1 = 1 / t1
|
909
|
+
y2 = 1 / t2
|
910
|
+
y3 = 1 / t3
|
911
|
+
|
912
|
+
g2 = (y2 - y1) / (l2 - l1)
|
913
|
+
g3 = (y3 - y1) / (l3 - l1)
|
914
|
+
|
915
|
+
c = (g3 - g2) / (l3 - l2) * 1 / (l1 + l2 + l3)
|
916
|
+
b = g2 - c * (l1 * l1 + l1 * l2 + l2 * l2)
|
917
|
+
a = y1 - (b + l1 * l1 * c) * l1
|
918
|
+
return a, b, c
|
919
|
+
|
920
|
+
|
921
|
+
def ntc_get_abc(value):
|
922
|
+
a = value[CONF_A]
|
923
|
+
b = value[CONF_B]
|
924
|
+
c = value[CONF_C]
|
925
|
+
return a, b, c
|
926
|
+
|
927
|
+
|
928
|
+
def ntc_process_calibration(value):
|
929
|
+
if isinstance(value, dict):
|
930
|
+
value = cv.Schema(
|
931
|
+
{
|
932
|
+
cv.Required(CONF_A): cv.float_,
|
933
|
+
cv.Required(CONF_B): cv.float_,
|
934
|
+
cv.Required(CONF_C): cv.float_,
|
935
|
+
}
|
936
|
+
)(value)
|
937
|
+
a, b, c = ntc_get_abc(value)
|
938
|
+
elif isinstance(value, list):
|
939
|
+
if len(value) != 3:
|
940
|
+
raise cv.Invalid(
|
941
|
+
"Steinhart–Hart Calibration must consist of exactly three values"
|
942
|
+
)
|
943
|
+
value = cv.Schema([validate_ntc_calibration_parameter])(value)
|
944
|
+
a, b, c = ntc_calc_steinhart_hart(value)
|
945
|
+
else:
|
946
|
+
raise cv.Invalid(
|
947
|
+
f"Calibration parameter accepts either a list for steinhart-hart calibration, or mapping for b-constant calibration, not {type(value)}"
|
948
|
+
)
|
949
|
+
_LOGGER.info("Coefficient: a:%s, b:%s, c:%s", a, b, c)
|
950
|
+
return {
|
951
|
+
CONF_A: a,
|
952
|
+
CONF_B: b,
|
953
|
+
CONF_C: c,
|
954
|
+
}
|
955
|
+
|
956
|
+
|
957
|
+
@FILTER_REGISTRY.register(
|
958
|
+
"to_ntc_resistance",
|
959
|
+
ToNTCResistanceFilter,
|
960
|
+
cv.All(
|
961
|
+
cv.Schema(
|
962
|
+
{
|
963
|
+
cv.Required(CONF_CALIBRATION): ntc_process_calibration,
|
964
|
+
}
|
965
|
+
),
|
966
|
+
),
|
967
|
+
)
|
968
|
+
async def calibrate_ntc_resistance_filter_to_code(config, filter_id):
|
969
|
+
calib = config[CONF_CALIBRATION]
|
970
|
+
return cg.new_Pvariable(
|
971
|
+
filter_id,
|
972
|
+
calib[CONF_A],
|
973
|
+
calib[CONF_B],
|
974
|
+
calib[CONF_C],
|
975
|
+
)
|
976
|
+
|
977
|
+
|
978
|
+
@FILTER_REGISTRY.register(
|
979
|
+
"to_ntc_temperature",
|
980
|
+
ToNTCTemperatureFilter,
|
981
|
+
cv.All(
|
982
|
+
cv.Schema(
|
983
|
+
{
|
984
|
+
cv.Required(CONF_CALIBRATION): ntc_process_calibration,
|
985
|
+
}
|
986
|
+
),
|
987
|
+
),
|
988
|
+
)
|
989
|
+
async def calibrate_ntc_temperature_filter_to_code(config, filter_id):
|
990
|
+
calib = config[CONF_CALIBRATION]
|
991
|
+
return cg.new_Pvariable(
|
992
|
+
filter_id,
|
993
|
+
calib[CONF_A],
|
994
|
+
calib[CONF_B],
|
995
|
+
calib[CONF_C],
|
996
|
+
)
|
997
|
+
|
998
|
+
|
855
999
|
def _mean(xs):
|
856
1000
|
return sum(xs) / len(xs)
|
857
1001
|
|
@@ -481,5 +481,28 @@ optional<float> RoundMultipleFilter::new_value(float value) {
|
|
481
481
|
return value;
|
482
482
|
}
|
483
483
|
|
484
|
+
optional<float> ToNTCResistanceFilter::new_value(float value) {
|
485
|
+
if (!std::isfinite(value)) {
|
486
|
+
return NAN;
|
487
|
+
}
|
488
|
+
double k = 273.15;
|
489
|
+
// https://de.wikipedia.org/wiki/Steinhart-Hart-Gleichung#cite_note-stein2_s4-3
|
490
|
+
double t = value + k;
|
491
|
+
double y = (this->a_ - 1 / (t)) / (2 * this->c_);
|
492
|
+
double x = sqrt(pow(this->b_ / (3 * this->c_), 3) + y * y);
|
493
|
+
double resistance = exp(pow(x - y, 1 / 3.0) - pow(x + y, 1 / 3.0));
|
494
|
+
return resistance;
|
495
|
+
}
|
496
|
+
|
497
|
+
optional<float> ToNTCTemperatureFilter::new_value(float value) {
|
498
|
+
if (!std::isfinite(value)) {
|
499
|
+
return NAN;
|
500
|
+
}
|
501
|
+
double lr = log(double(value));
|
502
|
+
double v = this->a_ + this->b_ * lr + this->c_ * lr * lr * lr;
|
503
|
+
double temp = float(1.0 / v - 273.15);
|
504
|
+
return temp;
|
505
|
+
}
|
506
|
+
|
484
507
|
} // namespace sensor
|
485
508
|
} // namespace esphome
|
@@ -439,5 +439,27 @@ class RoundMultipleFilter : public Filter {
|
|
439
439
|
float multiple_;
|
440
440
|
};
|
441
441
|
|
442
|
+
class ToNTCResistanceFilter : public Filter {
|
443
|
+
public:
|
444
|
+
ToNTCResistanceFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
|
445
|
+
optional<float> new_value(float value) override;
|
446
|
+
|
447
|
+
protected:
|
448
|
+
double a_;
|
449
|
+
double b_;
|
450
|
+
double c_;
|
451
|
+
};
|
452
|
+
|
453
|
+
class ToNTCTemperatureFilter : public Filter {
|
454
|
+
public:
|
455
|
+
ToNTCTemperatureFilter(double a, double b, double c) : a_(a), b_(b), c_(c) {}
|
456
|
+
optional<float> new_value(float value) override;
|
457
|
+
|
458
|
+
protected:
|
459
|
+
double a_;
|
460
|
+
double b_;
|
461
|
+
double c_;
|
462
|
+
};
|
463
|
+
|
442
464
|
} // namespace sensor
|
443
465
|
} // namespace esphome
|
@@ -37,14 +37,14 @@ CONFIG_SCHEMA = (
|
|
37
37
|
cv.Schema(
|
38
38
|
{
|
39
39
|
cv.GenerateID(): cv.declare_id(SGP30Component),
|
40
|
-
cv.
|
40
|
+
cv.Optional(CONF_ECO2): sensor.sensor_schema(
|
41
41
|
unit_of_measurement=UNIT_PARTS_PER_MILLION,
|
42
42
|
icon=ICON_MOLECULE_CO2,
|
43
43
|
accuracy_decimals=0,
|
44
44
|
device_class=DEVICE_CLASS_CARBON_DIOXIDE,
|
45
45
|
state_class=STATE_CLASS_MEASUREMENT,
|
46
46
|
),
|
47
|
-
cv.
|
47
|
+
cv.Optional(CONF_TVOC): sensor.sensor_schema(
|
48
48
|
unit_of_measurement=UNIT_PARTS_PER_BILLION,
|
49
49
|
icon=ICON_RADIATOR,
|
50
50
|
accuracy_decimals=0,
|
@@ -86,32 +86,30 @@ async def to_code(config):
|
|
86
86
|
await cg.register_component(var, config)
|
87
87
|
await i2c.register_i2c_device(var, config)
|
88
88
|
|
89
|
-
if
|
90
|
-
sens = await sensor.new_sensor(
|
89
|
+
if eco2_config := config.get(CONF_ECO2):
|
90
|
+
sens = await sensor.new_sensor(eco2_config)
|
91
91
|
cg.add(var.set_eco2_sensor(sens))
|
92
92
|
|
93
|
-
if
|
94
|
-
sens = await sensor.new_sensor(
|
93
|
+
if tvoc_config := config.get(CONF_TVOC):
|
94
|
+
sens = await sensor.new_sensor(tvoc_config)
|
95
95
|
cg.add(var.set_tvoc_sensor(sens))
|
96
96
|
|
97
|
-
if
|
98
|
-
sens = await sensor.new_sensor(
|
97
|
+
if eco2_baseline_config := config.get(CONF_ECO2_BASELINE):
|
98
|
+
sens = await sensor.new_sensor(eco2_baseline_config)
|
99
99
|
cg.add(var.set_eco2_baseline_sensor(sens))
|
100
100
|
|
101
|
-
if
|
102
|
-
sens = await sensor.new_sensor(
|
101
|
+
if tvoc_baseline_config := config.get(CONF_TVOC_BASELINE):
|
102
|
+
sens = await sensor.new_sensor(tvoc_baseline_config)
|
103
103
|
cg.add(var.set_tvoc_baseline_sensor(sens))
|
104
104
|
|
105
|
-
if CONF_STORE_BASELINE
|
106
|
-
cg.add(var.set_store_baseline(
|
105
|
+
if (store_baseline := config.get(CONF_STORE_BASELINE)) is not None:
|
106
|
+
cg.add(var.set_store_baseline(store_baseline))
|
107
107
|
|
108
|
-
if
|
109
|
-
baseline_config = config[CONF_BASELINE]
|
108
|
+
if baseline_config := config.get(CONF_BASELINE):
|
110
109
|
cg.add(var.set_eco2_baseline(baseline_config[CONF_ECO2_BASELINE]))
|
111
110
|
cg.add(var.set_tvoc_baseline(baseline_config[CONF_TVOC_BASELINE]))
|
112
111
|
|
113
|
-
if
|
114
|
-
compensation_config = config[CONF_COMPENSATION]
|
112
|
+
if compensation_config := config.get(CONF_COMPENSATION):
|
115
113
|
sens = await cg.get_variable(compensation_config[CONF_HUMIDITY_SOURCE])
|
116
114
|
cg.add(var.set_humidity_sensor(sens))
|
117
115
|
sens = await cg.get_variable(compensation_config[CONF_TEMPERATURE_SOURCE])
|
@@ -3,6 +3,7 @@ from esphome.components import i2c, sensirion_common, sensor
|
|
3
3
|
import esphome.config_validation as cv
|
4
4
|
from esphome.const import (
|
5
5
|
CONF_COMPENSATION,
|
6
|
+
CONF_GAIN_FACTOR,
|
6
7
|
CONF_ID,
|
7
8
|
CONF_STORE_BASELINE,
|
8
9
|
CONF_TEMPERATURE_SOURCE,
|
@@ -24,7 +25,6 @@ SGP4xComponent = sgp4x_ns.class_(
|
|
24
25
|
)
|
25
26
|
|
26
27
|
CONF_ALGORITHM_TUNING = "algorithm_tuning"
|
27
|
-
CONF_GAIN_FACTOR = "gain_factor"
|
28
28
|
CONF_GATING_MAX_DURATION_MINUTES = "gating_max_duration_minutes"
|
29
29
|
CONF_HUMIDITY_SOURCE = "humidity_source"
|
30
30
|
CONF_INDEX_OFFSET = "index_offset"
|
@@ -12,14 +12,22 @@ void SHT4XComponent::start_heater_() {
|
|
12
12
|
uint8_t cmd[] = {MEASURECOMMANDS[this->heater_command_]};
|
13
13
|
|
14
14
|
ESP_LOGD(TAG, "Heater turning on");
|
15
|
-
this->write(cmd, 1)
|
15
|
+
if (this->write(cmd, 1) != i2c::ERROR_OK) {
|
16
|
+
this->status_set_error("Failed to turn on heater");
|
17
|
+
}
|
16
18
|
}
|
17
19
|
|
18
20
|
void SHT4XComponent::setup() {
|
19
21
|
ESP_LOGCONFIG(TAG, "Setting up sht4x...");
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
+
auto err = this->write(nullptr, 0);
|
24
|
+
if (err != i2c::ERROR_OK) {
|
25
|
+
this->mark_failed();
|
26
|
+
return;
|
27
|
+
}
|
28
|
+
|
29
|
+
if (std::isfinite(this->duty_cycle_) && this->duty_cycle_ > 0.0f) {
|
30
|
+
uint32_t heater_interval = static_cast<uint32_t>(static_cast<uint16_t>(this->heater_time_) / this->duty_cycle_);
|
23
31
|
ESP_LOGD(TAG, "Heater interval: %" PRIu32, heater_interval);
|
24
32
|
|
25
33
|
if (this->heater_power_ == SHT4X_HEATERPOWER_HIGH) {
|
@@ -47,37 +55,50 @@ void SHT4XComponent::setup() {
|
|
47
55
|
}
|
48
56
|
}
|
49
57
|
|
50
|
-
void SHT4XComponent::dump_config() {
|
58
|
+
void SHT4XComponent::dump_config() {
|
59
|
+
ESP_LOGCONFIG(TAG, "SHT4x:");
|
60
|
+
LOG_I2C_DEVICE(this);
|
61
|
+
if (this->is_failed()) {
|
62
|
+
ESP_LOGE(TAG, "Communication with SHT4x failed!");
|
63
|
+
}
|
64
|
+
}
|
51
65
|
|
52
66
|
void SHT4XComponent::update() {
|
53
67
|
// Send command
|
54
|
-
this->write_command(MEASURECOMMANDS[this->precision_])
|
68
|
+
if (!this->write_command(MEASURECOMMANDS[this->precision_])) {
|
69
|
+
// Warning will be printed only if warning status is not set yet
|
70
|
+
this->status_set_warning("Failed to send measurement command");
|
71
|
+
return;
|
72
|
+
}
|
55
73
|
|
56
74
|
this->set_timeout(10, [this]() {
|
57
75
|
uint16_t buffer[2];
|
58
76
|
|
59
77
|
// Read measurement
|
60
|
-
|
78
|
+
if (!this->read_data(buffer, 2)) {
|
79
|
+
// Using ESP_LOGW to force the warning to be printed
|
80
|
+
ESP_LOGW(TAG, "Sensor read failed");
|
81
|
+
this->status_set_warning();
|
82
|
+
return;
|
83
|
+
}
|
61
84
|
|
62
|
-
|
63
|
-
// Evaluate and publish measurements
|
64
|
-
if (this->temp_sensor_ != nullptr) {
|
65
|
-
// Temp is contained in the first result word
|
66
|
-
float sensor_value_temp = buffer[0];
|
67
|
-
float temp = -45 + 175 * sensor_value_temp / 65535;
|
85
|
+
this->status_clear_warning();
|
68
86
|
|
69
|
-
|
70
|
-
|
87
|
+
// Evaluate and publish measurements
|
88
|
+
if (this->temp_sensor_ != nullptr) {
|
89
|
+
// Temp is contained in the first result word
|
90
|
+
float sensor_value_temp = buffer[0];
|
91
|
+
float temp = -45 + 175 * sensor_value_temp / 65535;
|
92
|
+
|
93
|
+
this->temp_sensor_->publish_state(temp);
|
94
|
+
}
|
71
95
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
96
|
+
if (this->humidity_sensor_ != nullptr) {
|
97
|
+
// Relative humidity is in the second result word
|
98
|
+
float sensor_value_rh = buffer[1];
|
99
|
+
float rh = -6 + 125 * sensor_value_rh / 65535;
|
76
100
|
|
77
|
-
|
78
|
-
}
|
79
|
-
} else {
|
80
|
-
ESP_LOGD(TAG, "Sensor read failed");
|
101
|
+
this->humidity_sensor_->publish_state(rh);
|
81
102
|
}
|
82
103
|
});
|
83
104
|
}
|
esphome/components/sht4x/sht4x.h
CHANGED
@@ -13,7 +13,7 @@ enum SHT4XPRECISION { SHT4X_PRECISION_HIGH = 0, SHT4X_PRECISION_MED, SHT4X_PRECI
|
|
13
13
|
|
14
14
|
enum SHT4XHEATERPOWER { SHT4X_HEATERPOWER_HIGH, SHT4X_HEATERPOWER_MED, SHT4X_HEATERPOWER_LOW };
|
15
15
|
|
16
|
-
enum SHT4XHEATERTIME { SHT4X_HEATERTIME_LONG = 1100, SHT4X_HEATERTIME_SHORT = 110 };
|
16
|
+
enum SHT4XHEATERTIME : uint16_t { SHT4X_HEATERTIME_LONG = 1100, SHT4X_HEATERTIME_SHORT = 110 };
|
17
17
|
|
18
18
|
class SHT4XComponent : public PollingComponent, public sensirion_common::SensirionI2CDevice {
|
19
19
|
public:
|