esphome 2025.7.4__py3-none-any.whl → 2025.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +190 -83
- esphome/automation.py +2 -4
- esphome/build_gen/__init__.py +0 -0
- esphome/build_gen/platformio.py +102 -0
- esphome/components/a4988/a4988.cpp +0 -1
- esphome/components/absolute_humidity/absolute_humidity.cpp +0 -2
- esphome/components/absolute_humidity/sensor.py +2 -2
- esphome/components/adc/__init__.py +123 -85
- esphome/components/adc/adc_sensor.h +98 -35
- esphome/components/adc/adc_sensor_common.cpp +10 -4
- esphome/components/adc/adc_sensor_esp32.cpp +291 -123
- esphome/components/adc/adc_sensor_esp8266.cpp +1 -4
- esphome/components/adc/adc_sensor_libretiny.cpp +1 -2
- esphome/components/adc/adc_sensor_rp2040.cpp +1 -2
- esphome/components/adc/adc_sensor_zephyr.cpp +207 -0
- esphome/components/adc/sensor.py +61 -27
- esphome/components/adc128s102/adc128s102.cpp +1 -4
- esphome/components/ade7880/sensor.py +75 -49
- esphome/components/ads1115/ads1115.cpp +0 -1
- esphome/components/ads1118/ads1118.cpp +0 -1
- esphome/components/ags10/ags10.cpp +0 -4
- esphome/components/aht10/aht10.cpp +0 -4
- esphome/components/aic3204/aic3204.cpp +0 -2
- esphome/components/airthings_wave_plus/__init__.py +1 -1
- esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +22 -4
- esphome/components/airthings_wave_plus/airthings_wave_plus.h +10 -1
- esphome/components/airthings_wave_plus/sensor.py +55 -28
- esphome/components/alarm_control_panel/__init__.py +4 -9
- esphome/components/am2315c/am2315c.cpp +0 -2
- esphome/components/am2320/am2320.cpp +0 -1
- esphome/components/animation/__init__.py +14 -11
- esphome/components/apds9306/apds9306.cpp +0 -4
- esphome/components/apds9960/apds9960.cpp +0 -1
- esphome/components/api/__init__.py +29 -4
- esphome/components/api/api_connection.cpp +378 -401
- esphome/components/api/api_connection.h +112 -56
- esphome/components/api/api_frame_helper.cpp +69 -896
- esphome/components/api/api_frame_helper.h +31 -126
- esphome/components/api/api_frame_helper_noise.cpp +583 -0
- esphome/components/api/api_frame_helper_noise.h +68 -0
- esphome/components/api/api_frame_helper_plaintext.cpp +290 -0
- esphome/components/api/api_frame_helper_plaintext.h +53 -0
- esphome/components/api/api_noise_context.h +2 -4
- esphome/components/api/api_pb2.cpp +1601 -1808
- esphome/components/api/api_pb2.h +367 -323
- esphome/components/api/api_pb2_dump.cpp +1137 -3466
- esphome/components/api/api_pb2_includes.h +34 -0
- esphome/components/api/api_pb2_service.cpp +94 -105
- esphome/components/api/api_pb2_service.h +27 -16
- esphome/components/api/api_server.cpp +18 -17
- esphome/components/api/api_server.h +8 -5
- esphome/components/api/client.py +16 -8
- esphome/components/api/custom_api_device.h +68 -14
- esphome/components/api/homeassistant_service.h +24 -19
- esphome/components/api/list_entities.cpp +3 -5
- esphome/components/api/list_entities.h +2 -4
- esphome/components/api/proto.cpp +3 -5
- esphome/components/api/proto.h +239 -274
- esphome/components/api/subscribe_state.cpp +2 -4
- esphome/components/api/subscribe_state.h +2 -4
- esphome/components/api/user_services.cpp +2 -4
- esphome/components/api/user_services.h +8 -8
- esphome/components/as3935/as3935.cpp +0 -2
- esphome/components/as3935_spi/as3935_spi.cpp +0 -2
- esphome/components/as5600/__init__.py +1 -1
- esphome/components/as5600/as5600.cpp +0 -2
- esphome/components/as5600/sensor/__init__.py +0 -1
- esphome/components/as7341/as7341.cpp +0 -1
- esphome/components/async_tcp/__init__.py +1 -1
- esphome/components/at581x/at581x.cpp +1 -1
- esphome/components/atm90e26/atm90e26.cpp +0 -1
- esphome/components/atm90e32/atm90e32.cpp +475 -116
- esphome/components/atm90e32/atm90e32.h +43 -5
- esphome/components/audio/audio.h +2 -2
- esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +0 -2
- esphome/components/beken_spi_led_strip/led_strip.cpp +0 -2
- esphome/components/bh1750/bh1750.cpp +0 -1
- esphome/components/binary_sensor/__init__.py +14 -12
- esphome/components/ble_client/__init__.py +4 -7
- esphome/components/bluetooth_proxy/__init__.py +40 -3
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +392 -81
- esphome/components/bluetooth_proxy/bluetooth_connection.h +16 -5
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +102 -311
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +30 -14
- esphome/components/bme280_base/bme280_base.cpp +15 -16
- esphome/components/bme680/bme680.cpp +2 -3
- esphome/components/bme680_bsec/bme680_bsec.cpp +0 -2
- esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +0 -2
- esphome/components/bmi160/bmi160.cpp +0 -1
- esphome/components/bmp085/bmp085.cpp +0 -1
- esphome/components/bmp280_base/bmp280_base.cpp +13 -14
- esphome/components/bmp3xx_base/bmp3xx_base.cpp +0 -1
- esphome/components/bmp581/bmp581.cpp +0 -2
- esphome/components/bp1658cj/bp1658cj.cpp +0 -1
- esphome/components/bp5758d/bp5758d.cpp +0 -1
- esphome/components/button/__init__.py +0 -1
- esphome/components/canbus/__init__.py +2 -3
- esphome/components/canbus/canbus.cpp +0 -1
- esphome/components/cap1188/cap1188.cpp +0 -2
- esphome/components/captive_portal/__init__.py +1 -1
- esphome/components/cd74hc4067/cd74hc4067.cpp +0 -2
- esphome/components/ch422g/ch422g.cpp +0 -1
- esphome/components/chsc6x/chsc6x_touchscreen.cpp +0 -3
- esphome/components/climate/__init__.py +0 -1
- esphome/components/climate/climate_traits.h +24 -0
- esphome/components/cm1106/cm1106.cpp +0 -1
- esphome/components/const/__init__.py +6 -0
- esphome/components/cover/__init__.py +0 -1
- esphome/components/cover/cover.cpp +9 -13
- esphome/components/cs5460a/cs5460a.cpp +0 -2
- esphome/components/cse7761/cse7761.cpp +0 -1
- esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +0 -2
- esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +0 -2
- esphome/components/dac7678/dac7678_output.cpp +0 -2
- esphome/components/dallas_temp/dallas_temp.cpp +0 -1
- esphome/components/datetime/__init__.py +0 -2
- esphome/components/debug/__init__.py +15 -1
- esphome/components/debug/debug_zephyr.cpp +281 -0
- esphome/components/debug/sensor.py +2 -1
- esphome/components/deep_sleep/deep_sleep_component.cpp +0 -1
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +20 -1
- esphome/components/dfrobot_sen0395/__init__.py +1 -2
- esphome/components/dht/dht.cpp +0 -1
- esphome/components/dht12/dht12.cpp +0 -1
- esphome/components/display/__init__.py +16 -3
- esphome/components/display_menu_base/__init__.py +1 -1
- esphome/components/dps310/dps310.cpp +0 -2
- esphome/components/ds1307/ds1307.cpp +0 -1
- esphome/components/ds2484/ds2484.cpp +0 -1
- esphome/components/duty_cycle/duty_cycle_sensor.cpp +0 -1
- esphome/components/ee895/ee895.cpp +0 -1
- esphome/components/ektf2232/touchscreen/ektf2232.cpp +0 -1
- esphome/components/emc2101/emc2101.cpp +0 -2
- esphome/components/ens160_base/ens160_base.cpp +0 -2
- esphome/components/ens210/ens210.cpp +0 -1
- esphome/components/es7210/es7210.cpp +0 -2
- esphome/components/es7243e/es7243e.cpp +0 -2
- esphome/components/es8156/es8156.cpp +0 -2
- esphome/components/es8311/es8311.cpp +0 -2
- esphome/components/es8388/es8388.cpp +0 -2
- esphome/components/esp32/__init__.py +203 -60
- esphome/components/esp32/boards.py +17 -0
- esphome/components/esp32/gpio.cpp +0 -1
- esphome/components/esp32/gpio.py +1 -2
- esphome/components/esp32/gpio_esp32_h2.py +2 -7
- esphome/components/esp32/gpio_esp32_p4.py +2 -7
- esphome/components/esp32/post_build.py.script +112 -61
- esphome/components/esp32_ble/__init__.py +41 -2
- esphome/components/esp32_ble/ble.cpp +14 -10
- esphome/components/esp32_ble/ble.h +18 -18
- esphome/components/esp32_ble/ble_advertising.cpp +5 -5
- esphome/components/esp32_ble/ble_advertising.h +7 -5
- esphome/components/esp32_ble/ble_event.h +139 -73
- esphome/components/esp32_ble/ble_scan_result.h +2 -4
- esphome/components/esp32_ble/ble_uuid.cpp +5 -5
- esphome/components/esp32_ble/ble_uuid.h +6 -5
- esphome/components/esp32_ble_beacon/__init__.py +4 -0
- esphome/components/esp32_ble_client/__init__.py +1 -1
- esphome/components/esp32_ble_client/ble_characteristic.cpp +4 -4
- esphome/components/esp32_ble_client/ble_characteristic.h +6 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +155 -104
- esphome/components/esp32_ble_client/ble_client_base.h +17 -6
- esphome/components/esp32_ble_client/ble_descriptor.h +6 -4
- esphome/components/esp32_ble_client/ble_service.cpp +4 -4
- esphome/components/esp32_ble_client/ble_service.h +6 -4
- esphome/components/esp32_ble_server/__init__.py +15 -12
- esphome/components/esp32_ble_tracker/__init__.py +79 -11
- esphome/components/esp32_ble_tracker/automation.h +4 -4
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +264 -261
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +103 -37
- esphome/components/esp32_camera/__init__.py +13 -1
- esphome/components/esp32_camera/esp32_camera.cpp +7 -2
- esphome/components/esp32_camera/esp32_camera.h +1 -0
- esphome/components/esp32_dac/esp32_dac.cpp +3 -19
- esphome/components/esp32_dac/esp32_dac.h +4 -8
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -6
- esphome/components/esp32_rmt_led_strip/light.py +1 -1
- esphome/components/esp32_touch/__init__.py +2 -3
- esphome/components/esp32_touch/esp32_touch.h +9 -6
- esphome/components/esp32_touch/esp32_touch_common.cpp +2 -0
- esphome/components/esp32_touch/esp32_touch_v1.cpp +7 -9
- esphome/components/esp32_touch/esp32_touch_v2.cpp +10 -6
- esphome/components/esp8266/__init__.py +3 -1
- esphome/components/esp8266_pwm/esp8266_pwm.cpp +0 -1
- esphome/components/esphome/ota/__init__.py +1 -2
- esphome/components/esphome/ota/ota_esphome.cpp +150 -77
- esphome/components/esphome/ota/ota_esphome.h +8 -1
- esphome/components/espnow/__init__.py +309 -0
- esphome/components/espnow/automation.h +175 -0
- esphome/components/espnow/espnow_component.cpp +468 -0
- esphome/components/espnow/espnow_component.h +183 -0
- esphome/components/espnow/espnow_err.h +19 -0
- esphome/components/espnow/espnow_packet.h +166 -0
- esphome/components/ethernet/__init__.py +7 -1
- esphome/components/ethernet/esp_eth_phy_jl1101.c +5 -0
- esphome/components/ethernet/ethernet_component.cpp +0 -1
- esphome/components/ethernet/ethernet_component.h +4 -0
- esphome/components/ethernet_info/ethernet_info_text_sensor.h +0 -3
- esphome/components/event/__init__.py +0 -1
- esphome/components/factory_reset/__init__.py +92 -0
- esphome/components/factory_reset/factory_reset.cpp +76 -0
- esphome/components/factory_reset/factory_reset.h +43 -0
- esphome/components/fan/__init__.py +0 -1
- esphome/components/fan/fan_traits.h +16 -0
- esphome/components/fastled_base/fastled_light.cpp +0 -1
- esphome/components/fastled_spi/light.py +1 -3
- esphome/components/fingerprint_grow/fingerprint_grow.cpp +0 -2
- esphome/components/font/__init__.py +9 -1
- esphome/components/fs3000/fs3000.cpp +0 -2
- esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp +0 -2
- esphome/components/ft63x6/ft63x6.cpp +0 -1
- esphome/components/gdk101/gdk101.cpp +0 -1
- esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +0 -1
- esphome/components/gl_r01_i2c/sensor.py +1 -1
- esphome/components/gpio/one_wire/gpio_one_wire.cpp +0 -1
- esphome/components/gpio/switch/gpio_switch.cpp +0 -2
- esphome/components/gpio_expander/cached_gpio.h +24 -15
- esphome/components/gps/__init__.py +6 -2
- esphome/components/gps/gps.cpp +50 -49
- esphome/components/gps/gps.h +4 -8
- esphome/components/gps/time/gps_time.cpp +3 -9
- esphome/components/gps/time/gps_time.h +4 -7
- esphome/components/graph/__init__.py +1 -1
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +0 -1
- esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +0 -1
- esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +21 -12
- esphome/components/gt911/touchscreen/gt911_touchscreen.h +26 -2
- esphome/components/haier/climate.py +5 -10
- esphome/components/haier/haier_base.cpp +0 -1
- esphome/components/hbridge/switch/hbridge_switch.cpp +0 -2
- esphome/components/hdc1080/hdc1080.cpp +0 -2
- esphome/components/heatpumpir/climate.py +2 -2
- esphome/components/hlw8012/hlw8012.cpp +0 -1
- esphome/components/hm3301/hm3301.cpp +0 -1
- esphome/components/hmc5883l/hmc5883l.cpp +0 -1
- esphome/components/homeassistant/__init__.py +1 -0
- esphome/components/homeassistant/number/__init__.py +1 -0
- esphome/components/homeassistant/number/homeassistant_number.cpp +11 -7
- esphome/components/homeassistant/switch/__init__.py +1 -0
- esphome/components/homeassistant/switch/homeassistant_switch.cpp +9 -5
- esphome/components/honeywellabp/honeywellabp.cpp +1 -4
- esphome/components/host/__init__.py +2 -0
- esphome/components/hte501/hte501.cpp +0 -1
- esphome/components/http_request/__init__.py +2 -3
- esphome/components/http_request/http_request_idf.cpp +2 -2
- esphome/components/htu21d/htu21d.cpp +0 -2
- esphome/components/htu31d/htu31d.cpp +0 -2
- esphome/components/hx711/hx711.cpp +0 -1
- esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +0 -1
- esphome/components/hydreon_rgxx/sensor.py +4 -5
- esphome/components/i2c/i2c_bus.h +1 -1
- esphome/components/i2c/i2c_bus_arduino.cpp +1 -2
- esphome/components/i2c/i2c_bus_esp_idf.cpp +192 -17
- esphome/components/i2c/i2c_bus_esp_idf.h +11 -1
- esphome/components/i2s_audio/__init__.py +6 -5
- esphome/components/i2s_audio/i2s_audio.cpp +0 -2
- esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +1 -4
- esphome/components/i2s_audio/microphone/__init__.py +4 -6
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +46 -19
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +4 -3
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +273 -269
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +19 -34
- esphome/components/ili9xxx/display.py +4 -3
- esphome/components/ili9xxx/ili9xxx_display.cpp +0 -2
- esphome/components/image/__init__.py +123 -92
- esphome/components/improv_serial/__init__.py +7 -8
- esphome/components/ina219/ina219.cpp +0 -1
- esphome/components/ina226/ina226.cpp +0 -2
- esphome/components/ina260/ina260.cpp +0 -2
- esphome/components/ina2xx_base/__init__.py +2 -5
- esphome/components/ina2xx_base/ina2xx_base.cpp +0 -2
- esphome/components/ina3221/ina3221.cpp +0 -1
- esphome/components/internal_temperature/internal_temperature.cpp +0 -2
- esphome/components/interval/interval.h +5 -9
- esphome/components/json/__init__.py +1 -1
- esphome/components/kmeteriso/kmeteriso.cpp +0 -2
- esphome/components/lc709203f/lc709203f.cpp +0 -2
- esphome/components/lcd_gpio/display.py +1 -3
- esphome/components/lcd_gpio/gpio_lcd_display.cpp +0 -1
- esphome/components/lcd_pcf8574/pcf8574_display.cpp +0 -1
- esphome/components/ld2410/__init__.py +4 -6
- esphome/components/ld2410/binary_sensor.py +4 -0
- esphome/components/ld2410/ld2410.cpp +56 -100
- esphome/components/ld2410/ld2410.h +17 -15
- esphome/components/ld2410/sensor.py +24 -10
- esphome/components/ld2412/__init__.py +46 -0
- esphome/components/ld2412/binary_sensor.py +70 -0
- esphome/components/ld2412/button/__init__.py +74 -0
- esphome/components/ld2412/button/factory_reset_button.cpp +9 -0
- esphome/components/ld2412/button/factory_reset_button.h +18 -0
- esphome/components/ld2412/button/query_button.cpp +9 -0
- esphome/components/ld2412/button/query_button.h +18 -0
- esphome/components/ld2412/button/restart_button.cpp +9 -0
- esphome/components/ld2412/button/restart_button.h +18 -0
- esphome/components/ld2412/button/start_dynamic_background_correction_button.cpp +11 -0
- esphome/components/ld2412/button/start_dynamic_background_correction_button.h +18 -0
- esphome/components/ld2412/ld2412.cpp +861 -0
- esphome/components/ld2412/ld2412.h +141 -0
- esphome/components/ld2412/number/__init__.py +126 -0
- esphome/components/ld2412/number/gate_threshold_number.cpp +14 -0
- esphome/components/ld2412/number/gate_threshold_number.h +19 -0
- esphome/components/ld2412/number/light_threshold_number.cpp +12 -0
- esphome/components/ld2412/number/light_threshold_number.h +18 -0
- esphome/components/ld2412/number/max_distance_timeout_number.cpp +12 -0
- esphome/components/ld2412/number/max_distance_timeout_number.h +18 -0
- esphome/components/ld2412/select/__init__.py +82 -0
- esphome/components/ld2412/select/baud_rate_select.cpp +12 -0
- esphome/components/ld2412/select/baud_rate_select.h +18 -0
- esphome/components/ld2412/select/distance_resolution_select.cpp +12 -0
- esphome/components/ld2412/select/distance_resolution_select.h +18 -0
- esphome/components/ld2412/select/light_out_control_select.cpp +12 -0
- esphome/components/ld2412/select/light_out_control_select.h +18 -0
- esphome/components/ld2412/sensor.py +124 -0
- esphome/components/ld2412/switch/__init__.py +45 -0
- esphome/components/ld2412/switch/bluetooth_switch.cpp +12 -0
- esphome/components/ld2412/switch/bluetooth_switch.h +18 -0
- esphome/components/ld2412/switch/engineering_mode_switch.cpp +12 -0
- esphome/components/ld2412/switch/engineering_mode_switch.h +18 -0
- esphome/components/ld2412/text_sensor.py +34 -0
- esphome/components/ld2420/ld2420.cpp +0 -1
- esphome/components/ld2450/__init__.py +3 -4
- esphome/components/ld2450/binary_sensor.py +3 -0
- esphome/components/ld2450/ld2450.cpp +77 -165
- esphome/components/ld2450/ld2450.h +26 -54
- esphome/components/ld2450/sensor.py +120 -6
- esphome/components/ld2450/text_sensor.py +5 -4
- esphome/components/ld24xx/__init__.py +1 -0
- esphome/components/ld24xx/ld24xx.h +65 -0
- esphome/components/ledc/ledc_output.cpp +0 -1
- esphome/components/libretiny/__init__.py +2 -0
- esphome/components/light/__init__.py +0 -1
- esphome/components/light/effects.py +70 -45
- esphome/components/light/light_call.cpp +101 -66
- esphome/components/light/light_color_values.h +16 -11
- esphome/components/light/light_json_schema.cpp +46 -44
- esphome/components/light/light_state.cpp +8 -11
- esphome/components/light/light_traits.h +17 -0
- esphome/components/lightwaverf/lightwaverf.cpp +0 -2
- esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +0 -1
- esphome/components/lock/__init__.py +0 -1
- esphome/components/logger/__init__.py +31 -9
- esphome/components/logger/logger.cpp +12 -7
- esphome/components/logger/logger.h +25 -14
- esphome/components/logger/logger_esp32.cpp +2 -7
- esphome/components/logger/logger_esp8266.cpp +2 -4
- esphome/components/logger/logger_host.cpp +2 -4
- esphome/components/logger/logger_libretiny.cpp +2 -4
- esphome/components/logger/logger_rp2040.cpp +2 -4
- esphome/components/logger/logger_zephyr.cpp +86 -0
- esphome/components/logger/select/logger_level_select.cpp +2 -4
- esphome/components/logger/select/logger_level_select.h +2 -4
- esphome/components/logger/task_log_buffer.cpp +2 -4
- esphome/components/logger/task_log_buffer.h +2 -4
- esphome/components/lps22/sensor.py +5 -5
- esphome/components/ltr390/ltr390.cpp +0 -2
- esphome/components/ltr501/ltr501.cpp +0 -1
- esphome/components/ltr_als_ps/ltr_als_ps.cpp +0 -1
- esphome/components/lvgl/__init__.py +14 -13
- esphome/components/lvgl/automation.py +2 -4
- esphome/components/lvgl/defines.py +0 -2
- esphome/components/lvgl/helpers.py +1 -1
- esphome/components/lvgl/lv_validation.py +7 -4
- esphome/components/lvgl/lvgl_esphome.cpp +2 -3
- esphome/components/lvgl/styles.py +2 -2
- esphome/components/lvgl/types.py +1 -1
- esphome/components/lvgl/widgets/__init__.py +2 -2
- esphome/components/lvgl/widgets/arc.py +14 -11
- esphome/components/lvgl/widgets/buttonmatrix.py +1 -1
- esphome/components/lvgl/widgets/qrcode.py +7 -7
- esphome/components/lvgl/widgets/spinner.py +6 -6
- esphome/components/lvgl/widgets/switch.py +2 -2
- esphome/components/lvgl/widgets/tabview.py +3 -3
- esphome/components/lvgl/widgets/tileview.py +15 -7
- esphome/components/m5stack_8angle/m5stack_8angle.cpp +0 -1
- esphome/components/matrix_keypad/__init__.py +4 -3
- esphome/components/max17043/max17043.cpp +0 -2
- esphome/components/max31855/max31855.cpp +1 -4
- esphome/components/max31856/max31856.cpp +0 -4
- esphome/components/max31865/max31865.cpp +0 -1
- esphome/components/max44009/max44009.cpp +0 -1
- esphome/components/max6675/max6675.cpp +1 -4
- esphome/components/max6956/max6956.cpp +0 -1
- esphome/components/max7219/max7219.cpp +0 -1
- esphome/components/max7219digit/display.py +1 -1
- esphome/components/max7219digit/max7219digit.cpp +0 -1
- esphome/components/max9611/max9611.cpp +0 -1
- esphome/components/mcp23008/__init__.py +1 -1
- esphome/components/mcp23008/mcp23008.cpp +0 -1
- esphome/components/mcp23016/mcp23016.cpp +0 -1
- esphome/components/mcp23017/__init__.py +1 -1
- esphome/components/mcp23017/mcp23017.cpp +0 -1
- esphome/components/mcp23s08/__init__.py +1 -1
- esphome/components/mcp23s08/mcp23s08.cpp +0 -1
- esphome/components/mcp23s17/__init__.py +1 -1
- esphome/components/mcp23s17/mcp23s17.cpp +0 -1
- esphome/components/mcp23x08_base/__init__.py +2 -0
- esphome/components/mcp23x08_base/mcp23x08_base.cpp +9 -7
- esphome/components/mcp23x08_base/mcp23x08_base.h +9 -4
- esphome/components/mcp23x17_base/__init__.py +2 -0
- esphome/components/mcp23x17_base/mcp23x17_base.cpp +20 -7
- esphome/components/mcp23x17_base/mcp23x17_base.h +9 -4
- esphome/components/mcp23xxx_base/__init__.py +11 -5
- esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +15 -12
- esphome/components/mcp23xxx_base/mcp23xxx_base.h +8 -7
- esphome/components/mcp3008/mcp3008.cpp +1 -4
- esphome/components/mcp3204/mcp3204.cpp +1 -4
- esphome/components/mcp4461/mcp4461.cpp +0 -1
- esphome/components/mcp4725/mcp4725.cpp +0 -1
- esphome/components/mcp4728/mcp4728.cpp +0 -1
- esphome/components/mcp9600/mcp9600.cpp +0 -2
- esphome/components/mcp9808/mcp9808.cpp +0 -2
- esphome/components/mdns/__init__.py +3 -0
- esphome/components/mdns/mdns_component.cpp +2 -0
- esphome/components/mdns/mdns_component.h +4 -0
- esphome/components/media_player/__init__.py +40 -0
- esphome/components/media_player/automation.h +16 -0
- esphome/components/media_player/media_player.cpp +13 -0
- esphome/components/media_player/media_player.h +50 -3
- esphome/components/micro_wake_word/micro_wake_word.cpp +0 -3
- esphome/components/mics_4514/mics_4514.cpp +1 -6
- esphome/components/midea/ir_transmitter.h +4 -4
- esphome/components/mipi/__init__.py +416 -0
- esphome/components/mipi_dsi/__init__.py +5 -0
- esphome/components/mipi_dsi/display.py +233 -0
- esphome/components/mipi_dsi/mipi_dsi.cpp +379 -0
- esphome/components/mipi_dsi/mipi_dsi.h +123 -0
- esphome/components/mipi_dsi/models/__init__.py +0 -0
- esphome/components/mipi_dsi/models/guition.py +38 -0
- esphome/components/mipi_dsi/models/m5stack.py +57 -0
- esphome/components/mipi_dsi/models/waveshare.py +105 -0
- esphome/components/mipi_rgb/models/lilygo.py +0 -0
- esphome/components/mipi_spi/__init__.py +0 -9
- esphome/components/mipi_spi/display.py +220 -256
- esphome/components/mipi_spi/mipi_spi.cpp +1 -485
- esphome/components/mipi_spi/mipi_spi.h +556 -108
- esphome/components/mipi_spi/models/__init__.py +0 -65
- esphome/components/mipi_spi/models/adafruit.py +30 -0
- esphome/components/mipi_spi/models/amoled.py +41 -5
- esphome/components/mipi_spi/models/ili.py +5 -5
- esphome/components/mipi_spi/models/jc.py +1 -3
- esphome/components/mipi_spi/models/lilygo.py +1 -1
- esphome/components/mipi_spi/models/waveshare.py +16 -1
- esphome/components/mixer/speaker/__init__.py +4 -5
- esphome/components/mlx90393/sensor.py +7 -5
- esphome/components/mlx90393/sensor_mlx90393.cpp +0 -1
- esphome/components/mlx90614/mlx90614.cpp +0 -1
- esphome/components/mmc5603/mmc5603.cpp +0 -1
- esphome/components/mmc5983/mmc5983.cpp +0 -2
- esphome/components/mpl3115a2/mpl3115a2.cpp +0 -2
- esphome/components/mpr121/__init__.py +7 -6
- esphome/components/mpr121/mpr121.cpp +0 -1
- esphome/components/mpu6050/mpu6050.cpp +0 -1
- esphome/components/mpu6886/mpu6886.cpp +0 -1
- esphome/components/mqtt/__init__.py +1 -2
- esphome/components/mqtt/mqtt_button.cpp +1 -1
- esphome/components/mqtt/mqtt_client.cpp +0 -1
- esphome/components/mqtt/mqtt_component.cpp +8 -14
- esphome/components/mqtt/mqtt_component.h +0 -7
- esphome/components/mqtt/mqtt_sensor.cpp +0 -1
- esphome/components/mqtt/mqtt_sensor.h +0 -1
- esphome/components/mqtt/mqtt_text_sensor.cpp +0 -1
- esphome/components/mqtt/mqtt_text_sensor.h +0 -1
- esphome/components/ms5611/ms5611.cpp +0 -1
- esphome/components/ms8607/ms8607.cpp +0 -1
- esphome/components/msa3xx/msa3xx.cpp +0 -2
- esphome/components/my9231/my9231.cpp +0 -2
- esphome/components/nau7802/nau7802.cpp +0 -1
- esphome/components/neopixelbus/light.py +3 -0
- esphome/components/network/util.cpp +29 -0
- esphome/components/nextion/nextion.cpp +2 -2
- esphome/components/nfc/binary_sensor/{binary_sensor.cpp → nfc_binary_sensor.cpp} +1 -1
- esphome/components/npi19/npi19.cpp +0 -2
- esphome/components/nrf52/__init__.py +223 -0
- esphome/components/nrf52/boards.py +34 -0
- esphome/components/nrf52/const.py +18 -0
- esphome/components/nrf52/gpio.py +79 -0
- esphome/components/number/__init__.py +2 -1
- esphome/components/one_wire/__init__.py +1 -2
- esphome/components/one_wire/one_wire.cpp +0 -2
- esphome/components/one_wire/one_wire.h +0 -2
- esphome/components/opentherm/hub.cpp +0 -1
- esphome/components/opentherm/number/__init__.py +2 -2
- esphome/components/openthread/__init__.py +2 -3
- esphome/components/openthread/openthread.cpp +30 -13
- esphome/components/openthread/openthread.h +3 -0
- esphome/components/openthread/openthread_esp.cpp +3 -1
- esphome/components/opt3001/sensor.py +2 -6
- esphome/components/output/__init__.py +38 -0
- esphome/components/output/automation.h +24 -0
- esphome/components/output/switch/output_switch.cpp +0 -2
- esphome/components/packages/__init__.py +1 -2
- esphome/components/packet_transport/__init__.py +4 -3
- esphome/components/pca6416a/pca6416a.cpp +0 -1
- esphome/components/pca9554/pca9554.cpp +0 -1
- esphome/components/pca9685/pca9685_output.cpp +0 -2
- esphome/components/pcf85063/pcf85063.cpp +0 -1
- esphome/components/pcf8563/pcf8563.cpp +0 -1
- esphome/components/pcf8574/pcf8574.cpp +0 -1
- esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +0 -1
- esphome/components/pipsolar/pipsolar.cpp +54 -42
- esphome/components/pipsolar/pipsolar.h +5 -4
- esphome/components/pipsolar/sensor/__init__.py +1 -1
- esphome/components/pm2005/pm2005.cpp +0 -1
- esphome/components/pmsa003i/pmsa003i.cpp +0 -2
- esphome/components/pmwcs3/sensor.py +1 -2
- esphome/components/pn532/pn532.cpp +0 -2
- esphome/components/pn532_spi/pn532_spi.cpp +0 -2
- esphome/components/power_supply/power_supply.cpp +7 -10
- esphome/components/power_supply/power_supply.h +1 -1
- esphome/components/psram/__init__.py +6 -1
- esphome/components/pulse_counter/pulse_counter_sensor.cpp +0 -1
- esphome/components/pulse_counter/sensor.py +9 -6
- esphome/components/pylontech/pylontech.cpp +0 -1
- esphome/components/qmc5883l/qmc5883l.cpp +0 -1
- esphome/components/qmp6988/qmp6988.cpp +0 -2
- esphome/components/qspi_dbi/display.py +2 -3
- esphome/components/qspi_dbi/qspi_dbi.cpp +0 -2
- esphome/components/qwiic_pir/binary_sensor.py +2 -3
- esphome/components/qwiic_pir/qwiic_pir.cpp +0 -2
- esphome/components/rc522/rc522.cpp +9 -31
- esphome/components/rc522_spi/rc522_spi.cpp +0 -1
- esphome/components/remote_base/__init__.py +5 -6
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -1
- esphome/components/remote_receiver/remote_receiver_esp8266.cpp +0 -1
- esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -1
- esphome/components/remote_transmitter/__init__.py +26 -0
- esphome/components/remote_transmitter/automation.h +18 -0
- esphome/components/remote_transmitter/remote_transmitter.h +2 -1
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -1
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
- esphome/components/resampler/speaker/__init__.py +4 -5
- esphome/components/rf_bridge/__init__.py +4 -8
- esphome/components/rotary_encoder/rotary_encoder.cpp +0 -2
- esphome/components/rp2040/__init__.py +3 -1
- esphome/components/rp2040_pio_led_strip/led_strip.cpp +0 -2
- esphome/components/rp2040_pio_led_strip/light.py +1 -2
- esphome/components/rp2040_pwm/rp2040_pwm.cpp +1 -5
- esphome/components/rpi_dpi_rgb/display.py +13 -15
- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -3
- esphome/components/runtime_stats/__init__.py +34 -0
- esphome/components/runtime_stats/runtime_stats.cpp +102 -0
- esphome/components/runtime_stats/runtime_stats.h +132 -0
- esphome/components/scd30/scd30.cpp +0 -2
- esphome/components/scd30/sensor.py +1 -2
- esphome/components/scd4x/scd4x.cpp +0 -1
- esphome/components/scd4x/sensor.py +1 -3
- esphome/components/sdl/display.py +3 -1
- esphome/components/sdl/sdl_esphome.cpp +0 -2
- esphome/components/sdp3x/sdp3x.cpp +0 -2
- esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +0 -2
- esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +0 -3
- esphome/components/select/__init__.py +2 -3
- esphome/components/select/select_traits.cpp +1 -1
- esphome/components/select/select_traits.h +1 -1
- esphome/components/sen0321/sen0321.cpp +0 -1
- esphome/components/sen5x/sen5x.cpp +0 -2
- esphome/components/senseair/senseair.cpp +7 -3
- esphome/components/senseair/senseair.h +11 -0
- esphome/components/sensor/__init__.py +36 -4
- esphome/components/sensor/filter.cpp +49 -10
- esphome/components/sensor/filter.h +22 -7
- esphome/components/sensor/sensor.cpp +0 -1
- esphome/components/sensor/sensor.h +0 -9
- esphome/components/sfa30/sfa30.cpp +0 -4
- esphome/components/sgp30/sgp30.cpp +0 -2
- esphome/components/sgp4x/sensor.py +1 -1
- esphome/components/sgp4x/sgp4x.cpp +0 -2
- esphome/components/shelly_dimmer/shelly_dimmer.cpp +0 -2
- esphome/components/sht3xd/sht3xd.cpp +0 -2
- esphome/components/sht4x/sht4x.cpp +0 -2
- esphome/components/shtcx/shtcx.cpp +0 -1
- esphome/components/sim800l/__init__.py +2 -4
- esphome/components/sm16716/sm16716.cpp +0 -1
- esphome/components/sm2135/sm2135.cpp +0 -1
- esphome/components/sm2235/sm2235.cpp +0 -1
- esphome/components/sm2335/sm2335.cpp +0 -1
- esphome/components/sn74hc165/sn74hc165.cpp +0 -1
- esphome/components/sn74hc595/sn74hc595.cpp +0 -1
- esphome/components/sntp/sntp_component.cpp +0 -1
- esphome/components/sound_level/sensor.py +1 -1
- esphome/components/speaker/media_player/__init__.py +21 -33
- esphome/components/speaker/media_player/audio_pipeline.cpp +4 -7
- esphome/components/spi/__init__.py +29 -13
- esphome/components/spi/spi.cpp +0 -2
- esphome/components/spi_device/spi_device.cpp +1 -4
- esphome/components/sprinkler/__init__.py +4 -4
- esphome/components/sps30/sps30.cpp +0 -1
- esphome/components/ssd1306_base/__init__.py +11 -11
- esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
- esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +0 -1
- esphome/components/ssd1306_spi/ssd1306_spi.cpp +0 -1
- esphome/components/ssd1322_spi/ssd1322_spi.cpp +0 -1
- esphome/components/ssd1325_spi/ssd1325_spi.cpp +0 -1
- esphome/components/ssd1327_i2c/ssd1327_i2c.cpp +0 -1
- esphome/components/ssd1327_spi/ssd1327_spi.cpp +0 -1
- esphome/components/ssd1331_spi/ssd1331_spi.cpp +0 -1
- esphome/components/ssd1351_spi/ssd1351_spi.cpp +0 -1
- esphome/components/st7567_i2c/st7567_i2c.cpp +0 -1
- esphome/components/st7567_spi/st7567_spi.cpp +0 -1
- esphome/components/st7701s/display.py +10 -14
- esphome/components/st7701s/st7701s.cpp +0 -3
- esphome/components/st7735/st7735.cpp +0 -1
- esphome/components/st7789v/st7789v.cpp +0 -1
- esphome/components/st7920/st7920.cpp +0 -1
- esphome/components/status_led/light/status_led_light.cpp +0 -2
- esphome/components/status_led/status_led.cpp +0 -1
- esphome/components/stepper/__init__.py +2 -4
- esphome/components/sts3x/sts3x.cpp +0 -1
- esphome/components/substitutions/__init__.py +10 -16
- esphome/components/substitutions/jinja.py +24 -1
- esphome/components/sun/__init__.py +2 -3
- esphome/components/switch/__init__.py +31 -1
- esphome/components/switch/automation.h +24 -0
- esphome/components/switch/switch.cpp +8 -0
- esphome/components/switch/switch.h +8 -0
- esphome/components/sx126x/sx126x.cpp +0 -2
- esphome/components/sx127x/sx127x.cpp +0 -2
- esphome/components/sx1509/__init__.py +7 -5
- esphome/components/sx1509/output/sx1509_float_output.cpp +1 -1
- esphome/components/sx1509/sx1509.cpp +0 -2
- esphome/components/syslog/esphome_syslog.cpp +1 -1
- esphome/components/tc74/tc74.cpp +0 -1
- esphome/components/tca9548a/tca9548a.cpp +0 -1
- esphome/components/tca9555/tca9555.cpp +0 -1
- esphome/components/tcs34725/tcs34725.cpp +0 -1
- esphome/components/tee501/tee501.cpp +0 -1
- esphome/components/tem3200/tem3200.cpp +0 -2
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +0 -1
- esphome/components/template/cover/template_cover.cpp +0 -1
- esphome/components/template/select/template_select.cpp +0 -1
- esphome/components/template/text/template_text.cpp +0 -2
- esphome/components/template/valve/template_valve.cpp +0 -1
- esphome/components/text/__init__.py +0 -1
- esphome/components/text/text_traits.h +2 -0
- esphome/components/text_sensor/__init__.py +2 -1
- esphome/components/text_sensor/text_sensor.cpp +0 -2
- esphome/components/text_sensor/text_sensor.h +0 -8
- esphome/components/thermostat/climate.py +4 -4
- esphome/components/time/__init__.py +7 -4
- esphome/components/time/real_time_clock.cpp +16 -3
- esphome/components/tlc59208f/tlc59208f_output.cpp +0 -2
- esphome/components/tlc5947/tlc5947.cpp +0 -2
- esphome/components/tlc5971/tlc5971.cpp +0 -2
- esphome/components/tm1621/tm1621.cpp +0 -2
- esphome/components/tm1637/tm1637.cpp +0 -2
- esphome/components/tm1638/tm1638.cpp +0 -2
- esphome/components/tm1651/__init__.py +45 -48
- esphome/components/tm1651/tm1651.cpp +213 -47
- esphome/components/tm1651/tm1651.h +37 -32
- esphome/components/tmp117/tmp117.cpp +0 -2
- esphome/components/tsl2561/tsl2561.cpp +0 -1
- esphome/components/tsl2591/tsl2591.cpp +0 -1
- esphome/components/tt21100/touchscreen/tt21100.cpp +0 -2
- esphome/components/ttp229_bsf/ttp229_bsf.cpp +0 -1
- esphome/components/ttp229_lsf/ttp229_lsf.cpp +0 -1
- esphome/components/tuya/climate/__init__.py +9 -10
- esphome/components/tuya/number/__init__.py +8 -6
- esphome/components/tx20/tx20.cpp +0 -1
- esphome/components/uart/uart_component_esp32_arduino.cpp +0 -1
- esphome/components/uart/uart_component_esp8266.cpp +0 -1
- esphome/components/uart/uart_component_esp_idf.cpp +0 -2
- esphome/components/uart/uart_component_libretiny.cpp +0 -2
- esphome/components/uart/uart_component_rp2040.cpp +0 -2
- esphome/components/udp/__init__.py +1 -1
- esphome/components/ufire_ec/sensor.py +1 -2
- esphome/components/ufire_ec/ufire_ec.cpp +0 -2
- esphome/components/ufire_ise/sensor.py +1 -2
- esphome/components/ufire_ise/ufire_ise.cpp +0 -2
- esphome/components/ultrasonic/ultrasonic_sensor.cpp +0 -1
- esphome/components/update/__init__.py +0 -1
- esphome/components/uptime/sensor/uptime_seconds_sensor.cpp +0 -1
- esphome/components/uptime/sensor/uptime_seconds_sensor.h +0 -2
- esphome/components/usb_host/usb_host_client.cpp +0 -1
- esphome/components/usb_host/usb_host_component.cpp +0 -1
- esphome/components/valve/__init__.py +0 -1
- esphome/components/veml3235/veml3235.cpp +0 -3
- esphome/components/veml7700/veml7700.cpp +0 -2
- esphome/components/version/version_text_sensor.cpp +0 -1
- esphome/components/version/version_text_sensor.h +0 -1
- esphome/components/vl53l0x/vl53l0x_sensor.cpp +0 -4
- esphome/components/voice_assistant/voice_assistant.cpp +9 -8
- esphome/components/web_server/__init__.py +13 -0
- esphome/components/web_server/web_server.cpp +188 -353
- esphome/components/web_server/web_server.h +61 -1
- esphome/components/web_server_base/__init__.py +1 -1
- esphome/components/web_server_base/web_server_base.cpp +2 -0
- esphome/components/web_server_base/web_server_base.h +6 -0
- esphome/components/web_server_idf/web_server_idf.cpp +10 -8
- esphome/components/web_server_idf/web_server_idf.h +2 -0
- esphome/components/weikai_i2c/weikai_i2c.cpp +1 -2
- esphome/components/weikai_spi/weikai_spi.cpp +1 -1
- esphome/components/wifi/__init__.py +17 -43
- esphome/components/wifi/wifi_component.cpp +100 -36
- esphome/components/wifi/wifi_component.h +5 -1
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -0
- esphome/components/wifi/wifi_component_esp_idf.cpp +30 -0
- esphome/components/wifi_info/wifi_info_text_sensor.h +0 -6
- esphome/components/wifi_signal/wifi_signal_sensor.h +0 -1
- esphome/components/wireguard/wireguard.cpp +0 -2
- esphome/components/x9c/x9c.cpp +0 -2
- esphome/components/xgzp68xx/xgzp68xx.cpp +0 -1
- esphome/components/xl9535/xl9535.cpp +0 -2
- esphome/components/zephyr/__init__.py +252 -0
- esphome/components/zephyr/const.py +16 -0
- esphome/components/zephyr/core.cpp +90 -0
- esphome/components/zephyr/gpio.cpp +120 -0
- esphome/components/zephyr/gpio.h +38 -0
- esphome/components/zephyr/pre_build.py.script +4 -0
- esphome/components/zephyr/preferences.cpp +156 -0
- esphome/components/zephyr/preferences.h +13 -0
- esphome/config.py +38 -16
- esphome/config_helpers.py +1 -2
- esphome/config_validation.py +12 -16
- esphome/const.py +26 -1
- esphome/core/__init__.py +92 -51
- esphome/core/application.cpp +75 -21
- esphome/core/application.h +106 -171
- esphome/core/color.h +10 -0
- esphome/core/component.cpp +41 -25
- esphome/core/component.h +9 -6
- esphome/core/component_iterator.cpp +61 -261
- esphome/core/component_iterator.h +15 -0
- esphome/core/config.py +26 -11
- esphome/core/defines.h +40 -2
- esphome/core/entity_base.h +18 -0
- esphome/core/entity_helpers.py +45 -10
- esphome/core/helpers.cpp +8 -15
- esphome/core/helpers.h +60 -6
- esphome/core/lock_free_queue.h +1 -1
- esphome/core/scheduler.cpp +311 -77
- esphome/core/scheduler.h +141 -28
- esphome/cpp_generator.py +2 -6
- esphome/cpp_helpers.py +1 -1
- esphome/dashboard/dashboard.py +2 -3
- esphome/dashboard/dns.py +2 -8
- esphome/dashboard/web_server.py +34 -19
- esphome/espota2.py +1 -4
- esphome/git.py +3 -1
- esphome/helpers.py +23 -4
- esphome/log.py +3 -1
- esphome/mqtt.py +3 -5
- esphome/platformio_api.py +7 -4
- esphome/types.py +12 -0
- esphome/util.py +20 -8
- esphome/voluptuous_schema.py +4 -3
- esphome/vscode.py +1 -2
- esphome/wizard.py +1 -4
- esphome/writer.py +16 -108
- esphome/yaml_util.py +7 -5
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/METADATA +13 -14
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/RECORD +757 -677
- esphome/components/mipi_spi/models/commands.py +0 -82
- /esphome/components/nfc/binary_sensor/{binary_sensor.h → nfc_binary_sensor.h} +0 -0
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/WHEEL +0 -0
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/entry_points.txt +0 -0
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
#include "api_connection.h"
|
|
2
2
|
#ifdef USE_API
|
|
3
|
+
#ifdef USE_API_NOISE
|
|
4
|
+
#include "api_frame_helper_noise.h"
|
|
5
|
+
#endif
|
|
6
|
+
#ifdef USE_API_PLAINTEXT
|
|
7
|
+
#include "api_frame_helper_plaintext.h"
|
|
8
|
+
#endif
|
|
3
9
|
#include <cerrno>
|
|
4
10
|
#include <cinttypes>
|
|
5
11
|
#include <utility>
|
|
@@ -25,8 +31,7 @@
|
|
|
25
31
|
#include "esphome/components/voice_assistant/voice_assistant.h"
|
|
26
32
|
#endif
|
|
27
33
|
|
|
28
|
-
namespace esphome {
|
|
29
|
-
namespace api {
|
|
34
|
+
namespace esphome::api {
|
|
30
35
|
|
|
31
36
|
// Read a maximum of 5 messages per loop iteration to prevent starving other components.
|
|
32
37
|
// This is a balance between API responsiveness and allowing other components to run.
|
|
@@ -42,32 +47,53 @@ static const char *const TAG = "api.connection";
|
|
|
42
47
|
static const int CAMERA_STOP_STREAM = 5000;
|
|
43
48
|
#endif
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
#ifdef USE_DEVICES
|
|
51
|
+
// Helper macro for entity command handlers - gets entity by key and device_id, returns if not found, and creates call
|
|
52
|
+
// object
|
|
53
|
+
#define ENTITY_COMMAND_MAKE_CALL(entity_type, entity_var, getter_name) \
|
|
54
|
+
entity_type *entity_var = App.get_##getter_name##_by_key(msg.key, msg.device_id); \
|
|
55
|
+
if ((entity_var) == nullptr) \
|
|
56
|
+
return; \
|
|
57
|
+
auto call = (entity_var)->make_call();
|
|
58
|
+
|
|
59
|
+
// Helper macro for entity command handlers that don't use make_call() - gets entity by key and device_id and returns if
|
|
60
|
+
// not found
|
|
61
|
+
#define ENTITY_COMMAND_GET(entity_type, entity_var, getter_name) \
|
|
62
|
+
entity_type *entity_var = App.get_##getter_name##_by_key(msg.key, msg.device_id); \
|
|
63
|
+
if ((entity_var) == nullptr) \
|
|
64
|
+
return;
|
|
65
|
+
#else // No device support, use simpler macros
|
|
66
|
+
// Helper macro for entity command handlers - gets entity by key, returns if not found, and creates call
|
|
67
|
+
// object
|
|
46
68
|
#define ENTITY_COMMAND_MAKE_CALL(entity_type, entity_var, getter_name) \
|
|
47
69
|
entity_type *entity_var = App.get_##getter_name##_by_key(msg.key); \
|
|
48
70
|
if ((entity_var) == nullptr) \
|
|
49
71
|
return; \
|
|
50
72
|
auto call = (entity_var)->make_call();
|
|
51
73
|
|
|
52
|
-
// Helper macro for entity command handlers that don't use make_call() - gets entity by key and returns if
|
|
74
|
+
// Helper macro for entity command handlers that don't use make_call() - gets entity by key and returns if
|
|
75
|
+
// not found
|
|
53
76
|
#define ENTITY_COMMAND_GET(entity_type, entity_var, getter_name) \
|
|
54
77
|
entity_type *entity_var = App.get_##getter_name##_by_key(msg.key); \
|
|
55
78
|
if ((entity_var) == nullptr) \
|
|
56
79
|
return;
|
|
80
|
+
#endif // USE_DEVICES
|
|
57
81
|
|
|
58
82
|
APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent)
|
|
59
83
|
: parent_(parent), initial_state_iterator_(this), list_entities_iterator_(this) {
|
|
60
84
|
#if defined(USE_API_PLAINTEXT) && defined(USE_API_NOISE)
|
|
61
85
|
auto noise_ctx = parent->get_noise_ctx();
|
|
62
86
|
if (noise_ctx->has_psk()) {
|
|
63
|
-
this->helper_ =
|
|
87
|
+
this->helper_ =
|
|
88
|
+
std::unique_ptr<APIFrameHelper>{new APINoiseFrameHelper(std::move(sock), noise_ctx, &this->client_info_)};
|
|
64
89
|
} else {
|
|
65
|
-
this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))};
|
|
90
|
+
this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock), &this->client_info_)};
|
|
66
91
|
}
|
|
67
92
|
#elif defined(USE_API_PLAINTEXT)
|
|
68
|
-
this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))};
|
|
93
|
+
this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock), &this->client_info_)};
|
|
69
94
|
#elif defined(USE_API_NOISE)
|
|
70
|
-
this->helper_ = std::unique_ptr<APIFrameHelper>{
|
|
95
|
+
this->helper_ = std::unique_ptr<APIFrameHelper>{
|
|
96
|
+
new APINoiseFrameHelper(std::move(sock), parent->get_noise_ctx(), &this->client_info_)};
|
|
71
97
|
#else
|
|
72
98
|
#error "No frame helper defined"
|
|
73
99
|
#endif
|
|
@@ -86,13 +112,11 @@ void APIConnection::start() {
|
|
|
86
112
|
APIError err = this->helper_->init();
|
|
87
113
|
if (err != APIError::OK) {
|
|
88
114
|
on_fatal_error();
|
|
89
|
-
|
|
90
|
-
api_error_to_str(err), errno);
|
|
115
|
+
this->log_warning_("Helper init failed", err);
|
|
91
116
|
return;
|
|
92
117
|
}
|
|
93
|
-
this->client_info_ = helper_->getpeername();
|
|
94
|
-
this->
|
|
95
|
-
this->helper_->set_log_info(this->client_info_);
|
|
118
|
+
this->client_info_.peername = helper_->getpeername();
|
|
119
|
+
this->client_info_.name = this->client_info_.peername;
|
|
96
120
|
}
|
|
97
121
|
|
|
98
122
|
APIConnection::~APIConnection() {
|
|
@@ -119,8 +143,7 @@ void APIConnection::loop() {
|
|
|
119
143
|
APIError err = this->helper_->loop();
|
|
120
144
|
if (err != APIError::OK) {
|
|
121
145
|
on_fatal_error();
|
|
122
|
-
|
|
123
|
-
api_error_to_str(err), errno);
|
|
146
|
+
this->log_socket_operation_failed_(err);
|
|
124
147
|
return;
|
|
125
148
|
}
|
|
126
149
|
|
|
@@ -136,14 +159,7 @@ void APIConnection::loop() {
|
|
|
136
159
|
break;
|
|
137
160
|
} else if (err != APIError::OK) {
|
|
138
161
|
on_fatal_error();
|
|
139
|
-
|
|
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
|
-
}
|
|
162
|
+
this->log_warning_("Reading failed", err);
|
|
147
163
|
return;
|
|
148
164
|
} else {
|
|
149
165
|
this->last_traffic_ = now;
|
|
@@ -186,9 +202,11 @@ void APIConnection::loop() {
|
|
|
186
202
|
on_fatal_error();
|
|
187
203
|
ESP_LOGW(TAG, "%s is unresponsive; disconnecting", this->get_client_combined_info().c_str());
|
|
188
204
|
}
|
|
189
|
-
} else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS) {
|
|
205
|
+
} else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && !this->flags_.remove) {
|
|
206
|
+
// Only send ping if we're not disconnecting
|
|
190
207
|
ESP_LOGVV(TAG, "Sending keepalive PING");
|
|
191
|
-
|
|
208
|
+
PingRequest req;
|
|
209
|
+
this->flags_.sent_ping = this->send_message(req, PingRequest::MESSAGE_TYPE);
|
|
192
210
|
if (!this->flags_.sent_ping) {
|
|
193
211
|
// If we can't send the ping request directly (tx_buffer full),
|
|
194
212
|
// schedule it at the front of the batch so it will be sent with priority
|
|
@@ -203,24 +221,16 @@ void APIConnection::loop() {
|
|
|
203
221
|
if (this->image_reader_ && this->image_reader_->available() && this->helper_->can_write_without_blocking()) {
|
|
204
222
|
uint32_t to_send = std::min((size_t) MAX_BATCH_PACKET_SIZE, this->image_reader_->available());
|
|
205
223
|
bool done = this->image_reader_->available() == to_send;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// bytes data = 2;
|
|
217
|
-
buffer.encode_bytes(2, this->image_reader_->peek_data_buffer(), to_send);
|
|
218
|
-
// bool done = 3;
|
|
219
|
-
buffer.encode_bool(3, done);
|
|
220
|
-
|
|
221
|
-
bool success = this->send_buffer(buffer, CameraImageResponse::MESSAGE_TYPE);
|
|
222
|
-
|
|
223
|
-
if (success) {
|
|
224
|
+
|
|
225
|
+
CameraImageResponse msg;
|
|
226
|
+
msg.key = camera::Camera::instance()->get_object_id_hash();
|
|
227
|
+
msg.set_data(this->image_reader_->peek_data_buffer(), to_send);
|
|
228
|
+
msg.done = done;
|
|
229
|
+
#ifdef USE_DEVICES
|
|
230
|
+
msg.device_id = camera::Camera::instance()->get_device_id();
|
|
231
|
+
#endif
|
|
232
|
+
|
|
233
|
+
if (this->send_message_(msg, CameraImageResponse::MESSAGE_TYPE)) {
|
|
224
234
|
this->image_reader_->consume_data(to_send);
|
|
225
235
|
if (done) {
|
|
226
236
|
this->image_reader_->return_image();
|
|
@@ -229,35 +239,21 @@ void APIConnection::loop() {
|
|
|
229
239
|
}
|
|
230
240
|
#endif
|
|
231
241
|
|
|
242
|
+
#ifdef USE_API_HOMEASSISTANT_STATES
|
|
232
243
|
if (state_subs_at_ >= 0) {
|
|
233
|
-
|
|
234
|
-
if (state_subs_at_ < static_cast<int>(subs.size())) {
|
|
235
|
-
auto &it = subs[state_subs_at_];
|
|
236
|
-
SubscribeHomeAssistantStateResponse resp;
|
|
237
|
-
resp.entity_id = it.entity_id;
|
|
238
|
-
resp.attribute = it.attribute.value();
|
|
239
|
-
resp.once = it.once;
|
|
240
|
-
if (this->send_message(resp)) {
|
|
241
|
-
state_subs_at_++;
|
|
242
|
-
}
|
|
243
|
-
} else {
|
|
244
|
-
state_subs_at_ = -1;
|
|
245
|
-
}
|
|
244
|
+
this->process_state_subscriptions_();
|
|
246
245
|
}
|
|
246
|
+
#endif
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
|
|
250
|
-
return App.get_name() + component_type + entity->get_object_id();
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
DisconnectResponse APIConnection::disconnect(const DisconnectRequest &msg) {
|
|
249
|
+
bool APIConnection::send_disconnect_response(const DisconnectRequest &msg) {
|
|
254
250
|
// remote initiated disconnect_client
|
|
255
251
|
// don't close yet, we still need to send the disconnect response
|
|
256
252
|
// close will happen on next loop
|
|
257
253
|
ESP_LOGD(TAG, "%s disconnected", this->get_client_combined_info().c_str());
|
|
258
254
|
this->flags_.next_close = true;
|
|
259
255
|
DisconnectResponse resp;
|
|
260
|
-
return resp;
|
|
256
|
+
return this->send_message(resp, DisconnectResponse::MESSAGE_TYPE);
|
|
261
257
|
}
|
|
262
258
|
void APIConnection::on_disconnect_response(const DisconnectResponse &value) {
|
|
263
259
|
this->helper_->close();
|
|
@@ -277,8 +273,9 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess
|
|
|
277
273
|
#endif
|
|
278
274
|
|
|
279
275
|
// Calculate size
|
|
280
|
-
|
|
281
|
-
msg.calculate_size(
|
|
276
|
+
ProtoSize size_calc;
|
|
277
|
+
msg.calculate_size(size_calc);
|
|
278
|
+
uint32_t calculated_size = size_calc.get_size();
|
|
282
279
|
|
|
283
280
|
// Cache frame sizes to avoid repeated virtual calls
|
|
284
281
|
const uint8_t header_padding = conn->helper_->frame_header_padding();
|
|
@@ -326,19 +323,18 @@ uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConn
|
|
|
326
323
|
BinarySensorStateResponse resp;
|
|
327
324
|
resp.state = binary_sensor->state;
|
|
328
325
|
resp.missing_state = !binary_sensor->has_state();
|
|
329
|
-
|
|
330
|
-
|
|
326
|
+
return fill_and_encode_entity_state(binary_sensor, resp, BinarySensorStateResponse::MESSAGE_TYPE, conn,
|
|
327
|
+
remaining_size, is_single);
|
|
331
328
|
}
|
|
332
329
|
|
|
333
330
|
uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
334
331
|
bool is_single) {
|
|
335
332
|
auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity);
|
|
336
333
|
ListEntitiesBinarySensorResponse msg;
|
|
337
|
-
msg.
|
|
334
|
+
msg.set_device_class(binary_sensor->get_device_class_ref());
|
|
338
335
|
msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
return encode_message_to_buffer(msg, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
336
|
+
return fill_and_encode_entity_info(binary_sensor, msg, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn,
|
|
337
|
+
remaining_size, is_single);
|
|
342
338
|
}
|
|
343
339
|
#endif
|
|
344
340
|
|
|
@@ -352,14 +348,11 @@ uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *
|
|
|
352
348
|
auto *cover = static_cast<cover::Cover *>(entity);
|
|
353
349
|
CoverStateResponse msg;
|
|
354
350
|
auto traits = cover->get_traits();
|
|
355
|
-
msg.legacy_state =
|
|
356
|
-
(cover->position == cover::COVER_OPEN) ? enums::LEGACY_COVER_STATE_OPEN : enums::LEGACY_COVER_STATE_CLOSED;
|
|
357
351
|
msg.position = cover->position;
|
|
358
352
|
if (traits.get_supports_tilt())
|
|
359
353
|
msg.tilt = cover->tilt;
|
|
360
354
|
msg.current_operation = static_cast<enums::CoverOperation>(cover->current_operation);
|
|
361
|
-
|
|
362
|
-
return encode_message_to_buffer(msg, CoverStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
355
|
+
return fill_and_encode_entity_state(cover, msg, CoverStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
363
356
|
}
|
|
364
357
|
uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
365
358
|
bool is_single) {
|
|
@@ -370,26 +363,12 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c
|
|
|
370
363
|
msg.supports_position = traits.get_supports_position();
|
|
371
364
|
msg.supports_tilt = traits.get_supports_tilt();
|
|
372
365
|
msg.supports_stop = traits.get_supports_stop();
|
|
373
|
-
msg.
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
return encode_message_to_buffer(msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
366
|
+
msg.set_device_class(cover->get_device_class_ref());
|
|
367
|
+
return fill_and_encode_entity_info(cover, msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
368
|
+
is_single);
|
|
377
369
|
}
|
|
378
370
|
void APIConnection::cover_command(const CoverCommandRequest &msg) {
|
|
379
371
|
ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover)
|
|
380
|
-
if (msg.has_legacy_command) {
|
|
381
|
-
switch (msg.legacy_command) {
|
|
382
|
-
case enums::LEGACY_COVER_COMMAND_OPEN:
|
|
383
|
-
call.set_command_open();
|
|
384
|
-
break;
|
|
385
|
-
case enums::LEGACY_COVER_COMMAND_CLOSE:
|
|
386
|
-
call.set_command_close();
|
|
387
|
-
break;
|
|
388
|
-
case enums::LEGACY_COVER_COMMAND_STOP:
|
|
389
|
-
call.set_command_stop();
|
|
390
|
-
break;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
372
|
if (msg.has_position)
|
|
394
373
|
call.set_position(msg.position);
|
|
395
374
|
if (msg.has_tilt)
|
|
@@ -419,9 +398,8 @@ uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *co
|
|
|
419
398
|
if (traits.supports_direction())
|
|
420
399
|
msg.direction = static_cast<enums::FanDirection>(fan->direction);
|
|
421
400
|
if (traits.supports_preset_modes())
|
|
422
|
-
msg.
|
|
423
|
-
|
|
424
|
-
return encode_message_to_buffer(msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
401
|
+
msg.set_preset_mode(StringRef(fan->preset_mode));
|
|
402
|
+
return fill_and_encode_entity_state(fan, msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
425
403
|
}
|
|
426
404
|
uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
427
405
|
bool is_single) {
|
|
@@ -432,11 +410,8 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con
|
|
|
432
410
|
msg.supports_speed = traits.supports_speed();
|
|
433
411
|
msg.supports_direction = traits.supports_direction();
|
|
434
412
|
msg.supported_speed_count = traits.supported_speed_count();
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
msg.unique_id = get_default_unique_id("fan", fan);
|
|
438
|
-
fill_entity_info_base(fan, msg);
|
|
439
|
-
return encode_message_to_buffer(msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
413
|
+
msg.supported_preset_modes = &traits.supported_preset_modes_for_api_();
|
|
414
|
+
return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
440
415
|
}
|
|
441
416
|
void APIConnection::fan_command(const FanCommandRequest &msg) {
|
|
442
417
|
ENTITY_COMMAND_MAKE_CALL(fan::Fan, fan, fan)
|
|
@@ -479,26 +454,21 @@ uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *
|
|
|
479
454
|
resp.color_temperature = values.get_color_temperature();
|
|
480
455
|
resp.cold_white = values.get_cold_white();
|
|
481
456
|
resp.warm_white = values.get_warm_white();
|
|
482
|
-
if (light->supports_effects())
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
457
|
+
if (light->supports_effects()) {
|
|
458
|
+
// get_effect_name() returns temporary std::string - must store it
|
|
459
|
+
std::string effect_name = light->get_effect_name();
|
|
460
|
+
resp.set_effect(StringRef(effect_name));
|
|
461
|
+
}
|
|
462
|
+
return fill_and_encode_entity_state(light, resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
486
463
|
}
|
|
487
464
|
uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
488
465
|
bool is_single) {
|
|
489
466
|
auto *light = static_cast<light::LightState *>(entity);
|
|
490
467
|
ListEntitiesLightResponse msg;
|
|
491
468
|
auto traits = light->get_traits();
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
msg.legacy_supports_rgb = traits.supports_color_capability(light::ColorCapability::RGB);
|
|
496
|
-
msg.legacy_supports_white_value =
|
|
497
|
-
msg.legacy_supports_rgb && (traits.supports_color_capability(light::ColorCapability::WHITE) ||
|
|
498
|
-
traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE));
|
|
499
|
-
msg.legacy_supports_color_temperature = traits.supports_color_capability(light::ColorCapability::COLOR_TEMPERATURE) ||
|
|
500
|
-
traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE);
|
|
501
|
-
if (msg.legacy_supports_color_temperature) {
|
|
469
|
+
msg.supported_color_modes = &traits.get_supported_color_modes_for_api_();
|
|
470
|
+
if (traits.supports_color_capability(light::ColorCapability::COLOR_TEMPERATURE) ||
|
|
471
|
+
traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE)) {
|
|
502
472
|
msg.min_mireds = traits.get_min_mireds();
|
|
503
473
|
msg.max_mireds = traits.get_max_mireds();
|
|
504
474
|
}
|
|
@@ -508,9 +478,8 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c
|
|
|
508
478
|
msg.effects.push_back(effect->get_name());
|
|
509
479
|
}
|
|
510
480
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
return encode_message_to_buffer(msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
481
|
+
return fill_and_encode_entity_info(light, msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
482
|
+
is_single);
|
|
514
483
|
}
|
|
515
484
|
void APIConnection::light_command(const LightCommandRequest &msg) {
|
|
516
485
|
ENTITY_COMMAND_MAKE_CALL(light::LightState, light, light)
|
|
@@ -557,24 +526,20 @@ uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection
|
|
|
557
526
|
SensorStateResponse resp;
|
|
558
527
|
resp.state = sensor->state;
|
|
559
528
|
resp.missing_state = !sensor->has_state();
|
|
560
|
-
|
|
561
|
-
return encode_message_to_buffer(resp, SensorStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
529
|
+
return fill_and_encode_entity_state(sensor, resp, SensorStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
562
530
|
}
|
|
563
531
|
|
|
564
532
|
uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
565
533
|
bool is_single) {
|
|
566
534
|
auto *sensor = static_cast<sensor::Sensor *>(entity);
|
|
567
535
|
ListEntitiesSensorResponse msg;
|
|
568
|
-
msg.
|
|
536
|
+
msg.set_unit_of_measurement(sensor->get_unit_of_measurement_ref());
|
|
569
537
|
msg.accuracy_decimals = sensor->get_accuracy_decimals();
|
|
570
538
|
msg.force_update = sensor->get_force_update();
|
|
571
|
-
msg.
|
|
539
|
+
msg.set_device_class(sensor->get_device_class_ref());
|
|
572
540
|
msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class());
|
|
573
|
-
msg
|
|
574
|
-
|
|
575
|
-
msg.unique_id = get_default_unique_id("sensor", sensor);
|
|
576
|
-
fill_entity_info_base(sensor, msg);
|
|
577
|
-
return encode_message_to_buffer(msg, ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
541
|
+
return fill_and_encode_entity_info(sensor, msg, ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
542
|
+
is_single);
|
|
578
543
|
}
|
|
579
544
|
#endif
|
|
580
545
|
|
|
@@ -589,8 +554,8 @@ uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection
|
|
|
589
554
|
auto *a_switch = static_cast<switch_::Switch *>(entity);
|
|
590
555
|
SwitchStateResponse resp;
|
|
591
556
|
resp.state = a_switch->state;
|
|
592
|
-
|
|
593
|
-
|
|
557
|
+
return fill_and_encode_entity_state(a_switch, resp, SwitchStateResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
558
|
+
is_single);
|
|
594
559
|
}
|
|
595
560
|
|
|
596
561
|
uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -598,10 +563,9 @@ uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *
|
|
|
598
563
|
auto *a_switch = static_cast<switch_::Switch *>(entity);
|
|
599
564
|
ListEntitiesSwitchResponse msg;
|
|
600
565
|
msg.assumed_state = a_switch->assumed_state();
|
|
601
|
-
msg.
|
|
602
|
-
msg
|
|
603
|
-
|
|
604
|
-
return encode_message_to_buffer(msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
566
|
+
msg.set_device_class(a_switch->get_device_class_ref());
|
|
567
|
+
return fill_and_encode_entity_info(a_switch, msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
568
|
+
is_single);
|
|
605
569
|
}
|
|
606
570
|
void APIConnection::switch_command(const SwitchCommandRequest &msg) {
|
|
607
571
|
ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch)
|
|
@@ -624,21 +588,18 @@ uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnec
|
|
|
624
588
|
bool is_single) {
|
|
625
589
|
auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity);
|
|
626
590
|
TextSensorStateResponse resp;
|
|
627
|
-
resp.
|
|
591
|
+
resp.set_state(StringRef(text_sensor->state));
|
|
628
592
|
resp.missing_state = !text_sensor->has_state();
|
|
629
|
-
|
|
630
|
-
|
|
593
|
+
return fill_and_encode_entity_state(text_sensor, resp, TextSensorStateResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
594
|
+
is_single);
|
|
631
595
|
}
|
|
632
596
|
uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
633
597
|
bool is_single) {
|
|
634
598
|
auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity);
|
|
635
599
|
ListEntitiesTextSensorResponse msg;
|
|
636
|
-
msg.
|
|
637
|
-
msg
|
|
638
|
-
|
|
639
|
-
msg.unique_id = get_default_unique_id("text_sensor", text_sensor);
|
|
640
|
-
fill_entity_info_base(text_sensor, msg);
|
|
641
|
-
return encode_message_to_buffer(msg, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
600
|
+
msg.set_device_class(text_sensor->get_device_class_ref());
|
|
601
|
+
return fill_and_encode_entity_info(text_sensor, msg, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn,
|
|
602
|
+
remaining_size, is_single);
|
|
642
603
|
}
|
|
643
604
|
#endif
|
|
644
605
|
|
|
@@ -651,7 +612,6 @@ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection
|
|
|
651
612
|
bool is_single) {
|
|
652
613
|
auto *climate = static_cast<climate::Climate *>(entity);
|
|
653
614
|
ClimateStateResponse resp;
|
|
654
|
-
fill_entity_state_base(climate, resp);
|
|
655
615
|
auto traits = climate->get_traits();
|
|
656
616
|
resp.mode = static_cast<enums::ClimateMode>(climate->mode);
|
|
657
617
|
resp.action = static_cast<enums::ClimateAction>(climate->action);
|
|
@@ -665,20 +625,23 @@ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection
|
|
|
665
625
|
}
|
|
666
626
|
if (traits.get_supports_fan_modes() && climate->fan_mode.has_value())
|
|
667
627
|
resp.fan_mode = static_cast<enums::ClimateFanMode>(climate->fan_mode.value());
|
|
668
|
-
if (!traits.get_supported_custom_fan_modes().empty() && climate->custom_fan_mode.has_value())
|
|
669
|
-
resp.
|
|
628
|
+
if (!traits.get_supported_custom_fan_modes().empty() && climate->custom_fan_mode.has_value()) {
|
|
629
|
+
resp.set_custom_fan_mode(StringRef(climate->custom_fan_mode.value()));
|
|
630
|
+
}
|
|
670
631
|
if (traits.get_supports_presets() && climate->preset.has_value()) {
|
|
671
632
|
resp.preset = static_cast<enums::ClimatePreset>(climate->preset.value());
|
|
672
633
|
}
|
|
673
|
-
if (!traits.get_supported_custom_presets().empty() && climate->custom_preset.has_value())
|
|
674
|
-
resp.
|
|
634
|
+
if (!traits.get_supported_custom_presets().empty() && climate->custom_preset.has_value()) {
|
|
635
|
+
resp.set_custom_preset(StringRef(climate->custom_preset.value()));
|
|
636
|
+
}
|
|
675
637
|
if (traits.get_supports_swing_modes())
|
|
676
638
|
resp.swing_mode = static_cast<enums::ClimateSwingMode>(climate->swing_mode);
|
|
677
639
|
if (traits.get_supports_current_humidity())
|
|
678
640
|
resp.current_humidity = climate->current_humidity;
|
|
679
641
|
if (traits.get_supports_target_humidity())
|
|
680
642
|
resp.target_humidity = climate->target_humidity;
|
|
681
|
-
return
|
|
643
|
+
return fill_and_encode_entity_state(climate, resp, ClimateStateResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
644
|
+
is_single);
|
|
682
645
|
}
|
|
683
646
|
uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
684
647
|
bool is_single) {
|
|
@@ -689,29 +652,21 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection
|
|
|
689
652
|
msg.supports_current_humidity = traits.get_supports_current_humidity();
|
|
690
653
|
msg.supports_two_point_target_temperature = traits.get_supports_two_point_target_temperature();
|
|
691
654
|
msg.supports_target_humidity = traits.get_supports_target_humidity();
|
|
692
|
-
|
|
693
|
-
msg.supported_modes.push_back(static_cast<enums::ClimateMode>(mode));
|
|
655
|
+
msg.supported_modes = &traits.get_supported_modes_for_api_();
|
|
694
656
|
msg.visual_min_temperature = traits.get_visual_min_temperature();
|
|
695
657
|
msg.visual_max_temperature = traits.get_visual_max_temperature();
|
|
696
658
|
msg.visual_target_temperature_step = traits.get_visual_target_temperature_step();
|
|
697
659
|
msg.visual_current_temperature_step = traits.get_visual_current_temperature_step();
|
|
698
660
|
msg.visual_min_humidity = traits.get_visual_min_humidity();
|
|
699
661
|
msg.visual_max_humidity = traits.get_visual_max_humidity();
|
|
700
|
-
msg.legacy_supports_away = traits.supports_preset(climate::CLIMATE_PRESET_AWAY);
|
|
701
662
|
msg.supports_action = traits.get_supports_action();
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
msg.supported_custom_presets.push_back(custom_preset);
|
|
710
|
-
for (auto swing_mode : traits.get_supported_swing_modes())
|
|
711
|
-
msg.supported_swing_modes.push_back(static_cast<enums::ClimateSwingMode>(swing_mode));
|
|
712
|
-
msg.unique_id = get_default_unique_id("climate", climate);
|
|
713
|
-
fill_entity_info_base(climate, msg);
|
|
714
|
-
return encode_message_to_buffer(msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
663
|
+
msg.supported_fan_modes = &traits.get_supported_fan_modes_for_api_();
|
|
664
|
+
msg.supported_custom_fan_modes = &traits.get_supported_custom_fan_modes_for_api_();
|
|
665
|
+
msg.supported_presets = &traits.get_supported_presets_for_api_();
|
|
666
|
+
msg.supported_custom_presets = &traits.get_supported_custom_presets_for_api_();
|
|
667
|
+
msg.supported_swing_modes = &traits.get_supported_swing_modes_for_api_();
|
|
668
|
+
return fill_and_encode_entity_info(climate, msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
669
|
+
is_single);
|
|
715
670
|
}
|
|
716
671
|
void APIConnection::climate_command(const ClimateCommandRequest &msg) {
|
|
717
672
|
ENTITY_COMMAND_MAKE_CALL(climate::Climate, climate, climate)
|
|
@@ -751,23 +706,21 @@ uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection
|
|
|
751
706
|
NumberStateResponse resp;
|
|
752
707
|
resp.state = number->state;
|
|
753
708
|
resp.missing_state = !number->has_state();
|
|
754
|
-
|
|
755
|
-
return encode_message_to_buffer(resp, NumberStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
709
|
+
return fill_and_encode_entity_state(number, resp, NumberStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
756
710
|
}
|
|
757
711
|
|
|
758
712
|
uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
759
713
|
bool is_single) {
|
|
760
714
|
auto *number = static_cast<number::Number *>(entity);
|
|
761
715
|
ListEntitiesNumberResponse msg;
|
|
762
|
-
msg.
|
|
716
|
+
msg.set_unit_of_measurement(number->traits.get_unit_of_measurement_ref());
|
|
763
717
|
msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode());
|
|
764
|
-
msg.
|
|
718
|
+
msg.set_device_class(number->traits.get_device_class_ref());
|
|
765
719
|
msg.min_value = number->traits.get_min_value();
|
|
766
720
|
msg.max_value = number->traits.get_max_value();
|
|
767
721
|
msg.step = number->traits.get_step();
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
return encode_message_to_buffer(msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
722
|
+
return fill_and_encode_entity_info(number, msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
723
|
+
is_single);
|
|
771
724
|
}
|
|
772
725
|
void APIConnection::number_command(const NumberCommandRequest &msg) {
|
|
773
726
|
ENTITY_COMMAND_MAKE_CALL(number::Number, number, number)
|
|
@@ -789,16 +742,14 @@ uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *c
|
|
|
789
742
|
resp.year = date->year;
|
|
790
743
|
resp.month = date->month;
|
|
791
744
|
resp.day = date->day;
|
|
792
|
-
|
|
793
|
-
return encode_message_to_buffer(resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
745
|
+
return fill_and_encode_entity_state(date, resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
794
746
|
}
|
|
795
747
|
uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
796
748
|
bool is_single) {
|
|
797
749
|
auto *date = static_cast<datetime::DateEntity *>(entity);
|
|
798
750
|
ListEntitiesDateResponse msg;
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
return encode_message_to_buffer(msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
751
|
+
return fill_and_encode_entity_info(date, msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
752
|
+
is_single);
|
|
802
753
|
}
|
|
803
754
|
void APIConnection::date_command(const DateCommandRequest &msg) {
|
|
804
755
|
ENTITY_COMMAND_MAKE_CALL(datetime::DateEntity, date, date)
|
|
@@ -820,16 +771,14 @@ uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *c
|
|
|
820
771
|
resp.hour = time->hour;
|
|
821
772
|
resp.minute = time->minute;
|
|
822
773
|
resp.second = time->second;
|
|
823
|
-
|
|
824
|
-
return encode_message_to_buffer(resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
774
|
+
return fill_and_encode_entity_state(time, resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
825
775
|
}
|
|
826
776
|
uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
827
777
|
bool is_single) {
|
|
828
778
|
auto *time = static_cast<datetime::TimeEntity *>(entity);
|
|
829
779
|
ListEntitiesTimeResponse msg;
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
return encode_message_to_buffer(msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
780
|
+
return fill_and_encode_entity_info(time, msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
781
|
+
is_single);
|
|
833
782
|
}
|
|
834
783
|
void APIConnection::time_command(const TimeCommandRequest &msg) {
|
|
835
784
|
ENTITY_COMMAND_MAKE_CALL(datetime::TimeEntity, time, time)
|
|
@@ -852,16 +801,15 @@ uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnectio
|
|
|
852
801
|
ESPTime state = datetime->state_as_esptime();
|
|
853
802
|
resp.epoch_seconds = state.timestamp;
|
|
854
803
|
}
|
|
855
|
-
|
|
856
|
-
|
|
804
|
+
return fill_and_encode_entity_state(datetime, resp, DateTimeStateResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
805
|
+
is_single);
|
|
857
806
|
}
|
|
858
807
|
uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
859
808
|
bool is_single) {
|
|
860
809
|
auto *datetime = static_cast<datetime::DateTimeEntity *>(entity);
|
|
861
810
|
ListEntitiesDateTimeResponse msg;
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
return encode_message_to_buffer(msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
811
|
+
return fill_and_encode_entity_info(datetime, msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
812
|
+
is_single);
|
|
865
813
|
}
|
|
866
814
|
void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
|
|
867
815
|
ENTITY_COMMAND_MAKE_CALL(datetime::DateTimeEntity, datetime, datetime)
|
|
@@ -880,10 +828,9 @@ uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *c
|
|
|
880
828
|
bool is_single) {
|
|
881
829
|
auto *text = static_cast<text::Text *>(entity);
|
|
882
830
|
TextStateResponse resp;
|
|
883
|
-
resp.
|
|
831
|
+
resp.set_state(StringRef(text->state));
|
|
884
832
|
resp.missing_state = !text->has_state();
|
|
885
|
-
|
|
886
|
-
return encode_message_to_buffer(resp, TextStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
833
|
+
return fill_and_encode_entity_state(text, resp, TextStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
887
834
|
}
|
|
888
835
|
|
|
889
836
|
uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -893,10 +840,9 @@ uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *co
|
|
|
893
840
|
msg.mode = static_cast<enums::TextMode>(text->traits.get_mode());
|
|
894
841
|
msg.min_length = text->traits.get_min_length();
|
|
895
842
|
msg.max_length = text->traits.get_max_length();
|
|
896
|
-
msg.
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
return encode_message_to_buffer(msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
843
|
+
msg.set_pattern(text->traits.get_pattern_ref());
|
|
844
|
+
return fill_and_encode_entity_info(text, msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
845
|
+
is_single);
|
|
900
846
|
}
|
|
901
847
|
void APIConnection::text_command(const TextCommandRequest &msg) {
|
|
902
848
|
ENTITY_COMMAND_MAKE_CALL(text::Text, text, text)
|
|
@@ -915,21 +861,18 @@ uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection
|
|
|
915
861
|
bool is_single) {
|
|
916
862
|
auto *select = static_cast<select::Select *>(entity);
|
|
917
863
|
SelectStateResponse resp;
|
|
918
|
-
resp.
|
|
864
|
+
resp.set_state(StringRef(select->state));
|
|
919
865
|
resp.missing_state = !select->has_state();
|
|
920
|
-
|
|
921
|
-
return encode_message_to_buffer(resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
866
|
+
return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
922
867
|
}
|
|
923
868
|
|
|
924
869
|
uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
925
870
|
bool is_single) {
|
|
926
871
|
auto *select = static_cast<select::Select *>(entity);
|
|
927
872
|
ListEntitiesSelectResponse msg;
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
fill_entity_info_base(select, msg);
|
|
932
|
-
return encode_message_to_buffer(msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
873
|
+
msg.options = &select->traits.get_options();
|
|
874
|
+
return fill_and_encode_entity_info(select, msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
875
|
+
is_single);
|
|
933
876
|
}
|
|
934
877
|
void APIConnection::select_command(const SelectCommandRequest &msg) {
|
|
935
878
|
ENTITY_COMMAND_MAKE_CALL(select::Select, select, select)
|
|
@@ -943,10 +886,9 @@ uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *
|
|
|
943
886
|
bool is_single) {
|
|
944
887
|
auto *button = static_cast<button::Button *>(entity);
|
|
945
888
|
ListEntitiesButtonResponse msg;
|
|
946
|
-
msg.
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
return encode_message_to_buffer(msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
889
|
+
msg.set_device_class(button->get_device_class_ref());
|
|
890
|
+
return fill_and_encode_entity_info(button, msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
891
|
+
is_single);
|
|
950
892
|
}
|
|
951
893
|
void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg) {
|
|
952
894
|
ENTITY_COMMAND_GET(button::Button, button, button)
|
|
@@ -965,8 +907,7 @@ uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *c
|
|
|
965
907
|
auto *a_lock = static_cast<lock::Lock *>(entity);
|
|
966
908
|
LockStateResponse resp;
|
|
967
909
|
resp.state = static_cast<enums::LockState>(a_lock->state);
|
|
968
|
-
|
|
969
|
-
return encode_message_to_buffer(resp, LockStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
910
|
+
return fill_and_encode_entity_state(a_lock, resp, LockStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
970
911
|
}
|
|
971
912
|
|
|
972
913
|
uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
@@ -976,9 +917,8 @@ uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *co
|
|
|
976
917
|
msg.assumed_state = a_lock->traits.get_assumed_state();
|
|
977
918
|
msg.supports_open = a_lock->traits.get_supports_open();
|
|
978
919
|
msg.requires_code = a_lock->traits.get_requires_code();
|
|
979
|
-
msg
|
|
980
|
-
|
|
981
|
-
return encode_message_to_buffer(msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
920
|
+
return fill_and_encode_entity_info(a_lock, msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
921
|
+
is_single);
|
|
982
922
|
}
|
|
983
923
|
void APIConnection::lock_command(const LockCommandRequest &msg) {
|
|
984
924
|
ENTITY_COMMAND_GET(lock::Lock, a_lock, lock)
|
|
@@ -1008,21 +948,19 @@ uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *
|
|
|
1008
948
|
ValveStateResponse resp;
|
|
1009
949
|
resp.position = valve->position;
|
|
1010
950
|
resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation);
|
|
1011
|
-
|
|
1012
|
-
return encode_message_to_buffer(resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
951
|
+
return fill_and_encode_entity_state(valve, resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1013
952
|
}
|
|
1014
953
|
uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1015
954
|
bool is_single) {
|
|
1016
955
|
auto *valve = static_cast<valve::Valve *>(entity);
|
|
1017
956
|
ListEntitiesValveResponse msg;
|
|
1018
957
|
auto traits = valve->get_traits();
|
|
1019
|
-
msg.
|
|
958
|
+
msg.set_device_class(valve->get_device_class_ref());
|
|
1020
959
|
msg.assumed_state = traits.get_is_assumed_state();
|
|
1021
960
|
msg.supports_position = traits.get_supports_position();
|
|
1022
961
|
msg.supports_stop = traits.get_supports_stop();
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
return encode_message_to_buffer(msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
962
|
+
return fill_and_encode_entity_info(valve, msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
963
|
+
is_single);
|
|
1026
964
|
}
|
|
1027
965
|
void APIConnection::valve_command(const ValveCommandRequest &msg) {
|
|
1028
966
|
ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve)
|
|
@@ -1049,8 +987,8 @@ uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConne
|
|
|
1049
987
|
resp.state = static_cast<enums::MediaPlayerState>(report_state);
|
|
1050
988
|
resp.volume = media_player->volume;
|
|
1051
989
|
resp.muted = media_player->is_muted();
|
|
1052
|
-
|
|
1053
|
-
|
|
990
|
+
return fill_and_encode_entity_state(media_player, resp, MediaPlayerStateResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
991
|
+
is_single);
|
|
1054
992
|
}
|
|
1055
993
|
uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1056
994
|
bool is_single) {
|
|
@@ -1058,18 +996,18 @@ uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnec
|
|
|
1058
996
|
ListEntitiesMediaPlayerResponse msg;
|
|
1059
997
|
auto traits = media_player->get_traits();
|
|
1060
998
|
msg.supports_pause = traits.get_supports_pause();
|
|
999
|
+
msg.feature_flags = traits.get_feature_flags();
|
|
1061
1000
|
for (auto &supported_format : traits.get_supported_formats()) {
|
|
1062
|
-
|
|
1063
|
-
media_format
|
|
1001
|
+
msg.supported_formats.emplace_back();
|
|
1002
|
+
auto &media_format = msg.supported_formats.back();
|
|
1003
|
+
media_format.set_format(StringRef(supported_format.format));
|
|
1064
1004
|
media_format.sample_rate = supported_format.sample_rate;
|
|
1065
1005
|
media_format.num_channels = supported_format.num_channels;
|
|
1066
1006
|
media_format.purpose = static_cast<enums::MediaPlayerFormatPurpose>(supported_format.purpose);
|
|
1067
1007
|
media_format.sample_bytes = supported_format.sample_bytes;
|
|
1068
|
-
msg.supported_formats.push_back(media_format);
|
|
1069
1008
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
return encode_message_to_buffer(msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1009
|
+
return fill_and_encode_entity_info(media_player, msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn,
|
|
1010
|
+
remaining_size, is_single);
|
|
1073
1011
|
}
|
|
1074
1012
|
void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
|
|
1075
1013
|
ENTITY_COMMAND_MAKE_CALL(media_player::MediaPlayer, media_player, media_player)
|
|
@@ -1104,9 +1042,8 @@ uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection *
|
|
|
1104
1042
|
bool is_single) {
|
|
1105
1043
|
auto *camera = static_cast<camera::Camera *>(entity);
|
|
1106
1044
|
ListEntitiesCameraResponse msg;
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
return encode_message_to_buffer(msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1045
|
+
return fill_and_encode_entity_info(camera, msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
1046
|
+
is_single);
|
|
1110
1047
|
}
|
|
1111
1048
|
void APIConnection::camera_image(const CameraImageRequest &msg) {
|
|
1112
1049
|
if (camera::Camera::instance() == nullptr)
|
|
@@ -1130,6 +1067,12 @@ void APIConnection::on_get_time_response(const GetTimeResponse &value) {
|
|
|
1130
1067
|
}
|
|
1131
1068
|
#endif
|
|
1132
1069
|
|
|
1070
|
+
bool APIConnection::send_get_time_response(const GetTimeRequest &msg) {
|
|
1071
|
+
GetTimeResponse resp;
|
|
1072
|
+
resp.epoch_seconds = ::time(nullptr);
|
|
1073
|
+
return this->send_message(resp, GetTimeResponse::MESSAGE_TYPE);
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1133
1076
|
#ifdef USE_BLUETOOTH_PROXY
|
|
1134
1077
|
void APIConnection::subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) {
|
|
1135
1078
|
bluetooth_proxy::global_bluetooth_proxy->subscribe_api_connection(this, msg.flags);
|
|
@@ -1137,21 +1080,6 @@ void APIConnection::subscribe_bluetooth_le_advertisements(const SubscribeBluetoo
|
|
|
1137
1080
|
void APIConnection::unsubscribe_bluetooth_le_advertisements(const UnsubscribeBluetoothLEAdvertisementsRequest &msg) {
|
|
1138
1081
|
bluetooth_proxy::global_bluetooth_proxy->unsubscribe_api_connection(this);
|
|
1139
1082
|
}
|
|
1140
|
-
bool APIConnection::send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &msg) {
|
|
1141
|
-
if (this->client_api_version_major_ < 1 || this->client_api_version_minor_ < 7) {
|
|
1142
|
-
BluetoothLEAdvertisementResponse resp = msg;
|
|
1143
|
-
for (auto &service : resp.service_data) {
|
|
1144
|
-
service.legacy_data.assign(service.data.begin(), service.data.end());
|
|
1145
|
-
service.data.clear();
|
|
1146
|
-
}
|
|
1147
|
-
for (auto &manufacturer_data : resp.manufacturer_data) {
|
|
1148
|
-
manufacturer_data.legacy_data.assign(manufacturer_data.data.begin(), manufacturer_data.data.end());
|
|
1149
|
-
manufacturer_data.data.clear();
|
|
1150
|
-
}
|
|
1151
|
-
return this->send_message(resp);
|
|
1152
|
-
}
|
|
1153
|
-
return this->send_message(msg);
|
|
1154
|
-
}
|
|
1155
1083
|
void APIConnection::bluetooth_device_request(const BluetoothDeviceRequest &msg) {
|
|
1156
1084
|
bluetooth_proxy::global_bluetooth_proxy->bluetooth_device_request(msg);
|
|
1157
1085
|
}
|
|
@@ -1175,12 +1103,10 @@ void APIConnection::bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg)
|
|
|
1175
1103
|
bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_notify(msg);
|
|
1176
1104
|
}
|
|
1177
1105
|
|
|
1178
|
-
|
|
1106
|
+
bool APIConnection::send_subscribe_bluetooth_connections_free_response(
|
|
1179
1107
|
const SubscribeBluetoothConnectionsFreeRequest &msg) {
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
resp.limit = bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_connections_limit();
|
|
1183
|
-
return resp;
|
|
1108
|
+
bluetooth_proxy::global_bluetooth_proxy->send_connections_free(this);
|
|
1109
|
+
return true;
|
|
1184
1110
|
}
|
|
1185
1111
|
|
|
1186
1112
|
void APIConnection::bluetooth_scanner_set_mode(const BluetoothScannerSetModeRequest &msg) {
|
|
@@ -1241,28 +1167,25 @@ void APIConnection::on_voice_assistant_announce_request(const VoiceAssistantAnno
|
|
|
1241
1167
|
}
|
|
1242
1168
|
}
|
|
1243
1169
|
|
|
1244
|
-
|
|
1245
|
-
const VoiceAssistantConfigurationRequest &msg) {
|
|
1170
|
+
bool APIConnection::send_voice_assistant_get_configuration_response(const VoiceAssistantConfigurationRequest &msg) {
|
|
1246
1171
|
VoiceAssistantConfigurationResponse resp;
|
|
1247
1172
|
if (!this->check_voice_assistant_api_connection_()) {
|
|
1248
|
-
return resp;
|
|
1173
|
+
return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE);
|
|
1249
1174
|
}
|
|
1250
1175
|
|
|
1251
1176
|
auto &config = voice_assistant::global_voice_assistant->get_configuration();
|
|
1252
1177
|
for (auto &wake_word : config.available_wake_words) {
|
|
1253
|
-
|
|
1254
|
-
resp_wake_word
|
|
1255
|
-
resp_wake_word.wake_word
|
|
1178
|
+
resp.available_wake_words.emplace_back();
|
|
1179
|
+
auto &resp_wake_word = resp.available_wake_words.back();
|
|
1180
|
+
resp_wake_word.set_id(StringRef(wake_word.id));
|
|
1181
|
+
resp_wake_word.set_wake_word(StringRef(wake_word.wake_word));
|
|
1256
1182
|
for (const auto &lang : wake_word.trained_languages) {
|
|
1257
1183
|
resp_wake_word.trained_languages.push_back(lang);
|
|
1258
1184
|
}
|
|
1259
|
-
resp.available_wake_words.push_back(std::move(resp_wake_word));
|
|
1260
|
-
}
|
|
1261
|
-
for (auto &wake_word_id : config.active_wake_words) {
|
|
1262
|
-
resp.active_wake_words.push_back(wake_word_id);
|
|
1263
1185
|
}
|
|
1186
|
+
resp.active_wake_words = &config.active_wake_words;
|
|
1264
1187
|
resp.max_active_wake_words = config.max_active_wake_words;
|
|
1265
|
-
return resp;
|
|
1188
|
+
return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE);
|
|
1266
1189
|
}
|
|
1267
1190
|
|
|
1268
1191
|
void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) {
|
|
@@ -1284,8 +1207,8 @@ uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, A
|
|
|
1284
1207
|
auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity);
|
|
1285
1208
|
AlarmControlPanelStateResponse resp;
|
|
1286
1209
|
resp.state = static_cast<enums::AlarmControlPanelState>(a_alarm_control_panel->get_state());
|
|
1287
|
-
|
|
1288
|
-
|
|
1210
|
+
return fill_and_encode_entity_state(a_alarm_control_panel, resp, AlarmControlPanelStateResponse::MESSAGE_TYPE, conn,
|
|
1211
|
+
remaining_size, is_single);
|
|
1289
1212
|
}
|
|
1290
1213
|
uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn,
|
|
1291
1214
|
uint32_t remaining_size, bool is_single) {
|
|
@@ -1294,10 +1217,8 @@ uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, AP
|
|
|
1294
1217
|
msg.supported_features = a_alarm_control_panel->get_supported_features();
|
|
1295
1218
|
msg.requires_code = a_alarm_control_panel->get_requires_code();
|
|
1296
1219
|
msg.requires_code_to_arm = a_alarm_control_panel->get_requires_code_to_arm();
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
return encode_message_to_buffer(msg, ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
1300
|
-
is_single);
|
|
1220
|
+
return fill_and_encode_entity_info(a_alarm_control_panel, msg, ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE,
|
|
1221
|
+
conn, remaining_size, is_single);
|
|
1301
1222
|
}
|
|
1302
1223
|
void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) {
|
|
1303
1224
|
ENTITY_COMMAND_MAKE_CALL(alarm_control_panel::AlarmControlPanel, a_alarm_control_panel, alarm_control_panel)
|
|
@@ -1337,21 +1258,19 @@ void APIConnection::send_event(event::Event *event, const std::string &event_typ
|
|
|
1337
1258
|
uint16_t APIConnection::try_send_event_response(event::Event *event, const std::string &event_type, APIConnection *conn,
|
|
1338
1259
|
uint32_t remaining_size, bool is_single) {
|
|
1339
1260
|
EventResponse resp;
|
|
1340
|
-
resp.event_type
|
|
1341
|
-
|
|
1342
|
-
return encode_message_to_buffer(resp, EventResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1261
|
+
resp.set_event_type(StringRef(event_type));
|
|
1262
|
+
return fill_and_encode_entity_state(event, resp, EventResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1343
1263
|
}
|
|
1344
1264
|
|
|
1345
1265
|
uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1346
1266
|
bool is_single) {
|
|
1347
1267
|
auto *event = static_cast<event::Event *>(entity);
|
|
1348
1268
|
ListEntitiesEventResponse msg;
|
|
1349
|
-
msg.
|
|
1269
|
+
msg.set_device_class(event->get_device_class_ref());
|
|
1350
1270
|
for (const auto &event_type : event->get_event_types())
|
|
1351
1271
|
msg.event_types.push_back(event_type);
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
return encode_message_to_buffer(msg, ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1272
|
+
return fill_and_encode_entity_info(event, msg, ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
1273
|
+
is_single);
|
|
1355
1274
|
}
|
|
1356
1275
|
#endif
|
|
1357
1276
|
|
|
@@ -1371,23 +1290,21 @@ uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection
|
|
|
1371
1290
|
resp.has_progress = true;
|
|
1372
1291
|
resp.progress = update->update_info.progress;
|
|
1373
1292
|
}
|
|
1374
|
-
resp.
|
|
1375
|
-
resp.
|
|
1376
|
-
resp.
|
|
1377
|
-
resp.
|
|
1378
|
-
resp.
|
|
1293
|
+
resp.set_current_version(StringRef(update->update_info.current_version));
|
|
1294
|
+
resp.set_latest_version(StringRef(update->update_info.latest_version));
|
|
1295
|
+
resp.set_title(StringRef(update->update_info.title));
|
|
1296
|
+
resp.set_release_summary(StringRef(update->update_info.summary));
|
|
1297
|
+
resp.set_release_url(StringRef(update->update_info.release_url));
|
|
1379
1298
|
}
|
|
1380
|
-
|
|
1381
|
-
return encode_message_to_buffer(resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1299
|
+
return fill_and_encode_entity_state(update, resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1382
1300
|
}
|
|
1383
1301
|
uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
|
1384
1302
|
bool is_single) {
|
|
1385
1303
|
auto *update = static_cast<update::UpdateEntity *>(entity);
|
|
1386
1304
|
ListEntitiesUpdateResponse msg;
|
|
1387
|
-
msg.
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
return encode_message_to_buffer(msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1305
|
+
msg.set_device_class(update->get_device_class_ref());
|
|
1306
|
+
return fill_and_encode_entity_info(update, msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size,
|
|
1307
|
+
is_single);
|
|
1391
1308
|
}
|
|
1392
1309
|
void APIConnection::update_command(const UpdateCommandRequest &msg) {
|
|
1393
1310
|
ENTITY_COMMAND_GET(update::UpdateEntity, update, update)
|
|
@@ -1410,50 +1327,57 @@ void APIConnection::update_command(const UpdateCommandRequest &msg) {
|
|
|
1410
1327
|
#endif
|
|
1411
1328
|
|
|
1412
1329
|
bool APIConnection::try_send_log_message(int level, const char *tag, const char *line, size_t message_len) {
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
// Add size for level field (field ID 1, varint type)
|
|
1420
|
-
// 1 byte for field tag + size of the level varint
|
|
1421
|
-
msg_size += 1 + api::ProtoSize::varint(static_cast<uint32_t>(level));
|
|
1422
|
-
|
|
1423
|
-
// Add size for string field (field ID 3, string type)
|
|
1424
|
-
// 1 byte for field tag + size of length varint + string length
|
|
1425
|
-
msg_size += 1 + api::ProtoSize::varint(static_cast<uint32_t>(message_len)) + message_len;
|
|
1426
|
-
|
|
1427
|
-
// Create a pre-sized buffer
|
|
1428
|
-
auto buffer = this->create_buffer(msg_size);
|
|
1330
|
+
SubscribeLogsResponse msg;
|
|
1331
|
+
msg.level = static_cast<enums::LogLevel>(level);
|
|
1332
|
+
msg.set_message(reinterpret_cast<const uint8_t *>(line), message_len);
|
|
1333
|
+
return this->send_message_(msg, SubscribeLogsResponse::MESSAGE_TYPE);
|
|
1334
|
+
}
|
|
1429
1335
|
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1336
|
+
void APIConnection::complete_authentication_() {
|
|
1337
|
+
// Early return if already authenticated
|
|
1338
|
+
if (this->flags_.connection_state == static_cast<uint8_t>(ConnectionState::AUTHENTICATED)) {
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1433
1341
|
|
|
1434
|
-
|
|
1435
|
-
|
|
1342
|
+
this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED);
|
|
1343
|
+
ESP_LOGD(TAG, "%s connected", this->get_client_combined_info().c_str());
|
|
1344
|
+
#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
|
|
1345
|
+
this->parent_->get_client_connected_trigger()->trigger(this->client_info_.name, this->client_info_.peername);
|
|
1346
|
+
#endif
|
|
1347
|
+
#ifdef USE_HOMEASSISTANT_TIME
|
|
1348
|
+
if (homeassistant::global_homeassistant_time != nullptr) {
|
|
1349
|
+
this->send_time_request();
|
|
1350
|
+
}
|
|
1351
|
+
#endif
|
|
1436
1352
|
}
|
|
1437
1353
|
|
|
1438
|
-
|
|
1439
|
-
this->client_info_ = msg.client_info;
|
|
1440
|
-
this->
|
|
1441
|
-
this->helper_->set_log_info(this->get_client_combined_info());
|
|
1354
|
+
bool APIConnection::send_hello_response(const HelloRequest &msg) {
|
|
1355
|
+
this->client_info_.name = msg.client_info;
|
|
1356
|
+
this->client_info_.peername = this->helper_->getpeername();
|
|
1442
1357
|
this->client_api_version_major_ = msg.api_version_major;
|
|
1443
1358
|
this->client_api_version_minor_ = msg.api_version_minor;
|
|
1444
|
-
ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu32 ".%" PRIu32, this->client_info_.c_str(),
|
|
1445
|
-
this->
|
|
1359
|
+
ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu32 ".%" PRIu32, this->client_info_.name.c_str(),
|
|
1360
|
+
this->client_info_.peername.c_str(), this->client_api_version_major_, this->client_api_version_minor_);
|
|
1446
1361
|
|
|
1447
1362
|
HelloResponse resp;
|
|
1448
1363
|
resp.api_version_major = 1;
|
|
1449
|
-
resp.api_version_minor =
|
|
1450
|
-
|
|
1451
|
-
|
|
1364
|
+
resp.api_version_minor = 12;
|
|
1365
|
+
// Temporary string for concatenation - will be valid during send_message call
|
|
1366
|
+
std::string server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
|
|
1367
|
+
resp.set_server_info(StringRef(server_info));
|
|
1368
|
+
resp.set_name(StringRef(App.get_name()));
|
|
1452
1369
|
|
|
1370
|
+
#ifdef USE_API_PASSWORD
|
|
1371
|
+
// Password required - wait for authentication
|
|
1453
1372
|
this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::CONNECTED);
|
|
1454
|
-
|
|
1373
|
+
#else
|
|
1374
|
+
// No password configured - auto-authenticate
|
|
1375
|
+
this->complete_authentication_();
|
|
1376
|
+
#endif
|
|
1377
|
+
|
|
1378
|
+
return this->send_message(resp, HelloResponse::MESSAGE_TYPE);
|
|
1455
1379
|
}
|
|
1456
|
-
|
|
1380
|
+
bool APIConnection::send_connect_response(const ConnectRequest &msg) {
|
|
1457
1381
|
bool correct = true;
|
|
1458
1382
|
#ifdef USE_API_PASSWORD
|
|
1459
1383
|
correct = this->parent_->check_password(msg.password);
|
|
@@ -1463,87 +1387,106 @@ ConnectResponse APIConnection::connect(const ConnectRequest &msg) {
|
|
|
1463
1387
|
// bool invalid_password = 1;
|
|
1464
1388
|
resp.invalid_password = !correct;
|
|
1465
1389
|
if (correct) {
|
|
1466
|
-
|
|
1467
|
-
this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED);
|
|
1468
|
-
#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
|
|
1469
|
-
this->parent_->get_client_connected_trigger()->trigger(this->client_info_, this->client_peername_);
|
|
1470
|
-
#endif
|
|
1471
|
-
#ifdef USE_HOMEASSISTANT_TIME
|
|
1472
|
-
if (homeassistant::global_homeassistant_time != nullptr) {
|
|
1473
|
-
this->send_time_request();
|
|
1474
|
-
}
|
|
1475
|
-
#endif
|
|
1390
|
+
this->complete_authentication_();
|
|
1476
1391
|
}
|
|
1477
|
-
return resp;
|
|
1392
|
+
return this->send_message(resp, ConnectResponse::MESSAGE_TYPE);
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
bool APIConnection::send_ping_response(const PingRequest &msg) {
|
|
1396
|
+
PingResponse resp;
|
|
1397
|
+
return this->send_message(resp, PingResponse::MESSAGE_TYPE);
|
|
1478
1398
|
}
|
|
1479
|
-
|
|
1399
|
+
|
|
1400
|
+
bool APIConnection::send_device_info_response(const DeviceInfoRequest &msg) {
|
|
1480
1401
|
DeviceInfoResponse resp{};
|
|
1481
1402
|
#ifdef USE_API_PASSWORD
|
|
1482
|
-
resp.uses_password =
|
|
1483
|
-
#
|
|
1484
|
-
resp.
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
resp.
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
resp.
|
|
1403
|
+
resp.uses_password = true;
|
|
1404
|
+
#endif
|
|
1405
|
+
resp.set_name(StringRef(App.get_name()));
|
|
1406
|
+
resp.set_friendly_name(StringRef(App.get_friendly_name()));
|
|
1407
|
+
#ifdef USE_AREAS
|
|
1408
|
+
resp.set_suggested_area(StringRef(App.get_area()));
|
|
1409
|
+
#endif
|
|
1410
|
+
// mac_address must store temporary string - will be valid during send_message call
|
|
1411
|
+
std::string mac_address = get_mac_address_pretty();
|
|
1412
|
+
resp.set_mac_address(StringRef(mac_address));
|
|
1413
|
+
|
|
1414
|
+
// Compile-time StringRef constants
|
|
1415
|
+
static constexpr auto ESPHOME_VERSION_REF = StringRef::from_lit(ESPHOME_VERSION);
|
|
1416
|
+
resp.set_esphome_version(ESPHOME_VERSION_REF);
|
|
1417
|
+
|
|
1418
|
+
// get_compilation_time() returns temporary std::string - must store it
|
|
1419
|
+
std::string compilation_time = App.get_compilation_time();
|
|
1420
|
+
resp.set_compilation_time(StringRef(compilation_time));
|
|
1421
|
+
|
|
1422
|
+
// Compile-time StringRef constants for manufacturers
|
|
1492
1423
|
#if defined(USE_ESP8266) || defined(USE_ESP32)
|
|
1493
|
-
|
|
1424
|
+
static constexpr auto MANUFACTURER = StringRef::from_lit("Espressif");
|
|
1494
1425
|
#elif defined(USE_RP2040)
|
|
1495
|
-
|
|
1426
|
+
static constexpr auto MANUFACTURER = StringRef::from_lit("Raspberry Pi");
|
|
1496
1427
|
#elif defined(USE_BK72XX)
|
|
1497
|
-
|
|
1428
|
+
static constexpr auto MANUFACTURER = StringRef::from_lit("Beken");
|
|
1498
1429
|
#elif defined(USE_LN882X)
|
|
1499
|
-
|
|
1430
|
+
static constexpr auto MANUFACTURER = StringRef::from_lit("Lightning");
|
|
1500
1431
|
#elif defined(USE_RTL87XX)
|
|
1501
|
-
|
|
1432
|
+
static constexpr auto MANUFACTURER = StringRef::from_lit("Realtek");
|
|
1502
1433
|
#elif defined(USE_HOST)
|
|
1503
|
-
|
|
1434
|
+
static constexpr auto MANUFACTURER = StringRef::from_lit("Host");
|
|
1504
1435
|
#endif
|
|
1505
|
-
resp.
|
|
1436
|
+
resp.set_manufacturer(MANUFACTURER);
|
|
1437
|
+
|
|
1438
|
+
static constexpr auto MODEL = StringRef::from_lit(ESPHOME_BOARD);
|
|
1439
|
+
resp.set_model(MODEL);
|
|
1506
1440
|
#ifdef USE_DEEP_SLEEP
|
|
1507
1441
|
resp.has_deep_sleep = deep_sleep::global_has_deep_sleep;
|
|
1508
1442
|
#endif
|
|
1509
1443
|
#ifdef ESPHOME_PROJECT_NAME
|
|
1510
|
-
|
|
1511
|
-
|
|
1444
|
+
static constexpr auto PROJECT_NAME = StringRef::from_lit(ESPHOME_PROJECT_NAME);
|
|
1445
|
+
static constexpr auto PROJECT_VERSION = StringRef::from_lit(ESPHOME_PROJECT_VERSION);
|
|
1446
|
+
resp.set_project_name(PROJECT_NAME);
|
|
1447
|
+
resp.set_project_version(PROJECT_VERSION);
|
|
1512
1448
|
#endif
|
|
1513
1449
|
#ifdef USE_WEBSERVER
|
|
1514
1450
|
resp.webserver_port = USE_WEBSERVER_PORT;
|
|
1515
1451
|
#endif
|
|
1516
1452
|
#ifdef USE_BLUETOOTH_PROXY
|
|
1517
|
-
resp.legacy_bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->get_legacy_version();
|
|
1518
1453
|
resp.bluetooth_proxy_feature_flags = bluetooth_proxy::global_bluetooth_proxy->get_feature_flags();
|
|
1519
|
-
|
|
1454
|
+
// bt_mac must store temporary string - will be valid during send_message call
|
|
1455
|
+
std::string bluetooth_mac = bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_mac_address_pretty();
|
|
1456
|
+
resp.set_bluetooth_mac_address(StringRef(bluetooth_mac));
|
|
1520
1457
|
#endif
|
|
1521
1458
|
#ifdef USE_VOICE_ASSISTANT
|
|
1522
|
-
resp.legacy_voice_assistant_version = voice_assistant::global_voice_assistant->get_legacy_version();
|
|
1523
1459
|
resp.voice_assistant_feature_flags = voice_assistant::global_voice_assistant->get_feature_flags();
|
|
1524
1460
|
#endif
|
|
1525
1461
|
#ifdef USE_API_NOISE
|
|
1526
1462
|
resp.api_encryption_supported = true;
|
|
1527
1463
|
#endif
|
|
1528
1464
|
#ifdef USE_DEVICES
|
|
1465
|
+
size_t device_index = 0;
|
|
1529
1466
|
for (auto const &device : App.get_devices()) {
|
|
1530
|
-
|
|
1467
|
+
if (device_index >= ESPHOME_DEVICE_COUNT)
|
|
1468
|
+
break;
|
|
1469
|
+
auto &device_info = resp.devices[device_index++];
|
|
1531
1470
|
device_info.device_id = device->get_device_id();
|
|
1532
|
-
device_info.
|
|
1471
|
+
device_info.set_name(StringRef(device->get_name()));
|
|
1533
1472
|
device_info.area_id = device->get_area_id();
|
|
1534
|
-
resp.devices.push_back(device_info);
|
|
1535
1473
|
}
|
|
1536
1474
|
#endif
|
|
1537
1475
|
#ifdef USE_AREAS
|
|
1476
|
+
size_t area_index = 0;
|
|
1538
1477
|
for (auto const &area : App.get_areas()) {
|
|
1539
|
-
|
|
1478
|
+
if (area_index >= ESPHOME_AREA_COUNT)
|
|
1479
|
+
break;
|
|
1480
|
+
auto &area_info = resp.areas[area_index++];
|
|
1540
1481
|
area_info.area_id = area->get_area_id();
|
|
1541
|
-
area_info.
|
|
1542
|
-
resp.areas.push_back(area_info);
|
|
1482
|
+
area_info.set_name(StringRef(area->get_name()));
|
|
1543
1483
|
}
|
|
1544
1484
|
#endif
|
|
1545
|
-
|
|
1485
|
+
|
|
1486
|
+
return this->send_message(resp, DeviceInfoResponse::MESSAGE_TYPE);
|
|
1546
1487
|
}
|
|
1488
|
+
|
|
1489
|
+
#ifdef USE_API_HOMEASSISTANT_STATES
|
|
1547
1490
|
void APIConnection::on_home_assistant_state_response(const HomeAssistantStateResponse &msg) {
|
|
1548
1491
|
for (auto &it : this->parent_->get_state_subs()) {
|
|
1549
1492
|
if (it.entity_id == msg.entity_id && it.attribute.value() == msg.attribute) {
|
|
@@ -1551,6 +1494,7 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes
|
|
|
1551
1494
|
}
|
|
1552
1495
|
}
|
|
1553
1496
|
}
|
|
1497
|
+
#endif
|
|
1554
1498
|
#ifdef USE_API_SERVICES
|
|
1555
1499
|
void APIConnection::execute_service(const ExecuteServiceRequest &msg) {
|
|
1556
1500
|
bool found = false;
|
|
@@ -1565,28 +1509,27 @@ void APIConnection::execute_service(const ExecuteServiceRequest &msg) {
|
|
|
1565
1509
|
}
|
|
1566
1510
|
#endif
|
|
1567
1511
|
#ifdef USE_API_NOISE
|
|
1568
|
-
|
|
1569
|
-
psk_t psk{};
|
|
1512
|
+
bool APIConnection::send_noise_encryption_set_key_response(const NoiseEncryptionSetKeyRequest &msg) {
|
|
1570
1513
|
NoiseEncryptionSetKeyResponse resp;
|
|
1514
|
+
resp.success = false;
|
|
1515
|
+
|
|
1516
|
+
psk_t psk{};
|
|
1571
1517
|
if (base64_decode(msg.key, psk.data(), msg.key.size()) != psk.size()) {
|
|
1572
1518
|
ESP_LOGW(TAG, "Invalid encryption key length");
|
|
1573
|
-
|
|
1574
|
-
return resp;
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
|
-
if (!this->parent_->save_noise_psk(psk, true)) {
|
|
1519
|
+
} else if (!this->parent_->save_noise_psk(psk, true)) {
|
|
1578
1520
|
ESP_LOGW(TAG, "Failed to save encryption key");
|
|
1579
|
-
|
|
1580
|
-
|
|
1521
|
+
} else {
|
|
1522
|
+
resp.success = true;
|
|
1581
1523
|
}
|
|
1582
1524
|
|
|
1583
|
-
resp
|
|
1584
|
-
return resp;
|
|
1525
|
+
return this->send_message(resp, NoiseEncryptionSetKeyResponse::MESSAGE_TYPE);
|
|
1585
1526
|
}
|
|
1586
1527
|
#endif
|
|
1528
|
+
#ifdef USE_API_HOMEASSISTANT_STATES
|
|
1587
1529
|
void APIConnection::subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) {
|
|
1588
1530
|
state_subs_at_ = 0;
|
|
1589
1531
|
}
|
|
1532
|
+
#endif
|
|
1590
1533
|
bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
|
|
1591
1534
|
if (this->flags_.remove)
|
|
1592
1535
|
return false;
|
|
@@ -1596,8 +1539,7 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) {
|
|
|
1596
1539
|
APIError err = this->helper_->loop();
|
|
1597
1540
|
if (err != APIError::OK) {
|
|
1598
1541
|
on_fatal_error();
|
|
1599
|
-
|
|
1600
|
-
api_error_to_str(err), errno);
|
|
1542
|
+
this->log_socket_operation_failed_(err);
|
|
1601
1543
|
return false;
|
|
1602
1544
|
}
|
|
1603
1545
|
if (this->helper_->can_write_without_blocking())
|
|
@@ -1617,24 +1559,21 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) {
|
|
|
1617
1559
|
return false;
|
|
1618
1560
|
if (err != APIError::OK) {
|
|
1619
1561
|
on_fatal_error();
|
|
1620
|
-
|
|
1621
|
-
ESP_LOGW(TAG, "%s: Connection reset", this->get_client_combined_info().c_str());
|
|
1622
|
-
} else {
|
|
1623
|
-
ESP_LOGW(TAG, "%s: Packet write failed %s errno=%d", this->get_client_combined_info().c_str(),
|
|
1624
|
-
api_error_to_str(err), errno);
|
|
1625
|
-
}
|
|
1562
|
+
this->log_warning_("Packet write failed", err);
|
|
1626
1563
|
return false;
|
|
1627
1564
|
}
|
|
1628
1565
|
// Do not set last_traffic_ on send
|
|
1629
1566
|
return true;
|
|
1630
1567
|
}
|
|
1568
|
+
#ifdef USE_API_PASSWORD
|
|
1631
1569
|
void APIConnection::on_unauthenticated_access() {
|
|
1632
1570
|
this->on_fatal_error();
|
|
1633
|
-
ESP_LOGD(TAG, "%s
|
|
1571
|
+
ESP_LOGD(TAG, "%s access without authentication", this->get_client_combined_info().c_str());
|
|
1634
1572
|
}
|
|
1573
|
+
#endif
|
|
1635
1574
|
void APIConnection::on_no_setup_connection() {
|
|
1636
1575
|
this->on_fatal_error();
|
|
1637
|
-
ESP_LOGD(TAG, "%s
|
|
1576
|
+
ESP_LOGD(TAG, "%s access without full connection", this->get_client_combined_info().c_str());
|
|
1638
1577
|
}
|
|
1639
1578
|
void APIConnection::on_fatal_error() {
|
|
1640
1579
|
this->helper_->close();
|
|
@@ -1662,8 +1601,15 @@ void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator c
|
|
|
1662
1601
|
|
|
1663
1602
|
void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, MessageCreator creator, uint8_t message_type,
|
|
1664
1603
|
uint8_t estimated_size) {
|
|
1665
|
-
//
|
|
1666
|
-
|
|
1604
|
+
// Add high priority message and swap to front
|
|
1605
|
+
// This avoids expensive vector::insert which shifts all elements
|
|
1606
|
+
// Note: We only ever have one high-priority message at a time (ping OR disconnect)
|
|
1607
|
+
// If we're disconnecting, pings are blocked, so this simple swap is sufficient
|
|
1608
|
+
items.emplace_back(entity, std::move(creator), message_type, estimated_size);
|
|
1609
|
+
if (items.size() > 1) {
|
|
1610
|
+
// Swap the new high-priority item to the front
|
|
1611
|
+
std::swap(items.front(), items.back());
|
|
1612
|
+
}
|
|
1667
1613
|
}
|
|
1668
1614
|
|
|
1669
1615
|
bool APIConnection::schedule_batch_() {
|
|
@@ -1683,6 +1629,10 @@ ProtoWriteBuffer APIConnection::allocate_batch_message_buffer(uint16_t size) {
|
|
|
1683
1629
|
}
|
|
1684
1630
|
|
|
1685
1631
|
void APIConnection::process_batch_() {
|
|
1632
|
+
// Ensure PacketInfo remains trivially destructible for our placement new approach
|
|
1633
|
+
static_assert(std::is_trivially_destructible<PacketInfo>::value,
|
|
1634
|
+
"PacketInfo must remain trivially destructible with this placement-new approach");
|
|
1635
|
+
|
|
1686
1636
|
if (this->deferred_batch_.empty()) {
|
|
1687
1637
|
this->flags_.batch_scheduled = false;
|
|
1688
1638
|
return;
|
|
@@ -1694,6 +1644,8 @@ void APIConnection::process_batch_() {
|
|
|
1694
1644
|
return;
|
|
1695
1645
|
}
|
|
1696
1646
|
|
|
1647
|
+
// Get shared buffer reference once to avoid multiple calls
|
|
1648
|
+
auto &shared_buf = this->parent_->get_shared_buffer_ref();
|
|
1697
1649
|
size_t num_items = this->deferred_batch_.size();
|
|
1698
1650
|
|
|
1699
1651
|
// Fast path for single message - allocate exact size needed
|
|
@@ -1704,8 +1656,7 @@ void APIConnection::process_batch_() {
|
|
|
1704
1656
|
uint16_t payload_size =
|
|
1705
1657
|
item.creator(item.entity, this, std::numeric_limits<uint16_t>::max(), true, item.message_type);
|
|
1706
1658
|
|
|
1707
|
-
if (payload_size > 0 &&
|
|
1708
|
-
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, item.message_type)) {
|
|
1659
|
+
if (payload_size > 0 && this->send_buffer(ProtoWriteBuffer{&shared_buf}, item.message_type)) {
|
|
1709
1660
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
|
1710
1661
|
// Log messages after send attempt for VV debugging
|
|
1711
1662
|
// It's safe to use the buffer for logging at this point regardless of send result
|
|
@@ -1720,29 +1671,30 @@ void APIConnection::process_batch_() {
|
|
|
1720
1671
|
return;
|
|
1721
1672
|
}
|
|
1722
1673
|
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1674
|
+
size_t packets_to_process = std::min(num_items, MAX_PACKETS_PER_BATCH);
|
|
1675
|
+
|
|
1676
|
+
// Stack-allocated array for packet info
|
|
1677
|
+
alignas(PacketInfo) char packet_info_storage[MAX_PACKETS_PER_BATCH * sizeof(PacketInfo)];
|
|
1678
|
+
PacketInfo *packet_info = reinterpret_cast<PacketInfo *>(packet_info_storage);
|
|
1679
|
+
size_t packet_count = 0;
|
|
1726
1680
|
|
|
1727
1681
|
// Cache these values to avoid repeated virtual calls
|
|
1728
1682
|
const uint8_t header_padding = this->helper_->frame_header_padding();
|
|
1729
1683
|
const uint8_t footer_size = this->helper_->frame_footer_size();
|
|
1730
1684
|
|
|
1731
1685
|
// Initialize buffer and tracking variables
|
|
1732
|
-
|
|
1686
|
+
shared_buf.clear();
|
|
1733
1687
|
|
|
1734
1688
|
// Pre-calculate exact buffer size needed based on message types
|
|
1735
|
-
uint32_t total_estimated_size =
|
|
1689
|
+
uint32_t total_estimated_size = num_items * (header_padding + footer_size);
|
|
1736
1690
|
for (size_t i = 0; i < this->deferred_batch_.size(); i++) {
|
|
1737
1691
|
const auto &item = this->deferred_batch_[i];
|
|
1738
1692
|
total_estimated_size += item.estimated_size;
|
|
1739
1693
|
}
|
|
1740
1694
|
|
|
1741
1695
|
// Calculate total overhead for all messages
|
|
1742
|
-
uint32_t total_overhead = (header_padding + footer_size) * num_items;
|
|
1743
|
-
|
|
1744
1696
|
// Reserve based on estimated size (much more accurate than 24-byte worst-case)
|
|
1745
|
-
|
|
1697
|
+
shared_buf.reserve(total_estimated_size);
|
|
1746
1698
|
this->flags_.batch_first_message = true;
|
|
1747
1699
|
|
|
1748
1700
|
size_t items_processed = 0;
|
|
@@ -1754,8 +1706,8 @@ void APIConnection::process_batch_() {
|
|
|
1754
1706
|
// The actual message data follows after the header padding
|
|
1755
1707
|
uint32_t current_offset = 0;
|
|
1756
1708
|
|
|
1757
|
-
// Process items and encode directly to buffer
|
|
1758
|
-
for (size_t i = 0; i <
|
|
1709
|
+
// Process items and encode directly to buffer (up to our limit)
|
|
1710
|
+
for (size_t i = 0; i < packets_to_process; i++) {
|
|
1759
1711
|
const auto &item = this->deferred_batch_[i];
|
|
1760
1712
|
// Try to encode message
|
|
1761
1713
|
// The creator will calculate overhead to determine if the message fits
|
|
@@ -1769,7 +1721,11 @@ void APIConnection::process_batch_() {
|
|
|
1769
1721
|
// Message was encoded successfully
|
|
1770
1722
|
// payload_size is header_padding + actual payload size + footer_size
|
|
1771
1723
|
uint16_t proto_payload_size = payload_size - header_padding - footer_size;
|
|
1772
|
-
|
|
1724
|
+
// Use placement new to construct PacketInfo in pre-allocated stack array
|
|
1725
|
+
// This avoids default-constructing all MAX_PACKETS_PER_BATCH elements
|
|
1726
|
+
// Explicit destruction is not needed because PacketInfo is trivially destructible,
|
|
1727
|
+
// as ensured by the static_assert in its definition.
|
|
1728
|
+
new (&packet_info[packet_count++]) PacketInfo(item.message_type, current_offset, proto_payload_size);
|
|
1773
1729
|
|
|
1774
1730
|
// Update tracking variables
|
|
1775
1731
|
items_processed++;
|
|
@@ -1780,7 +1736,7 @@ void APIConnection::process_batch_() {
|
|
|
1780
1736
|
remaining_size -= payload_size;
|
|
1781
1737
|
// Calculate where the next message's header padding will start
|
|
1782
1738
|
// Current buffer size + footer space (that prepare_message_buffer will add for this message)
|
|
1783
|
-
current_offset =
|
|
1739
|
+
current_offset = shared_buf.size() + footer_size;
|
|
1784
1740
|
}
|
|
1785
1741
|
|
|
1786
1742
|
if (items_processed == 0) {
|
|
@@ -1790,21 +1746,15 @@ void APIConnection::process_batch_() {
|
|
|
1790
1746
|
|
|
1791
1747
|
// Add footer space for the last message (for Noise protocol MAC)
|
|
1792
1748
|
if (footer_size > 0) {
|
|
1793
|
-
auto &shared_buf = this->parent_->get_shared_buffer_ref();
|
|
1794
1749
|
shared_buf.resize(shared_buf.size() + footer_size);
|
|
1795
1750
|
}
|
|
1796
1751
|
|
|
1797
1752
|
// Send all collected packets
|
|
1798
|
-
APIError err =
|
|
1799
|
-
|
|
1753
|
+
APIError err = this->helper_->write_protobuf_packets(ProtoWriteBuffer{&shared_buf},
|
|
1754
|
+
std::span<const PacketInfo>(packet_info, packet_count));
|
|
1800
1755
|
if (err != APIError::OK && err != APIError::WOULD_BLOCK) {
|
|
1801
1756
|
on_fatal_error();
|
|
1802
|
-
|
|
1803
|
-
ESP_LOGW(TAG, "%s: Connection reset during batch write", this->get_client_combined_info().c_str());
|
|
1804
|
-
} else {
|
|
1805
|
-
ESP_LOGW(TAG, "%s: Batch write failed %s errno=%d", this->get_client_combined_info().c_str(),
|
|
1806
|
-
api_error_to_str(err), errno);
|
|
1807
|
-
}
|
|
1757
|
+
this->log_warning_("Batch write failed", err);
|
|
1808
1758
|
}
|
|
1809
1759
|
|
|
1810
1760
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
|
@@ -1860,6 +1810,33 @@ uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection
|
|
|
1860
1810
|
return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size, is_single);
|
|
1861
1811
|
}
|
|
1862
1812
|
|
|
1863
|
-
|
|
1864
|
-
|
|
1813
|
+
#ifdef USE_API_HOMEASSISTANT_STATES
|
|
1814
|
+
void APIConnection::process_state_subscriptions_() {
|
|
1815
|
+
const auto &subs = this->parent_->get_state_subs();
|
|
1816
|
+
if (this->state_subs_at_ >= static_cast<int>(subs.size())) {
|
|
1817
|
+
this->state_subs_at_ = -1;
|
|
1818
|
+
return;
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
const auto &it = subs[this->state_subs_at_];
|
|
1822
|
+
SubscribeHomeAssistantStateResponse resp;
|
|
1823
|
+
resp.set_entity_id(StringRef(it.entity_id));
|
|
1824
|
+
|
|
1825
|
+
// Avoid string copy by directly using the optional's value if it exists
|
|
1826
|
+
resp.set_attribute(it.attribute.has_value() ? StringRef(it.attribute.value()) : StringRef(""));
|
|
1827
|
+
|
|
1828
|
+
resp.once = it.once;
|
|
1829
|
+
if (this->send_message(resp, SubscribeHomeAssistantStateResponse::MESSAGE_TYPE)) {
|
|
1830
|
+
this->state_subs_at_++;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
#endif // USE_API_HOMEASSISTANT_STATES
|
|
1834
|
+
|
|
1835
|
+
void APIConnection::log_warning_(const char *message, APIError err) {
|
|
1836
|
+
ESP_LOGW(TAG, "%s: %s %s errno=%d", this->get_client_combined_info().c_str(), message, api_error_to_str(err), errno);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
void APIConnection::log_socket_operation_failed_(APIError err) { this->log_warning_("Socket operation failed", err); }
|
|
1840
|
+
|
|
1841
|
+
} // namespace esphome::api
|
|
1865
1842
|
#endif
|