esphome 2025.8.4__py3-none-any.whl → 2025.9.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +36 -42
- esphome/components/absolute_humidity/absolute_humidity.cpp +3 -5
- esphome/components/adc/adc_sensor_esp32.cpp +29 -6
- esphome/components/ags10/ags10.cpp +3 -18
- esphome/components/ags10/ags10.h +2 -12
- esphome/components/aht10/aht10.cpp +3 -3
- esphome/components/airthings_ble/__init__.py +2 -2
- esphome/components/alarm_control_panel/__init__.py +2 -2
- esphome/components/am2315c/am2315c.cpp +1 -17
- esphome/components/am2315c/am2315c.h +2 -3
- esphome/components/api/__init__.py +2 -2
- esphome/components/api/api_connection.cpp +34 -23
- esphome/components/api/api_connection.h +20 -39
- esphome/components/api/api_frame_helper.cpp +25 -25
- esphome/components/api/api_frame_helper.h +3 -3
- esphome/components/api/api_frame_helper_noise.cpp +75 -40
- esphome/components/api/api_frame_helper_noise.h +3 -7
- esphome/components/api/api_frame_helper_plaintext.cpp +17 -4
- esphome/components/api/api_frame_helper_plaintext.h +1 -4
- esphome/components/api/api_pb2.cpp +20 -2
- esphome/components/api/api_pb2.h +146 -141
- esphome/components/api/api_pb2_dump.cpp +12 -1
- esphome/components/api/proto.cpp +33 -37
- esphome/components/async_tcp/__init__.py +2 -2
- esphome/components/atm90e26/sensor.py +2 -0
- esphome/components/atm90e32/sensor.py +4 -2
- esphome/components/audio_adc/__init__.py +2 -2
- esphome/components/audio_dac/__init__.py +2 -2
- esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +1 -1
- esphome/components/bedjet/bedjet_hub.cpp +1 -1
- esphome/components/binary_sensor/__init__.py +2 -2
- esphome/components/binary_sensor/binary_sensor.cpp +13 -0
- esphome/components/binary_sensor/binary_sensor.h +4 -7
- esphome/components/bl0940/__init__.py +6 -1
- esphome/components/bl0940/bl0940.cpp +178 -41
- esphome/components/bl0940/bl0940.h +121 -76
- esphome/components/bl0940/button/__init__.py +27 -0
- esphome/components/bl0940/button/calibration_reset_button.cpp +20 -0
- esphome/components/bl0940/button/calibration_reset_button.h +19 -0
- esphome/components/bl0940/number/__init__.py +94 -0
- esphome/components/bl0940/number/calibration_number.cpp +29 -0
- esphome/components/bl0940/number/calibration_number.h +26 -0
- esphome/components/bl0940/sensor.py +151 -2
- esphome/components/bl0942/bl0942.cpp +1 -1
- esphome/components/ble_client/output/__init__.py +4 -4
- esphome/components/bluetooth_proxy/__init__.py +1 -1
- esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -1
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +15 -7
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +3 -2
- esphome/components/button/__init__.py +2 -2
- esphome/components/button/button.cpp +13 -0
- esphome/components/button/button.h +4 -7
- esphome/components/camera/buffer.h +18 -0
- esphome/components/camera/buffer_impl.cpp +20 -0
- esphome/components/camera/buffer_impl.h +26 -0
- esphome/components/camera/camera.h +43 -0
- esphome/components/camera/encoder.h +69 -0
- esphome/components/camera_encoder/__init__.py +62 -0
- esphome/components/camera_encoder/encoder_buffer_impl.cpp +23 -0
- esphome/components/camera_encoder/encoder_buffer_impl.h +25 -0
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +82 -0
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +39 -0
- esphome/components/captive_portal/__init__.py +2 -2
- esphome/components/captive_portal/captive_portal.cpp +35 -12
- esphome/components/captive_portal/captive_portal.h +3 -3
- esphome/components/ccs811/ccs811.cpp +3 -3
- esphome/components/climate/__init__.py +2 -2
- esphome/components/climate/climate.cpp +1 -1
- esphome/components/cover/__init__.py +5 -5
- esphome/components/cover/cover.cpp +1 -1
- esphome/components/cover/cover.h +2 -2
- esphome/components/dallas_temp/dallas_temp.cpp +2 -2
- esphome/components/datetime/__init__.py +2 -2
- esphome/components/datetime/date_entity.h +2 -2
- esphome/components/datetime/datetime_entity.h +2 -2
- esphome/components/datetime/time_entity.h +2 -2
- esphome/components/debug/debug_esp32.cpp +1 -1
- esphome/components/display/__init__.py +4 -4
- esphome/components/duty_time/duty_time_sensor.cpp +1 -1
- esphome/components/esp32/__init__.py +0 -5
- esphome/components/esp32/gpio.cpp +27 -23
- esphome/components/esp32/gpio.h +26 -11
- esphome/components/esp32/preferences.cpp +8 -4
- esphome/components/esp32_ble/__init__.py +7 -2
- esphome/components/esp32_ble_client/ble_client_base.cpp +7 -3
- esphome/components/esp32_ble_tracker/__init__.py +2 -2
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +9 -44
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -14
- esphome/components/esp8266/__init__.py +2 -2
- esphome/components/esp8266/core.cpp +2 -2
- esphome/components/esp8266/gpio.py +4 -4
- esphome/components/esp8266/preferences.cpp +30 -28
- esphome/components/esphome/ota/__init__.py +2 -2
- esphome/components/esphome/ota/ota_esphome.cpp +21 -19
- esphome/components/esphome/ota/ota_esphome.h +6 -5
- esphome/components/ethernet/__init__.py +7 -2
- esphome/components/ethernet/ethernet_component.cpp +1 -1
- esphome/components/event/__init__.py +2 -2
- esphome/components/event/event.h +4 -4
- esphome/components/fan/__init__.py +2 -2
- esphome/components/fan/fan.cpp +2 -1
- esphome/components/gdk101/gdk101.cpp +4 -4
- esphome/components/globals/__init__.py +2 -2
- esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +19 -18
- esphome/components/gpio_expander/cached_gpio.h +36 -16
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +5 -5
- esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +1 -1
- esphome/components/haier/haier_base.cpp +1 -1
- esphome/components/haier/hon_climate.cpp +1 -1
- esphome/components/hlw8012/hlw8012.cpp +5 -5
- esphome/components/honeywellabp2_i2c/honeywellabp2.cpp +4 -4
- esphome/components/host/preferences.h +3 -2
- esphome/components/hte501/hte501.cpp +3 -21
- esphome/components/hte501/hte501.h +2 -3
- esphome/components/http_request/ota/__init__.py +2 -2
- esphome/components/i2c/__init__.py +2 -2
- esphome/components/i2c/i2c.cpp +13 -9
- esphome/components/i2c/i2c_bus.h +36 -6
- esphome/components/i2s_audio/__init__.py +8 -2
- esphome/components/i2s_audio/media_player/__init__.py +1 -1
- esphome/components/i2s_audio/microphone/__init__.py +1 -1
- esphome/components/i2s_audio/speaker/__init__.py +1 -1
- esphome/components/inkplate/__init__.py +1 -0
- esphome/components/inkplate/const.py +105 -0
- esphome/components/inkplate/display.py +238 -0
- esphome/components/{inkplate6 → inkplate}/inkplate.cpp +156 -74
- esphome/components/{inkplate6 → inkplate}/inkplate.h +28 -68
- esphome/components/inkplate6/__init__.py +0 -1
- esphome/components/inkplate6/display.py +2 -211
- esphome/components/integration/integration_sensor.cpp +1 -1
- esphome/components/json/__init__.py +2 -2
- esphome/components/lc709203f/lc709203f.cpp +4 -17
- esphome/components/lc709203f/lc709203f.h +2 -3
- esphome/components/ld2420/text_sensor/{text_sensor.cpp → ld2420_text_sensor.cpp} +1 -1
- esphome/components/ld2450/ld2450.cpp +1 -1
- esphome/components/libretiny/preferences.cpp +13 -5
- esphome/components/light/__init__.py +2 -2
- esphome/components/light/addressable_light_effect.h +7 -0
- esphome/components/light/base_light_effects.h +8 -0
- esphome/components/light/light_call.cpp +22 -20
- esphome/components/light/light_effect.cpp +36 -0
- esphome/components/light/light_effect.h +14 -0
- esphome/components/light/light_json_schema.cpp +9 -1
- esphome/components/light/light_state.cpp +2 -2
- esphome/components/light/light_state.h +38 -0
- esphome/components/lock/__init__.py +2 -2
- esphome/components/lock/lock.h +2 -2
- esphome/components/logger/__init__.py +2 -2
- esphome/components/logger/logger.cpp +25 -4
- esphome/components/logger/logger.h +1 -1
- esphome/components/logger/logger_esp32.cpp +16 -8
- esphome/components/logger/logger_esp8266.cpp +11 -3
- esphome/components/logger/logger_libretiny.cpp +13 -3
- esphome/components/logger/logger_rp2040.cpp +14 -3
- esphome/components/logger/logger_zephyr.cpp +15 -4
- esphome/components/lvgl/defines.py +1 -0
- esphome/components/lvgl/hello_world.py +96 -33
- esphome/components/lvgl/number/lvgl_number.h +1 -1
- esphome/components/lvgl/select/lvgl_select.h +1 -1
- esphome/components/lvgl/widgets/__init__.py +0 -1
- esphome/components/lvgl/widgets/spinbox.py +20 -11
- esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +1 -1
- esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +1 -1
- esphome/components/mapping/__init__.py +13 -5
- esphome/components/mapping/mapping.h +69 -0
- esphome/components/max17043/max17043.cpp +2 -2
- esphome/components/mcp23016/__init__.py +1 -0
- esphome/components/mcp23016/mcp23016.cpp +20 -5
- esphome/components/mcp23016/mcp23016.h +10 -4
- esphome/components/mcp23x08_base/mcp23x08_base.cpp +1 -1
- esphome/components/mcp23x17_base/mcp23x17_base.cpp +2 -2
- esphome/components/mdns/__init__.py +2 -2
- esphome/components/mdns/mdns_component.cpp +145 -54
- esphome/components/media_player/__init__.py +2 -2
- esphome/components/micro_wake_word/__init__.py +2 -2
- esphome/components/microphone/__init__.py +2 -2
- esphome/components/mipi/__init__.py +77 -33
- esphome/components/mipi_rgb/__init__.py +2 -0
- esphome/components/mipi_rgb/display.py +321 -0
- esphome/components/mipi_rgb/mipi_rgb.cpp +388 -0
- esphome/components/mipi_rgb/mipi_rgb.h +127 -0
- esphome/components/mipi_rgb/models/guition.py +24 -0
- esphome/components/mipi_rgb/models/lilygo.py +228 -0
- esphome/components/mipi_rgb/models/rpi.py +9 -0
- esphome/components/mipi_rgb/models/st7701s.py +214 -0
- esphome/components/mipi_rgb/models/waveshare.py +64 -0
- esphome/components/mipi_spi/models/jc.py +229 -0
- esphome/components/mlx90614/mlx90614.cpp +1 -16
- esphome/components/mlx90614/mlx90614.h +0 -1
- esphome/components/mqtt/__init__.py +2 -2
- esphome/components/mqtt/mqtt_sensor.cpp +7 -2
- esphome/components/ms5611/ms5611.cpp +7 -6
- esphome/components/network/__init__.py +2 -2
- esphome/components/nextion/nextion_upload.cpp +4 -1
- esphome/components/nrf52/__init__.py +49 -6
- esphome/components/nrf52/const.py +1 -0
- esphome/components/nrf52/dfu.cpp +51 -0
- esphome/components/nrf52/dfu.h +24 -0
- esphome/components/ntc/ntc.cpp +1 -1
- esphome/components/number/__init__.py +2 -2
- esphome/components/number/automation.cpp +1 -1
- esphome/components/number/number.cpp +21 -0
- esphome/components/number/number.h +4 -13
- esphome/components/opentherm/hub.h +6 -6
- esphome/components/opentherm/number/{number.cpp → opentherm_number.cpp} +2 -2
- esphome/components/opentherm/output/{output.cpp → opentherm_output.cpp} +1 -1
- esphome/components/opentherm/switch/{switch.cpp → opentherm_switch.cpp} +1 -1
- esphome/components/ota/__init__.py +2 -2
- esphome/components/pca6416a/__init__.py +1 -0
- esphome/components/pca6416a/pca6416a.cpp +20 -5
- esphome/components/pca6416a/pca6416a.h +12 -5
- esphome/components/pca9554/__init__.py +2 -1
- esphome/components/pca9554/pca9554.cpp +12 -18
- esphome/components/pca9554/pca9554.h +10 -9
- esphome/components/pcf8574/__init__.py +1 -0
- esphome/components/pcf8574/pcf8574.cpp +14 -5
- esphome/components/pcf8574/pcf8574.h +13 -6
- esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +7 -7
- esphome/components/pipsolar/__init__.py +3 -3
- esphome/components/pipsolar/output/__init__.py +4 -4
- esphome/components/pulse_width/pulse_width.cpp +2 -2
- esphome/components/qmp6988/qmp6988.cpp +81 -126
- esphome/components/qmp6988/qmp6988.h +31 -37
- esphome/components/radon_eye_ble/__init__.py +2 -2
- esphome/components/remote_base/__init__.py +6 -8
- esphome/components/rotary_encoder/rotary_encoder.cpp +1 -1
- esphome/components/rp2040/__init__.py +2 -2
- esphome/components/runtime_stats/runtime_stats.cpp +10 -23
- esphome/components/runtime_stats/runtime_stats.h +4 -10
- esphome/components/safe_mode/__init__.py +2 -2
- esphome/components/safe_mode/safe_mode.cpp +33 -31
- esphome/components/script/script.cpp +6 -0
- esphome/components/script/script.h +19 -5
- esphome/components/sdm_meter/sensor.py +3 -1
- esphome/components/select/__init__.py +2 -2
- esphome/components/select/select.h +2 -2
- esphome/components/sen5x/sen5x.cpp +57 -55
- esphome/components/sen5x/sen5x.h +21 -15
- esphome/components/sen5x/sensor.py +67 -44
- esphome/components/sensirion_common/i2c_sensirion.cpp +18 -47
- esphome/components/sensirion_common/i2c_sensirion.h +39 -55
- esphome/components/sensor/__init__.py +2 -2
- esphome/components/sensor/automation.h +1 -1
- esphome/components/sensor/sensor.cpp +34 -6
- esphome/components/sensor/sensor.h +4 -21
- esphome/components/sgp30/sgp30.cpp +34 -35
- esphome/components/sgp30/sgp30.h +11 -10
- esphome/components/sgp4x/sgp4x.cpp +2 -2
- esphome/components/shelly_dimmer/light.py +7 -7
- esphome/components/sht4x/sht4x.cpp +1 -1
- esphome/components/sntp/sntp_component.cpp +36 -9
- esphome/components/sntp/sntp_component.h +7 -0
- esphome/components/sound_level/sound_level.cpp +1 -1
- esphome/components/speaker/__init__.py +2 -2
- esphome/components/speaker/media_player/__init__.py +2 -2
- esphome/components/speaker/media_player/speaker_media_player.cpp +1 -1
- esphome/components/spi/__init__.py +2 -2
- esphome/components/sprinkler/sprinkler.cpp +1 -1
- esphome/components/sps30/sps30.cpp +18 -23
- esphome/components/sps30/sps30.h +3 -3
- esphome/components/status_led/__init__.py +2 -2
- esphome/components/stepper/__init__.py +2 -2
- esphome/components/switch/__init__.py +2 -2
- esphome/components/switch/switch.cpp +5 -5
- esphome/components/sx1509/__init__.py +1 -1
- esphome/components/sx1509/sx1509.cpp +12 -7
- esphome/components/sx1509/sx1509.h +11 -4
- esphome/components/tca9555/tca9555.cpp +5 -5
- esphome/components/tee501/tee501.cpp +2 -21
- esphome/components/tee501/tee501.h +2 -4
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +1 -1
- esphome/components/template/datetime/template_date.cpp +1 -1
- esphome/components/template/datetime/template_datetime.cpp +2 -2
- esphome/components/template/datetime/template_time.cpp +1 -1
- esphome/components/template/number/template_number.cpp +1 -1
- esphome/components/template/select/template_select.cpp +1 -1
- esphome/components/template/text/template_text.cpp +1 -1
- esphome/components/text/__init__.py +2 -2
- esphome/components/text/text.h +2 -2
- esphome/components/text_sensor/__init__.py +2 -2
- esphome/components/text_sensor/text_sensor.h +4 -4
- esphome/components/thermostat/climate.py +11 -7
- esphome/components/thermostat/thermostat_climate.cpp +237 -206
- esphome/components/thermostat/thermostat_climate.h +52 -41
- esphome/components/time/__init__.py +2 -2
- esphome/components/tmp1075/tmp1075.cpp +1 -1
- esphome/components/total_daily_energy/total_daily_energy.cpp +1 -1
- esphome/components/touchscreen/__init__.py +2 -2
- esphome/components/tuya/number/tuya_number.cpp +1 -1
- esphome/components/udp/udp_component.cpp +3 -3
- esphome/components/ufire_ec/ufire_ec.cpp +4 -4
- esphome/components/ufire_ise/ufire_ise.cpp +4 -4
- esphome/components/update/__init__.py +2 -2
- esphome/components/usb_uart/usb_uart.cpp +1 -1
- esphome/components/valve/__init__.py +5 -5
- esphome/components/valve/valve.cpp +1 -1
- esphome/components/valve/valve.h +2 -2
- esphome/components/wake_on_lan/wake_on_lan.cpp +2 -2
- esphome/components/waveshare_epaper/waveshare_213v3.cpp +1 -1
- esphome/components/web_server/__init__.py +2 -2
- esphome/components/web_server/ota/__init__.py +2 -2
- esphome/components/web_server/ota/ota_web_server.cpp +11 -0
- esphome/components/web_server/web_server.cpp +58 -12
- esphome/components/web_server_base/__init__.py +2 -2
- esphome/components/wifi/__init__.py +5 -5
- esphome/components/wifi/wifi_component.cpp +3 -3
- esphome/components/wifi/wifi_component_esp_idf.cpp +2 -0
- esphome/config_validation.py +2 -2
- esphome/const.py +2 -1
- esphome/core/__init__.py +1 -0
- esphome/core/application.cpp +89 -51
- esphome/core/application.h +1 -0
- esphome/core/component.cpp +41 -19
- esphome/core/component.h +17 -13
- esphome/core/config.py +7 -7
- esphome/core/defines.h +4 -0
- esphome/core/entity_base.cpp +22 -8
- esphome/core/entity_base.h +43 -0
- esphome/core/helpers.cpp +26 -13
- esphome/core/helpers.h +4 -3
- esphome/core/ring_buffer.cpp +6 -2
- esphome/core/ring_buffer.h +2 -1
- esphome/core/scheduler.cpp +175 -94
- esphome/core/scheduler.h +66 -35
- esphome/core/time.cpp +6 -20
- esphome/coroutine.py +80 -3
- esphome/cpp_generator.py +13 -0
- esphome/cpp_helpers.py +2 -2
- esphome/dashboard/web_server.py +67 -10
- esphome/espota2.py +13 -6
- esphome/helpers.py +68 -83
- esphome/resolver.py +67 -0
- esphome/util.py +9 -6
- esphome/wizard.py +39 -26
- {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/METADATA +9 -9
- {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/RECORD +344 -313
- /esphome/components/ld2420/text_sensor/{text_sensor.h → ld2420_text_sensor.h} +0 -0
- /esphome/components/opentherm/number/{number.h → opentherm_number.h} +0 -0
- /esphome/components/opentherm/output/{output.h → opentherm_output.h} +0 -0
- /esphome/components/opentherm/switch/{switch.h → opentherm_switch.h} +0 -0
- {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/WHEEL +0 -0
- {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/entry_points.txt +0 -0
- {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.8.4.dist-info → esphome-2025.9.0b1.dist-info}/top_level.txt +0 -0
esphome/__main__.py
CHANGED
@@ -396,27 +396,29 @@ def check_permissions(port: str):
|
|
396
396
|
)
|
397
397
|
|
398
398
|
|
399
|
-
def upload_program(
|
399
|
+
def upload_program(
|
400
|
+
config: ConfigType, args: ArgsProtocol, devices: list[str]
|
401
|
+
) -> tuple[int, str | None]:
|
402
|
+
host = devices[0]
|
400
403
|
try:
|
401
404
|
module = importlib.import_module("esphome.components." + CORE.target_platform)
|
402
405
|
if getattr(module, "upload_program")(config, args, host):
|
403
|
-
return 0
|
406
|
+
return 0, host
|
404
407
|
except AttributeError:
|
405
408
|
pass
|
406
409
|
|
407
410
|
if get_port_type(host) == "SERIAL":
|
408
411
|
check_permissions(host)
|
412
|
+
|
413
|
+
exit_code = 1
|
409
414
|
if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
|
410
415
|
file = getattr(args, "file", None)
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
416
|
+
exit_code = upload_using_esptool(config, host, file, args.upload_speed)
|
417
|
+
elif CORE.target_platform == PLATFORM_RP2040 or CORE.is_libretiny:
|
418
|
+
exit_code = upload_using_platformio(config, host)
|
419
|
+
# else: Unknown target platform, exit_code remains 1
|
415
420
|
|
416
|
-
if
|
417
|
-
return upload_using_platformio(config, host)
|
418
|
-
|
419
|
-
return 1 # Unknown target platform
|
421
|
+
return exit_code, host if exit_code == 0 else None
|
420
422
|
|
421
423
|
ota_conf = {}
|
422
424
|
for ota_item in config.get(CONF_OTA, []):
|
@@ -433,10 +435,10 @@ def upload_program(config: ConfigType, args: ArgsProtocol, host: str) -> int | s
|
|
433
435
|
|
434
436
|
remote_port = int(ota_conf[CONF_PORT])
|
435
437
|
password = ota_conf.get(CONF_PASSWORD, "")
|
438
|
+
binary = args.file if getattr(args, "file", None) is not None else CORE.firmware_bin
|
436
439
|
|
437
440
|
# Check if we should use MQTT for address resolution
|
438
441
|
# This happens when no device was specified, or the current host is "MQTT"/"OTA"
|
439
|
-
devices: list[str] = args.device or []
|
440
442
|
if (
|
441
443
|
CONF_MQTT in config # pylint: disable=too-many-boolean-expressions
|
442
444
|
and (not devices or host in ("MQTT", "OTA"))
|
@@ -447,17 +449,23 @@ def upload_program(config: ConfigType, args: ArgsProtocol, host: str) -> int | s
|
|
447
449
|
):
|
448
450
|
from esphome import mqtt
|
449
451
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
return espota2.run_ota(host, remote_port, password, args.file)
|
452
|
+
devices = [
|
453
|
+
mqtt.get_esphome_device_ip(
|
454
|
+
config, args.username, args.password, args.client_id
|
455
|
+
)
|
456
|
+
]
|
456
457
|
|
457
|
-
return espota2.run_ota(
|
458
|
+
return espota2.run_ota(devices, remote_port, password, binary)
|
458
459
|
|
459
460
|
|
460
461
|
def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int | None:
|
462
|
+
try:
|
463
|
+
module = importlib.import_module("esphome.components." + CORE.target_platform)
|
464
|
+
if getattr(module, "show_logs")(config, args, devices):
|
465
|
+
return 0
|
466
|
+
except AttributeError:
|
467
|
+
pass
|
468
|
+
|
461
469
|
if "logger" not in config:
|
462
470
|
raise EsphomeError("Logger is not configured!")
|
463
471
|
|
@@ -551,17 +559,11 @@ def command_upload(args: ArgsProtocol, config: ConfigType) -> int | None:
|
|
551
559
|
purpose="uploading",
|
552
560
|
)
|
553
561
|
|
554
|
-
|
555
|
-
exit_code
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
if exit_code == 0:
|
560
|
-
_LOGGER.info("Successfully uploaded program.")
|
561
|
-
return 0
|
562
|
-
if len(devices) > 1:
|
563
|
-
_LOGGER.warning("Failed to upload to %s", device)
|
564
|
-
|
562
|
+
exit_code, _ = upload_program(config, args, devices)
|
563
|
+
if exit_code == 0:
|
564
|
+
_LOGGER.info("Successfully uploaded program.")
|
565
|
+
else:
|
566
|
+
_LOGGER.warning("Failed to upload to %s", devices)
|
565
567
|
return exit_code
|
566
568
|
|
567
569
|
|
@@ -614,19 +616,11 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None:
|
|
614
616
|
purpose="uploading",
|
615
617
|
)
|
616
618
|
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
if exit_code == 0:
|
623
|
-
_LOGGER.info("Successfully uploaded program.")
|
624
|
-
successful_device = device
|
625
|
-
break
|
626
|
-
if len(devices) > 1:
|
627
|
-
_LOGGER.warning("Failed to upload to %s", device)
|
628
|
-
|
629
|
-
if successful_device is None:
|
619
|
+
exit_code, successful_device = upload_program(config, args, devices)
|
620
|
+
if exit_code == 0:
|
621
|
+
_LOGGER.info("Successfully uploaded program.")
|
622
|
+
else:
|
623
|
+
_LOGGER.warning("Failed to upload to %s", devices)
|
630
624
|
return exit_code
|
631
625
|
|
632
626
|
if args.no_logs:
|
@@ -61,11 +61,10 @@ void AbsoluteHumidityComponent::loop() {
|
|
61
61
|
ESP_LOGW(TAG, "No valid state from temperature sensor!");
|
62
62
|
}
|
63
63
|
if (no_humidity) {
|
64
|
-
ESP_LOGW(TAG, "No valid state from
|
64
|
+
ESP_LOGW(TAG, "No valid state from humidity sensor!");
|
65
65
|
}
|
66
|
-
ESP_LOGW(TAG, "Unable to calculate absolute humidity.");
|
67
66
|
this->publish_state(NAN);
|
68
|
-
this->status_set_warning();
|
67
|
+
this->status_set_warning(LOG_STR("Unable to calculate absolute humidity."));
|
69
68
|
return;
|
70
69
|
}
|
71
70
|
|
@@ -87,9 +86,8 @@ void AbsoluteHumidityComponent::loop() {
|
|
87
86
|
es = es_wobus(temperature_c);
|
88
87
|
break;
|
89
88
|
default:
|
90
|
-
ESP_LOGE(TAG, "Invalid saturation vapor pressure equation selection!");
|
91
89
|
this->publish_state(NAN);
|
92
|
-
this->status_set_error();
|
90
|
+
this->status_set_error("Invalid saturation vapor pressure equation selection!");
|
93
91
|
return;
|
94
92
|
}
|
95
93
|
ESP_LOGD(TAG, "Saturation vapor pressure %f kPa", es);
|
@@ -241,6 +241,8 @@ float ADCSensor::sample_autorange_() {
|
|
241
241
|
cali_config.bitwidth = ADC_BITWIDTH_DEFAULT;
|
242
242
|
|
243
243
|
err = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
|
244
|
+
ESP_LOGVV(TAG, "Autorange atten=%d: Calibration handle creation %s (err=%d)", atten,
|
245
|
+
(err == ESP_OK) ? "SUCCESS" : "FAILED", err);
|
244
246
|
#else
|
245
247
|
adc_cali_line_fitting_config_t cali_config = {
|
246
248
|
.unit_id = this->adc_unit_,
|
@@ -251,10 +253,14 @@ float ADCSensor::sample_autorange_() {
|
|
251
253
|
#endif
|
252
254
|
};
|
253
255
|
err = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
|
256
|
+
ESP_LOGVV(TAG, "Autorange atten=%d: Calibration handle creation %s (err=%d)", atten,
|
257
|
+
(err == ESP_OK) ? "SUCCESS" : "FAILED", err);
|
254
258
|
#endif
|
255
259
|
|
256
260
|
int raw;
|
257
261
|
err = adc_oneshot_read(this->adc_handle_, this->channel_, &raw);
|
262
|
+
ESP_LOGVV(TAG, "Autorange atten=%d: Raw ADC read %s, value=%d (err=%d)", atten,
|
263
|
+
(err == ESP_OK) ? "SUCCESS" : "FAILED", raw, err);
|
258
264
|
|
259
265
|
if (err != ESP_OK) {
|
260
266
|
ESP_LOGW(TAG, "ADC read failed in autorange with error %d", err);
|
@@ -275,8 +281,10 @@ float ADCSensor::sample_autorange_() {
|
|
275
281
|
err = adc_cali_raw_to_voltage(handle, raw, &voltage_mv);
|
276
282
|
if (err == ESP_OK) {
|
277
283
|
voltage = voltage_mv / 1000.0f;
|
284
|
+
ESP_LOGVV(TAG, "Autorange atten=%d: CALIBRATED - raw=%d -> %dmV -> %.6fV", atten, raw, voltage_mv, voltage);
|
278
285
|
} else {
|
279
286
|
voltage = raw * 3.3f / 4095.0f;
|
287
|
+
ESP_LOGVV(TAG, "Autorange atten=%d: UNCALIBRATED FALLBACK - raw=%d -> %.6fV (3.3V ref)", atten, raw, voltage);
|
280
288
|
}
|
281
289
|
// Clean up calibration handle
|
282
290
|
#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \
|
@@ -287,6 +295,7 @@ float ADCSensor::sample_autorange_() {
|
|
287
295
|
#endif
|
288
296
|
} else {
|
289
297
|
voltage = raw * 3.3f / 4095.0f;
|
298
|
+
ESP_LOGVV(TAG, "Autorange atten=%d: NO CALIBRATION - raw=%d -> %.6fV (3.3V ref)", atten, raw, voltage);
|
290
299
|
}
|
291
300
|
|
292
301
|
return {raw, voltage};
|
@@ -324,18 +333,32 @@ float ADCSensor::sample_autorange_() {
|
|
324
333
|
}
|
325
334
|
|
326
335
|
const int adc_half = 2048;
|
327
|
-
uint32_t c12 = std::min(raw12, adc_half);
|
328
|
-
|
329
|
-
|
330
|
-
uint32_t
|
331
|
-
|
336
|
+
const uint32_t c12 = std::min(raw12, adc_half);
|
337
|
+
|
338
|
+
const int32_t c6_signed = adc_half - std::abs(raw6 - adc_half);
|
339
|
+
const uint32_t c6 = (c6_signed > 0) ? c6_signed : 0; // Clamp to prevent underflow
|
340
|
+
|
341
|
+
const int32_t c2_signed = adc_half - std::abs(raw2 - adc_half);
|
342
|
+
const uint32_t c2 = (c2_signed > 0) ? c2_signed : 0; // Clamp to prevent underflow
|
343
|
+
|
344
|
+
const uint32_t c0 = std::min(4095 - raw0, adc_half);
|
345
|
+
const uint32_t csum = c12 + c6 + c2 + c0;
|
346
|
+
|
347
|
+
ESP_LOGVV(TAG, "Autorange summary:");
|
348
|
+
ESP_LOGVV(TAG, " Raw readings: 12db=%d, 6db=%d, 2.5db=%d, 0db=%d", raw12, raw6, raw2, raw0);
|
349
|
+
ESP_LOGVV(TAG, " Voltages: 12db=%.6f, 6db=%.6f, 2.5db=%.6f, 0db=%.6f", mv12, mv6, mv2, mv0);
|
350
|
+
ESP_LOGVV(TAG, " Coefficients: c12=%u, c6=%u, c2=%u, c0=%u, sum=%u", c12, c6, c2, c0, csum);
|
332
351
|
|
333
352
|
if (csum == 0) {
|
334
353
|
ESP_LOGE(TAG, "Invalid weight sum in autorange calculation");
|
335
354
|
return NAN;
|
336
355
|
}
|
337
356
|
|
338
|
-
|
357
|
+
const float final_result = (mv12 * c12 + mv6 * c6 + mv2 * c2 + mv0 * c0) / csum;
|
358
|
+
ESP_LOGV(TAG, "Autorange final: (%.6f*%u + %.6f*%u + %.6f*%u + %.6f*%u)/%u = %.6fV", mv12, c12, mv6, c6, mv2, c2, mv0,
|
359
|
+
c0, csum, final_result);
|
360
|
+
|
361
|
+
return final_result;
|
339
362
|
}
|
340
363
|
|
341
364
|
} // namespace adc
|
@@ -89,7 +89,7 @@ void AGS10Component::dump_config() {
|
|
89
89
|
bool AGS10Component::new_i2c_address(uint8_t newaddress) {
|
90
90
|
uint8_t rev_newaddress = ~newaddress;
|
91
91
|
std::array<uint8_t, 5> data{newaddress, rev_newaddress, newaddress, rev_newaddress, 0};
|
92
|
-
data[4] =
|
92
|
+
data[4] = crc8(data.data(), 4, 0xFF, 0x31, true);
|
93
93
|
if (!this->write_bytes(REG_ADDRESS, data)) {
|
94
94
|
this->error_code_ = COMMUNICATION_FAILED;
|
95
95
|
this->status_set_warning();
|
@@ -109,7 +109,7 @@ bool AGS10Component::set_zero_point_with_current_resistance() { return this->set
|
|
109
109
|
|
110
110
|
bool AGS10Component::set_zero_point_with(uint16_t value) {
|
111
111
|
std::array<uint8_t, 5> data{0x00, 0x0C, (uint8_t) ((value >> 8) & 0xFF), (uint8_t) (value & 0xFF), 0};
|
112
|
-
data[4] =
|
112
|
+
data[4] = crc8(data.data(), 4, 0xFF, 0x31, true);
|
113
113
|
if (!this->write_bytes(REG_CALIBRATION, data)) {
|
114
114
|
this->error_code_ = COMMUNICATION_FAILED;
|
115
115
|
this->status_set_warning();
|
@@ -184,7 +184,7 @@ template<size_t N> optional<std::array<uint8_t, N>> AGS10Component::read_and_che
|
|
184
184
|
auto res = *data;
|
185
185
|
auto crc_byte = res[len];
|
186
186
|
|
187
|
-
if (crc_byte !=
|
187
|
+
if (crc_byte != crc8(res.data(), len, 0xFF, 0x31, true)) {
|
188
188
|
this->error_code_ = CRC_CHECK_FAILED;
|
189
189
|
ESP_LOGE(TAG, "Reading AGS10 version failed: crc error!");
|
190
190
|
return optional<std::array<uint8_t, N>>();
|
@@ -192,20 +192,5 @@ template<size_t N> optional<std::array<uint8_t, N>> AGS10Component::read_and_che
|
|
192
192
|
|
193
193
|
return data;
|
194
194
|
}
|
195
|
-
|
196
|
-
template<size_t N> uint8_t AGS10Component::calc_crc8_(std::array<uint8_t, N> dat, uint8_t num) {
|
197
|
-
uint8_t i, byte1, crc = 0xFF;
|
198
|
-
for (byte1 = 0; byte1 < num; byte1++) {
|
199
|
-
crc ^= (dat[byte1]);
|
200
|
-
for (i = 0; i < 8; i++) {
|
201
|
-
if (crc & 0x80) {
|
202
|
-
crc = (crc << 1) ^ 0x31;
|
203
|
-
} else {
|
204
|
-
crc = (crc << 1);
|
205
|
-
}
|
206
|
-
}
|
207
|
-
}
|
208
|
-
return crc;
|
209
|
-
}
|
210
195
|
} // namespace ags10
|
211
196
|
} // namespace esphome
|
esphome/components/ags10/ags10.h
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#pragma once
|
2
2
|
|
3
|
+
#include "esphome/components/i2c/i2c.h"
|
4
|
+
#include "esphome/components/sensor/sensor.h"
|
3
5
|
#include "esphome/core/automation.h"
|
4
6
|
#include "esphome/core/component.h"
|
5
|
-
#include "esphome/components/sensor/sensor.h"
|
6
|
-
#include "esphome/components/i2c/i2c.h"
|
7
7
|
|
8
8
|
namespace esphome {
|
9
9
|
namespace ags10 {
|
@@ -99,16 +99,6 @@ class AGS10Component : public PollingComponent, public i2c::I2CDevice {
|
|
99
99
|
* Read, checks and returns data from the sensor.
|
100
100
|
*/
|
101
101
|
template<size_t N> optional<std::array<uint8_t, N>> read_and_check_(uint8_t a_register);
|
102
|
-
|
103
|
-
/**
|
104
|
-
* Calculates CRC8 value.
|
105
|
-
*
|
106
|
-
* CRC8 calculation, initial value: 0xFF, polynomial: 0x31 (x8+ x5+ x4+1)
|
107
|
-
*
|
108
|
-
* @param[in] dat the data buffer
|
109
|
-
* @param num number of bytes in the buffer
|
110
|
-
*/
|
111
|
-
template<size_t N> uint8_t calc_crc8_(std::array<uint8_t, N> dat, uint8_t num);
|
112
102
|
};
|
113
103
|
|
114
104
|
template<typename... Ts> class AGS10NewI2cAddressAction : public Action<Ts...>, public Parented<AGS10Component> {
|
@@ -96,7 +96,7 @@ void AHT10Component::read_data_() {
|
|
96
96
|
ESP_LOGD(TAG, "Read attempt %d at %ums", this->read_count_, (unsigned) (millis() - this->start_time_));
|
97
97
|
}
|
98
98
|
if (this->read(data, 6) != i2c::ERROR_OK) {
|
99
|
-
this->status_set_warning("Read failed, will retry");
|
99
|
+
this->status_set_warning(LOG_STR("Read failed, will retry"));
|
100
100
|
this->restart_read_();
|
101
101
|
return;
|
102
102
|
}
|
@@ -113,7 +113,7 @@ void AHT10Component::read_data_() {
|
|
113
113
|
} else {
|
114
114
|
ESP_LOGD(TAG, "Invalid humidity, retrying");
|
115
115
|
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
|
116
|
-
this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
|
116
|
+
this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
|
117
117
|
}
|
118
118
|
this->restart_read_();
|
119
119
|
return;
|
@@ -144,7 +144,7 @@ void AHT10Component::update() {
|
|
144
144
|
return;
|
145
145
|
this->start_time_ = millis();
|
146
146
|
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
|
147
|
-
this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
|
147
|
+
this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
|
148
148
|
return;
|
149
149
|
}
|
150
150
|
this->restart_read_();
|
@@ -18,6 +18,6 @@ CONFIG_SCHEMA = cv.Schema(
|
|
18
18
|
).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
|
19
19
|
|
20
20
|
|
21
|
-
def to_code(config):
|
21
|
+
async def to_code(config):
|
22
22
|
var = cg.new_Pvariable(config[CONF_ID])
|
23
|
-
|
23
|
+
await esp32_ble_tracker.register_ble_device(var, config)
|
@@ -13,7 +13,7 @@ from esphome.const import (
|
|
13
13
|
CONF_TRIGGER_ID,
|
14
14
|
CONF_WEB_SERVER,
|
15
15
|
)
|
16
|
-
from esphome.core import CORE, coroutine_with_priority
|
16
|
+
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
17
17
|
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
18
18
|
from esphome.cpp_generator import MockObjClass
|
19
19
|
|
@@ -345,6 +345,6 @@ async def alarm_control_panel_is_armed_to_code(
|
|
345
345
|
return cg.new_Pvariable(condition_id, template_arg, paren)
|
346
346
|
|
347
347
|
|
348
|
-
@coroutine_with_priority(
|
348
|
+
@coroutine_with_priority(CoroPriority.CORE)
|
349
349
|
async def to_code(config):
|
350
350
|
cg.add_global(alarm_control_panel_ns.using)
|
@@ -29,22 +29,6 @@ namespace am2315c {
|
|
29
29
|
|
30
30
|
static const char *const TAG = "am2315c";
|
31
31
|
|
32
|
-
uint8_t AM2315C::crc8_(uint8_t *data, uint8_t len) {
|
33
|
-
uint8_t crc = 0xFF;
|
34
|
-
while (len--) {
|
35
|
-
crc ^= *data++;
|
36
|
-
for (uint8_t i = 0; i < 8; i++) {
|
37
|
-
if (crc & 0x80) {
|
38
|
-
crc <<= 1;
|
39
|
-
crc ^= 0x31;
|
40
|
-
} else {
|
41
|
-
crc <<= 1;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
}
|
45
|
-
return crc;
|
46
|
-
}
|
47
|
-
|
48
32
|
bool AM2315C::reset_register_(uint8_t reg) {
|
49
33
|
// code based on demo code sent by www.aosong.com
|
50
34
|
// no further documentation.
|
@@ -86,7 +70,7 @@ bool AM2315C::convert_(uint8_t *data, float &humidity, float &temperature) {
|
|
86
70
|
humidity = raw * 9.5367431640625e-5;
|
87
71
|
raw = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5];
|
88
72
|
temperature = raw * 1.9073486328125e-4 - 50;
|
89
|
-
return
|
73
|
+
return crc8(data, 6, 0xFF, 0x31, true) == data[6];
|
90
74
|
}
|
91
75
|
|
92
76
|
void AM2315C::setup() {
|
@@ -21,9 +21,9 @@
|
|
21
21
|
// SOFTWARE.
|
22
22
|
#pragma once
|
23
23
|
|
24
|
-
#include "esphome/core/component.h"
|
25
|
-
#include "esphome/components/sensor/sensor.h"
|
26
24
|
#include "esphome/components/i2c/i2c.h"
|
25
|
+
#include "esphome/components/sensor/sensor.h"
|
26
|
+
#include "esphome/core/component.h"
|
27
27
|
|
28
28
|
namespace esphome {
|
29
29
|
namespace am2315c {
|
@@ -39,7 +39,6 @@ class AM2315C : public PollingComponent, public i2c::I2CDevice {
|
|
39
39
|
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; }
|
40
40
|
|
41
41
|
protected:
|
42
|
-
uint8_t crc8_(uint8_t *data, uint8_t len);
|
43
42
|
bool convert_(uint8_t *data, float &humidity, float &temperature);
|
44
43
|
bool reset_register_(uint8_t reg);
|
45
44
|
|
@@ -24,7 +24,7 @@ from esphome.const import (
|
|
24
24
|
CONF_TRIGGER_ID,
|
25
25
|
CONF_VARIABLES,
|
26
26
|
)
|
27
|
-
from esphome.core import CORE, coroutine_with_priority
|
27
|
+
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
28
28
|
|
29
29
|
DOMAIN = "api"
|
30
30
|
DEPENDENCIES = ["network"]
|
@@ -134,7 +134,7 @@ CONFIG_SCHEMA = cv.All(
|
|
134
134
|
)
|
135
135
|
|
136
136
|
|
137
|
-
@coroutine_with_priority(
|
137
|
+
@coroutine_with_priority(CoroPriority.WEB)
|
138
138
|
async def to_code(config):
|
139
139
|
var = cg.new_Pvariable(config[CONF_ID])
|
140
140
|
await cg.register_component(var, config)
|
@@ -112,7 +112,7 @@ void APIConnection::start() {
|
|
112
112
|
APIError err = this->helper_->init();
|
113
113
|
if (err != APIError::OK) {
|
114
114
|
on_fatal_error();
|
115
|
-
this->log_warning_("Helper init failed", err);
|
115
|
+
this->log_warning_(LOG_STR("Helper init failed"), err);
|
116
116
|
return;
|
117
117
|
}
|
118
118
|
this->client_info_.peername = helper_->getpeername();
|
@@ -159,7 +159,7 @@ void APIConnection::loop() {
|
|
159
159
|
break;
|
160
160
|
} else if (err != APIError::OK) {
|
161
161
|
on_fatal_error();
|
162
|
-
this->log_warning_("Reading failed", err);
|
162
|
+
this->log_warning_(LOG_STR("Reading failed"), err);
|
163
163
|
return;
|
164
164
|
} else {
|
165
165
|
this->last_traffic_ = now;
|
@@ -289,16 +289,26 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess
|
|
289
289
|
return 0; // Doesn't fit
|
290
290
|
}
|
291
291
|
|
292
|
-
// Allocate buffer space - pass payload size, allocation functions add header/footer space
|
293
|
-
ProtoWriteBuffer buffer = is_single ? conn->allocate_single_message_buffer(calculated_size)
|
294
|
-
: conn->allocate_batch_message_buffer(calculated_size);
|
295
|
-
|
296
292
|
// Get buffer size after allocation (which includes header padding)
|
297
293
|
std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref();
|
298
|
-
|
294
|
+
|
295
|
+
if (is_single || conn->flags_.batch_first_message) {
|
296
|
+
// Single message or first batch message
|
297
|
+
conn->prepare_first_message_buffer(shared_buf, header_padding, total_calculated_size);
|
298
|
+
if (conn->flags_.batch_first_message) {
|
299
|
+
conn->flags_.batch_first_message = false;
|
300
|
+
}
|
301
|
+
} else {
|
302
|
+
// Batch message second or later
|
303
|
+
// Add padding for previous message footer + this message header
|
304
|
+
size_t current_size = shared_buf.size();
|
305
|
+
shared_buf.reserve(current_size + total_calculated_size);
|
306
|
+
shared_buf.resize(current_size + footer_size + header_padding);
|
307
|
+
}
|
299
308
|
|
300
309
|
// Encode directly into buffer
|
301
|
-
|
310
|
+
size_t size_before_encode = shared_buf.size();
|
311
|
+
msg.encode({&shared_buf});
|
302
312
|
|
303
313
|
// Calculate actual encoded size (not including header that was already added)
|
304
314
|
size_t actual_payload_size = shared_buf.size() - size_before_encode;
|
@@ -1060,8 +1070,14 @@ void APIConnection::camera_image(const CameraImageRequest &msg) {
|
|
1060
1070
|
|
1061
1071
|
#ifdef USE_HOMEASSISTANT_TIME
|
1062
1072
|
void APIConnection::on_get_time_response(const GetTimeResponse &value) {
|
1063
|
-
if (homeassistant::global_homeassistant_time != nullptr)
|
1073
|
+
if (homeassistant::global_homeassistant_time != nullptr) {
|
1064
1074
|
homeassistant::global_homeassistant_time->set_epoch_time(value.epoch_seconds);
|
1075
|
+
#ifdef USE_TIME_TIMEZONE
|
1076
|
+
if (!value.timezone.empty() && value.timezone != homeassistant::global_homeassistant_time->get_timezone()) {
|
1077
|
+
homeassistant::global_homeassistant_time->set_timezone(value.timezone);
|
1078
|
+
}
|
1079
|
+
#endif
|
1080
|
+
}
|
1065
1081
|
}
|
1066
1082
|
#endif
|
1067
1083
|
|
@@ -1555,7 +1571,7 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) {
|
|
1555
1571
|
return false;
|
1556
1572
|
if (err != APIError::OK) {
|
1557
1573
|
on_fatal_error();
|
1558
|
-
this->log_warning_("Packet write failed", err);
|
1574
|
+
this->log_warning_(LOG_STR("Packet write failed"), err);
|
1559
1575
|
return false;
|
1560
1576
|
}
|
1561
1577
|
// Do not set last_traffic_ on send
|
@@ -1616,14 +1632,6 @@ bool APIConnection::schedule_batch_() {
|
|
1616
1632
|
return true;
|
1617
1633
|
}
|
1618
1634
|
|
1619
|
-
ProtoWriteBuffer APIConnection::allocate_single_message_buffer(uint16_t size) { return this->create_buffer(size); }
|
1620
|
-
|
1621
|
-
ProtoWriteBuffer APIConnection::allocate_batch_message_buffer(uint16_t size) {
|
1622
|
-
ProtoWriteBuffer result = this->prepare_message_buffer(size, this->flags_.batch_first_message);
|
1623
|
-
this->flags_.batch_first_message = false;
|
1624
|
-
return result;
|
1625
|
-
}
|
1626
|
-
|
1627
1635
|
void APIConnection::process_batch_() {
|
1628
1636
|
// Ensure PacketInfo remains trivially destructible for our placement new approach
|
1629
1637
|
static_assert(std::is_trivially_destructible<PacketInfo>::value,
|
@@ -1731,7 +1739,7 @@ void APIConnection::process_batch_() {
|
|
1731
1739
|
}
|
1732
1740
|
remaining_size -= payload_size;
|
1733
1741
|
// Calculate where the next message's header padding will start
|
1734
|
-
// Current buffer size + footer space
|
1742
|
+
// Current buffer size + footer space for this message
|
1735
1743
|
current_offset = shared_buf.size() + footer_size;
|
1736
1744
|
}
|
1737
1745
|
|
@@ -1750,7 +1758,7 @@ void APIConnection::process_batch_() {
|
|
1750
1758
|
std::span<const PacketInfo>(packet_info, packet_count));
|
1751
1759
|
if (err != APIError::OK && err != APIError::WOULD_BLOCK) {
|
1752
1760
|
on_fatal_error();
|
1753
|
-
this->log_warning_("Batch write failed", err);
|
1761
|
+
this->log_warning_(LOG_STR("Batch write failed"), err);
|
1754
1762
|
}
|
1755
1763
|
|
1756
1764
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
@@ -1828,11 +1836,14 @@ void APIConnection::process_state_subscriptions_() {
|
|
1828
1836
|
}
|
1829
1837
|
#endif // USE_API_HOMEASSISTANT_STATES
|
1830
1838
|
|
1831
|
-
void APIConnection::log_warning_(const
|
1832
|
-
ESP_LOGW(TAG, "%s: %s %s errno=%d", this->get_client_combined_info().c_str(), message
|
1839
|
+
void APIConnection::log_warning_(const LogString *message, APIError err) {
|
1840
|
+
ESP_LOGW(TAG, "%s: %s %s errno=%d", this->get_client_combined_info().c_str(), LOG_STR_ARG(message),
|
1841
|
+
LOG_STR_ARG(api_error_to_logstr(err)), errno);
|
1833
1842
|
}
|
1834
1843
|
|
1835
|
-
void APIConnection::log_socket_operation_failed_(APIError err) {
|
1844
|
+
void APIConnection::log_socket_operation_failed_(APIError err) {
|
1845
|
+
this->log_warning_(LOG_STR("Socket operation failed"), err);
|
1846
|
+
}
|
1836
1847
|
|
1837
1848
|
} // namespace esphome::api
|
1838
1849
|
#endif
|
@@ -44,7 +44,7 @@ static constexpr size_t MAX_PACKETS_PER_BATCH = 64; // ESP32 has 8KB+ stack, HO
|
|
44
44
|
static constexpr size_t MAX_PACKETS_PER_BATCH = 32; // ESP8266/RP2040/etc have smaller stacks
|
45
45
|
#endif
|
46
46
|
|
47
|
-
class APIConnection : public APIServerConnection {
|
47
|
+
class APIConnection final : public APIServerConnection {
|
48
48
|
public:
|
49
49
|
friend class APIServer;
|
50
50
|
friend class ListEntitiesIterator;
|
@@ -252,44 +252,21 @@ class APIConnection : public APIServerConnection {
|
|
252
252
|
|
253
253
|
// Get header padding size - used for both reserve and insert
|
254
254
|
uint8_t header_padding = this->helper_->frame_header_padding();
|
255
|
-
|
256
255
|
// Get shared buffer from parent server
|
257
256
|
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
|
257
|
+
this->prepare_first_message_buffer(shared_buf, header_padding,
|
258
|
+
reserve_size + header_padding + this->helper_->frame_footer_size());
|
259
|
+
return {&shared_buf};
|
260
|
+
}
|
261
|
+
|
262
|
+
void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) {
|
258
263
|
shared_buf.clear();
|
259
264
|
// Reserve space for header padding + message + footer
|
260
265
|
// - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext)
|
261
266
|
// - Footer: space for MAC (16 bytes for Noise, 0 for Plaintext)
|
262
|
-
shared_buf.reserve(
|
267
|
+
shared_buf.reserve(total_size);
|
263
268
|
// Resize to add header padding so message encoding starts at the correct position
|
264
269
|
shared_buf.resize(header_padding);
|
265
|
-
return {&shared_buf};
|
266
|
-
}
|
267
|
-
|
268
|
-
// Prepare buffer for next message in batch
|
269
|
-
ProtoWriteBuffer prepare_message_buffer(uint16_t message_size, bool is_first_message) {
|
270
|
-
// Get reference to shared buffer (it maintains state between batch messages)
|
271
|
-
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
|
272
|
-
|
273
|
-
if (is_first_message) {
|
274
|
-
shared_buf.clear();
|
275
|
-
}
|
276
|
-
|
277
|
-
size_t current_size = shared_buf.size();
|
278
|
-
|
279
|
-
// Calculate padding to add:
|
280
|
-
// - First message: just header padding
|
281
|
-
// - Subsequent messages: footer for previous message + header padding for this message
|
282
|
-
size_t padding_to_add = is_first_message
|
283
|
-
? this->helper_->frame_header_padding()
|
284
|
-
: this->helper_->frame_header_padding() + this->helper_->frame_footer_size();
|
285
|
-
|
286
|
-
// Reserve space for padding + message
|
287
|
-
shared_buf.reserve(current_size + padding_to_add + message_size);
|
288
|
-
|
289
|
-
// Resize to add the padding bytes
|
290
|
-
shared_buf.resize(current_size + padding_to_add);
|
291
|
-
|
292
|
-
return {&shared_buf};
|
293
270
|
}
|
294
271
|
|
295
272
|
bool try_to_clear_buffer(bool log_out_of_space);
|
@@ -297,10 +274,6 @@ class APIConnection : public APIServerConnection {
|
|
297
274
|
|
298
275
|
std::string get_client_combined_info() const { return this->client_info_.get_combined_info(); }
|
299
276
|
|
300
|
-
// Buffer allocator methods for batch processing
|
301
|
-
ProtoWriteBuffer allocate_single_message_buffer(uint16_t size);
|
302
|
-
ProtoWriteBuffer allocate_batch_message_buffer(uint16_t size);
|
303
|
-
|
304
277
|
protected:
|
305
278
|
// Helper function to handle authentication completion
|
306
279
|
void complete_authentication_();
|
@@ -328,9 +301,17 @@ class APIConnection : public APIServerConnection {
|
|
328
301
|
APIConnection *conn, uint32_t remaining_size, bool is_single) {
|
329
302
|
// Set common fields that are shared by all entity types
|
330
303
|
msg.key = entity->get_object_id_hash();
|
331
|
-
//
|
332
|
-
|
333
|
-
|
304
|
+
// Try to use static reference first to avoid allocation
|
305
|
+
StringRef static_ref = entity->get_object_id_ref_for_api_();
|
306
|
+
// Store dynamic string outside the if-else to maintain lifetime
|
307
|
+
std::string object_id;
|
308
|
+
if (!static_ref.empty()) {
|
309
|
+
msg.set_object_id(static_ref);
|
310
|
+
} else {
|
311
|
+
// Dynamic case - need to allocate
|
312
|
+
object_id = entity->get_object_id();
|
313
|
+
msg.set_object_id(StringRef(object_id));
|
314
|
+
}
|
334
315
|
|
335
316
|
if (entity->has_own_name()) {
|
336
317
|
msg.set_name(entity->get_name());
|
@@ -751,7 +732,7 @@ class APIConnection : public APIServerConnection {
|
|
751
732
|
}
|
752
733
|
|
753
734
|
// Helper function to log API errors with errno
|
754
|
-
void log_warning_(const
|
735
|
+
void log_warning_(const LogString *message, APIError err);
|
755
736
|
// Specific helper for duplicated error message
|
756
737
|
void log_socket_operation_failed_(APIError err);
|
757
738
|
};
|