esphome 2025.9.3__py3-none-any.whl → 2025.10.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 +87 -31
- esphome/address_cache.py +142 -0
- esphome/automation.py +130 -32
- esphome/build_gen/platformio.py +1 -3
- esphome/codegen.py +1 -0
- esphome/components/animation/animation.cpp +2 -2
- esphome/components/api/__init__.py +166 -3
- esphome/components/api/api_connection.cpp +84 -41
- esphome/components/api/api_connection.h +22 -16
- esphome/components/api/api_frame_helper.cpp +33 -19
- esphome/components/api/api_frame_helper.h +19 -4
- esphome/components/api/api_frame_helper_noise.cpp +41 -53
- esphome/components/api/api_frame_helper_noise.h +1 -1
- esphome/components/api/api_frame_helper_plaintext.cpp +22 -31
- esphome/components/api/api_frame_helper_plaintext.h +1 -1
- esphome/components/api/api_pb2.cpp +189 -15
- esphome/components/api/api_pb2.h +132 -20
- esphome/components/api/api_pb2_dump.cpp +97 -9
- esphome/components/api/api_pb2_service.cpp +118 -160
- esphome/components/api/api_pb2_service.h +31 -3
- esphome/components/api/api_server.cpp +68 -10
- esphome/components/api/api_server.h +32 -4
- esphome/components/api/custom_api_device.h +8 -8
- esphome/components/api/homeassistant_service.h +123 -6
- esphome/components/api/proto.h +6 -2
- esphome/components/api/user_services.h +2 -2
- esphome/components/as7341/sensor.py +1 -1
- esphome/components/audio/__init__.py +1 -1
- esphome/components/audio/audio.cpp +1 -1
- esphome/components/audio/audio_decoder.cpp +9 -9
- esphome/components/bl0906/bl0906.cpp +2 -2
- esphome/components/bl0942/bl0942.cpp +2 -2
- esphome/components/ble_client/__init__.py +1 -1
- esphome/components/bluetooth_proxy/__init__.py +4 -30
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +11 -4
- esphome/components/bluetooth_proxy/bluetooth_connection.h +2 -2
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +2 -2
- esphome/components/camera_encoder/__init__.py +2 -4
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.cpp +4 -2
- esphome/components/camera_encoder/esp32_camera_jpeg_encoder.h +3 -1
- esphome/components/canbus/canbus.cpp +7 -5
- esphome/components/canbus/canbus.h +4 -4
- esphome/components/captive_portal/__init__.py +18 -1
- esphome/components/captive_portal/captive_portal.cpp +40 -46
- esphome/components/captive_portal/captive_portal.h +20 -22
- esphome/components/captive_portal/dns_server_esp32_idf.cpp +205 -0
- esphome/components/captive_portal/dns_server_esp32_idf.h +27 -0
- esphome/components/ccs811/ccs811.cpp +1 -1
- esphome/components/climate/climate.cpp +10 -7
- esphome/components/cm1106/cm1106.cpp +1 -1
- esphome/components/copy/lock/copy_lock.cpp +1 -1
- esphome/components/cover/cover.cpp +1 -0
- esphome/components/daikin_arc/daikin_arc.cpp +19 -12
- esphome/components/deep_sleep/__init__.py +9 -2
- esphome/components/deep_sleep/deep_sleep_component.h +11 -9
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +51 -27
- esphome/components/ektf2232/touchscreen/__init__.py +8 -5
- esphome/components/ektf2232/touchscreen/ektf2232.cpp +4 -4
- esphome/components/ektf2232/touchscreen/ektf2232.h +2 -2
- esphome/components/epaper_spi/__init__.py +1 -0
- esphome/components/epaper_spi/display.py +80 -0
- esphome/components/epaper_spi/epaper_spi.cpp +227 -0
- esphome/components/epaper_spi/epaper_spi.h +93 -0
- esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.cpp +42 -0
- esphome/components/epaper_spi/epaper_spi_model_7p3in_spectra_e6.h +45 -0
- esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +135 -0
- esphome/components/epaper_spi/epaper_spi_spectra_e6.h +23 -0
- esphome/components/es7210/es7210.cpp +3 -3
- esphome/components/esp32/__init__.py +254 -339
- esphome/components/esp32/boards.py +81 -0
- esphome/components/esp32/preferences.cpp +23 -17
- esphome/components/esp32_ble/__init__.py +159 -44
- esphome/components/esp32_ble/ble.cpp +47 -3
- esphome/components/esp32_ble/ble.h +18 -0
- esphome/components/esp32_ble/ble_advertising.cpp +7 -3
- esphome/components/esp32_ble/ble_advertising.h +4 -0
- esphome/components/esp32_ble/ble_uuid.cpp +16 -42
- esphome/components/esp32_ble_beacon/__init__.py +3 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +14 -12
- esphome/components/esp32_ble_server/__init__.py +28 -14
- esphome/components/esp32_ble_server/ble_characteristic.cpp +67 -57
- esphome/components/esp32_ble_server/ble_characteristic.h +27 -16
- esphome/components/esp32_ble_server/ble_descriptor.cpp +4 -3
- esphome/components/esp32_ble_server/ble_descriptor.h +13 -9
- esphome/components/esp32_ble_server/ble_server.cpp +59 -24
- esphome/components/esp32_ble_server/ble_server.h +38 -20
- esphome/components/esp32_ble_server/ble_server_automations.cpp +49 -33
- esphome/components/esp32_ble_server/ble_server_automations.h +39 -24
- esphome/components/esp32_ble_tracker/__init__.py +25 -80
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -4
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +0 -3
- esphome/components/esp32_camera/__init__.py +1 -3
- esphome/components/esp32_can/esp32_can.cpp +22 -4
- esphome/components/esp32_can/esp32_can.h +3 -0
- esphome/components/esp32_hosted/__init__.py +2 -1
- esphome/components/esp32_improv/esp32_improv_component.cpp +102 -44
- esphome/components/esp32_improv/esp32_improv_component.h +6 -1
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
- esphome/components/esp8266/__init__.py +3 -3
- esphome/components/esphome/ota/__init__.py +21 -2
- esphome/components/esphome/ota/ota_esphome.cpp +455 -145
- esphome/components/esphome/ota/ota_esphome.h +49 -2
- esphome/components/ethernet/__init__.py +39 -22
- esphome/components/ethernet/ethernet_component.cpp +28 -5
- esphome/components/ethernet/ethernet_component.h +5 -1
- esphome/components/external_components/__init__.py +8 -6
- esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
- esphome/components/fingerprint_grow/fingerprint_grow.h +2 -1
- esphome/components/font/__init__.py +5 -5
- esphome/components/graph/graph.cpp +1 -1
- esphome/components/graphical_display_menu/graphical_display_menu.cpp +3 -2
- esphome/components/haier/hon_climate.cpp +2 -2
- esphome/components/haier/hon_climate.h +1 -1
- esphome/components/hdc1080/hdc1080.cpp +42 -34
- esphome/components/hdc1080/hdc1080.h +1 -3
- esphome/components/homeassistant/number/homeassistant_number.cpp +2 -2
- esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
- esphome/components/http_request/__init__.py +3 -3
- esphome/components/htu21d/htu21d.cpp +13 -18
- esphome/components/htu21d/htu21d.h +1 -1
- esphome/components/i2s_audio/__init__.py +1 -2
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
- esphome/components/ili9xxx/ili9xxx_display.cpp +2 -2
- esphome/components/improv_serial/improv_serial_component.cpp +12 -15
- esphome/components/improv_serial/improv_serial_component.h +6 -8
- esphome/components/json/json_util.cpp +35 -43
- esphome/components/json/json_util.h +57 -0
- esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +2 -2
- esphome/components/key_collector/key_collector.h +4 -4
- esphome/components/libretiny/__init__.py +6 -6
- esphome/components/libretiny/preferences.cpp +23 -16
- esphome/components/light/light_call.cpp +98 -120
- esphome/components/light/light_call.h +17 -7
- esphome/components/lm75b/__init__.py +0 -0
- esphome/components/lm75b/lm75b.cpp +39 -0
- esphome/components/lm75b/lm75b.h +19 -0
- esphome/components/lm75b/sensor.py +34 -0
- esphome/components/lock/lock.h +12 -6
- esphome/components/logger/__init__.py +15 -27
- esphome/components/logger/logger.cpp +10 -20
- esphome/components/logger/logger.h +105 -62
- esphome/components/logger/logger_esp32.cpp +0 -48
- esphome/components/logger/logger_zephyr.cpp +2 -3
- esphome/components/logger/select/logger_level_select.cpp +6 -7
- esphome/components/logger/select/logger_level_select.h +7 -0
- esphome/components/ltr501/ltr501.cpp +7 -6
- esphome/components/ltr_als_ps/ltr_als_ps.cpp +7 -6
- esphome/components/matrix_keypad/matrix_keypad.h +4 -4
- esphome/components/max7219digit/max7219digit.cpp +1 -1
- esphome/components/mcp2515/mcp2515.cpp +31 -3
- esphome/components/mcp2515/mcp2515_defs.h +3 -1
- esphome/components/md5/md5.cpp +0 -26
- esphome/components/md5/md5.h +10 -20
- esphome/components/mdns/__init__.py +19 -6
- esphome/components/mdns/mdns_component.cpp +27 -59
- esphome/components/mdns/mdns_component.h +23 -10
- esphome/components/mdns/mdns_esp32.cpp +7 -7
- esphome/components/mdns/mdns_esp8266.cpp +6 -6
- esphome/components/mdns/mdns_libretiny.cpp +3 -3
- esphome/components/mdns/mdns_rp2040.cpp +3 -3
- esphome/components/mipi/__init__.py +1 -5
- esphome/components/mipi_spi/display.py +24 -8
- esphome/components/mipi_spi/mipi_spi.h +3 -3
- esphome/components/mixer/speaker/mixer_speaker.cpp +3 -3
- esphome/components/mmc5603/mmc5603.cpp +3 -3
- esphome/components/modbus/modbus.cpp +27 -13
- esphome/components/modbus/modbus.h +5 -3
- esphome/components/modbus/modbus_definitions.h +86 -0
- esphome/components/modbus_controller/__init__.py +29 -1
- esphome/components/modbus_controller/const.py +4 -0
- esphome/components/modbus_controller/modbus_controller.cpp +38 -13
- esphome/components/modbus_controller/modbus_controller.h +18 -29
- esphome/components/mpr121/mpr121.cpp +41 -42
- esphome/components/mpr121/mpr121.h +0 -1
- esphome/components/nau7802/nau7802.cpp +2 -2
- esphome/components/network/__init__.py +7 -3
- esphome/components/nextion/display.py +4 -4
- esphome/components/nextion/nextion.cpp +8 -8
- esphome/components/number/__init__.py +2 -0
- esphome/components/number/number_call.cpp +23 -12
- esphome/components/number/number_call.h +5 -0
- esphome/components/online_image/bmp_image.cpp +2 -1
- esphome/components/online_image/jpeg_image.cpp +4 -2
- esphome/components/openthread/openthread.cpp +6 -7
- esphome/components/openthread/openthread.h +0 -1
- esphome/components/ota/ota_backend.h +1 -0
- esphome/components/packages/__init__.py +10 -8
- esphome/components/packet_transport/packet_transport.cpp +2 -0
- esphome/components/pid/pid_controller.cpp +1 -1
- esphome/components/prometheus/prometheus_handler.cpp +239 -239
- esphome/components/psram/__init__.py +30 -28
- esphome/components/qmc5883l/qmc5883l.cpp +15 -0
- esphome/components/qmc5883l/qmc5883l.h +3 -0
- esphome/components/qmc5883l/sensor.py +31 -12
- esphome/components/remote_base/gobox_protocol.cpp +3 -3
- esphome/components/remote_receiver/__init__.py +14 -2
- esphome/components/remote_receiver/{remote_receiver_esp8266.cpp → remote_receiver.cpp} +2 -2
- esphome/components/remote_receiver/remote_receiver.h +4 -0
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +18 -1
- esphome/components/remote_transmitter/__init__.py +2 -2
- esphome/components/remote_transmitter/remote_transmitter.cpp +103 -0
- esphome/components/rp2040/__init__.py +11 -11
- esphome/components/rtttl/rtttl.cpp +2 -2
- esphome/components/scd30/sensor.py +1 -1
- esphome/components/script/__init__.py +1 -1
- esphome/components/script/script.h +7 -7
- esphome/components/select/select.cpp +5 -4
- esphome/components/select/select_call.cpp +1 -1
- esphome/components/sensirion_common/i2c_sensirion.cpp +2 -1
- esphome/components/sensor/__init__.py +2 -0
- esphome/components/sha256/__init__.py +22 -0
- esphome/components/sha256/sha256.cpp +116 -0
- esphome/components/sha256/sha256.h +60 -0
- esphome/components/socket/lwip_raw_tcp_impl.cpp +34 -6
- esphome/components/sonoff_d1/sonoff_d1.cpp +1 -1
- esphome/components/spi/__init__.py +0 -3
- esphome/components/split_buffer/__init__.py +5 -0
- esphome/components/split_buffer/split_buffer.cpp +133 -0
- esphome/components/split_buffer/split_buffer.h +40 -0
- esphome/components/sps30/sps30.cpp +14 -10
- esphome/components/sps30/sps30.h +2 -0
- esphome/components/st7567_i2c/st7567_i2c.cpp +3 -1
- esphome/components/st7789v/st7789v.cpp +3 -2
- esphome/components/statsd/statsd.cpp +1 -1
- esphome/components/substitutions/__init__.py +3 -1
- esphome/components/substitutions/jinja.py +13 -3
- esphome/components/sx126x/__init__.py +16 -0
- esphome/components/sx126x/sx126x.cpp +15 -1
- esphome/components/sx126x/sx126x.h +9 -1
- esphome/components/sx126x/sx126x_reg.h +2 -0
- esphome/components/text_sensor/text_sensor.cpp +16 -0
- esphome/components/text_sensor/text_sensor.h +3 -10
- esphome/components/tormatic/tormatic_cover.cpp +1 -1
- esphome/components/tuya/select/tuya_select.cpp +1 -1
- esphome/components/tuya/tuya.cpp +29 -4
- esphome/components/uart/__init__.py +36 -26
- esphome/components/uart/uart.h +6 -0
- esphome/components/uart/uart_component.cpp +8 -0
- esphome/components/uart/uart_component.h +28 -0
- esphome/components/uart/uart_component_esp_idf.cpp +64 -10
- esphome/components/uart/uart_component_esp_idf.h +5 -2
- esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +1 -1
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +1 -1
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +3 -3
- esphome/components/usb_host/__init__.py +2 -1
- esphome/components/usb_host/usb_host.h +82 -13
- esphome/components/usb_host/usb_host_client.cpp +180 -24
- esphome/components/usb_host/usb_host_component.cpp +1 -1
- esphome/components/usb_uart/__init__.py +0 -1
- esphome/components/usb_uart/ch34x.cpp +4 -4
- esphome/components/usb_uart/cp210x.cpp +3 -3
- esphome/components/usb_uart/usb_uart.cpp +88 -32
- esphome/components/usb_uart/usb_uart.h +30 -6
- esphome/components/valve/valve.cpp +1 -0
- esphome/components/veml7700/veml7700.cpp +7 -6
- esphome/components/version/version_text_sensor.cpp +2 -1
- esphome/components/voice_assistant/voice_assistant.cpp +3 -2
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +4 -4
- esphome/components/web_server/list_entities.cpp +3 -4
- esphome/components/web_server/list_entities.h +8 -10
- esphome/components/web_server/ota/__init__.py +1 -1
- esphome/components/web_server/ota/ota_web_server.cpp +9 -3
- esphome/components/web_server/web_server.cpp +509 -404
- esphome/components/web_server/web_server.h +5 -6
- esphome/components/web_server/web_server_v1.cpp +21 -19
- esphome/components/web_server_base/__init__.py +5 -2
- esphome/components/web_server_base/web_server_base.h +27 -7
- esphome/components/web_server_idf/__init__.py +1 -1
- esphome/components/web_server_idf/multipart.cpp +2 -2
- esphome/components/web_server_idf/multipart.h +2 -2
- esphome/components/web_server_idf/utils.cpp +2 -2
- esphome/components/web_server_idf/utils.h +2 -2
- esphome/components/web_server_idf/web_server_idf.cpp +118 -26
- esphome/components/web_server_idf/web_server_idf.h +12 -10
- esphome/components/wifi/__init__.py +13 -11
- esphome/components/wifi/wifi_component.cpp +73 -56
- esphome/components/wifi/wifi_component.h +4 -4
- esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
- esphome/components/wifi/wifi_component_esp_idf.cpp +24 -4
- esphome/components/wireguard/__init__.py +1 -1
- esphome/components/wts01/__init__.py +0 -0
- esphome/components/wts01/sensor.py +41 -0
- esphome/components/wts01/wts01.cpp +91 -0
- esphome/components/wts01/wts01.h +27 -0
- esphome/components/zephyr/__init__.py +5 -5
- esphome/components/zwave_proxy/__init__.py +43 -0
- esphome/components/zwave_proxy/zwave_proxy.cpp +346 -0
- esphome/components/zwave_proxy/zwave_proxy.h +93 -0
- esphome/config.py +79 -24
- esphome/config_validation.py +13 -15
- esphome/const.py +9 -2
- esphome/core/__init__.py +31 -22
- esphome/core/component.cpp +28 -18
- esphome/core/component_iterator.h +2 -1
- esphome/core/config.py +15 -15
- esphome/core/defines.h +19 -0
- esphome/core/hash_base.h +56 -0
- esphome/core/helpers.cpp +19 -3
- esphome/core/helpers.h +26 -0
- esphome/core/scheduler.cpp +5 -21
- esphome/core/scheduler.h +19 -8
- esphome/core/string_ref.h +1 -1
- esphome/core/time.cpp +5 -5
- esphome/cpp_generator.py +4 -29
- esphome/dashboard/const.py +21 -4
- esphome/dashboard/core.py +10 -8
- esphome/dashboard/dns.py +15 -0
- esphome/dashboard/entries.py +15 -21
- esphome/dashboard/models.py +76 -0
- esphome/dashboard/settings.py +7 -7
- esphome/dashboard/status/mdns.py +46 -2
- esphome/dashboard/web_server.py +367 -93
- esphome/espota2.py +111 -31
- esphome/external_files.py +6 -7
- esphome/git.py +8 -0
- esphome/helpers.py +124 -77
- esphome/loader.py +8 -9
- esphome/platformio_api.py +25 -18
- esphome/storage_json.py +26 -21
- esphome/types.py +30 -2
- esphome/util.py +32 -16
- esphome/vscode.py +8 -8
- esphome/wizard.py +10 -10
- esphome/writer.py +50 -15
- esphome/yaml_util.py +37 -31
- esphome/zeroconf.py +12 -3
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/METADATA +11 -11
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/RECORD +332 -312
- esphome/components/event_emitter/__init__.py +0 -5
- esphome/components/event_emitter/event_emitter.cpp +0 -14
- esphome/components/event_emitter/event_emitter.h +0 -63
- esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -125
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +0 -107
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +0 -110
- esphome/components/uart/uart_component_esp32_arduino.cpp +0 -214
- esphome/components/uart/uart_component_esp32_arduino.h +0 -60
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +0 -860
- esphome/core/string_ref.cpp +0 -12
- esphome/dashboard/util/file.py +0 -63
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/WHEEL +0 -0
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/entry_points.txt +0 -0
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.9.3.dist-info → esphome-2025.10.0b1.dist-info}/top_level.txt +0 -0
@@ -16,6 +16,7 @@
|
|
16
16
|
#include "user_services.h"
|
17
17
|
#endif
|
18
18
|
|
19
|
+
#include <map>
|
19
20
|
#include <vector>
|
20
21
|
|
21
22
|
namespace esphome::api {
|
@@ -37,13 +38,15 @@ class APIServer : public Component, public Controller {
|
|
37
38
|
void on_shutdown() override;
|
38
39
|
bool teardown() override;
|
39
40
|
#ifdef USE_API_PASSWORD
|
40
|
-
bool check_password(const
|
41
|
+
bool check_password(const uint8_t *password_data, size_t password_len) const;
|
41
42
|
void set_password(const std::string &password);
|
42
43
|
#endif
|
43
44
|
void set_port(uint16_t port);
|
44
45
|
void set_reboot_timeout(uint32_t reboot_timeout);
|
45
46
|
void set_batch_delay(uint16_t batch_delay);
|
46
47
|
uint16_t get_batch_delay() const { return batch_delay_; }
|
48
|
+
void set_listen_backlog(uint8_t listen_backlog) { this->listen_backlog_ = listen_backlog; }
|
49
|
+
void set_max_connections(uint8_t max_connections) { this->max_connections_ = max_connections; }
|
47
50
|
|
48
51
|
// Get reference to shared buffer for API connections
|
49
52
|
std::vector<uint8_t> &get_shared_buffer_ref() { return shared_write_buffer_; }
|
@@ -107,8 +110,19 @@ class APIServer : public Component, public Controller {
|
|
107
110
|
void on_media_player_update(media_player::MediaPlayer *obj) override;
|
108
111
|
#endif
|
109
112
|
#ifdef USE_API_HOMEASSISTANT_SERVICES
|
110
|
-
void
|
111
|
-
|
113
|
+
void send_homeassistant_action(const HomeassistantActionRequest &call);
|
114
|
+
|
115
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
116
|
+
// Action response handling
|
117
|
+
using ActionResponseCallback = std::function<void(const class ActionResponse &)>;
|
118
|
+
void register_action_response_callback(uint32_t call_id, ActionResponseCallback callback);
|
119
|
+
void handle_action_response(uint32_t call_id, bool success, const std::string &error_message);
|
120
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
121
|
+
void handle_action_response(uint32_t call_id, bool success, const std::string &error_message,
|
122
|
+
const uint8_t *response_data, size_t response_data_len);
|
123
|
+
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
124
|
+
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
125
|
+
#endif // USE_API_HOMEASSISTANT_SERVICES
|
112
126
|
#ifdef USE_API_SERVICES
|
113
127
|
void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
|
114
128
|
#endif
|
@@ -125,6 +139,9 @@ class APIServer : public Component, public Controller {
|
|
125
139
|
#ifdef USE_UPDATE
|
126
140
|
void on_update(update::UpdateEntity *obj) override;
|
127
141
|
#endif
|
142
|
+
#ifdef USE_ZWAVE_PROXY
|
143
|
+
void on_zwave_proxy_request(const esphome::api::ProtoMessage &msg);
|
144
|
+
#endif
|
128
145
|
|
129
146
|
bool is_connected() const;
|
130
147
|
|
@@ -181,12 +198,23 @@ class APIServer : public Component, public Controller {
|
|
181
198
|
#ifdef USE_API_SERVICES
|
182
199
|
std::vector<UserServiceDescriptor *> user_services_;
|
183
200
|
#endif
|
201
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
202
|
+
struct PendingActionResponse {
|
203
|
+
uint32_t call_id;
|
204
|
+
ActionResponseCallback callback;
|
205
|
+
};
|
206
|
+
std::vector<PendingActionResponse> action_response_callbacks_;
|
207
|
+
#endif
|
184
208
|
|
185
209
|
// Group smaller types together
|
186
210
|
uint16_t port_{6053};
|
187
211
|
uint16_t batch_delay_{100};
|
212
|
+
// Connection limits - these defaults will be overridden by config values
|
213
|
+
// from cv.SplitDefault in __init__.py which sets platform-specific defaults
|
214
|
+
uint8_t listen_backlog_{4};
|
215
|
+
uint8_t max_connections_{8};
|
188
216
|
bool shutting_down_ = false;
|
189
|
-
//
|
217
|
+
// 7 bytes used, 1 byte padding
|
190
218
|
|
191
219
|
#ifdef USE_API_NOISE
|
192
220
|
std::shared_ptr<APINoiseContext> noise_ctx_ = std::make_shared<APINoiseContext>();
|
@@ -179,9 +179,9 @@ class CustomAPIDevice {
|
|
179
179
|
* @param service_name The service to call.
|
180
180
|
*/
|
181
181
|
void call_homeassistant_service(const std::string &service_name) {
|
182
|
-
|
182
|
+
HomeassistantActionRequest resp;
|
183
183
|
resp.set_service(StringRef(service_name));
|
184
|
-
global_api_server->
|
184
|
+
global_api_server->send_homeassistant_action(resp);
|
185
185
|
}
|
186
186
|
|
187
187
|
/** Call a Home Assistant service from ESPHome.
|
@@ -199,7 +199,7 @@ class CustomAPIDevice {
|
|
199
199
|
* @param data The data for the service call, mapping from string to string.
|
200
200
|
*/
|
201
201
|
void call_homeassistant_service(const std::string &service_name, const std::map<std::string, std::string> &data) {
|
202
|
-
|
202
|
+
HomeassistantActionRequest resp;
|
203
203
|
resp.set_service(StringRef(service_name));
|
204
204
|
for (auto &it : data) {
|
205
205
|
resp.data.emplace_back();
|
@@ -207,7 +207,7 @@ class CustomAPIDevice {
|
|
207
207
|
kv.set_key(StringRef(it.first));
|
208
208
|
kv.value = it.second;
|
209
209
|
}
|
210
|
-
global_api_server->
|
210
|
+
global_api_server->send_homeassistant_action(resp);
|
211
211
|
}
|
212
212
|
|
213
213
|
/** Fire an ESPHome event in Home Assistant.
|
@@ -221,10 +221,10 @@ class CustomAPIDevice {
|
|
221
221
|
* @param event_name The event to fire.
|
222
222
|
*/
|
223
223
|
void fire_homeassistant_event(const std::string &event_name) {
|
224
|
-
|
224
|
+
HomeassistantActionRequest resp;
|
225
225
|
resp.set_service(StringRef(event_name));
|
226
226
|
resp.is_event = true;
|
227
|
-
global_api_server->
|
227
|
+
global_api_server->send_homeassistant_action(resp);
|
228
228
|
}
|
229
229
|
|
230
230
|
/** Fire an ESPHome event in Home Assistant.
|
@@ -241,7 +241,7 @@ class CustomAPIDevice {
|
|
241
241
|
* @param data The data for the event, mapping from string to string.
|
242
242
|
*/
|
243
243
|
void fire_homeassistant_event(const std::string &service_name, const std::map<std::string, std::string> &data) {
|
244
|
-
|
244
|
+
HomeassistantActionRequest resp;
|
245
245
|
resp.set_service(StringRef(service_name));
|
246
246
|
resp.is_event = true;
|
247
247
|
for (auto &it : data) {
|
@@ -250,7 +250,7 @@ class CustomAPIDevice {
|
|
250
250
|
kv.set_key(StringRef(it.first));
|
251
251
|
kv.value = it.second;
|
252
252
|
}
|
253
|
-
global_api_server->
|
253
|
+
global_api_server->send_homeassistant_action(resp);
|
254
254
|
}
|
255
255
|
#else
|
256
256
|
template<typename T = void> void call_homeassistant_service(const std::string &service_name) {
|
@@ -3,10 +3,15 @@
|
|
3
3
|
#include "api_server.h"
|
4
4
|
#ifdef USE_API
|
5
5
|
#ifdef USE_API_HOMEASSISTANT_SERVICES
|
6
|
+
#include <functional>
|
7
|
+
#include <utility>
|
8
|
+
#include <vector>
|
6
9
|
#include "api_pb2.h"
|
10
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
11
|
+
#include "esphome/components/json/json_util.h"
|
12
|
+
#endif
|
7
13
|
#include "esphome/core/automation.h"
|
8
14
|
#include "esphome/core/helpers.h"
|
9
|
-
#include <vector>
|
10
15
|
|
11
16
|
namespace esphome::api {
|
12
17
|
|
@@ -44,9 +49,47 @@ template<typename... Ts> class TemplatableKeyValuePair {
|
|
44
49
|
TemplatableStringValue<Ts...> value;
|
45
50
|
};
|
46
51
|
|
52
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
53
|
+
// Represents the response data from a Home Assistant action
|
54
|
+
class ActionResponse {
|
55
|
+
public:
|
56
|
+
ActionResponse(bool success, std::string error_message = "")
|
57
|
+
: success_(success), error_message_(std::move(error_message)) {}
|
58
|
+
|
59
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
60
|
+
ActionResponse(bool success, std::string error_message, const uint8_t *data, size_t data_len)
|
61
|
+
: success_(success), error_message_(std::move(error_message)) {
|
62
|
+
if (data == nullptr || data_len == 0)
|
63
|
+
return;
|
64
|
+
this->json_document_ = json::parse_json(data, data_len);
|
65
|
+
}
|
66
|
+
#endif
|
67
|
+
|
68
|
+
bool is_success() const { return this->success_; }
|
69
|
+
const std::string &get_error_message() const { return this->error_message_; }
|
70
|
+
|
71
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
72
|
+
// Get data as parsed JSON object (const version returns read-only view)
|
73
|
+
JsonObjectConst get_json() const { return this->json_document_.as<JsonObjectConst>(); }
|
74
|
+
#endif
|
75
|
+
|
76
|
+
protected:
|
77
|
+
bool success_;
|
78
|
+
std::string error_message_;
|
79
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
80
|
+
JsonDocument json_document_;
|
81
|
+
#endif
|
82
|
+
};
|
83
|
+
|
84
|
+
// Callback type for action responses
|
85
|
+
template<typename... Ts> using ActionResponseCallback = std::function<void(const ActionResponse &, Ts...)>;
|
86
|
+
#endif
|
87
|
+
|
47
88
|
template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts...> {
|
48
89
|
public:
|
49
|
-
explicit HomeAssistantServiceCallAction(APIServer *parent, bool is_event) : parent_(parent)
|
90
|
+
explicit HomeAssistantServiceCallAction(APIServer *parent, bool is_event) : parent_(parent) {
|
91
|
+
this->flags_.is_event = is_event;
|
92
|
+
}
|
50
93
|
|
51
94
|
template<typename T> void set_service(T service) { this->service_ = service; }
|
52
95
|
|
@@ -61,11 +104,29 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
|
|
61
104
|
this->variables_.emplace_back(std::move(key), value);
|
62
105
|
}
|
63
106
|
|
107
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
108
|
+
template<typename T> void set_response_template(T response_template) {
|
109
|
+
this->response_template_ = response_template;
|
110
|
+
this->flags_.has_response_template = true;
|
111
|
+
}
|
112
|
+
|
113
|
+
void set_wants_status() { this->flags_.wants_status = true; }
|
114
|
+
void set_wants_response() { this->flags_.wants_response = true; }
|
115
|
+
|
116
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
117
|
+
Trigger<JsonObjectConst, Ts...> *get_success_trigger_with_response() const {
|
118
|
+
return this->success_trigger_with_response_;
|
119
|
+
}
|
120
|
+
#endif
|
121
|
+
Trigger<Ts...> *get_success_trigger() const { return this->success_trigger_; }
|
122
|
+
Trigger<std::string, Ts...> *get_error_trigger() const { return this->error_trigger_; }
|
123
|
+
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
124
|
+
|
64
125
|
void play(Ts... x) override {
|
65
|
-
|
126
|
+
HomeassistantActionRequest resp;
|
66
127
|
std::string service_value = this->service_.value(x...);
|
67
128
|
resp.set_service(StringRef(service_value));
|
68
|
-
resp.is_event = this->
|
129
|
+
resp.is_event = this->flags_.is_event;
|
69
130
|
for (auto &it : this->data_) {
|
70
131
|
resp.data.emplace_back();
|
71
132
|
auto &kv = resp.data.back();
|
@@ -84,18 +145,74 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
|
|
84
145
|
kv.set_key(StringRef(it.key));
|
85
146
|
kv.value = it.value.value(x...);
|
86
147
|
}
|
87
|
-
|
148
|
+
|
149
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
150
|
+
if (this->flags_.wants_status) {
|
151
|
+
// Generate a unique call ID for this service call
|
152
|
+
static uint32_t call_id_counter = 1;
|
153
|
+
uint32_t call_id = call_id_counter++;
|
154
|
+
resp.call_id = call_id;
|
155
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
156
|
+
if (this->flags_.wants_response) {
|
157
|
+
resp.wants_response = true;
|
158
|
+
// Set response template if provided
|
159
|
+
if (this->flags_.has_response_template) {
|
160
|
+
std::string response_template_value = this->response_template_.value(x...);
|
161
|
+
resp.response_template = response_template_value;
|
162
|
+
}
|
163
|
+
}
|
164
|
+
#endif
|
165
|
+
|
166
|
+
auto captured_args = std::make_tuple(x...);
|
167
|
+
this->parent_->register_action_response_callback(call_id, [this, captured_args](const ActionResponse &response) {
|
168
|
+
std::apply(
|
169
|
+
[this, &response](auto &&...args) {
|
170
|
+
if (response.is_success()) {
|
171
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
172
|
+
if (this->flags_.wants_response) {
|
173
|
+
this->success_trigger_with_response_->trigger(response.get_json(), args...);
|
174
|
+
} else
|
175
|
+
#endif
|
176
|
+
{
|
177
|
+
this->success_trigger_->trigger(args...);
|
178
|
+
}
|
179
|
+
} else {
|
180
|
+
this->error_trigger_->trigger(response.get_error_message(), args...);
|
181
|
+
}
|
182
|
+
},
|
183
|
+
captured_args);
|
184
|
+
});
|
185
|
+
}
|
186
|
+
#endif
|
187
|
+
|
188
|
+
this->parent_->send_homeassistant_action(resp);
|
88
189
|
}
|
89
190
|
|
90
191
|
protected:
|
91
192
|
APIServer *parent_;
|
92
|
-
bool is_event_;
|
93
193
|
TemplatableStringValue<Ts...> service_{};
|
94
194
|
std::vector<TemplatableKeyValuePair<Ts...>> data_;
|
95
195
|
std::vector<TemplatableKeyValuePair<Ts...>> data_template_;
|
96
196
|
std::vector<TemplatableKeyValuePair<Ts...>> variables_;
|
197
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
198
|
+
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
199
|
+
TemplatableStringValue<Ts...> response_template_{""};
|
200
|
+
Trigger<JsonObjectConst, Ts...> *success_trigger_with_response_ = new Trigger<JsonObjectConst, Ts...>();
|
201
|
+
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
|
202
|
+
Trigger<Ts...> *success_trigger_ = new Trigger<Ts...>();
|
203
|
+
Trigger<std::string, Ts...> *error_trigger_ = new Trigger<std::string, Ts...>();
|
204
|
+
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
205
|
+
|
206
|
+
struct Flags {
|
207
|
+
uint8_t is_event : 1;
|
208
|
+
uint8_t wants_status : 1;
|
209
|
+
uint8_t wants_response : 1;
|
210
|
+
uint8_t has_response_template : 1;
|
211
|
+
uint8_t reserved : 5;
|
212
|
+
} flags_{0};
|
97
213
|
};
|
98
214
|
|
99
215
|
} // namespace esphome::api
|
216
|
+
|
100
217
|
#endif
|
101
218
|
#endif
|
esphome/components/api/proto.h
CHANGED
@@ -182,6 +182,10 @@ class ProtoLengthDelimited {
|
|
182
182
|
explicit ProtoLengthDelimited(const uint8_t *value, size_t length) : value_(value), length_(length) {}
|
183
183
|
std::string as_string() const { return std::string(reinterpret_cast<const char *>(this->value_), this->length_); }
|
184
184
|
|
185
|
+
// Direct access to raw data without string allocation
|
186
|
+
const uint8_t *data() const { return this->value_; }
|
187
|
+
size_t size() const { return this->length_; }
|
188
|
+
|
185
189
|
/**
|
186
190
|
* Decode the length-delimited data into an existing ProtoDecodableMessage instance.
|
187
191
|
*
|
@@ -827,7 +831,7 @@ class ProtoService {
|
|
827
831
|
}
|
828
832
|
|
829
833
|
// Authentication helper methods
|
830
|
-
bool check_connection_setup_() {
|
834
|
+
inline bool check_connection_setup_() {
|
831
835
|
if (!this->is_connection_setup()) {
|
832
836
|
this->on_no_setup_connection();
|
833
837
|
return false;
|
@@ -835,7 +839,7 @@ class ProtoService {
|
|
835
839
|
return true;
|
836
840
|
}
|
837
841
|
|
838
|
-
bool check_authenticated_() {
|
842
|
+
inline bool check_authenticated_() {
|
839
843
|
#ifdef USE_API_PASSWORD
|
840
844
|
if (!this->check_connection_setup_()) {
|
841
845
|
return false;
|
@@ -35,7 +35,7 @@ template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
|
|
35
35
|
msg.set_name(StringRef(this->name_));
|
36
36
|
msg.key = this->key_;
|
37
37
|
std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
|
38
|
-
for (
|
38
|
+
for (size_t i = 0; i < sizeof...(Ts); i++) {
|
39
39
|
msg.args.emplace_back();
|
40
40
|
auto &arg = msg.args.back();
|
41
41
|
arg.type = arg_types[i];
|
@@ -55,7 +55,7 @@ template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
|
|
55
55
|
|
56
56
|
protected:
|
57
57
|
virtual void execute(Ts... x) = 0;
|
58
|
-
template<int... S> void execute_(std::vector<ExecuteServiceArgument> args, seq<S...> type) {
|
58
|
+
template<int... S> void execute_(const std::vector<ExecuteServiceArgument> &args, seq<S...> type) {
|
59
59
|
this->execute((get_execute_arg_value<Ts>(args[S]))...);
|
60
60
|
}
|
61
61
|
|
@@ -2,6 +2,7 @@ import esphome.codegen as cg
|
|
2
2
|
from esphome.components import i2c, sensor
|
3
3
|
import esphome.config_validation as cv
|
4
4
|
from esphome.const import (
|
5
|
+
CONF_CLEAR,
|
5
6
|
CONF_GAIN,
|
6
7
|
CONF_ID,
|
7
8
|
DEVICE_CLASS_ILLUMINANCE,
|
@@ -29,7 +30,6 @@ CONF_F5 = "f5"
|
|
29
30
|
CONF_F6 = "f6"
|
30
31
|
CONF_F7 = "f7"
|
31
32
|
CONF_F8 = "f8"
|
32
|
-
CONF_CLEAR = "clear"
|
33
33
|
CONF_NIR = "nir"
|
34
34
|
|
35
35
|
UNIT_COUNTS = "#"
|
@@ -57,7 +57,7 @@ const char *audio_file_type_to_string(AudioFileType file_type) {
|
|
57
57
|
void scale_audio_samples(const int16_t *audio_samples, int16_t *output_buffer, int16_t scale_factor,
|
58
58
|
size_t samples_to_scale) {
|
59
59
|
// Note the assembly dsps_mulc function has audio glitches if the input and output buffers are the same.
|
60
|
-
for (
|
60
|
+
for (size_t i = 0; i < samples_to_scale; i++) {
|
61
61
|
int32_t acc = (int32_t) audio_samples[i] * (int32_t) scale_factor;
|
62
62
|
output_buffer[i] = (int16_t) (acc >> 15);
|
63
63
|
}
|
@@ -229,18 +229,18 @@ FileDecoderState AudioDecoder::decode_flac_() {
|
|
229
229
|
auto result = this->flac_decoder_->read_header(this->input_transfer_buffer_->get_buffer_start(),
|
230
230
|
this->input_transfer_buffer_->available());
|
231
231
|
|
232
|
-
if (result
|
233
|
-
|
234
|
-
}
|
235
|
-
|
236
|
-
if (result != esp_audio_libs::flac::FLAC_DECODER_SUCCESS) {
|
237
|
-
// Couldn't read FLAC header
|
232
|
+
if (result > esp_audio_libs::flac::FLAC_DECODER_HEADER_OUT_OF_DATA) {
|
233
|
+
// Serrious error reading FLAC header, there is no recovery
|
238
234
|
return FileDecoderState::FAILED;
|
239
235
|
}
|
240
236
|
|
241
237
|
size_t bytes_consumed = this->flac_decoder_->get_bytes_index();
|
242
238
|
this->input_transfer_buffer_->decrease_buffer_length(bytes_consumed);
|
243
239
|
|
240
|
+
if (result == esp_audio_libs::flac::FLAC_DECODER_HEADER_OUT_OF_DATA) {
|
241
|
+
return FileDecoderState::MORE_TO_PROCESS;
|
242
|
+
}
|
243
|
+
|
244
244
|
// Reallocate the output transfer buffer to the smallest necessary size
|
245
245
|
this->free_buffer_required_ = flac_decoder_->get_output_buffer_size_bytes();
|
246
246
|
if (!this->output_transfer_buffer_->reallocate(this->free_buffer_required_)) {
|
@@ -256,9 +256,9 @@ FileDecoderState AudioDecoder::decode_flac_() {
|
|
256
256
|
}
|
257
257
|
|
258
258
|
uint32_t output_samples = 0;
|
259
|
-
auto result = this->flac_decoder_->decode_frame(
|
260
|
-
|
261
|
-
|
259
|
+
auto result = this->flac_decoder_->decode_frame(this->input_transfer_buffer_->get_buffer_start(),
|
260
|
+
this->input_transfer_buffer_->available(),
|
261
|
+
this->output_transfer_buffer_->get_buffer_end(), &output_samples);
|
262
262
|
|
263
263
|
if (result == esp_audio_libs::flac::FLAC_DECODER_ERROR_OUT_OF_DATA) {
|
264
264
|
// Not an issue, just needs more data that we'll get next time.
|
@@ -97,10 +97,10 @@ void BL0906::handle_actions_() {
|
|
97
97
|
return;
|
98
98
|
}
|
99
99
|
ActionCallbackFuncPtr ptr_func = nullptr;
|
100
|
-
for (
|
100
|
+
for (size_t i = 0; i < this->action_queue_.size(); i++) {
|
101
101
|
ptr_func = this->action_queue_[i];
|
102
102
|
if (ptr_func) {
|
103
|
-
ESP_LOGI(TAG, "HandleActionCallback[%
|
103
|
+
ESP_LOGI(TAG, "HandleActionCallback[%zu]", i);
|
104
104
|
(this->*ptr_func)();
|
105
105
|
}
|
106
106
|
}
|
@@ -51,7 +51,7 @@ void BL0942::loop() {
|
|
51
51
|
if (!avail) {
|
52
52
|
return;
|
53
53
|
}
|
54
|
-
if (avail < sizeof(buffer)) {
|
54
|
+
if (static_cast<size_t>(avail) < sizeof(buffer)) {
|
55
55
|
if (!this->rx_start_) {
|
56
56
|
this->rx_start_ = millis();
|
57
57
|
} else if (millis() > this->rx_start_ + PKT_TIMEOUT_MS) {
|
@@ -148,7 +148,7 @@ void BL0942::setup() {
|
|
148
148
|
|
149
149
|
this->write_reg_(BL0942_REG_USR_WRPROT, 0);
|
150
150
|
|
151
|
-
if (this->read_reg_(BL0942_REG_MODE) != mode)
|
151
|
+
if (static_cast<uint32_t>(this->read_reg_(BL0942_REG_MODE)) != mode)
|
152
152
|
this->status_set_warning(LOG_STR("BL0942 setup failed!"));
|
153
153
|
|
154
154
|
this->flush();
|
@@ -116,7 +116,7 @@ CONFIG_SCHEMA = cv.All(
|
|
116
116
|
)
|
117
117
|
.extend(cv.COMPONENT_SCHEMA)
|
118
118
|
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA),
|
119
|
-
|
119
|
+
esp32_ble.consume_connection_slots(1, "ble_client"),
|
120
120
|
)
|
121
121
|
|
122
122
|
CONF_BLE_CLIENT_ID = "ble_client_id"
|
@@ -6,8 +6,6 @@ from esphome.components.esp32 import add_idf_sdkconfig_option
|
|
6
6
|
from esphome.components.esp32_ble import BTLoggers
|
7
7
|
import esphome.config_validation as cv
|
8
8
|
from esphome.const import CONF_ACTIVE, CONF_ID
|
9
|
-
from esphome.core import CORE
|
10
|
-
from esphome.log import AnsiFore, color
|
11
9
|
|
12
10
|
AUTO_LOAD = ["esp32_ble_client", "esp32_ble_tracker"]
|
13
11
|
DEPENDENCIES = ["api", "esp32"]
|
@@ -44,29 +42,7 @@ def validate_connections(config):
|
|
44
42
|
)
|
45
43
|
elif config[CONF_ACTIVE]:
|
46
44
|
connection_slots: int = config[CONF_CONNECTION_SLOTS]
|
47
|
-
|
48
|
-
config
|
49
|
-
)
|
50
|
-
|
51
|
-
# Warn about connection slot waste when using Arduino framework
|
52
|
-
if CORE.using_arduino and connection_slots:
|
53
|
-
_LOGGER.warning(
|
54
|
-
"Bluetooth Proxy with active connections on Arduino framework has suboptimal performance.\n"
|
55
|
-
"If BLE connections fail, they can waste connection slots for 10 seconds because\n"
|
56
|
-
"Arduino doesn't allow configuring the BLE connection timeout (fixed at 30s).\n"
|
57
|
-
"ESP-IDF framework allows setting it to 20s to match client timeouts.\n"
|
58
|
-
"\n"
|
59
|
-
"To switch to ESP-IDF, add this to your YAML:\n"
|
60
|
-
" esp32:\n"
|
61
|
-
" framework:\n"
|
62
|
-
" type: esp-idf\n"
|
63
|
-
"\n"
|
64
|
-
"For detailed migration instructions, see:\n"
|
65
|
-
"%s",
|
66
|
-
color(
|
67
|
-
AnsiFore.BLUE, "https://esphome.io/guides/esp32_arduino_to_idf.html"
|
68
|
-
),
|
69
|
-
)
|
45
|
+
esp32_ble.consume_connection_slots(connection_slots, "bluetooth_proxy")(config)
|
70
46
|
|
71
47
|
return {
|
72
48
|
**config,
|
@@ -81,19 +57,17 @@ CONFIG_SCHEMA = cv.All(
|
|
81
57
|
{
|
82
58
|
cv.GenerateID(): cv.declare_id(BluetoothProxy),
|
83
59
|
cv.Optional(CONF_ACTIVE, default=True): cv.boolean,
|
84
|
-
cv.
|
85
|
-
cv.only_with_esp_idf, cv.boolean
|
86
|
-
),
|
60
|
+
cv.Optional(CONF_CACHE_SERVICES, default=True): cv.boolean,
|
87
61
|
cv.Optional(
|
88
62
|
CONF_CONNECTION_SLOTS,
|
89
63
|
default=DEFAULT_CONNECTION_SLOTS,
|
90
64
|
): cv.All(
|
91
65
|
cv.positive_int,
|
92
|
-
cv.Range(min=1, max=
|
66
|
+
cv.Range(min=1, max=esp32_ble.IDF_MAX_CONNECTIONS),
|
93
67
|
),
|
94
68
|
cv.Optional(CONF_CONNECTIONS): cv.All(
|
95
69
|
cv.ensure_list(CONNECTION_SCHEMA),
|
96
|
-
cv.Length(min=1, max=
|
70
|
+
cv.Length(min=1, max=esp32_ble.IDF_MAX_CONNECTIONS),
|
97
71
|
),
|
98
72
|
}
|
99
73
|
)
|
@@ -514,7 +514,8 @@ esp_err_t BluetoothConnection::read_characteristic(uint16_t handle) {
|
|
514
514
|
return this->check_and_log_error_("esp_ble_gattc_read_char", err);
|
515
515
|
}
|
516
516
|
|
517
|
-
esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const
|
517
|
+
esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const uint8_t *data, size_t length,
|
518
|
+
bool response) {
|
518
519
|
if (!this->connected()) {
|
519
520
|
this->log_gatt_not_connected_("write", "characteristic");
|
520
521
|
return ESP_GATT_NOT_CONNECTED;
|
@@ -522,8 +523,11 @@ esp_err_t BluetoothConnection::write_characteristic(uint16_t handle, const std::
|
|
522
523
|
ESP_LOGV(TAG, "[%d] [%s] Writing GATT characteristic handle %d", this->connection_index_, this->address_str_.c_str(),
|
523
524
|
handle);
|
524
525
|
|
526
|
+
// ESP-IDF's API requires a non-const uint8_t* but it doesn't modify the data
|
527
|
+
// The BTC layer immediately copies the data to its own buffer (see btc_gattc.c)
|
528
|
+
// const_cast is safe here and was previously hidden by a C-style cast
|
525
529
|
esp_err_t err =
|
526
|
-
esp_ble_gattc_write_char(this->gattc_if_, this->conn_id_, handle,
|
530
|
+
esp_ble_gattc_write_char(this->gattc_if_, this->conn_id_, handle, length, const_cast<uint8_t *>(data),
|
527
531
|
response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
528
532
|
return this->check_and_log_error_("esp_ble_gattc_write_char", err);
|
529
533
|
}
|
@@ -540,7 +544,7 @@ esp_err_t BluetoothConnection::read_descriptor(uint16_t handle) {
|
|
540
544
|
return this->check_and_log_error_("esp_ble_gattc_read_char_descr", err);
|
541
545
|
}
|
542
546
|
|
543
|
-
esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const
|
547
|
+
esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const uint8_t *data, size_t length, bool response) {
|
544
548
|
if (!this->connected()) {
|
545
549
|
this->log_gatt_not_connected_("write", "descriptor");
|
546
550
|
return ESP_GATT_NOT_CONNECTED;
|
@@ -548,8 +552,11 @@ esp_err_t BluetoothConnection::write_descriptor(uint16_t handle, const std::stri
|
|
548
552
|
ESP_LOGV(TAG, "[%d] [%s] Writing GATT descriptor handle %d", this->connection_index_, this->address_str_.c_str(),
|
549
553
|
handle);
|
550
554
|
|
555
|
+
// ESP-IDF's API requires a non-const uint8_t* but it doesn't modify the data
|
556
|
+
// The BTC layer immediately copies the data to its own buffer (see btc_gattc.c)
|
557
|
+
// const_cast is safe here and was previously hidden by a C-style cast
|
551
558
|
esp_err_t err = esp_ble_gattc_write_char_descr(
|
552
|
-
this->gattc_if_, this->conn_id_, handle,
|
559
|
+
this->gattc_if_, this->conn_id_, handle, length, const_cast<uint8_t *>(data),
|
553
560
|
response ? ESP_GATT_WRITE_TYPE_RSP : ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
554
561
|
return this->check_and_log_error_("esp_ble_gattc_write_char_descr", err);
|
555
562
|
}
|
@@ -18,9 +18,9 @@ class BluetoothConnection final : public esp32_ble_client::BLEClientBase {
|
|
18
18
|
esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override;
|
19
19
|
|
20
20
|
esp_err_t read_characteristic(uint16_t handle);
|
21
|
-
esp_err_t write_characteristic(uint16_t handle, const
|
21
|
+
esp_err_t write_characteristic(uint16_t handle, const uint8_t *data, size_t length, bool response);
|
22
22
|
esp_err_t read_descriptor(uint16_t handle);
|
23
|
-
esp_err_t write_descriptor(uint16_t handle, const
|
23
|
+
esp_err_t write_descriptor(uint16_t handle, const uint8_t *data, size_t length, bool response);
|
24
24
|
|
25
25
|
esp_err_t notify_characteristic(uint16_t handle, bool enable);
|
26
26
|
|
@@ -305,7 +305,7 @@ void BluetoothProxy::bluetooth_gatt_write(const api::BluetoothGATTWriteRequest &
|
|
305
305
|
return;
|
306
306
|
}
|
307
307
|
|
308
|
-
auto err = connection->write_characteristic(msg.handle, msg.data, msg.response);
|
308
|
+
auto err = connection->write_characteristic(msg.handle, msg.data, msg.data_len, msg.response);
|
309
309
|
if (err != ESP_OK) {
|
310
310
|
this->send_gatt_error(msg.address, msg.handle, err);
|
311
311
|
}
|
@@ -331,7 +331,7 @@ void BluetoothProxy::bluetooth_gatt_write_descriptor(const api::BluetoothGATTWri
|
|
331
331
|
return;
|
332
332
|
}
|
333
333
|
|
334
|
-
auto err = connection->write_descriptor(msg.handle, msg.data, true);
|
334
|
+
auto err = connection->write_descriptor(msg.handle, msg.data, msg.data_len, true);
|
335
335
|
if (err != ESP_OK) {
|
336
336
|
this->send_gatt_error(msg.address, msg.handle, err);
|
337
337
|
}
|
@@ -2,7 +2,6 @@ import esphome.codegen as cg
|
|
2
2
|
from esphome.components.esp32 import add_idf_component
|
3
3
|
import esphome.config_validation as cv
|
4
4
|
from esphome.const import CONF_BUFFER_SIZE, CONF_ID, CONF_TYPE
|
5
|
-
from esphome.core import CORE
|
6
5
|
from esphome.types import ConfigType
|
7
6
|
|
8
7
|
CODEOWNERS = ["@DT-art1"]
|
@@ -51,9 +50,8 @@ async def to_code(config: ConfigType) -> None:
|
|
51
50
|
buffer = cg.new_Pvariable(config[CONF_ENCODER_BUFFER_ID])
|
52
51
|
cg.add(buffer.set_buffer_size(config[CONF_BUFFER_SIZE]))
|
53
52
|
if config[CONF_TYPE] == ESP32_CAMERA_ENCODER:
|
54
|
-
|
55
|
-
|
56
|
-
cg.add_build_flag("-DUSE_ESP32_CAMERA_JPEG_ENCODER")
|
53
|
+
add_idf_component(name="espressif/esp32-camera", ref="2.1.1")
|
54
|
+
cg.add_define("USE_ESP32_CAMERA_JPEG_ENCODER")
|
57
55
|
var = cg.new_Pvariable(
|
58
56
|
config[CONF_ID],
|
59
57
|
config[CONF_QUALITY],
|
@@ -1,3 +1,5 @@
|
|
1
|
+
#include "esphome/core/defines.h"
|
2
|
+
|
1
3
|
#ifdef USE_ESP32_CAMERA_JPEG_ENCODER
|
2
4
|
|
3
5
|
#include "esp32_camera_jpeg_encoder.h"
|
@@ -15,7 +17,7 @@ camera::EncoderError ESP32CameraJPEGEncoder::encode_pixels(camera::CameraImageSp
|
|
15
17
|
this->bytes_written_ = 0;
|
16
18
|
this->out_of_output_memory_ = false;
|
17
19
|
bool success = fmt2jpg_cb(pixels->get_data_buffer(), pixels->get_data_length(), spec->width, spec->height,
|
18
|
-
to_internal_(spec->format), this->quality_,
|
20
|
+
to_internal_(spec->format), this->quality_, callback, this);
|
19
21
|
|
20
22
|
if (!success)
|
21
23
|
return camera::ENCODER_ERROR_CONFIGURATION;
|
@@ -49,7 +51,7 @@ void ESP32CameraJPEGEncoder::dump_config() {
|
|
49
51
|
this->output_->get_max_size(), this->quality_, this->buffer_expand_size_);
|
50
52
|
}
|
51
53
|
|
52
|
-
size_t ESP32CameraJPEGEncoder::
|
54
|
+
size_t ESP32CameraJPEGEncoder::callback(void *arg, size_t index, const void *data, size_t len) {
|
53
55
|
ESP32CameraJPEGEncoder *that = reinterpret_cast<ESP32CameraJPEGEncoder *>(arg);
|
54
56
|
uint8_t *buffer = that->output_->get_data();
|
55
57
|
size_t buffer_length = that->output_->get_max_size();
|