esphome 2025.4.1__py3-none-any.whl → 2025.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +16 -14
- esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
- esphome/components/adc/__init__.py +51 -34
- esphome/components/airthings_wave_base/__init__.py +1 -1
- esphome/components/alarm_control_panel/__init__.py +37 -2
- esphome/components/am43/cover/__init__.py +4 -5
- esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
- esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
- esphome/components/analog_threshold/binary_sensor.py +10 -8
- esphome/components/anova/climate.py +4 -5
- esphome/components/api/__init__.py +25 -8
- esphome/components/api/api_connection.cpp +416 -662
- esphome/components/api/api_connection.h +256 -57
- esphome/components/api/api_frame_helper.cpp +232 -177
- esphome/components/api/api_frame_helper.h +61 -8
- esphome/components/api/api_noise_context.h +13 -4
- esphome/components/api/api_pb2.cpp +1422 -1
- esphome/components/api/api_pb2.h +255 -1
- esphome/components/api/api_pb2_service.cpp +162 -49
- esphome/components/api/api_pb2_service.h +90 -51
- esphome/components/api/api_pb2_size.h +361 -0
- esphome/components/api/api_server.cpp +110 -34
- esphome/components/api/api_server.h +8 -0
- esphome/components/api/proto.h +86 -17
- esphome/components/as3935_i2c/as3935_i2c.h +0 -3
- esphome/components/as7341/as7341.h +1 -1
- esphome/components/at581x/at581x.h +4 -4
- esphome/components/atm90e32/__init__.py +1 -0
- esphome/components/atm90e32/atm90e32.cpp +576 -199
- esphome/components/atm90e32/atm90e32.h +128 -31
- esphome/components/atm90e32/atm90e32_reg.h +4 -2
- esphome/components/atm90e32/button/__init__.py +62 -10
- esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
- esphome/components/atm90e32/button/atm90e32_button.h +36 -4
- esphome/components/atm90e32/number/__init__.py +130 -0
- esphome/components/atm90e32/number/atm90e32_number.h +16 -0
- esphome/components/atm90e32/sensor.py +21 -4
- esphome/components/atm90e32/text_sensor/__init__.py +48 -0
- esphome/components/audio/__init__.py +96 -49
- esphome/components/audio/audio.h +48 -0
- esphome/components/audio/audio_decoder.cpp +1 -1
- esphome/components/audio/audio_resampler.cpp +2 -0
- esphome/components/audio/audio_resampler.h +1 -0
- esphome/components/ballu/climate.py +2 -9
- esphome/components/bang_bang/climate.py +5 -6
- esphome/components/bedjet/bedjet_hub.cpp +1 -0
- esphome/components/bedjet/climate/__init__.py +3 -8
- esphome/components/bedjet/fan/__init__.py +2 -11
- esphome/components/binary/fan/__init__.py +13 -16
- esphome/components/binary_sensor/__init__.py +13 -10
- esphome/components/bl0906/constants.h +16 -16
- esphome/components/ble_client/text_sensor/__init__.py +3 -5
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +136 -21
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
- esphome/components/button/__init__.py +11 -8
- esphome/components/canbus/canbus.cpp +3 -0
- esphome/components/canbus/canbus.h +16 -0
- esphome/components/ccs811/sensor.py +9 -6
- esphome/components/climate/__init__.py +35 -2
- esphome/components/climate/climate_mode.h +1 -1
- esphome/components/climate/climate_traits.h +63 -57
- esphome/components/climate_ir/__init__.py +57 -17
- esphome/components/climate_ir_lg/climate.py +2 -5
- esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
- esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
- esphome/components/color/__init__.py +2 -0
- esphome/components/const/__init__.py +5 -0
- esphome/components/coolix/climate.py +2 -9
- esphome/components/copy/cover/__init__.py +10 -9
- esphome/components/copy/fan/__init__.py +11 -9
- esphome/components/copy/lock/__init__.py +11 -9
- esphome/components/copy/text/__init__.py +9 -6
- esphome/components/cover/__init__.py +37 -2
- esphome/components/cse7766/cse7766.cpp +2 -1
- esphome/components/cst226/binary_sensor/__init__.py +28 -0
- esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
- esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
- esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
- esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
- esphome/components/current_based/cover.py +37 -36
- esphome/components/current_based/current_based_cover.cpp +2 -1
- esphome/components/daikin/climate.py +2 -9
- esphome/components/daikin/daikin.cpp +15 -9
- esphome/components/daikin/daikin.h +5 -5
- esphome/components/daikin_arc/climate.py +2 -7
- esphome/components/daikin_brc/climate.py +3 -5
- esphome/components/dallas_temp/dallas_temp.cpp +17 -24
- esphome/components/dallas_temp/dallas_temp.h +0 -1
- esphome/components/daly_bms/daly_bms.cpp +2 -1
- esphome/components/debug/debug_component.cpp +6 -1
- esphome/components/debug/debug_component.h +8 -0
- esphome/components/debug/debug_esp32.cpp +109 -254
- esphome/components/debug/sensor.py +14 -0
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
- esphome/components/delonghi/climate.py +2 -9
- esphome/components/demo/__init__.py +18 -20
- esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
- esphome/components/display/rect.cpp +4 -9
- esphome/components/display/rect.h +1 -1
- esphome/components/dps310/sensor.py +6 -6
- esphome/components/ee895/sensor.py +9 -9
- esphome/components/emmeti/climate.py +2 -9
- esphome/components/endstop/cover.py +17 -16
- esphome/components/endstop/endstop_cover.cpp +2 -1
- esphome/components/ens160_base/__init__.py +12 -9
- esphome/components/esp32/__init__.py +60 -3
- esphome/components/esp32/core.cpp +11 -5
- esphome/components/esp32/gpio.cpp +86 -24
- esphome/components/esp32/gpio.py +15 -16
- esphome/components/esp32/gpio_esp32.py +1 -2
- esphome/components/esp32/gpio_esp32_c2.py +1 -1
- esphome/components/esp32/gpio_esp32_c3.py +1 -1
- esphome/components/esp32/gpio_esp32_c6.py +1 -1
- esphome/components/esp32/gpio_esp32_h2.py +1 -1
- esphome/components/esp32_ble/ble.cpp +1 -8
- esphome/components/esp32_ble/ble.h +5 -3
- esphome/components/esp32_ble/ble_advertising.cpp +2 -1
- esphome/components/esp32_ble/ble_advertising.h +1 -0
- esphome/components/esp32_ble_server/__init__.py +3 -0
- esphome/components/esp32_ble_tracker/__init__.py +7 -1
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
- esphome/components/esp32_camera/__init__.py +1 -1
- esphome/components/esp32_camera/esp32_camera.cpp +2 -10
- esphome/components/esp32_camera/esp32_camera.h +1 -1
- esphome/components/esp32_can/esp32_can.cpp +1 -1
- esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
- esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
- esphome/components/esp32_rmt_led_strip/light.py +9 -1
- esphome/components/esp32_touch/esp32_touch.cpp +1 -1
- esphome/components/esp8266/gpio.cpp +69 -8
- esphome/components/ethernet/ethernet_component.cpp +1 -1
- esphome/components/event/__init__.py +13 -10
- esphome/components/factory_reset/switch/__init__.py +7 -21
- esphome/components/fan/__init__.py +52 -5
- esphome/components/fastled_base/__init__.py +1 -4
- esphome/components/fastled_base/fastled_light.cpp +1 -1
- esphome/components/feedback/cover.py +38 -33
- esphome/components/feedback/feedback_cover.cpp +2 -1
- esphome/components/fujitsu_general/climate.py +2 -9
- esphome/components/gcja5/gcja5.cpp +2 -1
- esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
- esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
- esphome/components/gpio_expander/cached_gpio.h +22 -7
- esphome/components/gps/__init__.py +47 -17
- esphome/components/gps/gps.cpp +42 -23
- esphome/components/gps/gps.h +17 -13
- esphome/components/graph/__init__.py +1 -2
- esphome/components/gree/climate.py +4 -6
- esphome/components/gree/gree.cpp +16 -2
- esphome/components/gree/gree.h +2 -2
- esphome/components/growatt_solar/growatt_solar.cpp +2 -1
- esphome/components/haier/climate.py +37 -34
- esphome/components/hbridge/fan/__init__.py +19 -17
- esphome/components/he60r/cover.py +4 -5
- esphome/components/heatpumpir/climate.py +3 -6
- esphome/components/hitachi_ac344/climate.py +2 -9
- esphome/components/hitachi_ac424/climate.py +2 -9
- esphome/components/hlw8012/hlw8012.cpp +1 -1
- esphome/components/hm3301/hm3301.h +1 -1
- esphome/components/hte501/sensor.py +6 -6
- esphome/components/http_request/__init__.py +39 -6
- esphome/components/http_request/http_request.cpp +20 -0
- esphome/components/http_request/http_request.h +57 -15
- esphome/components/http_request/http_request_arduino.cpp +22 -6
- esphome/components/http_request/http_request_arduino.h +4 -3
- esphome/components/http_request/http_request_host.cpp +141 -0
- esphome/components/http_request/http_request_host.h +37 -0
- esphome/components/http_request/http_request_idf.cpp +35 -3
- esphome/components/http_request/http_request_idf.h +10 -3
- esphome/components/http_request/httplib.h +9691 -0
- esphome/components/http_request/update/__init__.py +11 -8
- esphome/components/hyt271/sensor.py +6 -6
- esphome/components/i2c/i2c.h +4 -0
- esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
- esphome/components/i2s_audio/__init__.py +131 -22
- esphome/components/i2s_audio/i2s_audio.h +44 -4
- esphome/components/i2s_audio/media_player/__init__.py +19 -9
- esphome/components/i2s_audio/microphone/__init__.py +63 -5
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
- esphome/components/i2s_audio/speaker/__init__.py +31 -5
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
- esphome/components/ili9xxx/ili9xxx_init.h +1 -1
- esphome/components/image/__init__.py +37 -17
- esphome/components/image/image.cpp +25 -8
- esphome/components/internal_temperature/internal_temperature.cpp +6 -4
- esphome/components/key_collector/__init__.py +35 -0
- esphome/components/key_collector/key_collector.cpp +8 -0
- esphome/components/key_collector/key_collector.h +10 -0
- esphome/components/kuntze/kuntze.cpp +2 -1
- esphome/components/ld2410/ld2410.h +1 -1
- esphome/components/ld2450/ld2450.h +1 -1
- esphome/components/light/__init__.py +57 -0
- esphome/components/lock/__init__.py +51 -4
- esphome/components/lock/automation.h +2 -13
- esphome/components/logger/__init__.py +22 -0
- esphome/components/logger/logger.cpp +154 -103
- esphome/components/logger/logger.h +211 -36
- esphome/components/logger/task_log_buffer.cpp +138 -0
- esphome/components/logger/task_log_buffer.h +69 -0
- esphome/components/lvgl/__init__.py +13 -5
- esphome/components/lvgl/automation.py +50 -1
- esphome/components/lvgl/defines.py +0 -1
- esphome/components/lvgl/lv_validation.py +10 -1
- esphome/components/lvgl/lvgl_esphome.cpp +5 -1
- esphome/components/lvgl/schemas.py +14 -14
- esphome/components/lvgl/text/__init__.py +1 -2
- esphome/components/lvgl/widgets/arc.py +7 -6
- esphome/components/lvgl/widgets/buttonmatrix.py +3 -3
- esphome/components/lvgl/widgets/checkbox.py +2 -2
- esphome/components/lvgl/widgets/dropdown.py +2 -1
- esphome/components/lvgl/widgets/img.py +15 -12
- esphome/components/mapping/__init__.py +134 -0
- esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
- esphome/components/max7219digit/max7219digit.cpp +28 -27
- esphome/components/mdns/__init__.py +11 -5
- esphome/components/mdns/mdns_component.cpp +11 -5
- esphome/components/mdns/mdns_component.h +3 -2
- esphome/components/mdns/mdns_esp32.cpp +4 -3
- esphome/components/mdns/mdns_esp8266.cpp +4 -2
- esphome/components/mdns/mdns_libretiny.cpp +4 -2
- esphome/components/mdns/mdns_rp2040.cpp +4 -2
- esphome/components/media_player/__init__.py +40 -6
- esphome/components/mhz19/sensor.py +11 -7
- esphome/components/micro_wake_word/__init__.py +99 -31
- esphome/components/micro_wake_word/automation.h +54 -0
- esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
- esphome/components/micro_wake_word/micro_wake_word.h +58 -105
- esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
- esphome/components/micro_wake_word/streaming_model.cpp +158 -41
- esphome/components/micro_wake_word/streaming_model.h +85 -13
- esphome/components/microphone/__init__.py +139 -9
- esphome/components/microphone/automation.h +14 -2
- esphome/components/microphone/microphone.cpp +21 -0
- esphome/components/microphone/microphone.h +14 -5
- esphome/components/microphone/microphone_source.cpp +95 -0
- esphome/components/microphone/microphone_source.h +80 -0
- esphome/components/mics_4514/sensor.py +25 -14
- esphome/components/midea/climate.py +3 -4
- esphome/components/midea_ir/climate.py +3 -5
- esphome/components/mipi_spi/__init__.py +15 -0
- esphome/components/mipi_spi/display.py +474 -0
- esphome/components/mipi_spi/mipi_spi.cpp +481 -0
- esphome/components/mipi_spi/mipi_spi.h +171 -0
- esphome/components/mipi_spi/models/__init__.py +65 -0
- esphome/components/mipi_spi/models/amoled.py +72 -0
- esphome/components/mipi_spi/models/commands.py +82 -0
- esphome/components/mipi_spi/models/cyd.py +10 -0
- esphome/components/mipi_spi/models/ili.py +749 -0
- esphome/components/mipi_spi/models/jc.py +260 -0
- esphome/components/mipi_spi/models/lanbon.py +15 -0
- esphome/components/mipi_spi/models/lilygo.py +60 -0
- esphome/components/mipi_spi/models/waveshare.py +139 -0
- esphome/components/mitsubishi/climate.py +2 -5
- esphome/components/mitsubishi/mitsubishi.cpp +9 -9
- esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
- esphome/components/mixer/speaker/mixer_speaker.h +1 -3
- esphome/components/mlx90393/sensor.py +5 -0
- esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
- esphome/components/mlx90393/sensor_mlx90393.h +21 -4
- esphome/components/modbus/modbus.cpp +2 -1
- esphome/components/mqtt/__init__.py +1 -1
- esphome/components/mqtt/mqtt_client.cpp +6 -2
- esphome/components/mqtt/mqtt_const.h +4 -0
- esphome/components/mqtt/mqtt_fan.cpp +39 -0
- esphome/components/mqtt/mqtt_fan.h +2 -0
- esphome/components/ms5611/sensor.py +6 -6
- esphome/components/ms8607/sensor.py +3 -3
- esphome/components/network/__init__.py +1 -1
- esphome/components/nextion/base_component.py +17 -16
- esphome/components/nextion/display.py +11 -2
- esphome/components/nextion/nextion.cpp +39 -1
- esphome/components/nextion/nextion.h +50 -0
- esphome/components/noblex/climate.py +2 -9
- esphome/components/number/__init__.py +12 -9
- esphome/components/one_wire/one_wire_bus.cpp +14 -10
- esphome/components/one_wire/one_wire_bus.h +14 -8
- esphome/components/online_image/bmp_image.cpp +48 -11
- esphome/components/online_image/bmp_image.h +2 -0
- esphome/components/opentherm/binary_sensor/__init__.py +2 -4
- esphome/components/opentherm/number/__init__.py +11 -20
- esphome/components/opentherm/sensor/__init__.py +3 -3
- esphome/components/opentherm/switch/__init__.py +3 -5
- esphome/components/output/lock/__init__.py +11 -9
- esphome/components/packages/__init__.py +33 -31
- esphome/components/packet_transport/__init__.py +201 -0
- esphome/components/packet_transport/binary_sensor.py +19 -0
- esphome/components/packet_transport/packet_transport.cpp +534 -0
- esphome/components/packet_transport/packet_transport.h +154 -0
- esphome/components/packet_transport/sensor.py +19 -0
- esphome/components/pca9685/pca9685_output.cpp +2 -1
- esphome/components/pid/climate.py +2 -4
- esphome/components/pm2005/__init__.py +1 -0
- esphome/components/pm2005/pm2005.cpp +123 -0
- esphome/components/pm2005/pm2005.h +46 -0
- esphome/components/pm2005/sensor.py +86 -0
- esphome/components/pmsa003i/pmsa003i.cpp +43 -16
- esphome/components/pmsa003i/pmsa003i.h +25 -25
- esphome/components/pmsx003/pmsx003.cpp +195 -230
- esphome/components/pmsx003/pmsx003.h +51 -33
- esphome/components/pmsx003/sensor.py +21 -11
- esphome/components/pn7150/pn7150.h +2 -2
- esphome/components/pn7160/pn7160.h +2 -2
- esphome/components/prometheus/prometheus_handler.cpp +174 -0
- esphome/components/prometheus/prometheus_handler.h +17 -0
- esphome/components/psram/__init__.py +7 -5
- esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
- esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
- esphome/components/pzem004t/pzem004t.cpp +2 -1
- esphome/components/qspi_dbi/__init__.py +0 -1
- esphome/components/qspi_dbi/display.py +2 -1
- esphome/components/qspi_dbi/models.py +1 -2
- esphome/components/remote_base/__init__.py +91 -0
- esphome/components/remote_base/beo4_protocol.cpp +153 -0
- esphome/components/remote_base/beo4_protocol.h +43 -0
- esphome/components/remote_base/gobox_protocol.cpp +131 -0
- esphome/components/remote_base/gobox_protocol.h +54 -0
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
- esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
- esphome/components/resampler/speaker/resampler_speaker.h +1 -1
- esphome/components/rf_bridge/rf_bridge.cpp +2 -1
- esphome/components/scd30/sensor.py +2 -3
- esphome/components/scd4x/sensor.py +4 -5
- esphome/components/sdp3x/sensor.py +2 -1
- esphome/components/sds011/sds011.cpp +2 -1
- esphome/components/select/__init__.py +19 -20
- esphome/components/sen5x/sen5x.cpp +55 -36
- esphome/components/sen5x/sensor.py +1 -1
- esphome/components/senseair/sensor.py +3 -3
- esphome/components/sensor/__init__.py +158 -14
- esphome/components/sensor/filter.cpp +23 -0
- esphome/components/sensor/filter.h +22 -0
- esphome/components/sgp30/sensor.py +14 -16
- esphome/components/sgp4x/sensor.py +1 -1
- esphome/components/sht4x/sht4x.cpp +43 -22
- esphome/components/sht4x/sht4x.h +1 -1
- esphome/components/shtcx/sensor.py +6 -6
- esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
- esphome/components/sml/text_sensor/__init__.py +4 -6
- esphome/components/sound_level/__init__.py +0 -0
- esphome/components/sound_level/sensor.py +97 -0
- esphome/components/sound_level/sound_level.cpp +194 -0
- esphome/components/sound_level/sound_level.h +73 -0
- esphome/components/speaker/media_player/__init__.py +4 -8
- esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
- esphome/components/speaker/media_player/speaker_media_player.h +0 -11
- esphome/components/speaker/speaker.h +4 -7
- esphome/components/speed/fan/__init__.py +17 -16
- esphome/components/spi/spi.h +11 -1
- esphome/components/sprinkler/__init__.py +18 -19
- esphome/components/sprinkler/sprinkler.cpp +6 -5
- esphome/components/switch/__init__.py +32 -42
- esphome/components/syslog/__init__.py +41 -0
- esphome/components/syslog/esphome_syslog.cpp +49 -0
- esphome/components/syslog/esphome_syslog.h +27 -0
- esphome/components/t6615/sensor.py +3 -3
- esphome/components/t6615/t6615.cpp +2 -1
- esphome/components/tca9555/tca9555.cpp +11 -6
- esphome/components/tcl112/climate.py +2 -9
- esphome/components/template/alarm_control_panel/__init__.py +7 -6
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
- esphome/components/template/cover/__init__.py +27 -21
- esphome/components/template/fan/__init__.py +14 -12
- esphome/components/template/lock/__init__.py +20 -25
- esphome/components/template/lock/automation.h +18 -0
- esphome/components/template/text/__init__.py +4 -3
- esphome/components/template/valve/__init__.py +32 -21
- esphome/components/template/valve/automation.h +24 -0
- esphome/components/text/__init__.py +32 -1
- esphome/components/text_sensor/__init__.py +24 -29
- esphome/components/thermostat/climate.py +5 -5
- esphome/components/time_based/cover.py +17 -16
- esphome/components/time_based/time_based_cover.cpp +2 -1
- esphome/components/tm1638/switch/__init__.py +10 -7
- esphome/components/tormatic/cover.py +4 -5
- esphome/components/toshiba/climate.py +3 -5
- esphome/components/touchscreen/touchscreen.cpp +3 -1
- esphome/components/tt21100/touchscreen/tt21100.cpp +1 -1
- esphome/components/tuya/climate/__init__.py +5 -6
- esphome/components/tuya/cover/__init__.py +6 -11
- esphome/components/tuya/select/__init__.py +15 -5
- esphome/components/tuya/select/tuya_select.cpp +6 -1
- esphome/components/tuya/select/tuya_select.h +5 -1
- esphome/components/uart/packet_transport/__init__.py +20 -0
- esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
- esphome/components/uart/packet_transport/uart_transport.h +41 -0
- esphome/components/uart/switch/uart_switch.cpp +2 -1
- esphome/components/udp/__init__.py +126 -128
- esphome/components/udp/automation.h +40 -0
- esphome/components/udp/binary_sensor.py +3 -25
- esphome/components/udp/packet_transport/__init__.py +29 -0
- esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
- esphome/components/udp/packet_transport/udp_transport.h +28 -0
- esphome/components/udp/sensor.py +3 -25
- esphome/components/udp/udp_component.cpp +26 -470
- esphome/components/udp/udp_component.h +21 -128
- esphome/components/update/__init__.py +31 -1
- esphome/components/uponor_smatrix/climate/__init__.py +4 -9
- esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
- esphome/components/uptime/text_sensor/__init__.py +47 -7
- esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
- esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
- esphome/components/valve/__init__.py +34 -3
- esphome/components/valve/automation.h +1 -19
- esphome/components/vl53l0x/sensor.py +11 -0
- esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
- esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
- esphome/components/voice_assistant/__init__.py +36 -10
- esphome/components/voice_assistant/voice_assistant.cpp +170 -144
- esphome/components/voice_assistant/voice_assistant.h +26 -25
- esphome/components/waveshare_epaper/display.py +6 -0
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
- esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
- esphome/components/weikai/weikai.cpp +0 -52
- esphome/components/whirlpool/climate.py +3 -5
- esphome/components/whynter/climate.py +3 -5
- esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
- esphome/components/yashima/climate.py +6 -6
- esphome/components/zhlt01/climate.py +2 -7
- esphome/config.py +13 -13
- esphome/config_validation.py +38 -58
- esphome/const.py +15 -1
- esphome/core/__init__.py +2 -0
- esphome/core/application.cpp +27 -10
- esphome/core/application.h +9 -1
- esphome/core/automation.h +4 -3
- esphome/core/component.cpp +28 -7
- esphome/core/component.h +10 -1
- esphome/core/defines.h +23 -17
- esphome/core/doxygen.h +13 -0
- esphome/core/macros.h +4 -0
- esphome/core/scheduler.cpp +7 -1
- esphome/cpp_generator.py +6 -2
- esphome/dashboard/web_server.py +3 -3
- esphome/helpers.py +39 -0
- esphome/loader.py +4 -0
- esphome/log.py +15 -19
- esphome/mqtt.py +23 -10
- esphome/platformio_api.py +1 -1
- esphome/schema_extractors.py +0 -1
- esphome/voluptuous_schema.py +3 -1
- esphome/vscode.py +15 -0
- esphome/wizard.py +47 -37
- esphome/zeroconf.py +7 -3
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/METADATA +10 -11
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/RECORD +456 -396
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/WHEEL +1 -1
- esphome/components/esp32_ble/const_esp32c6.h +0 -74
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/entry_points.txt +0 -0
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.4.1.dist-info → esphome-2025.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
#include "esphome/core/log.h"
|
2
|
+
#include "esphome/core/application.h"
|
3
|
+
#include "esphome/components/network/util.h"
|
4
|
+
#include "udp_transport.h"
|
5
|
+
|
6
|
+
namespace esphome {
|
7
|
+
namespace udp {
|
8
|
+
|
9
|
+
static const char *const TAG = "udp_transport";
|
10
|
+
|
11
|
+
bool UDPTransport::should_send() { return this->should_broadcast_ && network::is_connected(); }
|
12
|
+
void UDPTransport::setup() {
|
13
|
+
PacketTransport::setup();
|
14
|
+
this->should_broadcast_ = this->ping_pong_enable_;
|
15
|
+
#ifdef USE_SENSOR
|
16
|
+
this->should_broadcast_ |= !this->sensors_.empty();
|
17
|
+
#endif
|
18
|
+
#ifdef USE_BINARY_SENSOR
|
19
|
+
this->should_broadcast_ |= !this->binary_sensors_.empty();
|
20
|
+
#endif
|
21
|
+
if (this->should_broadcast_)
|
22
|
+
this->parent_->set_should_broadcast();
|
23
|
+
if (!this->providers_.empty() || this->is_encrypted_()) {
|
24
|
+
this->parent_->add_listener([this](std::vector<uint8_t> &buf) { this->process_(buf); });
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
void UDPTransport::update() {
|
29
|
+
PacketTransport::update();
|
30
|
+
this->updated_ = true;
|
31
|
+
this->resend_data_ = this->should_broadcast_;
|
32
|
+
}
|
33
|
+
|
34
|
+
void UDPTransport::send_packet(const std::vector<uint8_t> &buf) const { this->parent_->send_packet(buf); }
|
35
|
+
} // namespace udp
|
36
|
+
} // namespace esphome
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "../udp_component.h"
|
4
|
+
#ifdef USE_NETWORK
|
5
|
+
#include "esphome/core/component.h"
|
6
|
+
#include "esphome/components/packet_transport/packet_transport.h"
|
7
|
+
#include <vector>
|
8
|
+
|
9
|
+
namespace esphome {
|
10
|
+
namespace udp {
|
11
|
+
|
12
|
+
class UDPTransport : public packet_transport::PacketTransport, public Parented<UDPComponent> {
|
13
|
+
public:
|
14
|
+
void setup() override;
|
15
|
+
void update() override;
|
16
|
+
|
17
|
+
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
18
|
+
|
19
|
+
protected:
|
20
|
+
void send_packet(const std::vector<uint8_t> &buf) const override;
|
21
|
+
bool should_send() override;
|
22
|
+
bool should_broadcast_{false};
|
23
|
+
size_t get_max_packet_size() override { return MAX_PACKET_SIZE; }
|
24
|
+
};
|
25
|
+
|
26
|
+
} // namespace udp
|
27
|
+
} // namespace esphome
|
28
|
+
#endif
|
esphome/components/udp/sensor.py
CHANGED
@@ -1,27 +1,5 @@
|
|
1
|
-
import esphome.
|
2
|
-
from esphome.components.sensor import new_sensor, sensor_schema
|
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.sensor' component has been migrated to the 'packet_transport.sensor' component."
|
12
5
|
)
|
13
|
-
|
14
|
-
DEPENDENCIES = ["udp"]
|
15
|
-
|
16
|
-
CONFIG_SCHEMA = All(
|
17
|
-
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 new_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_sensor(config[CONF_PROVIDER], remote_id, var))
|
@@ -1,164 +1,24 @@
|
|
1
|
+
#include "esphome/core/defines.h"
|
2
|
+
#ifdef USE_NETWORK
|
1
3
|
#include "esphome/core/log.h"
|
2
4
|
#include "esphome/core/application.h"
|
3
5
|
#include "esphome/components/network/util.h"
|
4
6
|
#include "udp_component.h"
|
5
7
|
|
6
|
-
#include "esphome/components/xxtea/xxtea.h"
|
7
|
-
|
8
8
|
namespace esphome {
|
9
9
|
namespace udp {
|
10
10
|
|
11
|
-
/**
|
12
|
-
* Structure of a data packet; everything is little-endian
|
13
|
-
*
|
14
|
-
* --- In clear text ---
|
15
|
-
* MAGIC_NUMBER: 16 bits
|
16
|
-
* host name length: 1 byte
|
17
|
-
* host name: (length) bytes
|
18
|
-
* padding: 0 or more null bytes to a 4 byte boundary
|
19
|
-
*
|
20
|
-
* --- Encrypted (if key set) ----
|
21
|
-
* DATA_KEY: 1 byte: OR ROLLING_CODE_KEY:
|
22
|
-
* Rolling code (if enabled): 8 bytes
|
23
|
-
* Ping keys: if any
|
24
|
-
* repeat:
|
25
|
-
* PING_KEY: 1 byte
|
26
|
-
* ping code: 4 bytes
|
27
|
-
* Sensors:
|
28
|
-
* repeat:
|
29
|
-
* SENSOR_KEY: 1 byte
|
30
|
-
* float value: 4 bytes
|
31
|
-
* name length: 1 byte
|
32
|
-
* name
|
33
|
-
* Binary Sensors:
|
34
|
-
* repeat:
|
35
|
-
* BINARY_SENSOR_KEY: 1 byte
|
36
|
-
* bool value: 1 bytes
|
37
|
-
* name length: 1 byte
|
38
|
-
* name
|
39
|
-
*
|
40
|
-
* Padded to a 4 byte boundary with nulls
|
41
|
-
*
|
42
|
-
* Structure of a ping request packet:
|
43
|
-
* --- In clear text ---
|
44
|
-
* MAGIC_PING: 16 bits
|
45
|
-
* host name length: 1 byte
|
46
|
-
* host name: (length) bytes
|
47
|
-
* Ping key (4 bytes)
|
48
|
-
*
|
49
|
-
*/
|
50
11
|
static const char *const TAG = "udp";
|
51
12
|
|
52
|
-
static size_t round4(size_t value) { return (value + 3) & ~3; }
|
53
|
-
|
54
|
-
union FuData {
|
55
|
-
uint32_t u32;
|
56
|
-
float f32;
|
57
|
-
};
|
58
|
-
|
59
|
-
static const size_t MAX_PACKET_SIZE = 508;
|
60
|
-
static const uint16_t MAGIC_NUMBER = 0x4553;
|
61
|
-
static const uint16_t MAGIC_PING = 0x5048;
|
62
|
-
static const uint32_t PREF_HASH = 0x45535043;
|
63
|
-
enum DataKey {
|
64
|
-
ZERO_FILL_KEY,
|
65
|
-
DATA_KEY,
|
66
|
-
SENSOR_KEY,
|
67
|
-
BINARY_SENSOR_KEY,
|
68
|
-
PING_KEY,
|
69
|
-
ROLLING_CODE_KEY,
|
70
|
-
};
|
71
|
-
|
72
|
-
static const size_t MAX_PING_KEYS = 4;
|
73
|
-
|
74
|
-
static inline void add(std::vector<uint8_t> &vec, uint32_t data) {
|
75
|
-
vec.push_back(data & 0xFF);
|
76
|
-
vec.push_back((data >> 8) & 0xFF);
|
77
|
-
vec.push_back((data >> 16) & 0xFF);
|
78
|
-
vec.push_back((data >> 24) & 0xFF);
|
79
|
-
}
|
80
|
-
|
81
|
-
static inline uint32_t get_uint32(uint8_t *&buf) {
|
82
|
-
uint32_t data = *buf++;
|
83
|
-
data += *buf++ << 8;
|
84
|
-
data += *buf++ << 16;
|
85
|
-
data += *buf++ << 24;
|
86
|
-
return data;
|
87
|
-
}
|
88
|
-
|
89
|
-
static inline uint16_t get_uint16(uint8_t *&buf) {
|
90
|
-
uint16_t data = *buf++;
|
91
|
-
data += *buf++ << 8;
|
92
|
-
return data;
|
93
|
-
}
|
94
|
-
|
95
|
-
static inline void add(std::vector<uint8_t> &vec, uint8_t data) { vec.push_back(data); }
|
96
|
-
static inline void add(std::vector<uint8_t> &vec, uint16_t data) {
|
97
|
-
vec.push_back((uint8_t) data);
|
98
|
-
vec.push_back((uint8_t) (data >> 8));
|
99
|
-
}
|
100
|
-
static inline void add(std::vector<uint8_t> &vec, DataKey data) { vec.push_back(data); }
|
101
|
-
static void add(std::vector<uint8_t> &vec, const char *str) {
|
102
|
-
auto len = strlen(str);
|
103
|
-
vec.push_back(len);
|
104
|
-
for (size_t i = 0; i != len; i++) {
|
105
|
-
vec.push_back(*str++);
|
106
|
-
}
|
107
|
-
}
|
108
|
-
|
109
13
|
void UDPComponent::setup() {
|
110
|
-
this->name_ = App.get_name().c_str();
|
111
|
-
if (strlen(this->name_) > 255) {
|
112
|
-
this->mark_failed();
|
113
|
-
this->status_set_error("Device name exceeds 255 chars");
|
114
|
-
return;
|
115
|
-
}
|
116
|
-
this->resend_ping_key_ = this->ping_pong_enable_;
|
117
|
-
// restore the upper 32 bits of the rolling code, increment and save.
|
118
|
-
this->pref_ = global_preferences->make_preference<uint32_t>(PREF_HASH, true);
|
119
|
-
this->pref_.load(&this->rolling_code_[1]);
|
120
|
-
this->rolling_code_[1]++;
|
121
|
-
this->pref_.save(&this->rolling_code_[1]);
|
122
|
-
this->ping_key_ = random_uint32();
|
123
|
-
ESP_LOGV(TAG, "Rolling code incremented, upper part now %u", (unsigned) this->rolling_code_[1]);
|
124
|
-
#ifdef USE_SENSOR
|
125
|
-
for (auto &sensor : this->sensors_) {
|
126
|
-
sensor.sensor->add_on_state_callback([this, &sensor](float x) {
|
127
|
-
this->updated_ = true;
|
128
|
-
sensor.updated = true;
|
129
|
-
});
|
130
|
-
}
|
131
|
-
#endif
|
132
|
-
#ifdef USE_BINARY_SENSOR
|
133
|
-
for (auto &sensor : this->binary_sensors_) {
|
134
|
-
sensor.sensor->add_on_state_callback([this, &sensor](bool value) {
|
135
|
-
this->updated_ = true;
|
136
|
-
sensor.updated = true;
|
137
|
-
});
|
138
|
-
}
|
139
|
-
#endif
|
140
|
-
this->should_send_ = this->ping_pong_enable_;
|
141
|
-
#ifdef USE_SENSOR
|
142
|
-
this->should_send_ |= !this->sensors_.empty();
|
143
|
-
#endif
|
144
|
-
#ifdef USE_BINARY_SENSOR
|
145
|
-
this->should_send_ |= !this->binary_sensors_.empty();
|
146
|
-
#endif
|
147
|
-
this->should_listen_ = !this->providers_.empty() || this->is_encrypted_();
|
148
|
-
// initialise the header. This is invariant.
|
149
|
-
add(this->header_, MAGIC_NUMBER);
|
150
|
-
add(this->header_, this->name_);
|
151
|
-
// pad to a multiple of 4 bytes
|
152
|
-
while (this->header_.size() & 0x3)
|
153
|
-
this->header_.push_back(0);
|
154
14
|
#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
|
155
15
|
for (const auto &address : this->addresses_) {
|
156
16
|
struct sockaddr saddr {};
|
157
|
-
socket::set_sockaddr(&saddr, sizeof(saddr), address, this->
|
17
|
+
socket::set_sockaddr(&saddr, sizeof(saddr), address, this->broadcast_port_);
|
158
18
|
this->sockaddrs_.push_back(saddr);
|
159
19
|
}
|
160
20
|
// set up broadcast socket
|
161
|
-
if (this->
|
21
|
+
if (this->should_broadcast_) {
|
162
22
|
this->broadcast_socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
163
23
|
if (this->broadcast_socket_ == nullptr) {
|
164
24
|
this->mark_failed();
|
@@ -202,14 +62,14 @@ void UDPComponent::setup() {
|
|
202
62
|
|
203
63
|
server.sin_family = AF_INET;
|
204
64
|
server.sin_addr.s_addr = ESPHOME_INADDR_ANY;
|
205
|
-
server.sin_port = htons(this->
|
65
|
+
server.sin_port = htons(this->listen_port_);
|
206
66
|
|
207
67
|
if (this->listen_address_.has_value()) {
|
208
68
|
struct ip_mreq imreq = {};
|
209
69
|
imreq.imr_interface.s_addr = ESPHOME_INADDR_ANY;
|
210
70
|
inet_aton(this->listen_address_.value().str().c_str(), &imreq.imr_multiaddr);
|
211
71
|
server.sin_addr.s_addr = imreq.imr_multiaddr.s_addr;
|
212
|
-
|
72
|
+
ESP_LOGD(TAG, "Join multicast %s", this->listen_address_.value().str().c_str());
|
213
73
|
err = this->listen_socket_->setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, &imreq, sizeof(imreq));
|
214
74
|
if (err < 0) {
|
215
75
|
ESP_LOGE(TAG, "Failed to set IP_ADD_MEMBERSHIP. Error %d", errno);
|
@@ -236,341 +96,48 @@ void UDPComponent::setup() {
|
|
236
96
|
this->ipaddrs_.push_back(ipaddr);
|
237
97
|
}
|
238
98
|
if (this->should_listen_)
|
239
|
-
this->udp_client_.begin(this->
|
99
|
+
this->udp_client_.begin(this->listen_port_);
|
240
100
|
#endif
|
241
101
|
}
|
242
102
|
|
243
|
-
void UDPComponent::init_data_() {
|
244
|
-
this->data_.clear();
|
245
|
-
if (this->rolling_code_enable_) {
|
246
|
-
add(this->data_, ROLLING_CODE_KEY);
|
247
|
-
add(this->data_, this->rolling_code_[0]);
|
248
|
-
add(this->data_, this->rolling_code_[1]);
|
249
|
-
this->increment_code_();
|
250
|
-
} else {
|
251
|
-
add(this->data_, DATA_KEY);
|
252
|
-
}
|
253
|
-
for (auto pkey : this->ping_keys_) {
|
254
|
-
add(this->data_, PING_KEY);
|
255
|
-
add(this->data_, pkey.second);
|
256
|
-
}
|
257
|
-
}
|
258
|
-
|
259
|
-
void UDPComponent::flush_() {
|
260
|
-
if (!network::is_connected() || this->data_.empty())
|
261
|
-
return;
|
262
|
-
uint32_t buffer[MAX_PACKET_SIZE / 4];
|
263
|
-
memset(buffer, 0, sizeof buffer);
|
264
|
-
// len must be a multiple of 4
|
265
|
-
auto header_len = round4(this->header_.size()) / 4;
|
266
|
-
auto len = round4(data_.size()) / 4;
|
267
|
-
memcpy(buffer, this->header_.data(), this->header_.size());
|
268
|
-
memcpy(buffer + header_len, this->data_.data(), this->data_.size());
|
269
|
-
if (this->is_encrypted_()) {
|
270
|
-
xxtea::encrypt(buffer + header_len, len, (uint32_t *) this->encryption_key_.data());
|
271
|
-
}
|
272
|
-
auto total_len = (header_len + len) * 4;
|
273
|
-
this->send_packet_(buffer, total_len);
|
274
|
-
}
|
275
|
-
|
276
|
-
void UDPComponent::add_binary_data_(uint8_t key, const char *id, bool data) {
|
277
|
-
auto len = 1 + 1 + 1 + strlen(id);
|
278
|
-
if (len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
|
279
|
-
this->flush_();
|
280
|
-
}
|
281
|
-
add(this->data_, key);
|
282
|
-
add(this->data_, (uint8_t) data);
|
283
|
-
add(this->data_, id);
|
284
|
-
}
|
285
|
-
void UDPComponent::add_data_(uint8_t key, const char *id, float data) {
|
286
|
-
FuData udata{.f32 = data};
|
287
|
-
this->add_data_(key, id, udata.u32);
|
288
|
-
}
|
289
|
-
|
290
|
-
void UDPComponent::add_data_(uint8_t key, const char *id, uint32_t data) {
|
291
|
-
auto len = 4 + 1 + 1 + strlen(id);
|
292
|
-
if (len + this->header_.size() + this->data_.size() > MAX_PACKET_SIZE) {
|
293
|
-
this->flush_();
|
294
|
-
}
|
295
|
-
add(this->data_, key);
|
296
|
-
add(this->data_, data);
|
297
|
-
add(this->data_, id);
|
298
|
-
}
|
299
|
-
void UDPComponent::send_data_(bool all) {
|
300
|
-
if (!this->should_send_ || !network::is_connected())
|
301
|
-
return;
|
302
|
-
this->init_data_();
|
303
|
-
#ifdef USE_SENSOR
|
304
|
-
for (auto &sensor : this->sensors_) {
|
305
|
-
if (all || sensor.updated) {
|
306
|
-
sensor.updated = false;
|
307
|
-
this->add_data_(SENSOR_KEY, sensor.id, sensor.sensor->get_state());
|
308
|
-
}
|
309
|
-
}
|
310
|
-
#endif
|
311
|
-
#ifdef USE_BINARY_SENSOR
|
312
|
-
for (auto &sensor : this->binary_sensors_) {
|
313
|
-
if (all || sensor.updated) {
|
314
|
-
sensor.updated = false;
|
315
|
-
this->add_binary_data_(BINARY_SENSOR_KEY, sensor.id, sensor.sensor->state);
|
316
|
-
}
|
317
|
-
}
|
318
|
-
#endif
|
319
|
-
this->flush_();
|
320
|
-
this->updated_ = false;
|
321
|
-
this->resend_data_ = false;
|
322
|
-
}
|
323
|
-
|
324
|
-
void UDPComponent::update() {
|
325
|
-
this->updated_ = true;
|
326
|
-
this->resend_data_ = this->should_send_;
|
327
|
-
auto now = millis() / 1000;
|
328
|
-
if (this->last_key_time_ + this->ping_pong_recyle_time_ < now) {
|
329
|
-
this->resend_ping_key_ = this->ping_pong_enable_;
|
330
|
-
this->last_key_time_ = now;
|
331
|
-
}
|
332
|
-
}
|
333
|
-
|
334
103
|
void UDPComponent::loop() {
|
335
|
-
|
104
|
+
auto buf = std::vector<uint8_t>(MAX_PACKET_SIZE);
|
336
105
|
if (this->should_listen_) {
|
337
106
|
for (;;) {
|
338
107
|
#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
|
339
|
-
auto len = this->listen_socket_->read(buf,
|
108
|
+
auto len = this->listen_socket_->read(buf.data(), buf.size());
|
340
109
|
#endif
|
341
110
|
#ifdef USE_SOCKET_IMPL_LWIP_TCP
|
342
111
|
auto len = this->udp_client_.parsePacket();
|
343
112
|
if (len > 0)
|
344
|
-
len = this->udp_client_.read(buf,
|
345
|
-
#endif
|
346
|
-
if (len > 0) {
|
347
|
-
this->process_(buf, len);
|
348
|
-
continue;
|
349
|
-
}
|
350
|
-
break;
|
351
|
-
}
|
352
|
-
}
|
353
|
-
if (this->resend_ping_key_)
|
354
|
-
this->send_ping_pong_request_();
|
355
|
-
if (this->updated_) {
|
356
|
-
this->send_data_(this->resend_data_);
|
357
|
-
}
|
358
|
-
}
|
359
|
-
|
360
|
-
void UDPComponent::add_key_(const char *name, uint32_t key) {
|
361
|
-
if (!this->is_encrypted_())
|
362
|
-
return;
|
363
|
-
if (this->ping_keys_.count(name) == 0 && this->ping_keys_.size() == MAX_PING_KEYS) {
|
364
|
-
ESP_LOGW(TAG, "Ping key from %s discarded", name);
|
365
|
-
return;
|
366
|
-
}
|
367
|
-
this->ping_keys_[name] = key;
|
368
|
-
this->resend_data_ = true;
|
369
|
-
ESP_LOGV(TAG, "Ping key from %s now %X", name, (unsigned) key);
|
370
|
-
}
|
371
|
-
|
372
|
-
void UDPComponent::process_ping_request_(const char *name, uint8_t *ptr, size_t len) {
|
373
|
-
if (len != 4) {
|
374
|
-
ESP_LOGW(TAG, "Bad ping request");
|
375
|
-
return;
|
376
|
-
}
|
377
|
-
auto key = get_uint32(ptr);
|
378
|
-
this->add_key_(name, key);
|
379
|
-
ESP_LOGV(TAG, "Updated ping key for %s to %08X", name, (unsigned) key);
|
380
|
-
}
|
381
|
-
|
382
|
-
static bool process_rolling_code(Provider &provider, uint8_t *&buf, const uint8_t *end) {
|
383
|
-
if (end - buf < 8)
|
384
|
-
return false;
|
385
|
-
auto code0 = get_uint32(buf);
|
386
|
-
auto code1 = get_uint32(buf);
|
387
|
-
if (code1 < provider.last_code[1] || (code1 == provider.last_code[1] && code0 <= provider.last_code[0])) {
|
388
|
-
ESP_LOGW(TAG, "Rolling code for %s %08lX:%08lX is old", provider.name, (unsigned long) code1,
|
389
|
-
(unsigned long) code0);
|
390
|
-
return false;
|
391
|
-
}
|
392
|
-
provider.last_code[0] = code0;
|
393
|
-
provider.last_code[1] = code1;
|
394
|
-
return true;
|
395
|
-
}
|
396
|
-
|
397
|
-
/**
|
398
|
-
* Process a received packet
|
399
|
-
*/
|
400
|
-
void UDPComponent::process_(uint8_t *buf, const size_t len) {
|
401
|
-
auto ping_key_seen = !this->ping_pong_enable_;
|
402
|
-
if (len < 8) {
|
403
|
-
ESP_LOGV(TAG, "Bad length %zu", len);
|
404
|
-
return;
|
405
|
-
}
|
406
|
-
char namebuf[256]{};
|
407
|
-
uint8_t byte;
|
408
|
-
uint8_t *start_ptr = buf;
|
409
|
-
const uint8_t *end = buf + len;
|
410
|
-
FuData rdata{};
|
411
|
-
auto magic = get_uint16(buf);
|
412
|
-
if (magic != MAGIC_NUMBER && magic != MAGIC_PING) {
|
413
|
-
ESP_LOGV(TAG, "Bad magic %X", magic);
|
414
|
-
return;
|
415
|
-
}
|
416
|
-
|
417
|
-
auto hlen = *buf++;
|
418
|
-
if (hlen > len - 3) {
|
419
|
-
ESP_LOGV(TAG, "Bad hostname length %u > %zu", hlen, len - 3);
|
420
|
-
return;
|
421
|
-
}
|
422
|
-
memcpy(namebuf, buf, hlen);
|
423
|
-
if (strcmp(this->name_, namebuf) == 0) {
|
424
|
-
ESP_LOGV(TAG, "Ignoring our own data");
|
425
|
-
return;
|
426
|
-
}
|
427
|
-
buf += hlen;
|
428
|
-
if (magic == MAGIC_PING) {
|
429
|
-
this->process_ping_request_(namebuf, buf, end - buf);
|
430
|
-
return;
|
431
|
-
}
|
432
|
-
if (round4(len) != len) {
|
433
|
-
ESP_LOGW(TAG, "Bad length %zu", len);
|
434
|
-
return;
|
435
|
-
}
|
436
|
-
hlen = round4(hlen + 3);
|
437
|
-
buf = start_ptr + hlen;
|
438
|
-
if (buf == end) {
|
439
|
-
ESP_LOGV(TAG, "No data after header");
|
440
|
-
return;
|
441
|
-
}
|
442
|
-
|
443
|
-
if (this->providers_.count(namebuf) == 0) {
|
444
|
-
ESP_LOGVV(TAG, "Unknown hostname %s", namebuf);
|
445
|
-
return;
|
446
|
-
}
|
447
|
-
auto &provider = this->providers_[namebuf];
|
448
|
-
// if encryption not used with this host, ping check is pointless since it would be easily spoofed.
|
449
|
-
if (provider.encryption_key.empty())
|
450
|
-
ping_key_seen = true;
|
451
|
-
|
452
|
-
ESP_LOGV(TAG, "Found hostname %s", namebuf);
|
453
|
-
#ifdef USE_SENSOR
|
454
|
-
auto &sensors = this->remote_sensors_[namebuf];
|
455
|
-
#endif
|
456
|
-
#ifdef USE_BINARY_SENSOR
|
457
|
-
auto &binary_sensors = this->remote_binary_sensors_[namebuf];
|
113
|
+
len = this->udp_client_.read(buf.data(), buf.size());
|
458
114
|
#endif
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
if (byte == ROLLING_CODE_KEY) {
|
465
|
-
if (!process_rolling_code(provider, buf, end))
|
466
|
-
return;
|
467
|
-
} else if (byte != DATA_KEY) {
|
468
|
-
ESP_LOGV(TAG, "Expected rolling_key or data_key, got %X", byte);
|
469
|
-
return;
|
470
|
-
}
|
471
|
-
while (buf < end) {
|
472
|
-
byte = *buf++;
|
473
|
-
if (byte == ZERO_FILL_KEY)
|
474
|
-
continue;
|
475
|
-
if (byte == PING_KEY) {
|
476
|
-
if (end - buf < 4) {
|
477
|
-
ESP_LOGV(TAG, "PING_KEY requires 4 more bytes");
|
478
|
-
return;
|
479
|
-
}
|
480
|
-
auto key = get_uint32(buf);
|
481
|
-
if (key == this->ping_key_) {
|
482
|
-
ping_key_seen = true;
|
483
|
-
ESP_LOGV(TAG, "Found good ping key %X", (unsigned) key);
|
484
|
-
} else {
|
485
|
-
ESP_LOGV(TAG, "Unknown ping key %X", (unsigned) key);
|
486
|
-
}
|
487
|
-
continue;
|
488
|
-
}
|
489
|
-
if (!ping_key_seen) {
|
490
|
-
ESP_LOGW(TAG, "Ping key not seen");
|
491
|
-
this->resend_ping_key_ = true;
|
492
|
-
break;
|
115
|
+
if (len <= 0)
|
116
|
+
break;
|
117
|
+
buf.resize(len);
|
118
|
+
ESP_LOGV(TAG, "Received packet of length %zu", len);
|
119
|
+
this->packet_listeners_.call(buf);
|
493
120
|
}
|
494
|
-
if (byte == BINARY_SENSOR_KEY) {
|
495
|
-
if (end - buf < 3) {
|
496
|
-
ESP_LOGV(TAG, "Binary sensor key requires at least 3 more bytes");
|
497
|
-
return;
|
498
|
-
}
|
499
|
-
rdata.u32 = *buf++;
|
500
|
-
} else if (byte == SENSOR_KEY) {
|
501
|
-
if (end - buf < 6) {
|
502
|
-
ESP_LOGV(TAG, "Sensor key requires at least 6 more bytes");
|
503
|
-
return;
|
504
|
-
}
|
505
|
-
rdata.u32 = get_uint32(buf);
|
506
|
-
} else {
|
507
|
-
ESP_LOGW(TAG, "Unknown key byte %X", byte);
|
508
|
-
return;
|
509
|
-
}
|
510
|
-
|
511
|
-
hlen = *buf++;
|
512
|
-
if (end - buf < hlen) {
|
513
|
-
ESP_LOGV(TAG, "Name length of %u not available", hlen);
|
514
|
-
return;
|
515
|
-
}
|
516
|
-
memset(namebuf, 0, sizeof namebuf);
|
517
|
-
memcpy(namebuf, buf, hlen);
|
518
|
-
ESP_LOGV(TAG, "Found sensor key %d, id %s, data %lX", byte, namebuf, (unsigned long) rdata.u32);
|
519
|
-
buf += hlen;
|
520
|
-
#ifdef USE_SENSOR
|
521
|
-
if (byte == SENSOR_KEY && sensors.count(namebuf) != 0)
|
522
|
-
sensors[namebuf]->publish_state(rdata.f32);
|
523
|
-
#endif
|
524
|
-
#ifdef USE_BINARY_SENSOR
|
525
|
-
if (byte == BINARY_SENSOR_KEY && binary_sensors.count(namebuf) != 0)
|
526
|
-
binary_sensors[namebuf]->publish_state(rdata.u32 != 0);
|
527
|
-
#endif
|
528
121
|
}
|
529
122
|
}
|
530
123
|
|
531
124
|
void UDPComponent::dump_config() {
|
532
125
|
ESP_LOGCONFIG(TAG, "UDP:");
|
533
|
-
ESP_LOGCONFIG(TAG, " Port: %u", this->
|
534
|
-
ESP_LOGCONFIG(TAG, "
|
535
|
-
ESP_LOGCONFIG(TAG, " Ping-pong: %s", YESNO(this->ping_pong_enable_));
|
126
|
+
ESP_LOGCONFIG(TAG, " Listen Port: %u", this->listen_port_);
|
127
|
+
ESP_LOGCONFIG(TAG, " Broadcast Port: %u", this->broadcast_port_);
|
536
128
|
for (const auto &address : this->addresses_)
|
537
129
|
ESP_LOGCONFIG(TAG, " Address: %s", address.c_str());
|
538
130
|
if (this->listen_address_.has_value()) {
|
539
131
|
ESP_LOGCONFIG(TAG, " Listen address: %s", this->listen_address_.value().str().c_str());
|
540
132
|
}
|
541
|
-
|
542
|
-
|
543
|
-
ESP_LOGCONFIG(TAG, " Sensor: %s", sensor.id);
|
544
|
-
#endif
|
545
|
-
#ifdef USE_BINARY_SENSOR
|
546
|
-
for (auto sensor : this->binary_sensors_)
|
547
|
-
ESP_LOGCONFIG(TAG, " Binary Sensor: %s", sensor.id);
|
548
|
-
#endif
|
549
|
-
for (const auto &host : this->providers_) {
|
550
|
-
ESP_LOGCONFIG(TAG, " Remote host: %s", host.first.c_str());
|
551
|
-
ESP_LOGCONFIG(TAG, " Encrypted: %s", YESNO(!host.second.encryption_key.empty()));
|
552
|
-
#ifdef USE_SENSOR
|
553
|
-
for (const auto &sensor : this->remote_sensors_[host.first.c_str()])
|
554
|
-
ESP_LOGCONFIG(TAG, " Sensor: %s", sensor.first.c_str());
|
555
|
-
#endif
|
556
|
-
#ifdef USE_BINARY_SENSOR
|
557
|
-
for (const auto &sensor : this->remote_binary_sensors_[host.first.c_str()])
|
558
|
-
ESP_LOGCONFIG(TAG, " Binary Sensor: %s", sensor.first.c_str());
|
559
|
-
#endif
|
560
|
-
}
|
133
|
+
ESP_LOGCONFIG(TAG, " Broadcasting: %s", YESNO(this->should_broadcast_));
|
134
|
+
ESP_LOGCONFIG(TAG, " Listening: %s", YESNO(this->should_listen_));
|
561
135
|
}
|
562
|
-
|
563
|
-
|
564
|
-
if (++this->rolling_code_[0] == 0) {
|
565
|
-
this->rolling_code_[1]++;
|
566
|
-
this->pref_.save(&this->rolling_code_[1]);
|
567
|
-
}
|
568
|
-
}
|
569
|
-
}
|
570
|
-
void UDPComponent::send_packet_(void *data, size_t len) {
|
136
|
+
|
137
|
+
void UDPComponent::send_packet(const uint8_t *data, size_t size) {
|
571
138
|
#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS)
|
572
139
|
for (const auto &saddr : this->sockaddrs_) {
|
573
|
-
auto result = this->broadcast_socket_->sendto(data,
|
140
|
+
auto result = this->broadcast_socket_->sendto(data, size, 0, &saddr, sizeof(saddr));
|
574
141
|
if (result < 0)
|
575
142
|
ESP_LOGW(TAG, "sendto() error %d", errno);
|
576
143
|
}
|
@@ -578,8 +145,8 @@ void UDPComponent::send_packet_(void *data, size_t len) {
|
|
578
145
|
#ifdef USE_SOCKET_IMPL_LWIP_TCP
|
579
146
|
auto iface = IPAddress(0, 0, 0, 0);
|
580
147
|
for (const auto &saddr : this->ipaddrs_) {
|
581
|
-
if (this->udp_client_.beginPacketMulticast(saddr, this->
|
582
|
-
this->udp_client_.write(
|
148
|
+
if (this->udp_client_.beginPacketMulticast(saddr, this->broadcast_port_, iface, 128) != 0) {
|
149
|
+
this->udp_client_.write(data, size);
|
583
150
|
auto result = this->udp_client_.endPacket();
|
584
151
|
if (result == 0)
|
585
152
|
ESP_LOGW(TAG, "udp.write() error");
|
@@ -587,18 +154,7 @@ void UDPComponent::send_packet_(void *data, size_t len) {
|
|
587
154
|
}
|
588
155
|
#endif
|
589
156
|
}
|
590
|
-
|
591
|
-
void UDPComponent::send_ping_pong_request_() {
|
592
|
-
if (!this->ping_pong_enable_ || !network::is_connected())
|
593
|
-
return;
|
594
|
-
this->ping_key_ = random_uint32();
|
595
|
-
this->ping_header_.clear();
|
596
|
-
add(this->ping_header_, MAGIC_PING);
|
597
|
-
add(this->ping_header_, this->name_);
|
598
|
-
add(this->ping_header_, this->ping_key_);
|
599
|
-
this->send_packet_(this->ping_header_.data(), this->ping_header_.size());
|
600
|
-
this->resend_ping_key_ = false;
|
601
|
-
ESP_LOGV(TAG, "Sent new ping request %08X", (unsigned) this->ping_key_);
|
602
|
-
}
|
603
157
|
} // namespace udp
|
604
158
|
} // namespace esphome
|
159
|
+
|
160
|
+
#endif
|