esphome 2025.6.2__py3-none-any.whl → 2025.7.0b1__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 +1 -3
- esphome/codegen.py +2 -0
- esphome/components/ac_dimmer/ac_dimmer.cpp +6 -6
- esphome/components/adc/__init__.py +25 -1
- esphome/components/adc/adc_sensor.h +11 -11
- esphome/components/adc/adc_sensor_common.cpp +1 -1
- esphome/components/adc/adc_sensor_esp32.cpp +16 -8
- esphome/components/ade7880/ade7880.h +0 -2
- esphome/components/ads1115/ads1115.h +0 -1
- esphome/components/ads1118/ads1118.h +0 -1
- esphome/components/ags10/ags10.h +0 -2
- esphome/components/aic3204/aic3204.h +0 -1
- esphome/components/alarm_control_panel/__init__.py +5 -2
- esphome/components/alpha3/alpha3.h +0 -1
- esphome/components/am43/cover/am43_cover.h +0 -1
- esphome/components/am43/sensor/am43_sensor.h +0 -1
- esphome/components/analog_threshold/analog_threshold_binary_sensor.h +0 -2
- esphome/components/anova/anova.cpp +5 -1
- esphome/components/anova/anova.h +0 -1
- esphome/components/apds9960/apds9960.cpp +1 -1
- esphome/components/api/__init__.py +42 -20
- esphome/components/api/api_connection.cpp +318 -391
- esphome/components/api/api_connection.h +206 -126
- esphome/components/api/api_frame_helper.cpp +89 -124
- esphome/components/api/api_frame_helper.h +57 -45
- esphome/components/api/api_pb2.cpp +414 -4350
- esphome/components/api/api_pb2.h +287 -198
- esphome/components/api/api_pb2_dump.cpp +4333 -0
- esphome/components/api/api_pb2_service.cpp +180 -425
- esphome/components/api/api_pb2_service.h +7 -6
- esphome/components/api/api_pb2_size.h +2 -4
- esphome/components/api/api_server.cpp +138 -167
- esphome/components/api/api_server.h +66 -12
- esphome/components/api/client.py +10 -4
- esphome/components/api/list_entities.cpp +36 -105
- esphome/components/api/list_entities.h +31 -23
- esphome/components/api/proto.h +26 -3
- esphome/components/api/subscribe_state.cpp +23 -29
- esphome/components/api/subscribe_state.h +26 -19
- esphome/components/as5600/as5600.h +0 -1
- esphome/components/async_tcp/__init__.py +14 -5
- esphome/components/atc_mithermometer/atc_mithermometer.h +0 -1
- esphome/components/atm90e32/atm90e32.cpp +2 -1
- esphome/components/audio/audio_decoder.cpp +1 -1
- esphome/components/audio/audio_transfer_buffer.cpp +2 -2
- esphome/components/b_parasite/b_parasite.h +0 -1
- esphome/components/bedjet/bedjet_hub.cpp +5 -1
- esphome/components/bedjet/climate/bedjet_climate.cpp +5 -1
- esphome/components/beken_spi_led_strip/led_strip.cpp +4 -2
- esphome/components/bh1750/bh1750.cpp +5 -5
- esphome/components/binary_sensor/__init__.py +82 -5
- esphome/components/binary_sensor/automation.h +19 -1
- esphome/components/binary_sensor/binary_sensor.cpp +12 -30
- esphome/components/binary_sensor/binary_sensor.h +11 -25
- esphome/components/binary_sensor/filter.cpp +29 -24
- esphome/components/binary_sensor/filter.h +20 -10
- esphome/components/ble_client/output/ble_binary_output.h +0 -1
- esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +5 -1
- esphome/components/ble_client/sensor/ble_rssi_sensor.h +0 -1
- esphome/components/ble_client/sensor/ble_sensor.cpp +5 -1
- esphome/components/ble_client/sensor/ble_sensor.h +0 -1
- esphome/components/ble_client/switch/ble_switch.h +0 -1
- esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +5 -1
- esphome/components/ble_client/text_sensor/ble_text_sensor.h +0 -1
- esphome/components/ble_presence/ble_presence_device.h +0 -1
- esphome/components/ble_rssi/ble_rssi_sensor.h +0 -1
- esphome/components/ble_scanner/ble_scanner.h +0 -1
- esphome/components/bluetooth_proxy/bluetooth_connection.h +9 -2
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +16 -6
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -2
- esphome/components/bme680/sensor.py +1 -1
- esphome/components/bmp581/bmp581.h +0 -2
- esphome/components/button/__init__.py +5 -2
- esphome/components/camera/__init__.py +1 -0
- esphome/components/camera/camera.cpp +22 -0
- esphome/components/camera/camera.h +80 -0
- esphome/components/canbus/__init__.py +1 -0
- esphome/components/cap1188/cap1188.h +0 -1
- esphome/components/captive_portal/__init__.py +12 -2
- esphome/components/captive_portal/captive_portal.cpp +12 -2
- esphome/components/captive_portal/captive_portal.h +5 -2
- esphome/components/ccs811/ccs811.h +0 -2
- esphome/components/climate/__init__.py +5 -2
- esphome/components/cm1106/sensor.py +2 -2
- esphome/components/const/__init__.py +2 -0
- esphome/components/copy/binary_sensor/copy_binary_sensor.h +0 -1
- esphome/components/copy/button/copy_button.h +0 -1
- esphome/components/copy/cover/copy_cover.h +0 -1
- esphome/components/copy/fan/copy_fan.h +0 -1
- esphome/components/copy/lock/copy_lock.h +0 -1
- esphome/components/copy/number/copy_number.h +0 -1
- esphome/components/copy/select/copy_select.h +0 -1
- esphome/components/copy/sensor/copy_sensor.h +0 -1
- esphome/components/copy/switch/copy_switch.h +0 -1
- esphome/components/copy/text/copy_text.h +0 -1
- esphome/components/copy/text_sensor/copy_text_sensor.h +0 -1
- esphome/components/cover/__init__.py +5 -2
- esphome/components/cs5460a/cs5460a.h +0 -1
- esphome/components/datetime/__init__.py +4 -2
- esphome/components/debug/__init__.py +20 -0
- esphome/components/deep_sleep/__init__.py +43 -9
- esphome/components/demo/__init__.py +2 -2
- esphome/components/display/display.cpp +4 -3
- esphome/components/display/display.h +0 -2
- esphome/components/display/display_buffer.cpp +1 -1
- esphome/components/ds2484/__init__.py +1 -0
- esphome/components/ds2484/ds2484.cpp +209 -0
- esphome/components/ds2484/ds2484.h +43 -0
- esphome/components/ds2484/one_wire.py +37 -0
- esphome/components/duty_time/duty_time_sensor.h +0 -1
- esphome/components/ens160_base/ens160_base.h +0 -1
- esphome/components/es7210/es7210.h +0 -1
- esphome/components/es7243e/es7243e.h +0 -1
- esphome/components/es8156/es8156.h +0 -1
- esphome/components/es8311/es8311.h +0 -1
- esphome/components/es8388/es8388.h +0 -1
- esphome/components/esp32/__init__.py +102 -135
- esphome/components/esp32/core.cpp +0 -4
- esphome/components/esp32/gpio.h +1 -1
- esphome/components/esp32/helpers.cpp +69 -0
- esphome/components/esp32_ble/ble.cpp +5 -6
- esphome/components/esp32_ble/ble.h +29 -14
- esphome/components/esp32_ble/ble_event.h +6 -6
- esphome/components/esp32_ble_client/ble_client_base.cpp +21 -6
- esphome/components/esp32_ble_client/ble_client_base.h +24 -9
- esphome/components/esp32_ble_tracker/__init__.py +2 -8
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +5 -5
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +11 -7
- esphome/components/esp32_camera/__init__.py +111 -97
- esphome/components/esp32_camera/esp32_camera.cpp +41 -31
- esphome/components/esp32_camera/esp32_camera.h +35 -30
- esphome/components/esp32_camera_web_server/__init__.py +2 -1
- esphome/components/esp32_camera_web_server/camera_web_server.cpp +8 -8
- esphome/components/esp32_camera_web_server/camera_web_server.h +3 -3
- esphome/components/esp32_hall/sensor.py +2 -21
- esphome/components/esp32_hosted/__init__.py +101 -0
- esphome/components/esp32_hosted/esp32_hosted.py.script +12 -0
- esphome/components/esp32_improv/esp32_improv_component.cpp +3 -0
- esphome/components/esp32_rmt/__init__.py +0 -58
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +77 -63
- esphome/components/esp32_rmt_led_strip/led_strip.h +11 -17
- esphome/components/esp32_rmt_led_strip/light.py +14 -76
- esphome/components/esp32_touch/esp32_touch.h +174 -28
- esphome/components/esp32_touch/esp32_touch_common.cpp +162 -0
- esphome/components/esp32_touch/esp32_touch_v1.cpp +238 -0
- esphome/components/esp32_touch/esp32_touch_v2.cpp +397 -0
- esphome/components/esp8266/__init__.py +1 -0
- esphome/components/esp8266/gpio.cpp +10 -10
- esphome/components/esp8266/helpers.cpp +31 -0
- esphome/components/esphome/ota/__init__.py +1 -0
- esphome/components/esphome/ota/ota_esphome.cpp +24 -19
- esphome/components/ethernet/__init__.py +42 -23
- esphome/components/ethernet/esp_eth_phy_jl1101.c +0 -16
- esphome/components/ethernet/ethernet_component.cpp +69 -29
- esphome/components/ethernet/ethernet_component.h +18 -10
- esphome/components/event/__init__.py +5 -2
- esphome/components/ezo/ezo.h +0 -1
- esphome/components/ezo_pmp/ezo_pmp.h +0 -1
- esphome/components/fan/__init__.py +5 -2
- esphome/components/feedback/feedback_cover.h +0 -1
- esphome/components/font/__init__.py +92 -82
- esphome/components/font/font.cpp +9 -2
- esphome/components/font/font.h +20 -5
- esphome/components/fs3000/fs3000.h +0 -1
- esphome/components/gcja5/gcja5.h +0 -1
- esphome/components/gl_r01_i2c/__init__.py +0 -0
- esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +68 -0
- esphome/components/gl_r01_i2c/gl_r01_i2c.h +22 -0
- esphome/components/gl_r01_i2c/sensor.py +36 -0
- esphome/components/gp8403/gp8403.h +0 -1
- esphome/components/gpio/binary_sensor/__init__.py +17 -0
- esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +77 -3
- esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +40 -0
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +0 -2
- esphome/components/he60r/he60r.h +0 -1
- esphome/components/heatpumpir/climate.py +2 -1
- esphome/components/heatpumpir/heatpumpir.cpp +1 -0
- esphome/components/heatpumpir/heatpumpir.h +1 -0
- esphome/components/honeywellabp2_i2c/honeywellabp2.h +0 -1
- esphome/components/host/__init__.py +2 -1
- esphome/components/host/helpers.cpp +57 -0
- esphome/components/http_request/__init__.py +19 -1
- esphome/components/http_request/http_request.h +1 -1
- esphome/components/http_request/http_request_arduino.cpp +0 -1
- esphome/components/http_request/http_request_arduino.h +1 -0
- esphome/components/http_request/http_request_idf.cpp +0 -1
- esphome/components/http_request/ota/ota_http_request.cpp +1 -1
- esphome/components/http_request/update/http_request_update.cpp +28 -9
- esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +3 -9
- esphome/components/hydreon_rgxx/sensor.py +1 -1
- esphome/components/i2c/__init__.py +23 -11
- esphome/components/i2c/i2c_bus.h +8 -1
- esphome/components/i2c/i2c_bus_arduino.cpp +4 -3
- esphome/components/i2c/i2c_bus_arduino.h +6 -3
- esphome/components/i2c/i2c_bus_esp_idf.h +5 -3
- esphome/components/i2c_device/i2c_device.h +0 -1
- esphome/components/i2s_audio/__init__.py +2 -10
- esphome/components/i2s_audio/i2s_audio.cpp +1 -5
- esphome/components/i2s_audio/media_player/__init__.py +2 -2
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +2 -2
- esphome/components/iaqcore/iaqcore.h +0 -2
- esphome/components/image/__init__.py +123 -24
- esphome/components/improv_serial/improv_serial_component.cpp +0 -4
- esphome/components/ina219/ina219.cpp +7 -0
- esphome/components/ina219/ina219.h +1 -0
- esphome/components/ina260/ina260.h +0 -2
- esphome/components/inkbird_ibsth1_mini/inkbird_ibsth1_mini.h +0 -1
- esphome/components/inkplate6/display.py +15 -0
- esphome/components/inkplate6/inkplate.cpp +2 -2
- esphome/components/integration/integration_sensor.h +0 -1
- esphome/components/internal_temperature/internal_temperature.cpp +8 -27
- esphome/components/internal_temperature/sensor.py +0 -26
- esphome/components/interval/interval.h +0 -2
- esphome/components/ld2410/button/__init__.py +3 -3
- esphome/components/ld2410/button/factory_reset_button.cpp +9 -0
- esphome/components/ld2410/button/{reset_button.h → factory_reset_button.h} +2 -2
- esphome/components/ld2410/ld2410.cpp +430 -261
- esphome/components/ld2410/ld2410.h +44 -146
- esphome/components/ld2410/number/__init__.py +2 -2
- esphome/components/ld2410/sensor.py +1 -1
- esphome/components/ld2410/switch/__init__.py +1 -1
- esphome/components/ld2420/ld2420.cpp +196 -100
- esphome/components/ld2420/ld2420.h +46 -118
- esphome/components/ld2420/number/__init__.py +2 -2
- esphome/components/ld2420/sensor/__init__.py +6 -2
- esphome/components/ld2420/sensor/ld2420_sensor.h +1 -1
- esphome/components/ld2450/button/__init__.py +3 -3
- esphome/components/ld2450/button/factory_reset_button.cpp +9 -0
- esphome/components/ld2450/button/{reset_button.h → factory_reset_button.h} +2 -2
- esphome/components/ld2450/ld2450.cpp +384 -232
- esphome/components/ld2450/ld2450.h +60 -69
- esphome/components/ld2450/switch/__init__.py +1 -1
- esphome/components/ledc/ledc_output.cpp +1 -63
- esphome/components/libretiny/__init__.py +4 -3
- esphome/components/libretiny/const.py +5 -0
- esphome/components/libretiny/generate_components.py +1 -0
- esphome/components/libretiny/helpers.cpp +35 -0
- esphome/components/libretiny/lt_component.cpp +5 -3
- esphome/components/light/__init__.py +4 -2
- esphome/components/light/addressable_light.h +3 -3
- esphome/components/light/light_call.cpp +180 -243
- esphome/components/light/light_call.h +72 -20
- esphome/components/light/light_color_values.h +14 -14
- esphome/components/light/light_state.h +15 -13
- esphome/components/light/transformers.h +2 -2
- esphome/components/ln882x/__init__.py +52 -0
- esphome/components/ln882x/boards.py +285 -0
- esphome/components/lock/__init__.py +5 -2
- esphome/components/logger/__init__.py +40 -3
- esphome/components/logger/logger.cpp +47 -12
- esphome/components/logger/logger.h +80 -49
- esphome/components/logger/logger_esp32.cpp +3 -3
- esphome/components/lps22/__init__.py +0 -0
- esphome/components/lps22/lps22.cpp +75 -0
- esphome/components/lps22/lps22.h +27 -0
- esphome/components/lps22/sensor.py +58 -0
- esphome/components/ltr390/ltr390.h +0 -1
- esphome/components/ltr501/ltr501.h +0 -1
- esphome/components/ltr_als_ps/ltr_als_ps.h +0 -1
- esphome/components/lvgl/__init__.py +1 -1
- esphome/components/lvgl/schemas.py +66 -6
- esphome/components/lvgl/styles.py +24 -16
- esphome/components/lvgl/widgets/__init__.py +12 -2
- esphome/components/lvgl/widgets/lv_bar.py +40 -19
- esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +1 -1
- esphome/components/max9611/max9611.h +0 -1
- esphome/components/mcp23016/__init__.py +1 -1
- esphome/components/mcp23xxx_base/__init__.py +1 -1
- esphome/components/mcp4461/__init__.py +1 -1
- esphome/components/mcp4461/output/__init__.py +3 -2
- esphome/components/mcp9600/mcp9600.h +0 -2
- esphome/components/md5/md5.cpp +3 -3
- esphome/components/md5/md5.h +1 -6
- esphome/components/mdns/__init__.py +22 -11
- esphome/components/media_player/__init__.py +4 -3
- esphome/components/micro_wake_word/__init__.py +1 -5
- esphome/components/micro_wake_word/streaming_model.cpp +2 -2
- esphome/components/microphone/microphone.cpp +7 -9
- esphome/components/microphone/microphone.h +0 -2
- esphome/components/mipi_spi/display.py +1 -0
- esphome/components/mmc5603/mmc5603.cpp +1 -1
- esphome/components/modbus/modbus.cpp +33 -15
- esphome/components/modbus/modbus.h +9 -0
- esphome/components/modbus_controller/__init__.py +42 -10
- esphome/components/modbus_controller/modbus_controller.cpp +92 -11
- esphome/components/modbus_controller/modbus_controller.h +61 -7
- esphome/components/mopeka_pro_check/mopeka_pro_check.h +0 -1
- esphome/components/mopeka_std_check/mopeka_std_check.h +0 -1
- esphome/components/mpl3115a2/mpl3115a2.h +0 -2
- esphome/components/mqtt/__init__.py +16 -0
- esphome/components/mqtt/mqtt_backend.h +2 -1
- esphome/components/mqtt/mqtt_backend_esp32.cpp +126 -45
- esphome/components/mqtt/mqtt_backend_esp32.h +106 -4
- esphome/components/mqtt/mqtt_client.cpp +15 -9
- esphome/components/mqtt/mqtt_client.h +8 -3
- esphome/components/ms8607/ms8607.h +0 -1
- esphome/components/neopixelbus/light.py +4 -1
- esphome/components/neopixelbus/neopixelbus_light.h +1 -1
- esphome/components/network/__init__.py +4 -1
- esphome/components/network/ip_address.h +1 -0
- esphome/components/nextion/__init__.py +16 -0
- esphome/components/nextion/base_component.py +1 -0
- esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +1 -1
- esphome/components/nextion/display.py +14 -4
- esphome/components/nextion/nextion.cpp +166 -101
- esphome/components/nextion/nextion.h +84 -53
- esphome/components/nextion/nextion_commands.cpp +11 -10
- esphome/components/nextion/nextion_component.cpp +28 -28
- esphome/components/nextion/nextion_component.h +53 -18
- esphome/components/nextion/nextion_component_base.h +3 -0
- esphome/components/nextion/nextion_upload.cpp +36 -0
- esphome/components/nextion/nextion_upload_arduino.cpp +10 -35
- esphome/components/nextion/nextion_upload_idf.cpp +9 -33
- esphome/components/nextion/sensor/nextion_sensor.cpp +1 -1
- esphome/components/nextion/switch/nextion_switch.cpp +1 -1
- esphome/components/nextion/text_sensor/nextion_textsensor.cpp +1 -1
- esphome/components/nfc/nfc.cpp +3 -22
- esphome/components/nfc/nfc.h +3 -3
- esphome/components/number/__init__.py +5 -2
- esphome/components/online_image/__init__.py +5 -0
- esphome/components/online_image/online_image.cpp +6 -2
- esphome/components/online_image/online_image.h +4 -1
- esphome/components/opentherm/opentherm.cpp +7 -12
- esphome/components/openthread/__init__.py +47 -40
- esphome/components/openthread/const.py +1 -0
- esphome/components/openthread/openthread_esp.cpp +27 -5
- esphome/components/opt3001/__init__.py +0 -0
- esphome/components/opt3001/opt3001.cpp +122 -0
- esphome/components/opt3001/opt3001.h +27 -0
- esphome/components/opt3001/sensor.py +35 -0
- esphome/components/ota/__init__.py +17 -0
- esphome/components/ota/ota_backend.h +27 -1
- esphome/components/ota/ota_backend_arduino_esp32.cpp +12 -2
- esphome/components/ota/ota_backend_arduino_esp32.h +3 -0
- esphome/components/ota/ota_backend_arduino_esp8266.cpp +18 -4
- esphome/components/ota/ota_backend_arduino_esp8266.h +3 -0
- esphome/components/ota/ota_backend_arduino_libretiny.cpp +12 -2
- esphome/components/ota/ota_backend_arduino_libretiny.h +3 -0
- esphome/components/ota/ota_backend_arduino_rp2040.cpp +9 -2
- esphome/components/ota/ota_backend_arduino_rp2040.h +3 -0
- esphome/components/ota/ota_backend_esp_idf.cpp +10 -16
- esphome/components/ota/ota_backend_esp_idf.h +1 -0
- esphome/components/packages/__init__.py +5 -2
- esphome/components/packet_transport/binary_sensor.py +61 -4
- esphome/components/packet_transport/packet_transport.cpp +31 -1
- esphome/components/packet_transport/packet_transport.h +11 -5
- esphome/components/pcf8574/__init__.py +1 -1
- esphome/components/pi4ioe5v6408/__init__.py +84 -0
- esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +171 -0
- esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +70 -0
- esphome/components/pmsa003i/pmsa003i.h +0 -1
- esphome/components/pmsx003/pmsx003.h +0 -1
- esphome/components/pn7150/pn7150.cpp +7 -7
- esphome/components/pn7150/pn7150.h +0 -1
- esphome/components/pn7160/pn7160.cpp +7 -7
- esphome/components/pn7160/pn7160.h +0 -1
- esphome/components/preferences/syncer.h +2 -0
- esphome/components/prometheus/prometheus_handler.h +1 -1
- esphome/components/psram/psram.cpp +0 -20
- esphome/components/pulse_counter/pulse_counter_sensor.h +0 -1
- esphome/components/pulse_meter/pulse_meter_sensor.cpp +8 -4
- esphome/components/pulse_width/pulse_width.h +0 -1
- esphome/components/pvvx_mithermometer/display/pvvx_display.cpp +0 -4
- esphome/components/pvvx_mithermometer/display/pvvx_display.h +0 -2
- esphome/components/pvvx_mithermometer/pvvx_mithermometer.h +0 -1
- esphome/components/qr_code/__init__.py +13 -10
- esphome/components/qwiic_pir/qwiic_pir.h +0 -1
- esphome/components/radon_eye_ble/radon_eye_listener.cpp +1 -1
- esphome/components/rc522/rc522.h +0 -1
- esphome/components/rdm6300/rdm6300.h +0 -2
- esphome/components/remote_base/__init__.py +7 -5
- esphome/components/remote_base/remote_base.cpp +24 -21
- esphome/components/remote_base/remote_base.h +3 -26
- esphome/components/remote_receiver/__init__.py +40 -46
- esphome/components/remote_receiver/remote_receiver.h +4 -18
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -87
- esphome/components/remote_receiver/remote_receiver_esp8266.cpp +1 -1
- esphome/components/remote_transmitter/__init__.py +42 -43
- esphome/components/remote_transmitter/remote_transmitter.h +2 -14
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -77
- esphome/components/resistance/resistance_sensor.h +0 -1
- esphome/components/rp2040/__init__.py +1 -0
- esphome/components/rp2040/helpers.cpp +55 -0
- esphome/components/rp2040_pio_led_strip/led_strip.cpp +2 -2
- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -4
- esphome/components/rtttl/__init__.py +4 -4
- esphome/components/rtttl/rtttl.cpp +10 -1
- esphome/components/ruuvitag/ruuvitag.h +0 -1
- esphome/components/safe_mode/safe_mode.cpp +2 -0
- esphome/components/safe_mode/safe_mode.h +4 -1
- esphome/components/scd30/scd30.h +0 -1
- esphome/components/scd30/sensor.py +2 -2
- esphome/components/scd4x/scd4x.cpp +61 -54
- esphome/components/scd4x/scd4x.h +17 -15
- esphome/components/scd4x/sensor.py +4 -4
- esphome/components/script/script.h +0 -2
- esphome/components/sdp3x/sensor.py +1 -1
- esphome/components/select/__init__.py +5 -2
- esphome/components/sen5x/sen5x.h +0 -1
- esphome/components/senseair/senseair.h +0 -1
- esphome/components/sensor/__init__.py +4 -2
- esphome/components/sensor/filter.cpp +1 -1
- esphome/components/sensor/sensor.cpp +12 -6
- esphome/components/sensor/sensor.h +13 -5
- esphome/components/servo/servo.h +0 -1
- esphome/components/sfa30/sfa30.h +0 -1
- esphome/components/sgp30/sgp30.h +0 -1
- esphome/components/sgp4x/sgp4x.h +0 -1
- esphome/components/shelly_dimmer/stm32flash.cpp +1 -2
- esphome/components/sht4x/sht4x.h +0 -1
- esphome/components/sm300d2/sm300d2.h +0 -2
- esphome/components/smt100/sensor.py +8 -4
- esphome/components/smt100/smt100.cpp +5 -5
- esphome/components/smt100/smt100.h +3 -3
- esphome/components/sn74hc595/__init__.py +1 -1
- esphome/components/sn74hc595/sn74hc595.cpp +5 -4
- esphome/components/sntp/sntp_component.cpp +9 -3
- esphome/components/sntp/time.py +2 -0
- esphome/components/socket/__init__.py +17 -0
- esphome/components/spi/__init__.py +27 -6
- esphome/components/spi/spi.cpp +3 -2
- esphome/components/spi/spi.h +9 -3
- esphome/components/spi/spi_arduino.cpp +3 -5
- esphome/components/spi/spi_esp_idf.cpp +40 -21
- esphome/components/spi_led_strip/spi_led_strip.cpp +1 -1
- esphome/components/sps30/sps30.h +0 -1
- esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
- esphome/components/st7701s/st7701s.cpp +0 -4
- esphome/components/status/status_binary_sensor.h +0 -2
- esphome/components/substitutions/__init__.py +76 -19
- esphome/components/substitutions/jinja.py +99 -0
- esphome/components/sun/sun.cpp +3 -4
- esphome/components/switch/__init__.py +5 -2
- esphome/components/switch/binary_sensor/switch_binary_sensor.h +0 -1
- esphome/components/sx126x/__init__.py +317 -0
- esphome/components/sx126x/automation.h +62 -0
- esphome/components/sx126x/packet_transport/__init__.py +26 -0
- esphome/components/sx126x/packet_transport/sx126x_transport.cpp +26 -0
- esphome/components/sx126x/packet_transport/sx126x_transport.h +25 -0
- esphome/components/sx126x/sx126x.cpp +523 -0
- esphome/components/sx126x/sx126x.h +140 -0
- esphome/components/sx126x/sx126x_reg.h +163 -0
- esphome/components/sx127x/__init__.py +325 -0
- esphome/components/sx127x/automation.h +62 -0
- esphome/components/sx127x/packet_transport/__init__.py +26 -0
- esphome/components/sx127x/packet_transport/sx127x_transport.cpp +26 -0
- esphome/components/sx127x/packet_transport/sx127x_transport.h +25 -0
- esphome/components/sx127x/sx127x.cpp +498 -0
- esphome/components/sx127x/sx127x.h +128 -0
- esphome/components/sx127x/sx127x_reg.h +295 -0
- esphome/components/syslog/esphome_syslog.cpp +5 -3
- esphome/components/syslog/esphome_syslog.h +1 -1
- esphome/components/tca9555/__init__.py +1 -1
- esphome/components/template/binary_sensor/template_binary_sensor.cpp +1 -9
- esphome/components/text/__init__.py +5 -2
- esphome/components/text_sensor/__init__.py +5 -2
- esphome/components/thermostat/thermostat_climate.cpp +34 -31
- esphome/components/thermostat/thermostat_climate.h +43 -39
- esphome/components/time/__init__.py +16 -2
- esphome/components/time/real_time_clock.cpp +4 -0
- esphome/components/time/real_time_clock.h +5 -1
- esphome/components/tlc5971/tlc5971.cpp +4 -1
- esphome/components/tmp1075/tmp1075.h +0 -2
- esphome/components/tof10120/tof10120_sensor.h +0 -1
- esphome/components/tormatic/tormatic_cover.h +0 -1
- esphome/components/total_daily_energy/total_daily_energy.h +0 -1
- esphome/components/tsl2591/tsl2591.cpp +1 -1
- esphome/components/ttp229_bsf/ttp229_bsf.h +0 -1
- esphome/components/ttp229_lsf/ttp229_lsf.h +0 -1
- esphome/components/tx20/tx20.cpp +2 -2
- esphome/components/uart/__init__.py +18 -0
- esphome/components/uart/uart_component_esp_idf.cpp +1 -5
- esphome/components/update/__init__.py +5 -2
- esphome/components/update/update_entity.h +8 -0
- esphome/components/usb_host/__init__.py +5 -2
- esphome/components/valve/__init__.py +5 -2
- esphome/components/vbus/vbus.h +0 -1
- esphome/components/veml3235/veml3235.h +0 -1
- esphome/components/veml7700/veml7700.h +0 -1
- esphome/components/vl53l0x/vl53l0x_sensor.h +0 -1
- esphome/components/voice_assistant/voice_assistant.cpp +4 -4
- esphome/components/watchdog/watchdog.cpp +0 -4
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +6 -6
- esphome/components/web_server/__init__.py +34 -19
- esphome/components/web_server/ota/__init__.py +32 -0
- esphome/components/web_server/ota/ota_web_server.cpp +210 -0
- esphome/components/web_server/ota/ota_web_server.h +26 -0
- esphome/components/web_server/web_server.cpp +311 -430
- esphome/components/web_server/web_server.h +33 -23
- esphome/components/web_server/web_server_v1.cpp +4 -5
- esphome/components/web_server_base/__init__.py +5 -2
- esphome/components/web_server_base/web_server_base.cpp +2 -94
- esphome/components/web_server_base/web_server_base.h +5 -25
- esphome/components/web_server_idf/multipart.cpp +254 -0
- esphome/components/web_server_idf/multipart.h +86 -0
- esphome/components/web_server_idf/utils.cpp +32 -0
- esphome/components/web_server_idf/utils.h +10 -0
- esphome/components/web_server_idf/web_server_idf.cpp +162 -16
- esphome/components/web_server_idf/web_server_idf.h +11 -10
- esphome/components/wiegand/wiegand.cpp +2 -2
- esphome/components/wifi/__init__.py +18 -0
- esphome/components/wifi/wifi_component.cpp +17 -22
- esphome/components/wifi/wifi_component.h +27 -23
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +52 -59
- esphome/components/wifi/wifi_component_esp8266.cpp +46 -46
- esphome/components/wifi/wifi_component_esp_idf.cpp +35 -36
- esphome/components/wifi/wifi_component_libretiny.cpp +26 -27
- esphome/components/wifi/wifi_component_pico_w.cpp +3 -3
- esphome/components/wifi_info/wifi_info_text_sensor.cpp +6 -6
- esphome/components/wireguard/__init__.py +2 -11
- esphome/components/xiaomi_ble/xiaomi_ble.cpp +13 -1
- esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
- esphome/components/xiaomi_cgd1/xiaomi_cgd1.h +0 -1
- esphome/components/xiaomi_cgdk2/xiaomi_cgdk2.h +0 -1
- esphome/components/xiaomi_cgg1/xiaomi_cgg1.h +0 -1
- esphome/components/xiaomi_cgpr1/xiaomi_cgpr1.h +0 -1
- esphome/components/xiaomi_gcls002/xiaomi_gcls002.h +0 -1
- esphome/components/xiaomi_hhccjcy01/xiaomi_hhccjcy01.h +0 -1
- esphome/components/xiaomi_hhccjcy10/xiaomi_hhccjcy10.h +0 -1
- esphome/components/xiaomi_hhccpot002/xiaomi_hhccpot002.h +0 -1
- esphome/components/xiaomi_jqjcy01ym/xiaomi_jqjcy01ym.h +0 -1
- esphome/components/xiaomi_lywsd02/xiaomi_lywsd02.h +0 -1
- esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +0 -1
- esphome/components/xiaomi_lywsd03mmc/xiaomi_lywsd03mmc.h +0 -1
- esphome/components/xiaomi_lywsdcgq/xiaomi_lywsdcgq.h +0 -1
- esphome/components/xiaomi_mhoc303/xiaomi_mhoc303.h +0 -1
- esphome/components/xiaomi_mhoc401/xiaomi_mhoc401.h +0 -1
- esphome/components/xiaomi_miscale/xiaomi_miscale.h +0 -1
- esphome/components/xiaomi_mjyd02yla/xiaomi_mjyd02yla.h +0 -1
- esphome/components/xiaomi_mue4094rt/xiaomi_mue4094rt.h +0 -1
- esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.h +0 -1
- esphome/components/xiaomi_wx08zm/xiaomi_wx08zm.h +0 -1
- esphome/components/xiaomi_xmwsdj04mmc/__init__.py +0 -0
- esphome/components/xiaomi_xmwsdj04mmc/sensor.py +77 -0
- esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.cpp +77 -0
- esphome/components/xiaomi_xmwsdj04mmc/xiaomi_xmwsdj04mmc.h +36 -0
- esphome/components/zio_ultrasonic/zio_ultrasonic.h +0 -2
- esphome/components/zyaura/zyaura.h +0 -1
- esphome/config.py +88 -22
- esphome/config_helpers.py +74 -1
- esphome/config_validation.py +12 -1
- esphome/const.py +65 -10
- esphome/core/__init__.py +18 -2
- esphome/core/application.cpp +163 -10
- esphome/core/application.h +145 -165
- esphome/core/area.h +19 -0
- esphome/core/automation.h +58 -9
- esphome/core/color.cpp +3 -5
- esphome/core/color.h +16 -16
- esphome/core/component.cpp +151 -18
- esphome/core/component.h +98 -4
- esphome/core/component_iterator.cpp +7 -7
- esphome/core/component_iterator.h +9 -7
- esphome/core/config.py +155 -6
- esphome/core/controller.cpp +4 -2
- esphome/core/controller.h +1 -1
- esphome/core/datatypes.h +2 -2
- esphome/core/defines.h +17 -2
- esphome/core/device.h +20 -0
- esphome/core/entity_base.cpp +20 -15
- esphome/core/entity_base.h +76 -0
- esphome/core/entity_helpers.py +162 -1
- esphome/core/event_pool.h +81 -0
- esphome/core/helpers.cpp +75 -230
- esphome/core/helpers.h +164 -104
- esphome/core/lock_free_queue.h +151 -0
- esphome/core/log.cpp +2 -2
- esphome/core/log.h +2 -0
- esphome/core/optional.h +5 -0
- esphome/core/ring_buffer.cpp +2 -2
- esphome/core/scheduler.cpp +278 -103
- esphome/core/scheduler.h +157 -17
- esphome/core/time.cpp +5 -5
- esphome/core/time.h +5 -5
- esphome/cpp_generator.py +17 -0
- esphome/cpp_helpers.py +0 -22
- esphome/cpp_types.py +3 -1
- esphome/dashboard/entries.py +1 -1
- esphome/dashboard/util/text.py +5 -21
- esphome/dashboard/web_server.py +9 -1
- esphome/helpers.py +47 -0
- esphome/loader.py +15 -1
- esphome/pins.py +14 -8
- esphome/wizard.py +16 -3
- esphome/writer.py +21 -3
- esphome/yaml_util.py +0 -2
- {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/METADATA +10 -9
- {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/RECORD +593 -533
- esphome/components/esp32_ble/ble_event_pool.h +0 -72
- esphome/components/esp32_ble/queue.h +0 -85
- esphome/components/esp32_hall/esp32_hall.cpp +0 -25
- esphome/components/esp32_hall/esp32_hall.h +0 -23
- esphome/components/esp32_touch/esp32_touch.cpp +0 -355
- esphome/components/ld2410/button/reset_button.cpp +0 -9
- esphome/components/ld2450/button/reset_button.cpp +0 -9
- esphome/components/openthread/tlv.py +0 -65
- /esphome/{dashboard/enum.py → enum.py} +0 -0
- {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/WHEEL +0 -0
- {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/entry_points.txt +0 -0
- {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.6.2.dist-info → esphome-2025.7.0b1.dist-info}/top_level.txt +0 -0
|
@@ -28,8 +28,32 @@
|
|
|
28
28
|
namespace esphome {
|
|
29
29
|
namespace api {
|
|
30
30
|
|
|
31
|
+
// Read a maximum of 5 messages per loop iteration to prevent starving other components.
|
|
32
|
+
// This is a balance between API responsiveness and allowing other components to run.
|
|
33
|
+
// Since each message could contain multiple protobuf messages when using packet batching,
|
|
34
|
+
// this limits the number of messages processed, not the number of TCP packets.
|
|
35
|
+
static constexpr uint8_t MAX_MESSAGES_PER_LOOP = 5;
|
|
36
|
+
static constexpr uint8_t MAX_PING_RETRIES = 60;
|
|
37
|
+
static constexpr uint16_t PING_RETRY_INTERVAL = 1000;
|
|
38
|
+
static constexpr uint32_t KEEPALIVE_DISCONNECT_TIMEOUT = (KEEPALIVE_TIMEOUT_MS * 5) / 2;
|
|
39
|
+
|
|
31
40
|
static const char *const TAG = "api.connection";
|
|
32
|
-
|
|
41
|
+
#ifdef USE_CAMERA
|
|
42
|
+
static const int CAMERA_STOP_STREAM = 5000;
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
// Helper macro for entity command handlers - gets entity by key, returns if not found, and creates call object
|
|
46
|
+
#define ENTITY_COMMAND_MAKE_CALL(entity_type, entity_var, getter_name) \
|
|
47
|
+
entity_type *entity_var = App.get_##getter_name##_by_key(msg.key); \
|
|
48
|
+
if ((entity_var) == nullptr) \
|
|
49
|
+
return; \
|
|
50
|
+
auto call = (entity_var)->make_call();
|
|
51
|
+
|
|
52
|
+
// Helper macro for entity command handlers that don't use make_call() - gets entity by key and returns if not found
|
|
53
|
+
#define ENTITY_COMMAND_GET(entity_type, entity_var, getter_name) \
|
|
54
|
+
entity_type *entity_var = App.get_##getter_name##_by_key(msg.key); \
|
|
55
|
+
if ((entity_var) == nullptr) \
|
|
56
|
+
return;
|
|
33
57
|
|
|
34
58
|
APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent)
|
|
35
59
|
: parent_(parent), initial_state_iterator_(this), list_entities_iterator_(this) {
|
|
@@ -47,6 +71,11 @@ APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *pa
|
|
|
47
71
|
#else
|
|
48
72
|
#error "No frame helper defined"
|
|
49
73
|
#endif
|
|
74
|
+
#ifdef USE_CAMERA
|
|
75
|
+
if (camera::Camera::instance() != nullptr) {
|
|
76
|
+
this->image_reader_ = std::unique_ptr<camera::CameraImageReader>{camera::Camera::instance()->create_image_reader()};
|
|
77
|
+
}
|
|
78
|
+
#endif
|
|
50
79
|
}
|
|
51
80
|
|
|
52
81
|
uint32_t APIConnection::get_batch_delay_ms_() const { return this->parent_->get_batch_delay(); }
|
|
@@ -54,15 +83,11 @@ uint32_t APIConnection::get_batch_delay_ms_() const { return this->parent_->get_
|
|
|
54
83
|
void APIConnection::start() {
|
|
55
84
|
this->last_traffic_ = App.get_loop_component_start_time();
|
|
56
85
|
|
|
57
|
-
// Set next_ping_retry_ to prevent immediate ping
|
|
58
|
-
// This ensures the first ping happens after the keepalive period
|
|
59
|
-
this->next_ping_retry_ = this->last_traffic_ + KEEPALIVE_TIMEOUT_MS;
|
|
60
|
-
|
|
61
86
|
APIError err = this->helper_->init();
|
|
62
87
|
if (err != APIError::OK) {
|
|
63
88
|
on_fatal_error();
|
|
64
|
-
ESP_LOGW(TAG, "%s: Helper init failed: %s errno=%d", this->
|
|
65
|
-
errno);
|
|
89
|
+
ESP_LOGW(TAG, "%s: Helper init failed: %s errno=%d", this->get_client_combined_info().c_str(),
|
|
90
|
+
api_error_to_str(err), errno);
|
|
66
91
|
return;
|
|
67
92
|
}
|
|
68
93
|
this->client_info_ = helper_->getpeername();
|
|
@@ -84,104 +109,99 @@ APIConnection::~APIConnection() {
|
|
|
84
109
|
}
|
|
85
110
|
|
|
86
111
|
void APIConnection::loop() {
|
|
87
|
-
if (this->
|
|
88
|
-
return;
|
|
89
|
-
|
|
90
|
-
if (!network::is_connected()) {
|
|
91
|
-
// when network is disconnected force disconnect immediately
|
|
92
|
-
// don't wait for timeout
|
|
93
|
-
this->on_fatal_error();
|
|
94
|
-
ESP_LOGW(TAG, "%s: Network unavailable; disconnecting", this->client_combined_info_.c_str());
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
if (this->next_close_) {
|
|
112
|
+
if (this->flags_.next_close) {
|
|
98
113
|
// requested a disconnect
|
|
99
114
|
this->helper_->close();
|
|
100
|
-
this->
|
|
115
|
+
this->flags_.remove = true;
|
|
101
116
|
return;
|
|
102
117
|
}
|
|
103
118
|
|
|
104
119
|
APIError err = this->helper_->loop();
|
|
105
120
|
if (err != APIError::OK) {
|
|
106
121
|
on_fatal_error();
|
|
107
|
-
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->
|
|
122
|
+
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->get_client_combined_info().c_str(),
|
|
108
123
|
api_error_to_str(err), errno);
|
|
109
124
|
return;
|
|
110
125
|
}
|
|
111
126
|
|
|
127
|
+
const uint32_t now = App.get_loop_component_start_time();
|
|
112
128
|
// Check if socket has data ready before attempting to read
|
|
113
129
|
if (this->helper_->is_socket_ready()) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (buffer.data_len > 0) {
|
|
133
|
-
this->read_message(buffer.data_len, buffer.type, &buffer.container[buffer.data_offset]);
|
|
130
|
+
// Read up to MAX_MESSAGES_PER_LOOP messages per loop to improve throughput
|
|
131
|
+
for (uint8_t message_count = 0; message_count < MAX_MESSAGES_PER_LOOP; message_count++) {
|
|
132
|
+
ReadPacketBuffer buffer;
|
|
133
|
+
err = this->helper_->read_packet(&buffer);
|
|
134
|
+
if (err == APIError::WOULD_BLOCK) {
|
|
135
|
+
// No more data available
|
|
136
|
+
break;
|
|
137
|
+
} else if (err != APIError::OK) {
|
|
138
|
+
on_fatal_error();
|
|
139
|
+
if (err == APIError::SOCKET_READ_FAILED && errno == ECONNRESET) {
|
|
140
|
+
ESP_LOGW(TAG, "%s: Connection reset", this->get_client_combined_info().c_str());
|
|
141
|
+
} else if (err == APIError::CONNECTION_CLOSED) {
|
|
142
|
+
ESP_LOGW(TAG, "%s: Connection closed", this->get_client_combined_info().c_str());
|
|
143
|
+
} else {
|
|
144
|
+
ESP_LOGW(TAG, "%s: Reading failed: %s errno=%d", this->get_client_combined_info().c_str(),
|
|
145
|
+
api_error_to_str(err), errno);
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
134
148
|
} else {
|
|
135
|
-
this->
|
|
149
|
+
this->last_traffic_ = now;
|
|
150
|
+
// read a packet
|
|
151
|
+
if (buffer.data_len > 0) {
|
|
152
|
+
this->read_message(buffer.data_len, buffer.type, &buffer.container[buffer.data_offset]);
|
|
153
|
+
} else {
|
|
154
|
+
this->read_message(0, buffer.type, nullptr);
|
|
155
|
+
}
|
|
156
|
+
if (this->flags_.remove)
|
|
157
|
+
return;
|
|
136
158
|
}
|
|
137
|
-
if (this->remove_)
|
|
138
|
-
return;
|
|
139
159
|
}
|
|
140
160
|
}
|
|
141
161
|
|
|
142
|
-
// Process deferred batch if scheduled
|
|
143
|
-
if (this->
|
|
144
|
-
App.get_loop_component_start_time() - this->deferred_batch_.batch_start_time >= this->get_batch_delay_ms_()) {
|
|
162
|
+
// Process deferred batch if scheduled and timer has expired
|
|
163
|
+
if (this->flags_.batch_scheduled && now - this->deferred_batch_.batch_start_time >= this->get_batch_delay_ms_()) {
|
|
145
164
|
this->process_batch_();
|
|
146
165
|
}
|
|
147
166
|
|
|
148
|
-
if (!this->list_entities_iterator_.completed())
|
|
149
|
-
this->list_entities_iterator_
|
|
150
|
-
if (!this->initial_state_iterator_.completed()
|
|
151
|
-
this->initial_state_iterator_
|
|
167
|
+
if (!this->list_entities_iterator_.completed()) {
|
|
168
|
+
this->process_iterator_batch_(this->list_entities_iterator_);
|
|
169
|
+
} else if (!this->initial_state_iterator_.completed()) {
|
|
170
|
+
this->process_iterator_batch_(this->initial_state_iterator_);
|
|
152
171
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
172
|
+
// If we've completed initial states, process any remaining and clear the flag
|
|
173
|
+
if (this->initial_state_iterator_.completed()) {
|
|
174
|
+
// Process any remaining batched messages immediately
|
|
175
|
+
if (!this->deferred_batch_.empty()) {
|
|
176
|
+
this->process_batch_();
|
|
177
|
+
}
|
|
178
|
+
// Now that everything is sent, enable immediate sending for future state changes
|
|
179
|
+
this->flags_.should_try_send_immediately = true;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (this->flags_.sent_ping) {
|
|
157
184
|
// Disconnect if not responded within 2.5*keepalive
|
|
158
|
-
if (now - this->last_traffic_ >
|
|
185
|
+
if (now - this->last_traffic_ > KEEPALIVE_DISCONNECT_TIMEOUT) {
|
|
159
186
|
on_fatal_error();
|
|
160
|
-
ESP_LOGW(TAG, "%s is unresponsive; disconnecting", this->
|
|
187
|
+
ESP_LOGW(TAG, "%s is unresponsive; disconnecting", this->get_client_combined_info().c_str());
|
|
161
188
|
}
|
|
162
|
-
} else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS
|
|
189
|
+
} else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS) {
|
|
163
190
|
ESP_LOGVV(TAG, "Sending keepalive PING");
|
|
164
|
-
this->
|
|
165
|
-
if (!this->
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
on_fatal_error();
|
|
172
|
-
ESP_LOGE(TAG, "%s disconnecting", warn_str.c_str());
|
|
173
|
-
} else if (this->ping_retries_ >= 10) {
|
|
174
|
-
ESP_LOGW(TAG, "%s retrying in %u ms", warn_str.c_str(), ping_retry_interval);
|
|
175
|
-
} else {
|
|
176
|
-
ESP_LOGD(TAG, "%s retrying in %u ms", warn_str.c_str(), ping_retry_interval);
|
|
177
|
-
}
|
|
191
|
+
this->flags_.sent_ping = this->send_message(PingRequest());
|
|
192
|
+
if (!this->flags_.sent_ping) {
|
|
193
|
+
// If we can't send the ping request directly (tx_buffer full),
|
|
194
|
+
// schedule it at the front of the batch so it will be sent with priority
|
|
195
|
+
ESP_LOGW(TAG, "Buffer full, ping queued");
|
|
196
|
+
this->schedule_message_front_(nullptr, &APIConnection::try_send_ping_request, PingRequest::MESSAGE_TYPE);
|
|
197
|
+
this->flags_.sent_ping = true; // Mark as sent to avoid scheduling multiple pings
|
|
178
198
|
}
|
|
179
199
|
}
|
|
180
200
|
|
|
181
|
-
#ifdef
|
|
182
|
-
if (this->image_reader_
|
|
183
|
-
uint32_t to_send = std::min((size_t) MAX_PACKET_SIZE, this->image_reader_
|
|
184
|
-
bool done = this->image_reader_
|
|
201
|
+
#ifdef USE_CAMERA
|
|
202
|
+
if (this->image_reader_ && this->image_reader_->available() && this->helper_->can_write_without_blocking()) {
|
|
203
|
+
uint32_t to_send = std::min((size_t) MAX_PACKET_SIZE, this->image_reader_->available());
|
|
204
|
+
bool done = this->image_reader_->available() == to_send;
|
|
185
205
|
uint32_t msg_size = 0;
|
|
186
206
|
ProtoSize::add_fixed_field<4>(msg_size, 1, true);
|
|
187
207
|
// partial message size calculated manually since its a special case
|
|
@@ -191,28 +211,26 @@ void APIConnection::loop() {
|
|
|
191
211
|
|
|
192
212
|
auto buffer = this->create_buffer(msg_size);
|
|
193
213
|
// fixed32 key = 1;
|
|
194
|
-
buffer.encode_fixed32(1,
|
|
214
|
+
buffer.encode_fixed32(1, camera::Camera::instance()->get_object_id_hash());
|
|
195
215
|
// bytes data = 2;
|
|
196
|
-
buffer.encode_bytes(2, this->image_reader_
|
|
216
|
+
buffer.encode_bytes(2, this->image_reader_->peek_data_buffer(), to_send);
|
|
197
217
|
// bool done = 3;
|
|
198
218
|
buffer.encode_bool(3, done);
|
|
199
219
|
|
|
200
|
-
bool success = this->send_buffer(buffer,
|
|
220
|
+
bool success = this->send_buffer(buffer, CameraImageResponse::MESSAGE_TYPE);
|
|
201
221
|
|
|
202
222
|
if (success) {
|
|
203
|
-
this->image_reader_
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
223
|
+
this->image_reader_->consume_data(to_send);
|
|
224
|
+
if (done) {
|
|
225
|
+
this->image_reader_->return_image();
|
|
226
|
+
}
|
|
207
227
|
}
|
|
208
228
|
}
|
|
209
229
|
#endif
|
|
210
230
|
|
|
211
|
-
if (state_subs_at_
|
|
231
|
+
if (state_subs_at_ >= 0) {
|
|
212
232
|
const auto &subs = this->parent_->get_state_subs();
|
|
213
|
-
if (state_subs_at_
|
|
214
|
-
state_subs_at_ = -1;
|
|
215
|
-
} else {
|
|
233
|
+
if (state_subs_at_ < static_cast<int>(subs.size())) {
|
|
216
234
|
auto &it = subs[state_subs_at_];
|
|
217
235
|
SubscribeHomeAssistantStateResponse resp;
|
|
218
236
|
resp.entity_id = it.entity_id;
|
|
@@ -221,6 +239,8 @@ void APIConnection::loop() {
|
|
|
221
239
|
if (this->send_message(resp)) {
|
|
222
240
|
state_subs_at_++;
|
|
223
241
|
}
|
|
242
|
+
} else {
|
|
243
|
+
state_subs_at_ = -1;
|
|
224
244
|
}
|
|
225
245
|
}
|
|
226
246
|
}
|
|
@@ -233,20 +253,28 @@ DisconnectResponse APIConnection::disconnect(const DisconnectRequest &msg) {
|
|
|
233
253
|
// remote initiated disconnect_client
|
|
234
254
|
// don't close yet, we still need to send the disconnect response
|
|
235
255
|
// close will happen on next loop
|
|
236
|
-
ESP_LOGD(TAG, "%s disconnected", this->
|
|
237
|
-
this->
|
|
256
|
+
ESP_LOGD(TAG, "%s disconnected", this->get_client_combined_info().c_str());
|
|
257
|
+
this->flags_.next_close = true;
|
|
238
258
|
DisconnectResponse resp;
|
|
239
259
|
return resp;
|
|
240
260
|
}
|
|
241
261
|
void APIConnection::on_disconnect_response(const DisconnectResponse &value) {
|
|
242
262
|
this->helper_->close();
|
|
243
|
-
this->
|
|
263
|
+
this->flags_.remove = true;
|
|
244
264
|
}
|
|
245
265
|
|
|
246
266
|
// Encodes a message to the buffer and returns the total number of bytes used,
|
|
247
267
|
// including header and footer overhead. Returns 0 if the message doesn't fit.
|
|
248
268
|
uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint16_t message_type, APIConnection *conn,
|
|
249
269
|
uint32_t remaining_size, bool is_single) {
|
|
270
|
+
#ifdef HAS_PROTO_MESSAGE_DUMP
|
|
271
|
+
// If in log-only mode, just log and return
|
|
272
|
+
if (conn->flags_.log_only_mode) {
|
|
273
|
+
conn->log_send_message_(msg.message_name(), msg.dump());
|
|
274
|
+
return 1; // Return non-zero to indicate "success" for logging
|
|
275
|
+
}
|
|
276
|
+
#endif
|
|
277
|
+
|
|
250
278
|
// Calculate size
|
|
251
279
|
uint32_t calculated_size = 0;
|
|
252
280
|
msg.calculate_size(calculated_size);
|
|
@@ -287,12 +315,8 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint16_t mes
|
|
|
287
315
|
|
|
288
316
|
#ifdef USE_BINARY_SENSOR
|
|
289
317
|
bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor) {
|
|
290
|
-
return this->
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
void APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor) {
|
|
294
|
-
this->schedule_message_(binary_sensor, &APIConnection::try_send_binary_sensor_info,
|
|
295
|
-
ListEntitiesBinarySensorResponse::MESSAGE_TYPE);
|
|
318
|
+
return this->send_message_smart_(binary_sensor, &APIConnection::try_send_binary_sensor_state,
|
|
319
|
+
BinarySensorStateResponse::MESSAGE_TYPE);
|
|
296
320
|
}
|
|
297
321
|
|
|
298
322
|
uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -319,10 +343,7 @@ uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConne
|
|
|
319
343
|
|
|
320
344
|
#ifdef USE_COVER
|
|
321
345
|
bool APIConnection::send_cover_state(cover::Cover *cover) {
|
|
322
|
-
return this->
|
|
323
|
-
}
|
|
324
|
-
void APIConnection::send_cover_info(cover::Cover *cover) {
|
|
325
|
-
this->schedule_message_(cover, &APIConnection::try_send_cover_info, ListEntitiesCoverResponse::MESSAGE_TYPE);
|
|
346
|
+
return this->send_message_smart_(cover, &APIConnection::try_send_cover_state, CoverStateResponse::MESSAGE_TYPE);
|
|
326
347
|
}
|
|
327
348
|
uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
328
349
|
bool is_single) {
|
|
@@ -353,11 +374,7 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c
|
|
|
353
374
|
return encode_message_to_buffer(msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
354
375
|
}
|
|
355
376
|
void APIConnection::cover_command(const CoverCommandRequest &msg) {
|
|
356
|
-
cover::Cover
|
|
357
|
-
if (cover == nullptr)
|
|
358
|
-
return;
|
|
359
|
-
|
|
360
|
-
auto call = cover->make_call();
|
|
377
|
+
ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover)
|
|
361
378
|
if (msg.has_legacy_command) {
|
|
362
379
|
switch (msg.legacy_command) {
|
|
363
380
|
case enums::LEGACY_COVER_COMMAND_OPEN:
|
|
@@ -383,10 +400,7 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) {
|
|
|
383
400
|
|
|
384
401
|
#ifdef USE_FAN
|
|
385
402
|
bool APIConnection::send_fan_state(fan::Fan *fan) {
|
|
386
|
-
return this->
|
|
387
|
-
}
|
|
388
|
-
void APIConnection::send_fan_info(fan::Fan *fan) {
|
|
389
|
-
this->schedule_message_(fan, &APIConnection::try_send_fan_info, ListEntitiesFanResponse::MESSAGE_TYPE);
|
|
403
|
+
return this->send_message_smart_(fan, &APIConnection::try_send_fan_state, FanStateResponse::MESSAGE_TYPE);
|
|
390
404
|
}
|
|
391
405
|
uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
392
406
|
bool is_single) {
|
|
@@ -422,11 +436,7 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con
|
|
|
422
436
|
return encode_message_to_buffer(msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
423
437
|
}
|
|
424
438
|
void APIConnection::fan_command(const FanCommandRequest &msg) {
|
|
425
|
-
fan::Fan
|
|
426
|
-
if (fan == nullptr)
|
|
427
|
-
return;
|
|
428
|
-
|
|
429
|
-
auto call = fan->make_call();
|
|
439
|
+
ENTITY_COMMAND_MAKE_CALL(fan::Fan, fan, fan)
|
|
430
440
|
if (msg.has_state)
|
|
431
441
|
call.set_state(msg.state);
|
|
432
442
|
if (msg.has_oscillating)
|
|
@@ -445,10 +455,7 @@ void APIConnection::fan_command(const FanCommandRequest &msg) {
|
|
|
445
455
|
|
|
446
456
|
#ifdef USE_LIGHT
|
|
447
457
|
bool APIConnection::send_light_state(light::LightState *light) {
|
|
448
|
-
return this->
|
|
449
|
-
}
|
|
450
|
-
void APIConnection::send_light_info(light::LightState *light) {
|
|
451
|
-
this->schedule_message_(light, &APIConnection::try_send_light_info, ListEntitiesLightResponse::MESSAGE_TYPE);
|
|
458
|
+
return this->send_message_smart_(light, &APIConnection::try_send_light_state, LightStateResponse::MESSAGE_TYPE);
|
|
452
459
|
}
|
|
453
460
|
uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
454
461
|
bool is_single) {
|
|
@@ -502,11 +509,7 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c
|
|
|
502
509
|
return encode_message_to_buffer(msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
503
510
|
}
|
|
504
511
|
void APIConnection::light_command(const LightCommandRequest &msg) {
|
|
505
|
-
light::LightState
|
|
506
|
-
if (light == nullptr)
|
|
507
|
-
return;
|
|
508
|
-
|
|
509
|
-
auto call = light->make_call();
|
|
512
|
+
ENTITY_COMMAND_MAKE_CALL(light::LightState, light, light)
|
|
510
513
|
if (msg.has_state)
|
|
511
514
|
call.set_state(msg.state);
|
|
512
515
|
if (msg.has_brightness)
|
|
@@ -540,10 +543,7 @@ void APIConnection::light_command(const LightCommandRequest &msg) {
|
|
|
540
543
|
|
|
541
544
|
#ifdef USE_SENSOR
|
|
542
545
|
bool APIConnection::send_sensor_state(sensor::Sensor *sensor) {
|
|
543
|
-
return this->
|
|
544
|
-
}
|
|
545
|
-
void APIConnection::send_sensor_info(sensor::Sensor *sensor) {
|
|
546
|
-
this->schedule_message_(sensor, &APIConnection::try_send_sensor_info, ListEntitiesSensorResponse::MESSAGE_TYPE);
|
|
546
|
+
return this->send_message_smart_(sensor, &APIConnection::try_send_sensor_state, SensorStateResponse::MESSAGE_TYPE);
|
|
547
547
|
}
|
|
548
548
|
|
|
549
549
|
uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -575,10 +575,7 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *
|
|
|
575
575
|
|
|
576
576
|
#ifdef USE_SWITCH
|
|
577
577
|
bool APIConnection::send_switch_state(switch_::Switch *a_switch) {
|
|
578
|
-
return this->
|
|
579
|
-
}
|
|
580
|
-
void APIConnection::send_switch_info(switch_::Switch *a_switch) {
|
|
581
|
-
this->schedule_message_(a_switch, &APIConnection::try_send_switch_info, ListEntitiesSwitchResponse::MESSAGE_TYPE);
|
|
578
|
+
return this->send_message_smart_(a_switch, &APIConnection::try_send_switch_state, SwitchStateResponse::MESSAGE_TYPE);
|
|
582
579
|
}
|
|
583
580
|
|
|
584
581
|
uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -601,9 +598,7 @@ uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *
|
|
|
601
598
|
return encode_message_to_buffer(msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
602
599
|
}
|
|
603
600
|
void APIConnection::switch_command(const SwitchCommandRequest &msg) {
|
|
604
|
-
switch_::Switch
|
|
605
|
-
if (a_switch == nullptr)
|
|
606
|
-
return;
|
|
601
|
+
ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch)
|
|
607
602
|
|
|
608
603
|
if (msg.state) {
|
|
609
604
|
a_switch->turn_on();
|
|
@@ -615,12 +610,8 @@ void APIConnection::switch_command(const SwitchCommandRequest &msg) {
|
|
|
615
610
|
|
|
616
611
|
#ifdef USE_TEXT_SENSOR
|
|
617
612
|
bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor) {
|
|
618
|
-
return this->
|
|
619
|
-
|
|
620
|
-
}
|
|
621
|
-
void APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor) {
|
|
622
|
-
this->schedule_message_(text_sensor, &APIConnection::try_send_text_sensor_info,
|
|
623
|
-
ListEntitiesTextSensorResponse::MESSAGE_TYPE);
|
|
613
|
+
return this->send_message_smart_(text_sensor, &APIConnection::try_send_text_sensor_state,
|
|
614
|
+
TextSensorStateResponse::MESSAGE_TYPE);
|
|
624
615
|
}
|
|
625
616
|
|
|
626
617
|
uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -647,7 +638,7 @@ uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnect
|
|
|
647
638
|
|
|
648
639
|
#ifdef USE_CLIMATE
|
|
649
640
|
bool APIConnection::send_climate_state(climate::Climate *climate) {
|
|
650
|
-
return this->
|
|
641
|
+
return this->send_message_smart_(climate, &APIConnection::try_send_climate_state, ClimateStateResponse::MESSAGE_TYPE);
|
|
651
642
|
}
|
|
652
643
|
uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
653
644
|
bool is_single) {
|
|
@@ -682,9 +673,6 @@ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection
|
|
|
682
673
|
resp.target_humidity = climate->target_humidity;
|
|
683
674
|
return encode_message_to_buffer(resp, ClimateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
684
675
|
}
|
|
685
|
-
void APIConnection::send_climate_info(climate::Climate *climate) {
|
|
686
|
-
this->schedule_message_(climate, &APIConnection::try_send_climate_info, ListEntitiesClimateResponse::MESSAGE_TYPE);
|
|
687
|
-
}
|
|
688
676
|
uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
689
677
|
bool is_single) {
|
|
690
678
|
auto *climate = static_cast<climate::Climate *>(entity);
|
|
@@ -719,11 +707,7 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection
|
|
|
719
707
|
return encode_message_to_buffer(msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
720
708
|
}
|
|
721
709
|
void APIConnection::climate_command(const ClimateCommandRequest &msg) {
|
|
722
|
-
climate::Climate
|
|
723
|
-
if (climate == nullptr)
|
|
724
|
-
return;
|
|
725
|
-
|
|
726
|
-
auto call = climate->make_call();
|
|
710
|
+
ENTITY_COMMAND_MAKE_CALL(climate::Climate, climate, climate)
|
|
727
711
|
if (msg.has_mode)
|
|
728
712
|
call.set_mode(static_cast<climate::ClimateMode>(msg.mode));
|
|
729
713
|
if (msg.has_target_temperature)
|
|
@@ -750,10 +734,7 @@ void APIConnection::climate_command(const ClimateCommandRequest &msg) {
|
|
|
750
734
|
|
|
751
735
|
#ifdef USE_NUMBER
|
|
752
736
|
bool APIConnection::send_number_state(number::Number *number) {
|
|
753
|
-
return this->
|
|
754
|
-
}
|
|
755
|
-
void APIConnection::send_number_info(number::Number *number) {
|
|
756
|
-
this->schedule_message_(number, &APIConnection::try_send_number_info, ListEntitiesNumberResponse::MESSAGE_TYPE);
|
|
737
|
+
return this->send_message_smart_(number, &APIConnection::try_send_number_state, NumberStateResponse::MESSAGE_TYPE);
|
|
757
738
|
}
|
|
758
739
|
|
|
759
740
|
uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -781,11 +762,7 @@ uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *
|
|
|
781
762
|
return encode_message_to_buffer(msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
782
763
|
}
|
|
783
764
|
void APIConnection::number_command(const NumberCommandRequest &msg) {
|
|
784
|
-
number::Number
|
|
785
|
-
if (number == nullptr)
|
|
786
|
-
return;
|
|
787
|
-
|
|
788
|
-
auto call = number->make_call();
|
|
765
|
+
ENTITY_COMMAND_MAKE_CALL(number::Number, number, number)
|
|
789
766
|
call.set_value(msg.state);
|
|
790
767
|
call.perform();
|
|
791
768
|
}
|
|
@@ -793,7 +770,7 @@ void APIConnection::number_command(const NumberCommandRequest &msg) {
|
|
|
793
770
|
|
|
794
771
|
#ifdef USE_DATETIME_DATE
|
|
795
772
|
bool APIConnection::send_date_state(datetime::DateEntity *date) {
|
|
796
|
-
return this->
|
|
773
|
+
return this->send_message_smart_(date, &APIConnection::try_send_date_state, DateStateResponse::MESSAGE_TYPE);
|
|
797
774
|
}
|
|
798
775
|
uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
799
776
|
bool is_single) {
|
|
@@ -806,9 +783,6 @@ uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *c
|
|
|
806
783
|
fill_entity_state_base(date, resp);
|
|
807
784
|
return encode_message_to_buffer(resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
808
785
|
}
|
|
809
|
-
void APIConnection::send_date_info(datetime::DateEntity *date) {
|
|
810
|
-
this->schedule_message_(date, &APIConnection::try_send_date_info, ListEntitiesDateResponse::MESSAGE_TYPE);
|
|
811
|
-
}
|
|
812
786
|
uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
813
787
|
bool is_single) {
|
|
814
788
|
auto *date = static_cast<datetime::DateEntity *>(entity);
|
|
@@ -818,11 +792,7 @@ uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *co
|
|
|
818
792
|
return encode_message_to_buffer(msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
819
793
|
}
|
|
820
794
|
void APIConnection::date_command(const DateCommandRequest &msg) {
|
|
821
|
-
datetime::DateEntity
|
|
822
|
-
if (date == nullptr)
|
|
823
|
-
return;
|
|
824
|
-
|
|
825
|
-
auto call = date->make_call();
|
|
795
|
+
ENTITY_COMMAND_MAKE_CALL(datetime::DateEntity, date, date)
|
|
826
796
|
call.set_date(msg.year, msg.month, msg.day);
|
|
827
797
|
call.perform();
|
|
828
798
|
}
|
|
@@ -830,7 +800,7 @@ void APIConnection::date_command(const DateCommandRequest &msg) {
|
|
|
830
800
|
|
|
831
801
|
#ifdef USE_DATETIME_TIME
|
|
832
802
|
bool APIConnection::send_time_state(datetime::TimeEntity *time) {
|
|
833
|
-
return this->
|
|
803
|
+
return this->send_message_smart_(time, &APIConnection::try_send_time_state, TimeStateResponse::MESSAGE_TYPE);
|
|
834
804
|
}
|
|
835
805
|
uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
836
806
|
bool is_single) {
|
|
@@ -843,9 +813,6 @@ uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *c
|
|
|
843
813
|
fill_entity_state_base(time, resp);
|
|
844
814
|
return encode_message_to_buffer(resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
845
815
|
}
|
|
846
|
-
void APIConnection::send_time_info(datetime::TimeEntity *time) {
|
|
847
|
-
this->schedule_message_(time, &APIConnection::try_send_time_info, ListEntitiesTimeResponse::MESSAGE_TYPE);
|
|
848
|
-
}
|
|
849
816
|
uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
850
817
|
bool is_single) {
|
|
851
818
|
auto *time = static_cast<datetime::TimeEntity *>(entity);
|
|
@@ -855,11 +822,7 @@ uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *co
|
|
|
855
822
|
return encode_message_to_buffer(msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
856
823
|
}
|
|
857
824
|
void APIConnection::time_command(const TimeCommandRequest &msg) {
|
|
858
|
-
datetime::TimeEntity
|
|
859
|
-
if (time == nullptr)
|
|
860
|
-
return;
|
|
861
|
-
|
|
862
|
-
auto call = time->make_call();
|
|
825
|
+
ENTITY_COMMAND_MAKE_CALL(datetime::TimeEntity, time, time)
|
|
863
826
|
call.set_time(msg.hour, msg.minute, msg.second);
|
|
864
827
|
call.perform();
|
|
865
828
|
}
|
|
@@ -867,8 +830,8 @@ void APIConnection::time_command(const TimeCommandRequest &msg) {
|
|
|
867
830
|
|
|
868
831
|
#ifdef USE_DATETIME_DATETIME
|
|
869
832
|
bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) {
|
|
870
|
-
return this->
|
|
871
|
-
|
|
833
|
+
return this->send_message_smart_(datetime, &APIConnection::try_send_datetime_state,
|
|
834
|
+
DateTimeStateResponse::MESSAGE_TYPE);
|
|
872
835
|
}
|
|
873
836
|
uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
874
837
|
bool is_single) {
|
|
@@ -882,9 +845,6 @@ uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnectio
|
|
|
882
845
|
fill_entity_state_base(datetime, resp);
|
|
883
846
|
return encode_message_to_buffer(resp, DateTimeStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
884
847
|
}
|
|
885
|
-
void APIConnection::send_datetime_info(datetime::DateTimeEntity *datetime) {
|
|
886
|
-
this->schedule_message_(datetime, &APIConnection::try_send_datetime_info, ListEntitiesDateTimeResponse::MESSAGE_TYPE);
|
|
887
|
-
}
|
|
888
848
|
uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
889
849
|
bool is_single) {
|
|
890
850
|
auto *datetime = static_cast<datetime::DateTimeEntity *>(entity);
|
|
@@ -894,11 +854,7 @@ uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection
|
|
|
894
854
|
return encode_message_to_buffer(msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
895
855
|
}
|
|
896
856
|
void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
|
|
897
|
-
datetime::DateTimeEntity
|
|
898
|
-
if (datetime == nullptr)
|
|
899
|
-
return;
|
|
900
|
-
|
|
901
|
-
auto call = datetime->make_call();
|
|
857
|
+
ENTITY_COMMAND_MAKE_CALL(datetime::DateTimeEntity, datetime, datetime)
|
|
902
858
|
call.set_datetime(msg.epoch_seconds);
|
|
903
859
|
call.perform();
|
|
904
860
|
}
|
|
@@ -906,10 +862,7 @@ void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
|
|
|
906
862
|
|
|
907
863
|
#ifdef USE_TEXT
|
|
908
864
|
bool APIConnection::send_text_state(text::Text *text) {
|
|
909
|
-
return this->
|
|
910
|
-
}
|
|
911
|
-
void APIConnection::send_text_info(text::Text *text) {
|
|
912
|
-
this->schedule_message_(text, &APIConnection::try_send_text_info, ListEntitiesTextResponse::MESSAGE_TYPE);
|
|
865
|
+
return this->send_message_smart_(text, &APIConnection::try_send_text_state, TextStateResponse::MESSAGE_TYPE);
|
|
913
866
|
}
|
|
914
867
|
|
|
915
868
|
uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -935,11 +888,7 @@ uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *co
|
|
|
935
888
|
return encode_message_to_buffer(msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
936
889
|
}
|
|
937
890
|
void APIConnection::text_command(const TextCommandRequest &msg) {
|
|
938
|
-
text::Text
|
|
939
|
-
if (text == nullptr)
|
|
940
|
-
return;
|
|
941
|
-
|
|
942
|
-
auto call = text->make_call();
|
|
891
|
+
ENTITY_COMMAND_MAKE_CALL(text::Text, text, text)
|
|
943
892
|
call.set_value(msg.state);
|
|
944
893
|
call.perform();
|
|
945
894
|
}
|
|
@@ -947,10 +896,7 @@ void APIConnection::text_command(const TextCommandRequest &msg) {
|
|
|
947
896
|
|
|
948
897
|
#ifdef USE_SELECT
|
|
949
898
|
bool APIConnection::send_select_state(select::Select *select) {
|
|
950
|
-
return this->
|
|
951
|
-
}
|
|
952
|
-
void APIConnection::send_select_info(select::Select *select) {
|
|
953
|
-
this->schedule_message_(select, &APIConnection::try_send_select_info, ListEntitiesSelectResponse::MESSAGE_TYPE);
|
|
899
|
+
return this->send_message_smart_(select, &APIConnection::try_send_select_state, SelectStateResponse::MESSAGE_TYPE);
|
|
954
900
|
}
|
|
955
901
|
|
|
956
902
|
uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -974,20 +920,13 @@ uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *
|
|
|
974
920
|
return encode_message_to_buffer(msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
975
921
|
}
|
|
976
922
|
void APIConnection::select_command(const SelectCommandRequest &msg) {
|
|
977
|
-
select::Select
|
|
978
|
-
if (select == nullptr)
|
|
979
|
-
return;
|
|
980
|
-
|
|
981
|
-
auto call = select->make_call();
|
|
923
|
+
ENTITY_COMMAND_MAKE_CALL(select::Select, select, select)
|
|
982
924
|
call.set_option(msg.state);
|
|
983
925
|
call.perform();
|
|
984
926
|
}
|
|
985
927
|
#endif
|
|
986
928
|
|
|
987
929
|
#ifdef USE_BUTTON
|
|
988
|
-
void esphome::api::APIConnection::send_button_info(button::Button *button) {
|
|
989
|
-
this->schedule_message_(button, &APIConnection::try_send_button_info, ListEntitiesButtonResponse::MESSAGE_TYPE);
|
|
990
|
-
}
|
|
991
930
|
uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
992
931
|
bool is_single) {
|
|
993
932
|
auto *button = static_cast<button::Button *>(entity);
|
|
@@ -998,20 +937,14 @@ uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *
|
|
|
998
937
|
return encode_message_to_buffer(msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
999
938
|
}
|
|
1000
939
|
void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg) {
|
|
1001
|
-
button::Button
|
|
1002
|
-
if (button == nullptr)
|
|
1003
|
-
return;
|
|
1004
|
-
|
|
940
|
+
ENTITY_COMMAND_GET(button::Button, button, button)
|
|
1005
941
|
button->press();
|
|
1006
942
|
}
|
|
1007
943
|
#endif
|
|
1008
944
|
|
|
1009
945
|
#ifdef USE_LOCK
|
|
1010
946
|
bool APIConnection::send_lock_state(lock::Lock *a_lock) {
|
|
1011
|
-
return this->
|
|
1012
|
-
}
|
|
1013
|
-
void APIConnection::send_lock_info(lock::Lock *a_lock) {
|
|
1014
|
-
this->schedule_message_(a_lock, &APIConnection::try_send_lock_info, ListEntitiesLockResponse::MESSAGE_TYPE);
|
|
947
|
+
return this->send_message_smart_(a_lock, &APIConnection::try_send_lock_state, LockStateResponse::MESSAGE_TYPE);
|
|
1015
948
|
}
|
|
1016
949
|
|
|
1017
950
|
uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -1035,9 +968,7 @@ uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *co
|
|
|
1035
968
|
return encode_message_to_buffer(msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1036
969
|
}
|
|
1037
970
|
void APIConnection::lock_command(const LockCommandRequest &msg) {
|
|
1038
|
-
lock::Lock
|
|
1039
|
-
if (a_lock == nullptr)
|
|
1040
|
-
return;
|
|
971
|
+
ENTITY_COMMAND_GET(lock::Lock, a_lock, lock)
|
|
1041
972
|
|
|
1042
973
|
switch (msg.command) {
|
|
1043
974
|
case enums::LOCK_UNLOCK:
|
|
@@ -1055,7 +986,7 @@ void APIConnection::lock_command(const LockCommandRequest &msg) {
|
|
|
1055
986
|
|
|
1056
987
|
#ifdef USE_VALVE
|
|
1057
988
|
bool APIConnection::send_valve_state(valve::Valve *valve) {
|
|
1058
|
-
return this->
|
|
989
|
+
return this->send_message_smart_(valve, &APIConnection::try_send_valve_state, ValveStateResponse::MESSAGE_TYPE);
|
|
1059
990
|
}
|
|
1060
991
|
uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1061
992
|
bool is_single) {
|
|
@@ -1066,9 +997,6 @@ uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *
|
|
|
1066
997
|
fill_entity_state_base(valve, resp);
|
|
1067
998
|
return encode_message_to_buffer(resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1068
999
|
}
|
|
1069
|
-
void APIConnection::send_valve_info(valve::Valve *valve) {
|
|
1070
|
-
this->schedule_message_(valve, &APIConnection::try_send_valve_info, ListEntitiesValveResponse::MESSAGE_TYPE);
|
|
1071
|
-
}
|
|
1072
1000
|
uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1073
1001
|
bool is_single) {
|
|
1074
1002
|
auto *valve = static_cast<valve::Valve *>(entity);
|
|
@@ -1083,11 +1011,7 @@ uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *c
|
|
|
1083
1011
|
return encode_message_to_buffer(msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1084
1012
|
}
|
|
1085
1013
|
void APIConnection::valve_command(const ValveCommandRequest &msg) {
|
|
1086
|
-
valve::Valve
|
|
1087
|
-
if (valve == nullptr)
|
|
1088
|
-
return;
|
|
1089
|
-
|
|
1090
|
-
auto call = valve->make_call();
|
|
1014
|
+
ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve)
|
|
1091
1015
|
if (msg.has_position)
|
|
1092
1016
|
call.set_position(msg.position);
|
|
1093
1017
|
if (msg.stop)
|
|
@@ -1098,8 +1022,8 @@ void APIConnection::valve_command(const ValveCommandRequest &msg) {
|
|
|
1098
1022
|
|
|
1099
1023
|
#ifdef USE_MEDIA_PLAYER
|
|
1100
1024
|
bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_player) {
|
|
1101
|
-
return this->
|
|
1102
|
-
|
|
1025
|
+
return this->send_message_smart_(media_player, &APIConnection::try_send_media_player_state,
|
|
1026
|
+
MediaPlayerStateResponse::MESSAGE_TYPE);
|
|
1103
1027
|
}
|
|
1104
1028
|
uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1105
1029
|
bool is_single) {
|
|
@@ -1114,10 +1038,6 @@ uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConne
|
|
|
1114
1038
|
fill_entity_state_base(media_player, resp);
|
|
1115
1039
|
return encode_message_to_buffer(resp, MediaPlayerStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1116
1040
|
}
|
|
1117
|
-
void APIConnection::send_media_player_info(media_player::MediaPlayer *media_player) {
|
|
1118
|
-
this->schedule_message_(media_player, &APIConnection::try_send_media_player_info,
|
|
1119
|
-
ListEntitiesMediaPlayerResponse::MESSAGE_TYPE);
|
|
1120
|
-
}
|
|
1121
1041
|
uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1122
1042
|
bool is_single) {
|
|
1123
1043
|
auto *media_player = static_cast<media_player::MediaPlayer *>(entity);
|
|
@@ -1138,11 +1058,7 @@ uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnec
|
|
|
1138
1058
|
return encode_message_to_buffer(msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1139
1059
|
}
|
|
1140
1060
|
void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
|
|
1141
|
-
media_player::MediaPlayer
|
|
1142
|
-
if (media_player == nullptr)
|
|
1143
|
-
return;
|
|
1144
|
-
|
|
1145
|
-
auto call = media_player->make_call();
|
|
1061
|
+
ENTITY_COMMAND_MAKE_CALL(media_player::MediaPlayer, media_player, media_player)
|
|
1146
1062
|
if (msg.has_command) {
|
|
1147
1063
|
call.set_command(static_cast<media_player::MediaPlayerCommand>(msg.command));
|
|
1148
1064
|
}
|
|
@@ -1159,39 +1075,36 @@ void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
|
|
|
1159
1075
|
}
|
|
1160
1076
|
#endif
|
|
1161
1077
|
|
|
1162
|
-
#ifdef
|
|
1163
|
-
void APIConnection::set_camera_state(std::shared_ptr<
|
|
1164
|
-
if (!this->
|
|
1078
|
+
#ifdef USE_CAMERA
|
|
1079
|
+
void APIConnection::set_camera_state(std::shared_ptr<camera::CameraImage> image) {
|
|
1080
|
+
if (!this->flags_.state_subscription)
|
|
1165
1081
|
return;
|
|
1166
|
-
if (this->image_reader_
|
|
1082
|
+
if (!this->image_reader_)
|
|
1167
1083
|
return;
|
|
1168
|
-
if (
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
void APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
|
|
1173
|
-
this->schedule_message_(camera, &APIConnection::try_send_camera_info, ListEntitiesCameraResponse::MESSAGE_TYPE);
|
|
1084
|
+
if (this->image_reader_->available())
|
|
1085
|
+
return;
|
|
1086
|
+
if (image->was_requested_by(esphome::camera::API_REQUESTER) || image->was_requested_by(esphome::camera::IDLE))
|
|
1087
|
+
this->image_reader_->set_image(std::move(image));
|
|
1174
1088
|
}
|
|
1175
1089
|
uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1176
1090
|
bool is_single) {
|
|
1177
|
-
auto *camera = static_cast<
|
|
1091
|
+
auto *camera = static_cast<camera::Camera *>(entity);
|
|
1178
1092
|
ListEntitiesCameraResponse msg;
|
|
1179
1093
|
msg.unique_id = get_default_unique_id("camera", camera);
|
|
1180
1094
|
fill_entity_info_base(camera, msg);
|
|
1181
1095
|
return encode_message_to_buffer(msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1182
1096
|
}
|
|
1183
1097
|
void APIConnection::camera_image(const CameraImageRequest &msg) {
|
|
1184
|
-
if (
|
|
1098
|
+
if (camera::Camera::instance() == nullptr)
|
|
1185
1099
|
return;
|
|
1186
1100
|
|
|
1187
1101
|
if (msg.single)
|
|
1188
|
-
|
|
1102
|
+
camera::Camera::instance()->request_image(esphome::camera::API_REQUESTER);
|
|
1189
1103
|
if (msg.stream) {
|
|
1190
|
-
|
|
1104
|
+
camera::Camera::instance()->start_stream(esphome::camera::API_REQUESTER);
|
|
1191
1105
|
|
|
1192
|
-
App.scheduler.set_timeout(this->parent_, "
|
|
1193
|
-
|
|
1194
|
-
});
|
|
1106
|
+
App.scheduler.set_timeout(this->parent_, "api_camera_stop_stream", CAMERA_STOP_STREAM,
|
|
1107
|
+
[]() { camera::Camera::instance()->stop_stream(esphome::camera::API_REQUESTER); });
|
|
1195
1108
|
}
|
|
1196
1109
|
}
|
|
1197
1110
|
#endif
|
|
@@ -1263,66 +1176,53 @@ void APIConnection::bluetooth_scanner_set_mode(const BluetoothScannerSetModeRequ
|
|
|
1263
1176
|
#endif
|
|
1264
1177
|
|
|
1265
1178
|
#ifdef USE_VOICE_ASSISTANT
|
|
1179
|
+
bool APIConnection::check_voice_assistant_api_connection_() const {
|
|
1180
|
+
return voice_assistant::global_voice_assistant != nullptr &&
|
|
1181
|
+
voice_assistant::global_voice_assistant->get_api_connection() == this;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1266
1184
|
void APIConnection::subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) {
|
|
1267
1185
|
if (voice_assistant::global_voice_assistant != nullptr) {
|
|
1268
1186
|
voice_assistant::global_voice_assistant->client_subscription(this, msg.subscribe);
|
|
1269
1187
|
}
|
|
1270
1188
|
}
|
|
1271
1189
|
void APIConnection::on_voice_assistant_response(const VoiceAssistantResponse &msg) {
|
|
1272
|
-
if (
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
}
|
|
1190
|
+
if (!this->check_voice_assistant_api_connection_()) {
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1276
1193
|
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
}
|
|
1194
|
+
if (msg.error) {
|
|
1195
|
+
voice_assistant::global_voice_assistant->failed_to_start();
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
if (msg.port == 0) {
|
|
1199
|
+
// Use API Audio
|
|
1200
|
+
voice_assistant::global_voice_assistant->start_streaming();
|
|
1201
|
+
} else {
|
|
1202
|
+
struct sockaddr_storage storage;
|
|
1203
|
+
socklen_t len = sizeof(storage);
|
|
1204
|
+
this->helper_->getpeername((struct sockaddr *) &storage, &len);
|
|
1205
|
+
voice_assistant::global_voice_assistant->start_streaming(&storage, msg.port);
|
|
1290
1206
|
}
|
|
1291
1207
|
};
|
|
1292
1208
|
void APIConnection::on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) {
|
|
1293
|
-
if (
|
|
1294
|
-
if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
|
|
1295
|
-
return;
|
|
1296
|
-
}
|
|
1297
|
-
|
|
1209
|
+
if (this->check_voice_assistant_api_connection_()) {
|
|
1298
1210
|
voice_assistant::global_voice_assistant->on_event(msg);
|
|
1299
1211
|
}
|
|
1300
1212
|
}
|
|
1301
1213
|
void APIConnection::on_voice_assistant_audio(const VoiceAssistantAudio &msg) {
|
|
1302
|
-
if (
|
|
1303
|
-
if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
|
|
1304
|
-
return;
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1214
|
+
if (this->check_voice_assistant_api_connection_()) {
|
|
1307
1215
|
voice_assistant::global_voice_assistant->on_audio(msg);
|
|
1308
1216
|
}
|
|
1309
1217
|
};
|
|
1310
1218
|
void APIConnection::on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &msg) {
|
|
1311
|
-
if (
|
|
1312
|
-
if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
|
|
1313
|
-
return;
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1219
|
+
if (this->check_voice_assistant_api_connection_()) {
|
|
1316
1220
|
voice_assistant::global_voice_assistant->on_timer_event(msg);
|
|
1317
1221
|
}
|
|
1318
1222
|
};
|
|
1319
1223
|
|
|
1320
1224
|
void APIConnection::on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &msg) {
|
|
1321
|
-
if (
|
|
1322
|
-
if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
|
|
1323
|
-
return;
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1225
|
+
if (this->check_voice_assistant_api_connection_()) {
|
|
1326
1226
|
voice_assistant::global_voice_assistant->on_announce(msg);
|
|
1327
1227
|
}
|
|
1328
1228
|
}
|
|
@@ -1330,35 +1230,29 @@ void APIConnection::on_voice_assistant_announce_request(const VoiceAssistantAnno
|
|
|
1330
1230
|
VoiceAssistantConfigurationResponse APIConnection::voice_assistant_get_configuration(
|
|
1331
1231
|
const VoiceAssistantConfigurationRequest &msg) {
|
|
1332
1232
|
VoiceAssistantConfigurationResponse resp;
|
|
1333
|
-
if (
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
}
|
|
1233
|
+
if (!this->check_voice_assistant_api_connection_()) {
|
|
1234
|
+
return resp;
|
|
1235
|
+
}
|
|
1337
1236
|
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
}
|
|
1346
|
-
resp.available_wake_words.push_back(std::move(resp_wake_word));
|
|
1347
|
-
}
|
|
1348
|
-
for (auto &wake_word_id : config.active_wake_words) {
|
|
1349
|
-
resp.active_wake_words.push_back(wake_word_id);
|
|
1237
|
+
auto &config = voice_assistant::global_voice_assistant->get_configuration();
|
|
1238
|
+
for (auto &wake_word : config.available_wake_words) {
|
|
1239
|
+
VoiceAssistantWakeWord resp_wake_word;
|
|
1240
|
+
resp_wake_word.id = wake_word.id;
|
|
1241
|
+
resp_wake_word.wake_word = wake_word.wake_word;
|
|
1242
|
+
for (const auto &lang : wake_word.trained_languages) {
|
|
1243
|
+
resp_wake_word.trained_languages.push_back(lang);
|
|
1350
1244
|
}
|
|
1351
|
-
resp.
|
|
1245
|
+
resp.available_wake_words.push_back(std::move(resp_wake_word));
|
|
1352
1246
|
}
|
|
1247
|
+
for (auto &wake_word_id : config.active_wake_words) {
|
|
1248
|
+
resp.active_wake_words.push_back(wake_word_id);
|
|
1249
|
+
}
|
|
1250
|
+
resp.max_active_wake_words = config.max_active_wake_words;
|
|
1353
1251
|
return resp;
|
|
1354
1252
|
}
|
|
1355
1253
|
|
|
1356
1254
|
void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) {
|
|
1357
|
-
if (
|
|
1358
|
-
if (voice_assistant::global_voice_assistant->get_api_connection() != this) {
|
|
1359
|
-
return;
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1255
|
+
if (this->check_voice_assistant_api_connection_()) {
|
|
1362
1256
|
voice_assistant::global_voice_assistant->on_set_configuration(msg.active_wake_words);
|
|
1363
1257
|
}
|
|
1364
1258
|
}
|
|
@@ -1367,8 +1261,8 @@ void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetCon
|
|
|
1367
1261
|
|
|
1368
1262
|
#ifdef USE_ALARM_CONTROL_PANEL
|
|
1369
1263
|
bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
|
|
1370
|
-
return this->
|
|
1371
|
-
|
|
1264
|
+
return this->send_message_smart_(a_alarm_control_panel, &APIConnection::try_send_alarm_control_panel_state,
|
|
1265
|
+
AlarmControlPanelStateResponse::MESSAGE_TYPE);
|
|
1372
1266
|
}
|
|
1373
1267
|
uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn,
|
|
1374
1268
|
uint32_t remaining_size, bool is_single) {
|
|
@@ -1378,10 +1272,6 @@ uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, A
|
|
|
1378
1272
|
fill_entity_state_base(a_alarm_control_panel, resp);
|
|
1379
1273
|
return encode_message_to_buffer(resp, AlarmControlPanelStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1380
1274
|
}
|
|
1381
|
-
void APIConnection::send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
|
|
1382
|
-
this->schedule_message_(a_alarm_control_panel, &APIConnection::try_send_alarm_control_panel_info,
|
|
1383
|
-
ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE);
|
|
1384
|
-
}
|
|
1385
1275
|
uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn,
|
|
1386
1276
|
uint32_t remaining_size, bool is_single) {
|
|
1387
1277
|
auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity);
|
|
@@ -1395,11 +1285,7 @@ uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, AP
|
|
|
1395
1285
|
is_single);
|
|
1396
1286
|
}
|
|
1397
1287
|
void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) {
|
|
1398
|
-
alarm_control_panel::AlarmControlPanel
|
|
1399
|
-
if (a_alarm_control_panel == nullptr)
|
|
1400
|
-
return;
|
|
1401
|
-
|
|
1402
|
-
auto call = a_alarm_control_panel->make_call();
|
|
1288
|
+
ENTITY_COMMAND_MAKE_CALL(alarm_control_panel::AlarmControlPanel, a_alarm_control_panel, alarm_control_panel)
|
|
1403
1289
|
switch (msg.command) {
|
|
1404
1290
|
case enums::ALARM_CONTROL_PANEL_DISARM:
|
|
1405
1291
|
call.disarm();
|
|
@@ -1430,10 +1316,7 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe
|
|
|
1430
1316
|
|
|
1431
1317
|
#ifdef USE_EVENT
|
|
1432
1318
|
void APIConnection::send_event(event::Event *event, const std::string &event_type) {
|
|
1433
|
-
this->schedule_message_(event, MessageCreator(event_type
|
|
1434
|
-
}
|
|
1435
|
-
void APIConnection::send_event_info(event::Event *event) {
|
|
1436
|
-
this->schedule_message_(event, &APIConnection::try_send_event_info, ListEntitiesEventResponse::MESSAGE_TYPE);
|
|
1319
|
+
this->schedule_message_(event, MessageCreator(event_type), EventResponse::MESSAGE_TYPE);
|
|
1437
1320
|
}
|
|
1438
1321
|
uint16_t APIConnection::try_send_event_response(event::Event *event, const std::string &event_type, APIConnection *conn,
|
|
1439
1322
|
uint32_t remaining_size, bool is_single) {
|
|
@@ -1458,7 +1341,7 @@ uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *c
|
|
|
1458
1341
|
|
|
1459
1342
|
#ifdef USE_UPDATE
|
|
1460
1343
|
bool APIConnection::send_update_state(update::UpdateEntity *update) {
|
|
1461
|
-
return this->
|
|
1344
|
+
return this->send_message_smart_(update, &APIConnection::try_send_update_state, UpdateStateResponse::MESSAGE_TYPE);
|
|
1462
1345
|
}
|
|
1463
1346
|
uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1464
1347
|
bool is_single) {
|
|
@@ -1480,9 +1363,6 @@ uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection
|
|
|
1480
1363
|
fill_entity_state_base(update, resp);
|
|
1481
1364
|
return encode_message_to_buffer(resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1482
1365
|
}
|
|
1483
|
-
void APIConnection::send_update_info(update::UpdateEntity *update) {
|
|
1484
|
-
this->schedule_message_(update, &APIConnection::try_send_update_info, ListEntitiesUpdateResponse::MESSAGE_TYPE);
|
|
1485
|
-
}
|
|
1486
1366
|
uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1487
1367
|
bool is_single) {
|
|
1488
1368
|
auto *update = static_cast<update::UpdateEntity *>(entity);
|
|
@@ -1493,9 +1373,7 @@ uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *
|
|
|
1493
1373
|
return encode_message_to_buffer(msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1494
1374
|
}
|
|
1495
1375
|
void APIConnection::update_command(const UpdateCommandRequest &msg) {
|
|
1496
|
-
update::UpdateEntity
|
|
1497
|
-
if (update == nullptr)
|
|
1498
|
-
return;
|
|
1376
|
+
ENTITY_COMMAND_GET(update::UpdateEntity, update, update)
|
|
1499
1377
|
|
|
1500
1378
|
switch (msg.command) {
|
|
1501
1379
|
case enums::UPDATE_COMMAND_UPDATE:
|
|
@@ -1514,12 +1392,11 @@ void APIConnection::update_command(const UpdateCommandRequest &msg) {
|
|
|
1514
1392
|
}
|
|
1515
1393
|
#endif
|
|
1516
1394
|
|
|
1517
|
-
bool APIConnection::try_send_log_message(int level, const char *tag, const char *line) {
|
|
1518
|
-
if (this->
|
|
1395
|
+
bool APIConnection::try_send_log_message(int level, const char *tag, const char *line, size_t message_len) {
|
|
1396
|
+
if (this->flags_.log_subscription < level)
|
|
1519
1397
|
return false;
|
|
1520
1398
|
|
|
1521
1399
|
// Pre-calculate message size to avoid reallocations
|
|
1522
|
-
const size_t line_length = strlen(line);
|
|
1523
1400
|
uint32_t msg_size = 0;
|
|
1524
1401
|
|
|
1525
1402
|
// Add size for level field (field ID 1, varint type)
|
|
@@ -1528,14 +1405,14 @@ bool APIConnection::try_send_log_message(int level, const char *tag, const char
|
|
|
1528
1405
|
|
|
1529
1406
|
// Add size for string field (field ID 3, string type)
|
|
1530
1407
|
// 1 byte for field tag + size of length varint + string length
|
|
1531
|
-
msg_size += 1 + api::ProtoSize::varint(static_cast<uint32_t>(
|
|
1408
|
+
msg_size += 1 + api::ProtoSize::varint(static_cast<uint32_t>(message_len)) + message_len;
|
|
1532
1409
|
|
|
1533
1410
|
// Create a pre-sized buffer
|
|
1534
1411
|
auto buffer = this->create_buffer(msg_size);
|
|
1535
1412
|
|
|
1536
1413
|
// Encode the message (SubscribeLogsResponse)
|
|
1537
1414
|
buffer.encode_uint32(1, static_cast<uint32_t>(level)); // LogLevel level = 1
|
|
1538
|
-
buffer.encode_string(3, line,
|
|
1415
|
+
buffer.encode_string(3, line, message_len); // string message = 3
|
|
1539
1416
|
|
|
1540
1417
|
// SubscribeLogsResponse - 29
|
|
1541
1418
|
return this->send_buffer(buffer, SubscribeLogsResponse::MESSAGE_TYPE);
|
|
@@ -1544,8 +1421,7 @@ bool APIConnection::try_send_log_message(int level, const char *tag, const char
|
|
|
1544
1421
|
HelloResponse APIConnection::hello(const HelloRequest &msg) {
|
|
1545
1422
|
this->client_info_ = msg.client_info;
|
|
1546
1423
|
this->client_peername_ = this->helper_->getpeername();
|
|
1547
|
-
this->
|
|
1548
|
-
this->helper_->set_log_info(this->client_combined_info_);
|
|
1424
|
+
this->helper_->set_log_info(this->get_client_combined_info());
|
|
1549
1425
|
this->client_api_version_major_ = msg.api_version_major;
|
|
1550
1426
|
this->client_api_version_minor_ = msg.api_version_minor;
|
|
1551
1427
|
ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu32 ".%" PRIu32, this->client_info_.c_str(),
|
|
@@ -1557,19 +1433,24 @@ HelloResponse APIConnection::hello(const HelloRequest &msg) {
|
|
|
1557
1433
|
resp.server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
|
|
1558
1434
|
resp.name = App.get_name();
|
|
1559
1435
|
|
|
1560
|
-
this->
|
|
1436
|
+
this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::CONNECTED);
|
|
1561
1437
|
return resp;
|
|
1562
1438
|
}
|
|
1563
1439
|
ConnectResponse APIConnection::connect(const ConnectRequest &msg) {
|
|
1564
|
-
bool correct =
|
|
1440
|
+
bool correct = true;
|
|
1441
|
+
#ifdef USE_API_PASSWORD
|
|
1442
|
+
correct = this->parent_->check_password(msg.password);
|
|
1443
|
+
#endif
|
|
1565
1444
|
|
|
1566
1445
|
ConnectResponse resp;
|
|
1567
1446
|
// bool invalid_password = 1;
|
|
1568
1447
|
resp.invalid_password = !correct;
|
|
1569
1448
|
if (correct) {
|
|
1570
|
-
ESP_LOGD(TAG, "%s connected", this->
|
|
1571
|
-
this->
|
|
1449
|
+
ESP_LOGD(TAG, "%s connected", this->get_client_combined_info().c_str());
|
|
1450
|
+
this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED);
|
|
1451
|
+
#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
|
|
1572
1452
|
this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_);
|
|
1453
|
+
#endif
|
|
1573
1454
|
#ifdef USE_HOMEASSISTANT_TIME
|
|
1574
1455
|
if (homeassistant::global_homeassistant_time != nullptr) {
|
|
1575
1456
|
this->send_time_request();
|
|
@@ -1580,7 +1461,11 @@ ConnectResponse APIConnection::connect(const ConnectRequest &msg) {
|
|
|
1580
1461
|
}
|
|
1581
1462
|
DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
|
|
1582
1463
|
DeviceInfoResponse resp{};
|
|
1464
|
+
#ifdef USE_API_PASSWORD
|
|
1583
1465
|
resp.uses_password = this->parent_->uses_password();
|
|
1466
|
+
#else
|
|
1467
|
+
resp.uses_password = false;
|
|
1468
|
+
#endif
|
|
1584
1469
|
resp.name = App.get_name();
|
|
1585
1470
|
resp.friendly_name = App.get_friendly_name();
|
|
1586
1471
|
resp.suggested_area = App.get_area();
|
|
@@ -1593,6 +1478,8 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
|
|
|
1593
1478
|
resp.manufacturer = "Raspberry Pi";
|
|
1594
1479
|
#elif defined(USE_BK72XX)
|
|
1595
1480
|
resp.manufacturer = "Beken";
|
|
1481
|
+
#elif defined(USE_LN882X)
|
|
1482
|
+
resp.manufacturer = "Lightning";
|
|
1596
1483
|
#elif defined(USE_RTL87XX)
|
|
1597
1484
|
resp.manufacturer = "Realtek";
|
|
1598
1485
|
#elif defined(USE_HOST)
|
|
@@ -1620,6 +1507,23 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
|
|
|
1620
1507
|
#endif
|
|
1621
1508
|
#ifdef USE_API_NOISE
|
|
1622
1509
|
resp.api_encryption_supported = true;
|
|
1510
|
+
#endif
|
|
1511
|
+
#ifdef USE_DEVICES
|
|
1512
|
+
for (auto const &device : App.get_devices()) {
|
|
1513
|
+
DeviceInfo device_info;
|
|
1514
|
+
device_info.device_id = device->get_device_id();
|
|
1515
|
+
device_info.name = device->get_name();
|
|
1516
|
+
device_info.area_id = device->get_area_id();
|
|
1517
|
+
resp.devices.push_back(device_info);
|
|
1518
|
+
}
|
|
1519
|
+
#endif
|
|
1520
|
+
#ifdef USE_AREAS
|
|
1521
|
+
for (auto const &area : App.get_areas()) {
|
|
1522
|
+
AreaInfo area_info;
|
|
1523
|
+
area_info.area_id = area->get_area_id();
|
|
1524
|
+
area_info.name = area->get_name();
|
|
1525
|
+
resp.areas.push_back(area_info);
|
|
1526
|
+
}
|
|
1623
1527
|
#endif
|
|
1624
1528
|
return resp;
|
|
1625
1529
|
}
|
|
@@ -1665,7 +1569,7 @@ void APIConnection::subscribe_home_assistant_states(const SubscribeHomeAssistant
|
|
|
1665
1569
|
state_subs_at_ = 0;
|
|
1666
1570
|
}
|
|
1667
1571
|
bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
|
|
1668
|
-
if (this->
|
|
1572
|
+
if (this->flags_.remove)
|
|
1669
1573
|
return false;
|
|
1670
1574
|
if (this->helper_->can_write_without_blocking())
|
|
1671
1575
|
return true;
|
|
@@ -1673,7 +1577,7 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
|
|
|
1673
1577
|
APIError err = this->helper_->loop();
|
|
1674
1578
|
if (err != APIError::OK) {
|
|
1675
1579
|
on_fatal_error();
|
|
1676
|
-
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->
|
|
1580
|
+
ESP_LOGW(TAG, "%s: Socket operation failed: %s errno=%d", this->get_client_combined_info().c_str(),
|
|
1677
1581
|
api_error_to_str(err), errno);
|
|
1678
1582
|
return false;
|
|
1679
1583
|
}
|
|
@@ -1695,10 +1599,10 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint16_t message_type)
|
|
|
1695
1599
|
if (err != APIError::OK) {
|
|
1696
1600
|
on_fatal_error();
|
|
1697
1601
|
if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
|
|
1698
|
-
ESP_LOGW(TAG, "%s: Connection reset", this->
|
|
1602
|
+
ESP_LOGW(TAG, "%s: Connection reset", this->get_client_combined_info().c_str());
|
|
1699
1603
|
} else {
|
|
1700
|
-
ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", this->
|
|
1701
|
-
errno);
|
|
1604
|
+
ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", this->get_client_combined_info().c_str(),
|
|
1605
|
+
api_error_to_str(err), errno);
|
|
1702
1606
|
}
|
|
1703
1607
|
return false;
|
|
1704
1608
|
}
|
|
@@ -1707,15 +1611,15 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint16_t message_type)
|
|
|
1707
1611
|
}
|
|
1708
1612
|
void APIConnection::on_unauthenticated_access() {
|
|
1709
1613
|
this->on_fatal_error();
|
|
1710
|
-
ESP_LOGD(TAG, "%s requested access without authentication", this->
|
|
1614
|
+
ESP_LOGD(TAG, "%s requested access without authentication", this->get_client_combined_info().c_str());
|
|
1711
1615
|
}
|
|
1712
1616
|
void APIConnection::on_no_setup_connection() {
|
|
1713
1617
|
this->on_fatal_error();
|
|
1714
|
-
ESP_LOGD(TAG, "%s requested access without full connection", this->
|
|
1618
|
+
ESP_LOGD(TAG, "%s requested access without full connection", this->get_client_combined_info().c_str());
|
|
1715
1619
|
}
|
|
1716
1620
|
void APIConnection::on_fatal_error() {
|
|
1717
1621
|
this->helper_->close();
|
|
1718
|
-
this->
|
|
1622
|
+
this->flags_.remove = true;
|
|
1719
1623
|
}
|
|
1720
1624
|
|
|
1721
1625
|
void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator creator, uint16_t message_type) {
|
|
@@ -1724,7 +1628,9 @@ void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator c
|
|
|
1724
1628
|
// O(n) but optimized for RAM and not performance.
|
|
1725
1629
|
for (auto &item : items) {
|
|
1726
1630
|
if (item.entity == entity && item.message_type == message_type) {
|
|
1727
|
-
//
|
|
1631
|
+
// Clean up old creator before replacing
|
|
1632
|
+
item.creator.cleanup(message_type);
|
|
1633
|
+
// Move assign the new creator
|
|
1728
1634
|
item.creator = std::move(creator);
|
|
1729
1635
|
return;
|
|
1730
1636
|
}
|
|
@@ -1734,9 +1640,14 @@ void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator c
|
|
|
1734
1640
|
items.emplace_back(entity, std::move(creator), message_type);
|
|
1735
1641
|
}
|
|
1736
1642
|
|
|
1643
|
+
void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, MessageCreator creator, uint16_t message_type) {
|
|
1644
|
+
// Insert at front for high priority messages (no deduplication check)
|
|
1645
|
+
items.insert(items.begin(), BatchItem(entity, std::move(creator), message_type));
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1737
1648
|
bool APIConnection::schedule_batch_() {
|
|
1738
|
-
if (!this->
|
|
1739
|
-
this->
|
|
1649
|
+
if (!this->flags_.batch_scheduled) {
|
|
1650
|
+
this->flags_.batch_scheduled = true;
|
|
1740
1651
|
this->deferred_batch_.batch_start_time = App.get_loop_component_start_time();
|
|
1741
1652
|
}
|
|
1742
1653
|
return true;
|
|
@@ -1745,14 +1656,14 @@ bool APIConnection::schedule_batch_() {
|
|
|
1745
1656
|
ProtoWriteBuffer APIConnection::allocate_single_message_buffer(uint16_t size) { return this->create_buffer(size); }
|
|
1746
1657
|
|
|
1747
1658
|
ProtoWriteBuffer APIConnection::allocate_batch_message_buffer(uint16_t size) {
|
|
1748
|
-
ProtoWriteBuffer result = this->prepare_message_buffer(size, this->
|
|
1749
|
-
this->
|
|
1659
|
+
ProtoWriteBuffer result = this->prepare_message_buffer(size, this->flags_.batch_first_message);
|
|
1660
|
+
this->flags_.batch_first_message = false;
|
|
1750
1661
|
return result;
|
|
1751
1662
|
}
|
|
1752
1663
|
|
|
1753
1664
|
void APIConnection::process_batch_() {
|
|
1754
1665
|
if (this->deferred_batch_.empty()) {
|
|
1755
|
-
this->
|
|
1666
|
+
this->flags_.batch_scheduled = false;
|
|
1756
1667
|
return;
|
|
1757
1668
|
}
|
|
1758
1669
|
|
|
@@ -1762,22 +1673,28 @@ void APIConnection::process_batch_() {
|
|
|
1762
1673
|
return;
|
|
1763
1674
|
}
|
|
1764
1675
|
|
|
1765
|
-
size_t num_items = this->deferred_batch_.
|
|
1676
|
+
size_t num_items = this->deferred_batch_.size();
|
|
1766
1677
|
|
|
1767
1678
|
// Fast path for single message - allocate exact size needed
|
|
1768
1679
|
if (num_items == 1) {
|
|
1769
|
-
const auto &item = this->deferred_batch_
|
|
1680
|
+
const auto &item = this->deferred_batch_[0];
|
|
1770
1681
|
|
|
1771
1682
|
// Let the creator calculate size and encode if it fits
|
|
1772
|
-
uint16_t payload_size =
|
|
1683
|
+
uint16_t payload_size =
|
|
1684
|
+
item.creator(item.entity, this, std::numeric_limits<uint16_t>::max(), true, item.message_type);
|
|
1773
1685
|
|
|
1774
1686
|
if (payload_size > 0 &&
|
|
1775
1687
|
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, item.message_type)) {
|
|
1776
|
-
|
|
1688
|
+
#ifdef HAS_PROTO_MESSAGE_DUMP
|
|
1689
|
+
// Log messages after send attempt for VV debugging
|
|
1690
|
+
// It's safe to use the buffer for logging at this point regardless of send result
|
|
1691
|
+
this->log_batch_item_(item);
|
|
1692
|
+
#endif
|
|
1693
|
+
this->clear_batch_();
|
|
1777
1694
|
} else if (payload_size == 0) {
|
|
1778
1695
|
// Message too large
|
|
1779
1696
|
ESP_LOGW(TAG, "Message too large to send: type=%u", item.message_type);
|
|
1780
|
-
this->
|
|
1697
|
+
this->clear_batch_();
|
|
1781
1698
|
}
|
|
1782
1699
|
return;
|
|
1783
1700
|
}
|
|
@@ -1795,7 +1712,8 @@ void APIConnection::process_batch_() {
|
|
|
1795
1712
|
|
|
1796
1713
|
// Pre-calculate exact buffer size needed based on message types
|
|
1797
1714
|
uint32_t total_estimated_size = 0;
|
|
1798
|
-
for (
|
|
1715
|
+
for (size_t i = 0; i < this->deferred_batch_.size(); i++) {
|
|
1716
|
+
const auto &item = this->deferred_batch_[i];
|
|
1799
1717
|
total_estimated_size += get_estimated_message_size(item.message_type);
|
|
1800
1718
|
}
|
|
1801
1719
|
|
|
@@ -1804,7 +1722,7 @@ void APIConnection::process_batch_() {
|
|
|
1804
1722
|
|
|
1805
1723
|
// Reserve based on estimated size (much more accurate than 24-byte worst-case)
|
|
1806
1724
|
this->parent_->get_shared_buffer_ref().reserve(total_estimated_size + total_overhead);
|
|
1807
|
-
this->
|
|
1725
|
+
this->flags_.batch_first_message = true;
|
|
1808
1726
|
|
|
1809
1727
|
size_t items_processed = 0;
|
|
1810
1728
|
uint16_t remaining_size = std::numeric_limits<uint16_t>::max();
|
|
@@ -1816,10 +1734,11 @@ void APIConnection::process_batch_() {
|
|
|
1816
1734
|
uint32_t current_offset = 0;
|
|
1817
1735
|
|
|
1818
1736
|
// Process items and encode directly to buffer
|
|
1819
|
-
for (
|
|
1737
|
+
for (size_t i = 0; i < this->deferred_batch_.size(); i++) {
|
|
1738
|
+
const auto &item = this->deferred_batch_[i];
|
|
1820
1739
|
// Try to encode message
|
|
1821
1740
|
// The creator will calculate overhead to determine if the message fits
|
|
1822
|
-
uint16_t payload_size = item.creator(item.entity, this, remaining_size, false);
|
|
1741
|
+
uint16_t payload_size = item.creator(item.entity, this, remaining_size, false, item.message_type);
|
|
1823
1742
|
|
|
1824
1743
|
if (payload_size == 0) {
|
|
1825
1744
|
// Message won't fit, stop processing
|
|
@@ -1860,44 +1779,46 @@ void APIConnection::process_batch_() {
|
|
|
1860
1779
|
if (err != APIError::OK && err != APIError::WOULD_BLOCK) {
|
|
1861
1780
|
on_fatal_error();
|
|
1862
1781
|
if (err == APIError::SOCKET_WRITE_FAILED && errno == ECONNRESET) {
|
|
1863
|
-
ESP_LOGW(TAG, "%s: Connection reset during batch write", this->
|
|
1782
|
+
ESP_LOGW(TAG, "%s: Connection reset during batch write", this->get_client_combined_info().c_str());
|
|
1864
1783
|
} else {
|
|
1865
|
-
ESP_LOGW(TAG, "%s: Batch write failed %s errno=%d", this->
|
|
1866
|
-
errno);
|
|
1784
|
+
ESP_LOGW(TAG, "%s: Batch write failed %s errno=%d", this->get_client_combined_info().c_str(),
|
|
1785
|
+
api_error_to_str(err), errno);
|
|
1867
1786
|
}
|
|
1868
1787
|
}
|
|
1869
1788
|
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1789
|
+
#ifdef HAS_PROTO_MESSAGE_DUMP
|
|
1790
|
+
// Log messages after send attempt for VV debugging
|
|
1791
|
+
// It's safe to use the buffer for logging at this point regardless of send result
|
|
1792
|
+
for (size_t i = 0; i < items_processed; i++) {
|
|
1793
|
+
const auto &item = this->deferred_batch_[i];
|
|
1794
|
+
this->log_batch_item_(item);
|
|
1795
|
+
}
|
|
1796
|
+
#endif
|
|
1875
1797
|
|
|
1798
|
+
// Handle remaining items more efficiently
|
|
1799
|
+
if (items_processed < this->deferred_batch_.size()) {
|
|
1800
|
+
// Remove processed items from the beginning with proper cleanup
|
|
1801
|
+
this->deferred_batch_.remove_front(items_processed);
|
|
1876
1802
|
// Reschedule for remaining items
|
|
1877
1803
|
this->schedule_batch_();
|
|
1878
1804
|
} else {
|
|
1879
1805
|
// All items processed
|
|
1880
|
-
this->
|
|
1806
|
+
this->clear_batch_();
|
|
1881
1807
|
}
|
|
1882
1808
|
}
|
|
1883
1809
|
|
|
1884
1810
|
uint16_t APIConnection::MessageCreator::operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1885
|
-
bool is_single) const {
|
|
1886
|
-
switch (message_type_) {
|
|
1887
|
-
case 0: // Function pointer
|
|
1888
|
-
return data_.ptr(entity, conn, remaining_size, is_single);
|
|
1889
|
-
|
|
1811
|
+
bool is_single, uint16_t message_type) const {
|
|
1890
1812
|
#ifdef USE_EVENT
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1813
|
+
// Special case: EventResponse uses string pointer
|
|
1814
|
+
if (message_type == EventResponse::MESSAGE_TYPE) {
|
|
1815
|
+
auto *e = static_cast<event::Event *>(entity);
|
|
1816
|
+
return APIConnection::try_send_event_response(e, *data_.string_ptr, conn, remaining_size, is_single);
|
|
1817
|
+
}
|
|
1895
1818
|
#endif
|
|
1896
1819
|
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
return 0;
|
|
1900
|
-
}
|
|
1820
|
+
// All other message types use function pointers
|
|
1821
|
+
return data_.function_ptr(entity, conn, remaining_size, is_single);
|
|
1901
1822
|
}
|
|
1902
1823
|
|
|
1903
1824
|
uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -1912,6 +1833,12 @@ uint16_t APIConnection::try_send_disconnect_request(EntityBase *entity, APIConne
|
|
|
1912
1833
|
return encode_message_to_buffer(req, DisconnectRequest::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1913
1834
|
}
|
|
1914
1835
|
|
|
1836
|
+
uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1837
|
+
bool is_single) {
|
|
1838
|
+
PingRequest req;
|
|
1839
|
+
return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1915
1842
|
uint16_t APIConnection::get_estimated_message_size(uint16_t message_type) {
|
|
1916
1843
|
// Use generated ESTIMATED_SIZE constants from each message type
|
|
1917
1844
|
switch (message_type) {
|