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
@@ -1,7 +1,12 @@
|
|
1
1
|
import esphome.codegen as cg
|
2
2
|
from esphome.components import select
|
3
3
|
import esphome.config_validation as cv
|
4
|
-
from esphome.const import
|
4
|
+
from esphome.const import (
|
5
|
+
CONF_ENUM_DATAPOINT,
|
6
|
+
CONF_INT_DATAPOINT,
|
7
|
+
CONF_OPTIMISTIC,
|
8
|
+
CONF_OPTIONS,
|
9
|
+
)
|
5
10
|
|
6
11
|
from .. import CONF_TUYA_ID, Tuya, tuya_ns
|
7
12
|
|
@@ -26,17 +31,19 @@ def ensure_option_map(value):
|
|
26
31
|
return value
|
27
32
|
|
28
33
|
|
29
|
-
CONFIG_SCHEMA = (
|
34
|
+
CONFIG_SCHEMA = cv.All(
|
30
35
|
select.select_schema(TuyaSelect)
|
31
36
|
.extend(
|
32
37
|
{
|
33
38
|
cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya),
|
34
|
-
cv.
|
39
|
+
cv.Optional(CONF_ENUM_DATAPOINT): cv.uint8_t,
|
40
|
+
cv.Optional(CONF_INT_DATAPOINT): cv.uint8_t,
|
35
41
|
cv.Required(CONF_OPTIONS): ensure_option_map,
|
36
42
|
cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
37
43
|
}
|
38
44
|
)
|
39
|
-
.extend(cv.COMPONENT_SCHEMA)
|
45
|
+
.extend(cv.COMPONENT_SCHEMA),
|
46
|
+
cv.has_exactly_one_key(CONF_ENUM_DATAPOINT, CONF_INT_DATAPOINT),
|
40
47
|
)
|
41
48
|
|
42
49
|
|
@@ -47,5 +54,8 @@ async def to_code(config):
|
|
47
54
|
cg.add(var.set_select_mappings(list(options_map.keys())))
|
48
55
|
parent = await cg.get_variable(config[CONF_TUYA_ID])
|
49
56
|
cg.add(var.set_tuya_parent(parent))
|
50
|
-
|
57
|
+
if enum_datapoint := config.get(CONF_ENUM_DATAPOINT, None) is not None:
|
58
|
+
cg.add(var.set_select_id(enum_datapoint, False))
|
59
|
+
if int_datapoint := config.get(CONF_INT_DATAPOINT, None) is not None:
|
60
|
+
cg.add(var.set_select_id(int_datapoint, True))
|
51
61
|
cg.add(var.set_optimistic(config[CONF_OPTIMISTIC]))
|
@@ -31,7 +31,11 @@ void TuyaSelect::control(const std::string &value) {
|
|
31
31
|
if (idx.has_value()) {
|
32
32
|
uint8_t mapping = this->mappings_.at(idx.value());
|
33
33
|
ESP_LOGV(TAG, "Setting %u datapoint value to %u:%s", this->select_id_, mapping, value.c_str());
|
34
|
-
|
34
|
+
if (this->is_int_) {
|
35
|
+
this->parent_->set_integer_datapoint_value(this->select_id_, mapping);
|
36
|
+
} else {
|
37
|
+
this->parent_->set_enum_datapoint_value(this->select_id_, mapping);
|
38
|
+
}
|
35
39
|
return;
|
36
40
|
}
|
37
41
|
|
@@ -41,6 +45,7 @@ void TuyaSelect::control(const std::string &value) {
|
|
41
45
|
void TuyaSelect::dump_config() {
|
42
46
|
LOG_SELECT("", "Tuya Select", this);
|
43
47
|
ESP_LOGCONFIG(TAG, " Select has datapoint ID %u", this->select_id_);
|
48
|
+
ESP_LOGCONFIG(TAG, " Data type: %s", this->is_int_ ? "int" : "enum");
|
44
49
|
ESP_LOGCONFIG(TAG, " Options are:");
|
45
50
|
auto options = this->traits.get_options();
|
46
51
|
for (auto i = 0; i < this->mappings_.size(); i++) {
|
@@ -16,7 +16,10 @@ class TuyaSelect : public select::Select, public Component {
|
|
16
16
|
|
17
17
|
void set_tuya_parent(Tuya *parent) { this->parent_ = parent; }
|
18
18
|
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
|
19
|
-
void set_select_id(uint8_t select_id) {
|
19
|
+
void set_select_id(uint8_t select_id, bool is_int) {
|
20
|
+
this->select_id_ = select_id;
|
21
|
+
this->is_int_ = is_int;
|
22
|
+
}
|
20
23
|
void set_select_mappings(std::vector<uint8_t> mappings) { this->mappings_ = std::move(mappings); }
|
21
24
|
|
22
25
|
protected:
|
@@ -26,6 +29,7 @@ class TuyaSelect : public select::Select, public Component {
|
|
26
29
|
bool optimistic_ = false;
|
27
30
|
uint8_t select_id_;
|
28
31
|
std::vector<uint8_t> mappings_;
|
32
|
+
bool is_int_ = false;
|
29
33
|
};
|
30
34
|
|
31
35
|
} // namespace tuya
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from esphome.components.packet_transport import (
|
2
|
+
PacketTransport,
|
3
|
+
new_packet_transport,
|
4
|
+
transport_schema,
|
5
|
+
)
|
6
|
+
from esphome.cpp_types import PollingComponent
|
7
|
+
|
8
|
+
from .. import UART_DEVICE_SCHEMA, register_uart_device, uart_ns
|
9
|
+
|
10
|
+
CODEOWNERS = ["@clydebarrow"]
|
11
|
+
DEPENDENCIES = ["uart"]
|
12
|
+
|
13
|
+
UARTTransport = uart_ns.class_("UARTTransport", PacketTransport, PollingComponent)
|
14
|
+
|
15
|
+
CONFIG_SCHEMA = transport_schema(UARTTransport).extend(UART_DEVICE_SCHEMA)
|
16
|
+
|
17
|
+
|
18
|
+
async def to_code(config):
|
19
|
+
var, _ = await new_packet_transport(config)
|
20
|
+
await register_uart_device(var, config)
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#include "esphome/core/log.h"
|
2
|
+
#include "esphome/core/application.h"
|
3
|
+
#include "uart_transport.h"
|
4
|
+
|
5
|
+
namespace esphome {
|
6
|
+
namespace uart {
|
7
|
+
|
8
|
+
static const char *const TAG = "uart_transport";
|
9
|
+
|
10
|
+
void UARTTransport::loop() {
|
11
|
+
PacketTransport::loop();
|
12
|
+
|
13
|
+
while (this->parent_->available()) {
|
14
|
+
uint8_t byte;
|
15
|
+
if (!this->parent_->read_byte(&byte)) {
|
16
|
+
ESP_LOGW(TAG, "Failed to read byte from UART");
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
if (byte == FLAG_BYTE) {
|
20
|
+
if (this->rx_started_ && this->receive_buffer_.size() > 6) {
|
21
|
+
auto len = this->receive_buffer_.size();
|
22
|
+
auto crc = crc16(this->receive_buffer_.data(), len - 2);
|
23
|
+
if (crc != (this->receive_buffer_[len - 2] | (this->receive_buffer_[len - 1] << 8))) {
|
24
|
+
ESP_LOGD(TAG, "CRC mismatch, discarding packet");
|
25
|
+
this->rx_started_ = false;
|
26
|
+
this->receive_buffer_.clear();
|
27
|
+
continue;
|
28
|
+
}
|
29
|
+
this->receive_buffer_.resize(len - 2);
|
30
|
+
this->process_(this->receive_buffer_);
|
31
|
+
this->rx_started_ = false;
|
32
|
+
} else {
|
33
|
+
this->rx_started_ = true;
|
34
|
+
}
|
35
|
+
this->receive_buffer_.clear();
|
36
|
+
this->rx_control_ = false;
|
37
|
+
continue;
|
38
|
+
}
|
39
|
+
if (!this->rx_started_)
|
40
|
+
continue;
|
41
|
+
if (byte == CONTROL_BYTE) {
|
42
|
+
this->rx_control_ = true;
|
43
|
+
continue;
|
44
|
+
}
|
45
|
+
if (this->rx_control_) {
|
46
|
+
byte ^= 0x20;
|
47
|
+
this->rx_control_ = false;
|
48
|
+
}
|
49
|
+
if (this->receive_buffer_.size() == MAX_PACKET_SIZE) {
|
50
|
+
ESP_LOGD(TAG, "Packet too large, discarding");
|
51
|
+
this->rx_started_ = false;
|
52
|
+
this->receive_buffer_.clear();
|
53
|
+
continue;
|
54
|
+
}
|
55
|
+
this->receive_buffer_.push_back(byte);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
void UARTTransport::update() {
|
60
|
+
this->updated_ = true;
|
61
|
+
this->resend_data_ = true;
|
62
|
+
PacketTransport::update();
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Write a byte to the UART bus. If the byte is a flag or control byte, it will be escaped.
|
67
|
+
* @param byte The byte to write.
|
68
|
+
*/
|
69
|
+
void UARTTransport::write_byte_(uint8_t byte) const {
|
70
|
+
if (byte == FLAG_BYTE || byte == CONTROL_BYTE) {
|
71
|
+
this->parent_->write_byte(CONTROL_BYTE);
|
72
|
+
byte ^= 0x20;
|
73
|
+
}
|
74
|
+
this->parent_->write_byte(byte);
|
75
|
+
}
|
76
|
+
|
77
|
+
void UARTTransport::send_packet(const std::vector<uint8_t> &buf) const {
|
78
|
+
this->parent_->write_byte(FLAG_BYTE);
|
79
|
+
for (uint8_t byte : buf) {
|
80
|
+
this->write_byte_(byte);
|
81
|
+
}
|
82
|
+
auto crc = crc16(buf.data(), buf.size());
|
83
|
+
this->write_byte_(crc & 0xFF);
|
84
|
+
this->write_byte_(crc >> 8);
|
85
|
+
this->parent_->write_byte(FLAG_BYTE);
|
86
|
+
}
|
87
|
+
} // namespace uart
|
88
|
+
} // namespace esphome
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "esphome/core/component.h"
|
4
|
+
#include "esphome/components/packet_transport/packet_transport.h"
|
5
|
+
#include <vector>
|
6
|
+
#include "../uart.h"
|
7
|
+
|
8
|
+
namespace esphome {
|
9
|
+
namespace uart {
|
10
|
+
|
11
|
+
/**
|
12
|
+
* A transport protocol for sending and receiving packets over a UART connection.
|
13
|
+
* The protocol is based on Asynchronous HDLC framing. (https://en.wikipedia.org/wiki/High-Level_Data_Link_Control)
|
14
|
+
* There are two special bytes: FLAG_BYTE and CONTROL_BYTE.
|
15
|
+
* A 16-bit CRC is appended to the packet, then
|
16
|
+
* the protocol wraps the resulting data between FLAG_BYTEs.
|
17
|
+
* Any occurrence of FLAG_BYTE or CONTROL_BYTE in the data is escaped by emitting CONTROL_BYTE followed by the byte
|
18
|
+
* XORed with 0x20.
|
19
|
+
*/
|
20
|
+
static const uint16_t MAX_PACKET_SIZE = 508;
|
21
|
+
static const uint8_t FLAG_BYTE = 0x7E;
|
22
|
+
static const uint8_t CONTROL_BYTE = 0x7D;
|
23
|
+
|
24
|
+
class UARTTransport : public packet_transport::PacketTransport, public UARTDevice {
|
25
|
+
public:
|
26
|
+
void loop() override;
|
27
|
+
void update() override;
|
28
|
+
float get_setup_priority() const override { return setup_priority::PROCESSOR; }
|
29
|
+
|
30
|
+
protected:
|
31
|
+
void write_byte_(uint8_t byte) const;
|
32
|
+
void send_packet(const std::vector<uint8_t> &buf) const override;
|
33
|
+
bool should_send() override { return true; };
|
34
|
+
size_t get_max_packet_size() override { return MAX_PACKET_SIZE; }
|
35
|
+
std::vector<uint8_t> receive_buffer_{};
|
36
|
+
bool rx_started_{};
|
37
|
+
bool rx_control_{};
|
38
|
+
};
|
39
|
+
|
40
|
+
} // namespace uart
|
41
|
+
} // namespace esphome
|
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "uart_switch.h"
|
2
2
|
#include "esphome/core/log.h"
|
3
|
+
#include "esphome/core/application.h"
|
3
4
|
|
4
5
|
namespace esphome {
|
5
6
|
namespace uart {
|
@@ -8,7 +9,7 @@ static const char *const TAG = "uart.switch";
|
|
8
9
|
|
9
10
|
void UARTSwitch::loop() {
|
10
11
|
if (this->send_every_) {
|
11
|
-
const uint32_t now =
|
12
|
+
const uint32_t now = App.get_loop_component_start_time();
|
12
13
|
if (now - this->last_transmission_ > this->send_every_) {
|
13
14
|
this->write_command_(this->state);
|
14
15
|
this->last_transmission_ = now;
|
@@ -1,164 +1,162 @@
|
|
1
|
-
import
|
2
|
-
|
1
|
+
from esphome import automation
|
2
|
+
from esphome.automation import Trigger
|
3
3
|
import esphome.codegen as cg
|
4
|
-
from esphome.components.
|
5
|
-
from esphome.components.binary_sensor import BinarySensor
|
6
|
-
from esphome.components.sensor import Sensor
|
7
|
-
import esphome.config_validation as cv
|
8
|
-
from esphome.const import (
|
4
|
+
from esphome.components.packet_transport import (
|
9
5
|
CONF_BINARY_SENSORS,
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
CONF_PORT,
|
6
|
+
CONF_ENCRYPTION,
|
7
|
+
CONF_PING_PONG_ENABLE,
|
8
|
+
CONF_PROVIDERS,
|
9
|
+
CONF_ROLLING_CODE_ENABLE,
|
15
10
|
CONF_SENSORS,
|
16
11
|
)
|
17
|
-
|
12
|
+
import esphome.config_validation as cv
|
13
|
+
from esphome.const import CONF_DATA, CONF_ID, CONF_PORT, CONF_TRIGGER_ID
|
14
|
+
from esphome.core import Lambda
|
15
|
+
from esphome.cpp_generator import ExpressionStatement, MockObj
|
18
16
|
|
19
17
|
CODEOWNERS = ["@clydebarrow"]
|
20
18
|
DEPENDENCIES = ["network"]
|
21
|
-
AUTO_LOAD = ["socket"
|
22
|
-
MULTI_CONF = True
|
19
|
+
AUTO_LOAD = ["socket"]
|
23
20
|
|
21
|
+
MULTI_CONF = True
|
24
22
|
udp_ns = cg.esphome_ns.namespace("udp")
|
25
|
-
UDPComponent = udp_ns.class_("UDPComponent", cg.
|
23
|
+
UDPComponent = udp_ns.class_("UDPComponent", cg.Component)
|
24
|
+
UDPWriteAction = udp_ns.class_("UDPWriteAction", automation.Action)
|
25
|
+
trigger_args = cg.std_vector.template(cg.uint8)
|
26
26
|
|
27
|
-
CONF_BROADCAST = "broadcast"
|
28
|
-
CONF_BROADCAST_ID = "broadcast_id"
|
29
27
|
CONF_ADDRESSES = "addresses"
|
30
28
|
CONF_LISTEN_ADDRESS = "listen_address"
|
31
|
-
CONF_PROVIDER = "provider"
|
32
|
-
CONF_PROVIDERS = "providers"
|
33
|
-
CONF_REMOTE_ID = "remote_id"
|
34
29
|
CONF_UDP_ID = "udp_id"
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
def sensor_validation(cls: MockObjClass):
|
41
|
-
return cv.maybe_simple_value(
|
42
|
-
cv.Schema(
|
43
|
-
{
|
44
|
-
cv.Required(CONF_ID): cv.use_id(cls),
|
45
|
-
cv.Optional(CONF_BROADCAST_ID): cv.validate_id_name,
|
46
|
-
}
|
47
|
-
),
|
48
|
-
key=CONF_ID,
|
49
|
-
)
|
50
|
-
|
30
|
+
CONF_ON_RECEIVE = "on_receive"
|
31
|
+
CONF_LISTEN_PORT = "listen_port"
|
32
|
+
CONF_BROADCAST_PORT = "broadcast_port"
|
51
33
|
|
52
|
-
|
53
|
-
cv.Optional(CONF_ENCRYPTION): cv.maybe_simple_value(
|
54
|
-
cv.Schema(
|
55
|
-
{
|
56
|
-
cv.Required(CONF_KEY): cv.string,
|
57
|
-
}
|
58
|
-
),
|
59
|
-
key=CONF_KEY,
|
60
|
-
)
|
61
|
-
}
|
62
|
-
|
63
|
-
PROVIDER_SCHEMA = cv.Schema(
|
34
|
+
UDP_SCHEMA = cv.Schema(
|
64
35
|
{
|
65
|
-
cv.
|
36
|
+
cv.GenerateID(CONF_UDP_ID): cv.use_id(UDPComponent),
|
66
37
|
}
|
67
|
-
)
|
38
|
+
)
|
68
39
|
|
69
40
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
raise cv.Invalid("Rolling code requires an encryption key")
|
76
|
-
if config[CONF_PING_PONG_ENABLE]:
|
77
|
-
if not any(CONF_ENCRYPTION in p for p in config.get(CONF_PROVIDERS) or ()):
|
78
|
-
raise cv.Invalid("Ping-pong requires at least one encrypted provider")
|
79
|
-
return config
|
41
|
+
def is_relocated(option):
|
42
|
+
def validator(value):
|
43
|
+
raise cv.Invalid(
|
44
|
+
f"The '{option}' option should now be configured in the 'packet_transport' component"
|
45
|
+
)
|
80
46
|
|
47
|
+
return validator
|
81
48
|
|
82
|
-
|
83
|
-
|
84
|
-
.
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
cv.ipv4address,
|
93
|
-
),
|
94
|
-
cv.Optional(CONF_ROLLING_CODE_ENABLE, default=False): cv.boolean,
|
95
|
-
cv.Optional(CONF_PING_PONG_ENABLE, default=False): cv.boolean,
|
96
|
-
cv.Optional(
|
97
|
-
CONF_PING_PONG_RECYCLE_TIME, default="600s"
|
98
|
-
): cv.positive_time_period_seconds,
|
99
|
-
cv.Optional(CONF_SENSORS): cv.ensure_list(sensor_validation(Sensor)),
|
100
|
-
cv.Optional(CONF_BINARY_SENSORS): cv.ensure_list(
|
101
|
-
sensor_validation(BinarySensor)
|
102
|
-
),
|
103
|
-
cv.Optional(CONF_PROVIDERS): cv.ensure_list(PROVIDER_SCHEMA),
|
104
|
-
},
|
49
|
+
|
50
|
+
RELOCATED = {
|
51
|
+
cv.Optional(x): is_relocated(x)
|
52
|
+
for x in (
|
53
|
+
CONF_PROVIDERS,
|
54
|
+
CONF_ENCRYPTION,
|
55
|
+
CONF_PING_PONG_ENABLE,
|
56
|
+
CONF_ROLLING_CODE_ENABLE,
|
57
|
+
CONF_SENSORS,
|
58
|
+
CONF_BINARY_SENSORS,
|
105
59
|
)
|
106
|
-
|
107
|
-
validate_,
|
108
|
-
)
|
60
|
+
}
|
109
61
|
|
110
|
-
|
62
|
+
CONFIG_SCHEMA = cv.COMPONENT_SCHEMA.extend(
|
111
63
|
{
|
112
|
-
cv.
|
113
|
-
cv.
|
114
|
-
|
64
|
+
cv.GenerateID(): cv.declare_id(UDPComponent),
|
65
|
+
cv.Optional(CONF_PORT, default=18511): cv.Any(
|
66
|
+
cv.port,
|
67
|
+
cv.Schema(
|
68
|
+
{
|
69
|
+
cv.Required(CONF_LISTEN_PORT): cv.port,
|
70
|
+
cv.Required(CONF_BROADCAST_PORT): cv.port,
|
71
|
+
}
|
72
|
+
),
|
73
|
+
),
|
74
|
+
cv.Optional(
|
75
|
+
CONF_LISTEN_ADDRESS, default="255.255.255.255"
|
76
|
+
): cv.ipv4address_multi_broadcast,
|
77
|
+
cv.Optional(CONF_ADDRESSES, default=["255.255.255.255"]): cv.ensure_list(
|
78
|
+
cv.ipv4address,
|
79
|
+
),
|
80
|
+
cv.Optional(CONF_ON_RECEIVE): automation.validate_automation(
|
81
|
+
{
|
82
|
+
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
83
|
+
Trigger.template(trigger_args)
|
84
|
+
),
|
85
|
+
}
|
86
|
+
),
|
115
87
|
}
|
116
|
-
)
|
117
|
-
|
88
|
+
).extend(RELOCATED)
|
118
89
|
|
119
|
-
def require_internal_with_name(config):
|
120
|
-
if CONF_NAME in config and CONF_INTERNAL not in config:
|
121
|
-
raise cv.Invalid("Must provide internal: config when using name:")
|
122
|
-
return config
|
123
90
|
|
124
|
-
|
125
|
-
|
126
|
-
|
91
|
+
async def register_udp_client(var, config):
|
92
|
+
udp_var = await cg.get_variable(config[CONF_UDP_ID])
|
93
|
+
cg.add(var.set_parent(udp_var))
|
94
|
+
return udp_var
|
127
95
|
|
128
96
|
|
129
97
|
async def to_code(config):
|
130
98
|
cg.add_define("USE_UDP")
|
131
99
|
cg.add_global(udp_ns.using)
|
132
100
|
var = cg.new_Pvariable(config[CONF_ID])
|
133
|
-
await cg.register_component(var, config)
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
)
|
141
|
-
)
|
142
|
-
|
143
|
-
sens_id = sens_conf[CONF_ID]
|
144
|
-
sensor = await cg.get_variable(sens_id)
|
145
|
-
bcst_id = sens_conf.get(CONF_BROADCAST_ID, sens_id.id)
|
146
|
-
cg.add(var.add_sensor(bcst_id, sensor))
|
147
|
-
for sens_conf in config.get(CONF_BINARY_SENSORS, ()):
|
148
|
-
sens_id = sens_conf[CONF_ID]
|
149
|
-
sensor = await cg.get_variable(sens_id)
|
150
|
-
bcst_id = sens_conf.get(CONF_BROADCAST_ID, sens_id.id)
|
151
|
-
cg.add(var.add_binary_sensor(bcst_id, sensor))
|
101
|
+
var = await cg.register_component(var, config)
|
102
|
+
conf_port = config[CONF_PORT]
|
103
|
+
if isinstance(conf_port, int):
|
104
|
+
cg.add(var.set_listen_port(conf_port))
|
105
|
+
cg.add(var.set_broadcast_port(conf_port))
|
106
|
+
else:
|
107
|
+
cg.add(var.set_listen_port(conf_port[CONF_LISTEN_PORT]))
|
108
|
+
cg.add(var.set_broadcast_port(conf_port[CONF_BROADCAST_PORT]))
|
109
|
+
if (listen_address := str(config[CONF_LISTEN_ADDRESS])) != "255.255.255.255":
|
110
|
+
cg.add(var.set_listen_address(listen_address))
|
152
111
|
for address in config[CONF_ADDRESSES]:
|
153
112
|
cg.add(var.add_address(str(address)))
|
113
|
+
if on_receive := config.get(CONF_ON_RECEIVE):
|
114
|
+
on_receive = on_receive[0]
|
115
|
+
trigger = cg.new_Pvariable(on_receive[CONF_TRIGGER_ID])
|
116
|
+
trigger = await automation.build_automation(
|
117
|
+
trigger, [(trigger_args, "data")], on_receive
|
118
|
+
)
|
119
|
+
trigger = Lambda(str(ExpressionStatement(trigger.trigger(MockObj("data")))))
|
120
|
+
trigger = await cg.process_lambda(trigger, [(trigger_args, "data")])
|
121
|
+
cg.add(var.add_listener(trigger))
|
122
|
+
cg.add(var.set_should_listen())
|
123
|
+
|
124
|
+
|
125
|
+
def validate_raw_data(value):
|
126
|
+
if isinstance(value, str):
|
127
|
+
return value.encode("utf-8")
|
128
|
+
if isinstance(value, str):
|
129
|
+
return value
|
130
|
+
if isinstance(value, list):
|
131
|
+
return cv.Schema([cv.hex_uint8_t])(value)
|
132
|
+
raise cv.Invalid(
|
133
|
+
"data must either be a string wrapped in quotes or a list of bytes"
|
134
|
+
)
|
154
135
|
|
155
|
-
if encryption := config.get(CONF_ENCRYPTION):
|
156
|
-
cg.add(var.set_encryption_key(hash_encryption_key(encryption)))
|
157
136
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
137
|
+
@automation.register_action(
|
138
|
+
"udp.write",
|
139
|
+
UDPWriteAction,
|
140
|
+
cv.maybe_simple_value(
|
141
|
+
{
|
142
|
+
cv.GenerateID(): cv.use_id(UDPComponent),
|
143
|
+
cv.Required(CONF_DATA): cv.templatable(validate_raw_data),
|
144
|
+
},
|
145
|
+
key=CONF_DATA,
|
146
|
+
),
|
147
|
+
)
|
148
|
+
async def udp_write_to_code(config, action_id, template_arg, args):
|
149
|
+
var = cg.new_Pvariable(action_id, template_arg)
|
150
|
+
udp_var = await cg.get_variable(config[CONF_ID])
|
151
|
+
await cg.register_parented(var, udp_var)
|
152
|
+
cg.add(udp_var.set_should_broadcast())
|
153
|
+
data = config[CONF_DATA]
|
154
|
+
if isinstance(data, bytes):
|
155
|
+
data = list(data)
|
156
|
+
|
157
|
+
if cg.is_template(data):
|
158
|
+
templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8))
|
159
|
+
cg.add(var.set_data_template(templ))
|
160
|
+
else:
|
161
|
+
cg.add(var.set_data_static(data))
|
162
|
+
return var
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "udp_component.h"
|
4
|
+
#ifdef USE_NETWORK
|
5
|
+
#include "esphome/core/automation.h"
|
6
|
+
|
7
|
+
#include <vector>
|
8
|
+
|
9
|
+
namespace esphome {
|
10
|
+
namespace udp {
|
11
|
+
|
12
|
+
template<typename... Ts> class UDPWriteAction : public Action<Ts...>, public Parented<UDPComponent> {
|
13
|
+
public:
|
14
|
+
void set_data_template(std::function<std::vector<uint8_t>(Ts...)> func) {
|
15
|
+
this->data_func_ = func;
|
16
|
+
this->static_ = false;
|
17
|
+
}
|
18
|
+
void set_data_static(const std::vector<uint8_t> &data) {
|
19
|
+
this->data_static_ = data;
|
20
|
+
this->static_ = true;
|
21
|
+
}
|
22
|
+
|
23
|
+
void play(Ts... x) override {
|
24
|
+
if (this->static_) {
|
25
|
+
this->parent_->send_packet(this->data_static_);
|
26
|
+
} else {
|
27
|
+
auto val = this->data_func_(x...);
|
28
|
+
this->parent_->send_packet(val);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
protected:
|
33
|
+
bool static_{false};
|
34
|
+
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
|
35
|
+
std::vector<uint8_t> data_static_{};
|
36
|
+
};
|
37
|
+
|
38
|
+
} // namespace udp
|
39
|
+
} // namespace esphome
|
40
|
+
#endif
|
@@ -1,27 +1,5 @@
|
|
1
|
-
import esphome.
|
2
|
-
from esphome.components import binary_sensor
|
3
|
-
from esphome.config_validation import All, has_at_least_one_key
|
4
|
-
from esphome.const import CONF_ID
|
1
|
+
import esphome.config_validation as cv
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
CONF_REMOTE_ID,
|
9
|
-
CONF_UDP_ID,
|
10
|
-
SENSOR_SCHEMA,
|
11
|
-
require_internal_with_name,
|
3
|
+
CONFIG_SCHEMA = cv.invalid(
|
4
|
+
"The 'udp.binary_sensor' component has been migrated to the 'packet_transport.binary_sensor' component."
|
12
5
|
)
|
13
|
-
|
14
|
-
DEPENDENCIES = ["udp"]
|
15
|
-
|
16
|
-
CONFIG_SCHEMA = All(
|
17
|
-
binary_sensor.binary_sensor_schema().extend(SENSOR_SCHEMA),
|
18
|
-
has_at_least_one_key(CONF_ID, CONF_REMOTE_ID),
|
19
|
-
require_internal_with_name,
|
20
|
-
)
|
21
|
-
|
22
|
-
|
23
|
-
async def to_code(config):
|
24
|
-
var = await binary_sensor.new_binary_sensor(config)
|
25
|
-
comp = await cg.get_variable(config[CONF_UDP_ID])
|
26
|
-
remote_id = str(config.get(CONF_REMOTE_ID) or config.get(CONF_ID))
|
27
|
-
cg.add(comp.add_remote_binary_sensor(config[CONF_PROVIDER], remote_id, var))
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
from esphome.components.api import CONF_ENCRYPTION
|
3
|
+
from esphome.components.packet_transport import (
|
4
|
+
CONF_PING_PONG_ENABLE,
|
5
|
+
PacketTransport,
|
6
|
+
new_packet_transport,
|
7
|
+
transport_schema,
|
8
|
+
)
|
9
|
+
from esphome.const import CONF_BINARY_SENSORS, CONF_SENSORS
|
10
|
+
from esphome.cpp_types import PollingComponent
|
11
|
+
|
12
|
+
from .. import UDP_SCHEMA, register_udp_client, udp_ns
|
13
|
+
|
14
|
+
UDPTransport = udp_ns.class_("UDPTransport", PacketTransport, PollingComponent)
|
15
|
+
|
16
|
+
CONFIG_SCHEMA = transport_schema(UDPTransport).extend(UDP_SCHEMA)
|
17
|
+
|
18
|
+
|
19
|
+
async def to_code(config):
|
20
|
+
var, providers = await new_packet_transport(config)
|
21
|
+
udp_var = await register_udp_client(var, config)
|
22
|
+
if CONF_ENCRYPTION in config or providers:
|
23
|
+
cg.add(udp_var.set_should_listen())
|
24
|
+
if (
|
25
|
+
config[CONF_PING_PONG_ENABLE]
|
26
|
+
or config.get(CONF_SENSORS, ())
|
27
|
+
or config.get(CONF_BINARY_SENSORS, ())
|
28
|
+
):
|
29
|
+
cg.add(udp_var.set_should_broadcast())
|