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
@@ -9,6 +9,7 @@
|
|
9
9
|
#endif
|
10
10
|
|
11
11
|
#include <functional>
|
12
|
+
#include <span>
|
12
13
|
|
13
14
|
#include "esphome/core/automation.h"
|
14
15
|
#include "esphome/core/component.h"
|
@@ -74,17 +75,21 @@ class GAPScanEventHandler {
|
|
74
75
|
virtual void gap_scan_event_handler(const BLEScanResult &scan_result) = 0;
|
75
76
|
};
|
76
77
|
|
78
|
+
#ifdef USE_ESP32_BLE_CLIENT
|
77
79
|
class GATTcEventHandler {
|
78
80
|
public:
|
79
81
|
virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
80
82
|
esp_ble_gattc_cb_param_t *param) = 0;
|
81
83
|
};
|
84
|
+
#endif
|
82
85
|
|
86
|
+
#ifdef USE_ESP32_BLE_SERVER
|
83
87
|
class GATTsEventHandler {
|
84
88
|
public:
|
85
89
|
virtual void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
|
86
90
|
esp_ble_gatts_cb_param_t *param) = 0;
|
87
91
|
};
|
92
|
+
#endif
|
88
93
|
|
89
94
|
class BLEStatusEventHandler {
|
90
95
|
public:
|
@@ -114,6 +119,7 @@ class ESP32BLE : public Component {
|
|
114
119
|
void advertising_set_service_data(const std::vector<uint8_t> &data);
|
115
120
|
void advertising_set_manufacturer_data(const std::vector<uint8_t> &data);
|
116
121
|
void advertising_set_appearance(uint16_t appearance) { this->appearance_ = appearance; }
|
122
|
+
void advertising_set_service_data_and_name(std::span<const uint8_t> data, bool include_name);
|
117
123
|
void advertising_add_service_uuid(ESPBTUUID uuid);
|
118
124
|
void advertising_remove_service_uuid(ESPBTUUID uuid);
|
119
125
|
void advertising_register_raw_advertisement_callback(std::function<void(bool)> &&callback);
|
@@ -123,16 +129,24 @@ class ESP32BLE : public Component {
|
|
123
129
|
void register_gap_scan_event_handler(GAPScanEventHandler *handler) {
|
124
130
|
this->gap_scan_event_handlers_.push_back(handler);
|
125
131
|
}
|
132
|
+
#ifdef USE_ESP32_BLE_CLIENT
|
126
133
|
void register_gattc_event_handler(GATTcEventHandler *handler) { this->gattc_event_handlers_.push_back(handler); }
|
134
|
+
#endif
|
135
|
+
#ifdef USE_ESP32_BLE_SERVER
|
127
136
|
void register_gatts_event_handler(GATTsEventHandler *handler) { this->gatts_event_handlers_.push_back(handler); }
|
137
|
+
#endif
|
128
138
|
void register_ble_status_event_handler(BLEStatusEventHandler *handler) {
|
129
139
|
this->ble_status_event_handlers_.push_back(handler);
|
130
140
|
}
|
131
141
|
void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; }
|
132
142
|
|
133
143
|
protected:
|
144
|
+
#ifdef USE_ESP32_BLE_SERVER
|
134
145
|
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
|
146
|
+
#endif
|
147
|
+
#ifdef USE_ESP32_BLE_CLIENT
|
135
148
|
static void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
|
149
|
+
#endif
|
136
150
|
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
|
137
151
|
|
138
152
|
bool ble_setup_();
|
@@ -148,8 +162,12 @@ class ESP32BLE : public Component {
|
|
148
162
|
// Vectors (12 bytes each on 32-bit, naturally aligned to 4 bytes)
|
149
163
|
std::vector<GAPEventHandler *> gap_event_handlers_;
|
150
164
|
std::vector<GAPScanEventHandler *> gap_scan_event_handlers_;
|
165
|
+
#ifdef USE_ESP32_BLE_CLIENT
|
151
166
|
std::vector<GATTcEventHandler *> gattc_event_handlers_;
|
167
|
+
#endif
|
168
|
+
#ifdef USE_ESP32_BLE_SERVER
|
152
169
|
std::vector<GATTsEventHandler *> gatts_event_handlers_;
|
170
|
+
#endif
|
153
171
|
std::vector<BLEStatusEventHandler *> ble_status_event_handlers_;
|
154
172
|
|
155
173
|
// Large objects (size depends on template parameters, but typically aligned to 4 bytes)
|
@@ -43,7 +43,7 @@ void BLEAdvertising::remove_service_uuid(ESPBTUUID uuid) {
|
|
43
43
|
this->advertising_uuids_.end());
|
44
44
|
}
|
45
45
|
|
46
|
-
void BLEAdvertising::set_service_data(
|
46
|
+
void BLEAdvertising::set_service_data(std::span<const uint8_t> data) {
|
47
47
|
delete[] this->advertising_data_.p_service_data;
|
48
48
|
this->advertising_data_.p_service_data = nullptr;
|
49
49
|
this->advertising_data_.service_data_len = data.size();
|
@@ -54,6 +54,10 @@ void BLEAdvertising::set_service_data(const std::vector<uint8_t> &data) {
|
|
54
54
|
}
|
55
55
|
}
|
56
56
|
|
57
|
+
void BLEAdvertising::set_service_data(const std::vector<uint8_t> &data) {
|
58
|
+
this->set_service_data(std::span<const uint8_t>(data));
|
59
|
+
}
|
60
|
+
|
57
61
|
void BLEAdvertising::set_manufacturer_data(const std::vector<uint8_t> &data) {
|
58
62
|
delete[] this->advertising_data_.p_manufacturer_data;
|
59
63
|
this->advertising_data_.p_manufacturer_data = nullptr;
|
@@ -84,7 +88,7 @@ esp_err_t BLEAdvertising::services_advertisement_() {
|
|
84
88
|
esp_err_t err;
|
85
89
|
|
86
90
|
this->advertising_data_.set_scan_rsp = false;
|
87
|
-
this->advertising_data_.include_name = !this->scan_response_;
|
91
|
+
this->advertising_data_.include_name = this->include_name_in_adv_ || !this->scan_response_;
|
88
92
|
this->advertising_data_.include_txpower = !this->scan_response_;
|
89
93
|
err = esp_ble_gap_config_adv_data(&this->advertising_data_);
|
90
94
|
if (err != ESP_OK) {
|
@@ -148,7 +152,7 @@ void BLEAdvertising::loop() {
|
|
148
152
|
if (now - this->last_advertisement_time_ > this->advertising_cycle_time_) {
|
149
153
|
this->stop();
|
150
154
|
this->current_adv_index_ += 1;
|
151
|
-
if (this->current_adv_index_ >= this->raw_advertisements_callbacks_.size()) {
|
155
|
+
if (static_cast<size_t>(this->current_adv_index_) >= this->raw_advertisements_callbacks_.size()) {
|
152
156
|
this->current_adv_index_ = -1;
|
153
157
|
}
|
154
158
|
this->start();
|
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
#include <array>
|
6
6
|
#include <functional>
|
7
|
+
#include <span>
|
7
8
|
#include <vector>
|
8
9
|
|
9
10
|
#ifdef USE_ESP32
|
@@ -36,6 +37,8 @@ class BLEAdvertising {
|
|
36
37
|
void set_manufacturer_data(const std::vector<uint8_t> &data);
|
37
38
|
void set_appearance(uint16_t appearance) { this->advertising_data_.appearance = appearance; }
|
38
39
|
void set_service_data(const std::vector<uint8_t> &data);
|
40
|
+
void set_service_data(std::span<const uint8_t> data);
|
41
|
+
void set_include_name(bool include_name) { this->include_name_in_adv_ = include_name; }
|
39
42
|
void register_raw_advertisement_callback(std::function<void(bool)> &&callback);
|
40
43
|
|
41
44
|
void start();
|
@@ -45,6 +48,7 @@ class BLEAdvertising {
|
|
45
48
|
esp_err_t services_advertisement_();
|
46
49
|
|
47
50
|
bool scan_response_;
|
51
|
+
bool include_name_in_adv_{false};
|
48
52
|
esp_ble_adv_data_t advertising_data_;
|
49
53
|
esp_ble_adv_data_t scan_response_data_;
|
50
54
|
esp_ble_adv_params_t advertising_params_;
|
@@ -42,32 +42,18 @@ ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) {
|
|
42
42
|
ESPBTUUID ESPBTUUID::from_raw(const std::string &data) {
|
43
43
|
ESPBTUUID ret;
|
44
44
|
if (data.length() == 4) {
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
uint8_t lsb_shift = i <= 2 ? (2 - i) * 4 : 0;
|
51
|
-
|
52
|
-
if (msb > '9')
|
53
|
-
msb -= 7;
|
54
|
-
if (lsb > '9')
|
55
|
-
lsb -= 7;
|
56
|
-
ret.uuid_.uuid.uuid16 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << lsb_shift;
|
45
|
+
// 16-bit UUID as 4-character hex string
|
46
|
+
auto parsed = parse_hex<uint16_t>(data);
|
47
|
+
if (parsed.has_value()) {
|
48
|
+
ret.uuid_.len = ESP_UUID_LEN_16;
|
49
|
+
ret.uuid_.uuid.uuid16 = parsed.value();
|
57
50
|
}
|
58
51
|
} else if (data.length() == 8) {
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
uint8_t lsb_shift = i <= 6 ? (6 - i) * 4 : 0;
|
65
|
-
|
66
|
-
if (msb > '9')
|
67
|
-
msb -= 7;
|
68
|
-
if (lsb > '9')
|
69
|
-
lsb -= 7;
|
70
|
-
ret.uuid_.uuid.uuid32 += (((msb & 0x0F) << 4) | (lsb & 0x0F)) << lsb_shift;
|
52
|
+
// 32-bit UUID as 8-character hex string
|
53
|
+
auto parsed = parse_hex<uint32_t>(data);
|
54
|
+
if (parsed.has_value()) {
|
55
|
+
ret.uuid_.len = ESP_UUID_LEN_32;
|
56
|
+
ret.uuid_.uuid.uuid32 = parsed.value();
|
71
57
|
}
|
72
58
|
} else if (data.length() == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be
|
73
59
|
// investigated (lack of time)
|
@@ -145,28 +131,16 @@ bool ESPBTUUID::operator==(const ESPBTUUID &uuid) const {
|
|
145
131
|
if (this->uuid_.len == uuid.uuid_.len) {
|
146
132
|
switch (this->uuid_.len) {
|
147
133
|
case ESP_UUID_LEN_16:
|
148
|
-
|
149
|
-
return true;
|
150
|
-
}
|
151
|
-
break;
|
134
|
+
return this->uuid_.uuid.uuid16 == uuid.uuid_.uuid.uuid16;
|
152
135
|
case ESP_UUID_LEN_32:
|
153
|
-
|
154
|
-
return true;
|
155
|
-
}
|
156
|
-
break;
|
136
|
+
return this->uuid_.uuid.uuid32 == uuid.uuid_.uuid.uuid32;
|
157
137
|
case ESP_UUID_LEN_128:
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
}
|
162
|
-
}
|
163
|
-
return true;
|
164
|
-
break;
|
138
|
+
return memcmp(this->uuid_.uuid.uuid128, uuid.uuid_.uuid.uuid128, ESP_UUID_LEN_128) == 0;
|
139
|
+
default:
|
140
|
+
return false;
|
165
141
|
}
|
166
|
-
} else {
|
167
|
-
return this->as_128bit() == uuid.as_128bit();
|
168
142
|
}
|
169
|
-
return
|
143
|
+
return this->as_128bit() == uuid.as_128bit();
|
170
144
|
}
|
171
145
|
esp_bt_uuid_t ESPBTUUID::get_uuid() const { return this->uuid_; }
|
172
146
|
std::string ESPBTUUID::to_string() const {
|
@@ -4,7 +4,7 @@ from esphome.components.esp32 import add_idf_sdkconfig_option
|
|
4
4
|
from esphome.components.esp32_ble import CONF_BLE_ID
|
5
5
|
import esphome.config_validation as cv
|
6
6
|
from esphome.const import CONF_ID, CONF_TX_POWER, CONF_TYPE, CONF_UUID
|
7
|
-
from esphome.core import
|
7
|
+
from esphome.core import TimePeriod
|
8
8
|
|
9
9
|
AUTO_LOAD = ["esp32_ble"]
|
10
10
|
DEPENDENCIES = ["esp32"]
|
@@ -86,6 +86,5 @@ async def to_code(config):
|
|
86
86
|
|
87
87
|
cg.add_define("USE_ESP32_BLE_ADVERTISING")
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
|
89
|
+
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
90
|
+
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
|
@@ -43,13 +43,6 @@ void BLEClientBase::setup() {
|
|
43
43
|
void BLEClientBase::set_state(espbt::ClientState st) {
|
44
44
|
ESP_LOGV(TAG, "[%d] [%s] Set state %d", this->connection_index_, this->address_str_.c_str(), (int) st);
|
45
45
|
ESPBTClient::set_state(st);
|
46
|
-
|
47
|
-
if (st == espbt::ClientState::READY_TO_CONNECT) {
|
48
|
-
// Enable loop for state processing
|
49
|
-
this->enable_loop();
|
50
|
-
// Connect immediately instead of waiting for next loop
|
51
|
-
this->connect();
|
52
|
-
}
|
53
46
|
}
|
54
47
|
|
55
48
|
void BLEClientBase::loop() {
|
@@ -65,8 +58,8 @@ void BLEClientBase::loop() {
|
|
65
58
|
}
|
66
59
|
this->set_state(espbt::ClientState::IDLE);
|
67
60
|
}
|
68
|
-
// If
|
69
|
-
// will enable it again when
|
61
|
+
// If idle, we can disable the loop as connect()
|
62
|
+
// will enable it again when a connection is needed.
|
70
63
|
else if (this->state_ == espbt::ClientState::IDLE) {
|
71
64
|
this->disable_loop();
|
72
65
|
}
|
@@ -108,9 +101,20 @@ bool BLEClientBase::parse_device(const espbt::ESPBTDevice &device) {
|
|
108
101
|
#endif
|
109
102
|
|
110
103
|
void BLEClientBase::connect() {
|
104
|
+
// Prevent duplicate connection attempts
|
105
|
+
if (this->state_ == espbt::ClientState::CONNECTING || this->state_ == espbt::ClientState::CONNECTED ||
|
106
|
+
this->state_ == espbt::ClientState::ESTABLISHED) {
|
107
|
+
ESP_LOGW(TAG, "[%d] [%s] Connection already in progress, state=%s", this->connection_index_,
|
108
|
+
this->address_str_.c_str(), espbt::client_state_to_string(this->state_));
|
109
|
+
return;
|
110
|
+
}
|
111
111
|
ESP_LOGI(TAG, "[%d] [%s] 0x%02x Connecting", this->connection_index_, this->address_str_.c_str(),
|
112
112
|
this->remote_addr_type_);
|
113
113
|
this->paired_ = false;
|
114
|
+
// Enable loop for state processing
|
115
|
+
this->enable_loop();
|
116
|
+
// Immediately transition to CONNECTING to prevent duplicate connection attempts
|
117
|
+
this->set_state(espbt::ClientState::CONNECTING);
|
114
118
|
|
115
119
|
// Determine connection parameters based on connection type
|
116
120
|
if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) {
|
@@ -168,7 +172,7 @@ void BLEClientBase::unconditional_disconnect() {
|
|
168
172
|
this->log_gattc_warning_("esp_ble_gattc_close", err);
|
169
173
|
}
|
170
174
|
|
171
|
-
if (this->state_ == espbt::ClientState::
|
175
|
+
if (this->state_ == espbt::ClientState::DISCOVERED) {
|
172
176
|
this->set_address(0);
|
173
177
|
this->set_state(espbt::ClientState::IDLE);
|
174
178
|
} else {
|
@@ -212,8 +216,6 @@ void BLEClientBase::handle_connection_result_(esp_err_t ret) {
|
|
212
216
|
if (ret) {
|
213
217
|
this->log_gattc_warning_("esp_ble_gattc_open", ret);
|
214
218
|
this->set_state(espbt::ClientState::IDLE);
|
215
|
-
} else {
|
216
|
-
this->set_state(espbt::ClientState::CONNECTING);
|
217
219
|
}
|
218
220
|
}
|
219
221
|
|
@@ -26,7 +26,7 @@ from esphome.const import (
|
|
26
26
|
from esphome.core import CORE
|
27
27
|
from esphome.schema_extractors import SCHEMA_EXTRACT
|
28
28
|
|
29
|
-
AUTO_LOAD = ["esp32_ble", "bytebuffer"
|
29
|
+
AUTO_LOAD = ["esp32_ble", "bytebuffer"]
|
30
30
|
CODEOWNERS = ["@jesserockz", "@clydebarrow", "@Rapsssito"]
|
31
31
|
DEPENDENCIES = ["esp32"]
|
32
32
|
DOMAIN = "esp32_ble_server"
|
@@ -488,6 +488,7 @@ async def to_code_descriptor(descriptor_conf, char_var):
|
|
488
488
|
cg.add(desc_var.set_value(value))
|
489
489
|
if CONF_ON_WRITE in descriptor_conf:
|
490
490
|
on_write_conf = descriptor_conf[CONF_ON_WRITE]
|
491
|
+
cg.add_define("USE_ESP32_BLE_SERVER_DESCRIPTOR_ON_WRITE")
|
491
492
|
await automation.build_automation(
|
492
493
|
BLETriggers_ns.create_descriptor_on_write_trigger(desc_var),
|
493
494
|
[(cg.std_vector.template(cg.uint8), "x"), (cg.uint16, "id")],
|
@@ -505,23 +506,32 @@ async def to_code_characteristic(service_var, char_conf):
|
|
505
506
|
)
|
506
507
|
if CONF_ON_WRITE in char_conf:
|
507
508
|
on_write_conf = char_conf[CONF_ON_WRITE]
|
509
|
+
cg.add_define("USE_ESP32_BLE_SERVER_CHARACTERISTIC_ON_WRITE")
|
508
510
|
await automation.build_automation(
|
509
511
|
BLETriggers_ns.create_characteristic_on_write_trigger(char_var),
|
510
512
|
[(cg.std_vector.template(cg.uint8), "x"), (cg.uint16, "id")],
|
511
513
|
on_write_conf,
|
512
514
|
)
|
513
515
|
if CONF_VALUE in char_conf:
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
516
|
+
# Check if the value is templated (Lambda)
|
517
|
+
value_data = char_conf[CONF_VALUE][CONF_DATA]
|
518
|
+
if isinstance(value_data, cv.Lambda):
|
519
|
+
# Templated value - need the full action infrastructure
|
520
|
+
action_conf = {
|
521
|
+
CONF_ID: char_conf[CONF_ID],
|
522
|
+
CONF_VALUE: char_conf[CONF_VALUE],
|
523
|
+
}
|
524
|
+
value_action = await ble_server_characteristic_set_value(
|
525
|
+
action_conf,
|
526
|
+
char_conf[CONF_CHAR_VALUE_ACTION_ID_],
|
527
|
+
cg.TemplateArguments(),
|
528
|
+
{},
|
529
|
+
)
|
530
|
+
cg.add(value_action.play())
|
531
|
+
else:
|
532
|
+
# Static value - just set it directly without action infrastructure
|
533
|
+
value = await parse_value(char_conf[CONF_VALUE], {})
|
534
|
+
cg.add(char_var.set_value(value))
|
525
535
|
for descriptor_conf in char_conf[CONF_DESCRIPTORS]:
|
526
536
|
await to_code_descriptor(descriptor_conf, char_var)
|
527
537
|
|
@@ -560,12 +570,14 @@ async def to_code(config):
|
|
560
570
|
else:
|
561
571
|
cg.add(var.enqueue_start_service(service_var))
|
562
572
|
if CONF_ON_CONNECT in config:
|
573
|
+
cg.add_define("USE_ESP32_BLE_SERVER_ON_CONNECT")
|
563
574
|
await automation.build_automation(
|
564
575
|
BLETriggers_ns.create_server_on_connect_trigger(var),
|
565
576
|
[(cg.uint16, "id")],
|
566
577
|
config[CONF_ON_CONNECT],
|
567
578
|
)
|
568
579
|
if CONF_ON_DISCONNECT in config:
|
580
|
+
cg.add_define("USE_ESP32_BLE_SERVER_ON_DISCONNECT")
|
569
581
|
await automation.build_automation(
|
570
582
|
BLETriggers_ns.create_server_on_disconnect_trigger(var),
|
571
583
|
[(cg.uint16, "id")],
|
@@ -573,8 +585,7 @@ async def to_code(config):
|
|
573
585
|
)
|
574
586
|
cg.add_define("USE_ESP32_BLE_SERVER")
|
575
587
|
cg.add_define("USE_ESP32_BLE_ADVERTISING")
|
576
|
-
|
577
|
-
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
588
|
+
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
578
589
|
|
579
590
|
|
580
591
|
@automation.register_action(
|
@@ -595,6 +606,7 @@ async def ble_server_characteristic_set_value(config, action_id, template_arg, a
|
|
595
606
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
596
607
|
value = await parse_value(config[CONF_VALUE], args)
|
597
608
|
cg.add(var.set_buffer(value))
|
609
|
+
cg.add_define("USE_ESP32_BLE_SERVER_SET_VALUE_ACTION")
|
598
610
|
return var
|
599
611
|
|
600
612
|
|
@@ -613,6 +625,7 @@ async def ble_server_descriptor_set_value(config, action_id, template_arg, args)
|
|
613
625
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
614
626
|
value = await parse_value(config[CONF_VALUE], args)
|
615
627
|
cg.add(var.set_buffer(value))
|
628
|
+
cg.add_define("USE_ESP32_BLE_SERVER_DESCRIPTOR_SET_VALUE_ACTION")
|
616
629
|
return var
|
617
630
|
|
618
631
|
|
@@ -630,4 +643,5 @@ async def ble_server_descriptor_set_value(config, action_id, template_arg, args)
|
|
630
643
|
)
|
631
644
|
async def ble_server_characteristic_notify(config, action_id, template_arg, args):
|
632
645
|
paren = await cg.get_variable(config[CONF_ID])
|
646
|
+
cg.add_define("USE_ESP32_BLE_SERVER_NOTIFY_ACTION")
|
633
647
|
return cg.new_Pvariable(action_id, template_arg, paren)
|
@@ -49,13 +49,17 @@ void BLECharacteristic::notify() {
|
|
49
49
|
this->service_->get_server()->get_connected_client_count() == 0)
|
50
50
|
return;
|
51
51
|
|
52
|
-
|
52
|
+
const uint16_t *clients = this->service_->get_server()->get_clients();
|
53
|
+
uint8_t client_count = this->service_->get_server()->get_client_count();
|
54
|
+
|
55
|
+
for (uint8_t i = 0; i < client_count; i++) {
|
56
|
+
uint16_t client = clients[i];
|
53
57
|
size_t length = this->value_.size();
|
54
|
-
//
|
55
|
-
|
58
|
+
// Find the client in the list of clients to notify
|
59
|
+
auto *entry = this->find_client_in_notify_list_(client);
|
60
|
+
if (entry == nullptr)
|
56
61
|
continue;
|
57
|
-
|
58
|
-
bool require_ack = this->clients_to_notify_[client];
|
62
|
+
bool require_ack = entry->indicate;
|
59
63
|
// TODO: Remove this block when INDICATE acknowledgment is supported
|
60
64
|
if (require_ack) {
|
61
65
|
ESP_LOGW(TAG, "INDICATE acknowledgment is not yet supported (i.e. it works as a NOTIFY)");
|
@@ -73,16 +77,17 @@ void BLECharacteristic::notify() {
|
|
73
77
|
void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) {
|
74
78
|
// If the descriptor is the CCCD descriptor, listen to its write event to know if the client wants to be notified
|
75
79
|
if (descriptor->get_uuid() == ESPBTUUID::from_uint16(ESP_GATT_UUID_CHAR_CLIENT_CONFIG)) {
|
76
|
-
descriptor->
|
80
|
+
descriptor->on_write([this](std::span<const uint8_t> value, uint16_t conn_id) {
|
77
81
|
if (value.size() != 2)
|
78
82
|
return;
|
79
83
|
uint16_t cccd = encode_uint16(value[1], value[0]);
|
80
84
|
bool notify = (cccd & 1) != 0;
|
81
85
|
bool indicate = (cccd & 2) != 0;
|
86
|
+
// Remove existing entry if present
|
87
|
+
this->remove_client_from_notify_list_(conn_id);
|
88
|
+
// Add new entry if needed
|
82
89
|
if (notify || indicate) {
|
83
|
-
this->clients_to_notify_
|
84
|
-
} else {
|
85
|
-
this->clients_to_notify_.erase(conn_id);
|
90
|
+
this->clients_to_notify_.push_back({conn_id, indicate});
|
86
91
|
}
|
87
92
|
});
|
88
93
|
}
|
@@ -120,69 +125,49 @@ bool BLECharacteristic::is_created() {
|
|
120
125
|
if (this->state_ != CREATING_DEPENDENTS)
|
121
126
|
return false;
|
122
127
|
|
123
|
-
bool created = true;
|
124
128
|
for (auto *descriptor : this->descriptors_) {
|
125
|
-
|
129
|
+
if (!descriptor->is_created())
|
130
|
+
return false;
|
126
131
|
}
|
127
|
-
if
|
128
|
-
|
129
|
-
return
|
132
|
+
// All descriptors are created if we reach here
|
133
|
+
this->state_ = CREATED;
|
134
|
+
return true;
|
130
135
|
}
|
131
136
|
|
132
137
|
bool BLECharacteristic::is_failed() {
|
133
138
|
if (this->state_ == FAILED)
|
134
139
|
return true;
|
135
140
|
|
136
|
-
bool failed = false;
|
137
141
|
for (auto *descriptor : this->descriptors_) {
|
138
|
-
|
142
|
+
if (descriptor->is_failed()) {
|
143
|
+
this->state_ = FAILED;
|
144
|
+
return true;
|
145
|
+
}
|
139
146
|
}
|
140
|
-
|
141
|
-
this->state_ = FAILED;
|
142
|
-
return this->state_ == FAILED;
|
147
|
+
return false;
|
143
148
|
}
|
144
149
|
|
145
|
-
void BLECharacteristic::
|
150
|
+
void BLECharacteristic::set_property_bit_(esp_gatt_char_prop_t bit, bool value) {
|
146
151
|
if (value) {
|
147
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ |
|
152
|
+
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ | bit);
|
148
153
|
} else {
|
149
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ & ~
|
154
|
+
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ & ~bit);
|
150
155
|
}
|
151
156
|
}
|
157
|
+
|
158
|
+
void BLECharacteristic::set_broadcast_property(bool value) {
|
159
|
+
this->set_property_bit_(ESP_GATT_CHAR_PROP_BIT_BROADCAST, value);
|
160
|
+
}
|
152
161
|
void BLECharacteristic::set_indicate_property(bool value) {
|
153
|
-
|
154
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ | ESP_GATT_CHAR_PROP_BIT_INDICATE);
|
155
|
-
} else {
|
156
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ & ~ESP_GATT_CHAR_PROP_BIT_INDICATE);
|
157
|
-
}
|
162
|
+
this->set_property_bit_(ESP_GATT_CHAR_PROP_BIT_INDICATE, value);
|
158
163
|
}
|
159
164
|
void BLECharacteristic::set_notify_property(bool value) {
|
160
|
-
|
161
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ | ESP_GATT_CHAR_PROP_BIT_NOTIFY);
|
162
|
-
} else {
|
163
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ & ~ESP_GATT_CHAR_PROP_BIT_NOTIFY);
|
164
|
-
}
|
165
|
-
}
|
166
|
-
void BLECharacteristic::set_read_property(bool value) {
|
167
|
-
if (value) {
|
168
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ | ESP_GATT_CHAR_PROP_BIT_READ);
|
169
|
-
} else {
|
170
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ & ~ESP_GATT_CHAR_PROP_BIT_READ);
|
171
|
-
}
|
172
|
-
}
|
173
|
-
void BLECharacteristic::set_write_property(bool value) {
|
174
|
-
if (value) {
|
175
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ | ESP_GATT_CHAR_PROP_BIT_WRITE);
|
176
|
-
} else {
|
177
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ & ~ESP_GATT_CHAR_PROP_BIT_WRITE);
|
178
|
-
}
|
165
|
+
this->set_property_bit_(ESP_GATT_CHAR_PROP_BIT_NOTIFY, value);
|
179
166
|
}
|
167
|
+
void BLECharacteristic::set_read_property(bool value) { this->set_property_bit_(ESP_GATT_CHAR_PROP_BIT_READ, value); }
|
168
|
+
void BLECharacteristic::set_write_property(bool value) { this->set_property_bit_(ESP_GATT_CHAR_PROP_BIT_WRITE, value); }
|
180
169
|
void BLECharacteristic::set_write_no_response_property(bool value) {
|
181
|
-
|
182
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ | ESP_GATT_CHAR_PROP_BIT_WRITE_NR);
|
183
|
-
} else {
|
184
|
-
this->properties_ = (esp_gatt_char_prop_t) (this->properties_ & ~ESP_GATT_CHAR_PROP_BIT_WRITE_NR);
|
185
|
-
}
|
170
|
+
this->set_property_bit_(ESP_GATT_CHAR_PROP_BIT_WRITE_NR, value);
|
186
171
|
}
|
187
172
|
|
188
173
|
void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
|
@@ -207,8 +192,9 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
|
|
207
192
|
if (!param->read.need_rsp)
|
208
193
|
break; // For some reason you can request a read but not want a response
|
209
194
|
|
210
|
-
this->
|
211
|
-
|
195
|
+
if (this->on_read_callback_) {
|
196
|
+
(*this->on_read_callback_)(param->read.conn_id);
|
197
|
+
}
|
212
198
|
|
213
199
|
uint16_t max_offset = 22;
|
214
200
|
|
@@ -276,8 +262,9 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
|
|
276
262
|
}
|
277
263
|
|
278
264
|
if (!param->write.is_prep) {
|
279
|
-
this->
|
280
|
-
|
265
|
+
if (this->on_write_callback_) {
|
266
|
+
(*this->on_write_callback_)(this->value_, param->write.conn_id);
|
267
|
+
}
|
281
268
|
}
|
282
269
|
|
283
270
|
break;
|
@@ -288,8 +275,9 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
|
|
288
275
|
break;
|
289
276
|
this->write_event_ = false;
|
290
277
|
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
|
291
|
-
this->
|
292
|
-
|
278
|
+
if (this->on_write_callback_) {
|
279
|
+
(*this->on_write_callback_)(this->value_, param->exec_write.conn_id);
|
280
|
+
}
|
293
281
|
}
|
294
282
|
esp_err_t err =
|
295
283
|
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, nullptr);
|
@@ -307,6 +295,28 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
|
|
307
295
|
}
|
308
296
|
}
|
309
297
|
|
298
|
+
void BLECharacteristic::remove_client_from_notify_list_(uint16_t conn_id) {
|
299
|
+
// Since we typically have very few clients (often just 1), we can optimize
|
300
|
+
// for the common case by swapping with the last element and popping
|
301
|
+
for (size_t i = 0; i < this->clients_to_notify_.size(); i++) {
|
302
|
+
if (this->clients_to_notify_[i].conn_id == conn_id) {
|
303
|
+
// Swap with last element and pop (safe even when i is the last element)
|
304
|
+
this->clients_to_notify_[i] = this->clients_to_notify_.back();
|
305
|
+
this->clients_to_notify_.pop_back();
|
306
|
+
return;
|
307
|
+
}
|
308
|
+
}
|
309
|
+
}
|
310
|
+
|
311
|
+
BLECharacteristic::ClientNotificationEntry *BLECharacteristic::find_client_in_notify_list_(uint16_t conn_id) {
|
312
|
+
for (auto &entry : this->clients_to_notify_) {
|
313
|
+
if (entry.conn_id == conn_id) {
|
314
|
+
return &entry;
|
315
|
+
}
|
316
|
+
}
|
317
|
+
return nullptr;
|
318
|
+
}
|
319
|
+
|
310
320
|
} // namespace esp32_ble_server
|
311
321
|
} // namespace esphome
|
312
322
|
|