esphome 2025.7.4__py3-none-any.whl → 2025.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +190 -83
- esphome/automation.py +2 -4
- esphome/build_gen/__init__.py +0 -0
- esphome/build_gen/platformio.py +102 -0
- esphome/components/a4988/a4988.cpp +0 -1
- esphome/components/absolute_humidity/absolute_humidity.cpp +0 -2
- esphome/components/absolute_humidity/sensor.py +2 -2
- esphome/components/adc/__init__.py +123 -85
- esphome/components/adc/adc_sensor.h +98 -35
- esphome/components/adc/adc_sensor_common.cpp +10 -4
- esphome/components/adc/adc_sensor_esp32.cpp +291 -123
- esphome/components/adc/adc_sensor_esp8266.cpp +1 -4
- esphome/components/adc/adc_sensor_libretiny.cpp +1 -2
- esphome/components/adc/adc_sensor_rp2040.cpp +1 -2
- esphome/components/adc/adc_sensor_zephyr.cpp +207 -0
- esphome/components/adc/sensor.py +61 -27
- esphome/components/adc128s102/adc128s102.cpp +1 -4
- esphome/components/ade7880/sensor.py +75 -49
- esphome/components/ads1115/ads1115.cpp +0 -1
- esphome/components/ads1118/ads1118.cpp +0 -1
- esphome/components/ags10/ags10.cpp +0 -4
- esphome/components/aht10/aht10.cpp +0 -4
- esphome/components/aic3204/aic3204.cpp +0 -2
- esphome/components/airthings_wave_plus/__init__.py +1 -1
- esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +22 -4
- esphome/components/airthings_wave_plus/airthings_wave_plus.h +10 -1
- esphome/components/airthings_wave_plus/sensor.py +55 -28
- esphome/components/alarm_control_panel/__init__.py +4 -9
- esphome/components/am2315c/am2315c.cpp +0 -2
- esphome/components/am2320/am2320.cpp +0 -1
- esphome/components/animation/__init__.py +14 -11
- esphome/components/apds9306/apds9306.cpp +0 -4
- esphome/components/apds9960/apds9960.cpp +0 -1
- esphome/components/api/__init__.py +29 -4
- esphome/components/api/api_connection.cpp +378 -401
- esphome/components/api/api_connection.h +112 -56
- esphome/components/api/api_frame_helper.cpp +69 -896
- esphome/components/api/api_frame_helper.h +31 -126
- esphome/components/api/api_frame_helper_noise.cpp +583 -0
- esphome/components/api/api_frame_helper_noise.h +68 -0
- esphome/components/api/api_frame_helper_plaintext.cpp +290 -0
- esphome/components/api/api_frame_helper_plaintext.h +53 -0
- esphome/components/api/api_noise_context.h +2 -4
- esphome/components/api/api_pb2.cpp +1601 -1808
- esphome/components/api/api_pb2.h +367 -323
- esphome/components/api/api_pb2_dump.cpp +1137 -3466
- esphome/components/api/api_pb2_includes.h +34 -0
- esphome/components/api/api_pb2_service.cpp +94 -105
- esphome/components/api/api_pb2_service.h +27 -16
- esphome/components/api/api_server.cpp +18 -17
- esphome/components/api/api_server.h +8 -5
- esphome/components/api/client.py +16 -8
- esphome/components/api/custom_api_device.h +68 -14
- esphome/components/api/homeassistant_service.h +24 -19
- esphome/components/api/list_entities.cpp +3 -5
- esphome/components/api/list_entities.h +2 -4
- esphome/components/api/proto.cpp +3 -5
- esphome/components/api/proto.h +239 -274
- esphome/components/api/subscribe_state.cpp +2 -4
- esphome/components/api/subscribe_state.h +2 -4
- esphome/components/api/user_services.cpp +2 -4
- esphome/components/api/user_services.h +8 -8
- esphome/components/as3935/as3935.cpp +0 -2
- esphome/components/as3935_spi/as3935_spi.cpp +0 -2
- esphome/components/as5600/__init__.py +1 -1
- esphome/components/as5600/as5600.cpp +0 -2
- esphome/components/as5600/sensor/__init__.py +0 -1
- esphome/components/as7341/as7341.cpp +0 -1
- esphome/components/async_tcp/__init__.py +1 -1
- esphome/components/at581x/at581x.cpp +1 -1
- esphome/components/atm90e26/atm90e26.cpp +0 -1
- esphome/components/atm90e32/atm90e32.cpp +475 -116
- esphome/components/atm90e32/atm90e32.h +43 -5
- esphome/components/audio/audio.h +2 -2
- esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +0 -2
- esphome/components/beken_spi_led_strip/led_strip.cpp +0 -2
- esphome/components/bh1750/bh1750.cpp +0 -1
- esphome/components/binary_sensor/__init__.py +14 -12
- esphome/components/ble_client/__init__.py +4 -7
- esphome/components/bluetooth_proxy/__init__.py +40 -3
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +392 -81
- esphome/components/bluetooth_proxy/bluetooth_connection.h +16 -5
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +102 -311
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +30 -14
- esphome/components/bme280_base/bme280_base.cpp +15 -16
- esphome/components/bme680/bme680.cpp +2 -3
- esphome/components/bme680_bsec/bme680_bsec.cpp +0 -2
- esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +0 -2
- esphome/components/bmi160/bmi160.cpp +0 -1
- esphome/components/bmp085/bmp085.cpp +0 -1
- esphome/components/bmp280_base/bmp280_base.cpp +13 -14
- esphome/components/bmp3xx_base/bmp3xx_base.cpp +0 -1
- esphome/components/bmp581/bmp581.cpp +0 -2
- esphome/components/bp1658cj/bp1658cj.cpp +0 -1
- esphome/components/bp5758d/bp5758d.cpp +0 -1
- esphome/components/button/__init__.py +0 -1
- esphome/components/canbus/__init__.py +2 -3
- esphome/components/canbus/canbus.cpp +0 -1
- esphome/components/cap1188/cap1188.cpp +0 -2
- esphome/components/captive_portal/__init__.py +1 -1
- esphome/components/cd74hc4067/cd74hc4067.cpp +0 -2
- esphome/components/ch422g/ch422g.cpp +0 -1
- esphome/components/chsc6x/chsc6x_touchscreen.cpp +0 -3
- esphome/components/climate/__init__.py +0 -1
- esphome/components/climate/climate_traits.h +24 -0
- esphome/components/cm1106/cm1106.cpp +0 -1
- esphome/components/const/__init__.py +6 -0
- esphome/components/cover/__init__.py +0 -1
- esphome/components/cover/cover.cpp +9 -13
- esphome/components/cs5460a/cs5460a.cpp +0 -2
- esphome/components/cse7761/cse7761.cpp +0 -1
- esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +0 -2
- esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +0 -2
- esphome/components/dac7678/dac7678_output.cpp +0 -2
- esphome/components/dallas_temp/dallas_temp.cpp +0 -1
- esphome/components/datetime/__init__.py +0 -2
- esphome/components/debug/__init__.py +15 -1
- esphome/components/debug/debug_zephyr.cpp +281 -0
- esphome/components/debug/sensor.py +2 -1
- esphome/components/deep_sleep/deep_sleep_component.cpp +0 -1
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +20 -1
- esphome/components/dfrobot_sen0395/__init__.py +1 -2
- esphome/components/dht/dht.cpp +0 -1
- esphome/components/dht12/dht12.cpp +0 -1
- esphome/components/display/__init__.py +16 -3
- esphome/components/display_menu_base/__init__.py +1 -1
- esphome/components/dps310/dps310.cpp +0 -2
- esphome/components/ds1307/ds1307.cpp +0 -1
- esphome/components/ds2484/ds2484.cpp +0 -1
- esphome/components/duty_cycle/duty_cycle_sensor.cpp +0 -1
- esphome/components/ee895/ee895.cpp +0 -1
- esphome/components/ektf2232/touchscreen/ektf2232.cpp +0 -1
- esphome/components/emc2101/emc2101.cpp +0 -2
- esphome/components/ens160_base/ens160_base.cpp +0 -2
- esphome/components/ens210/ens210.cpp +0 -1
- esphome/components/es7210/es7210.cpp +0 -2
- esphome/components/es7243e/es7243e.cpp +0 -2
- esphome/components/es8156/es8156.cpp +0 -2
- esphome/components/es8311/es8311.cpp +0 -2
- esphome/components/es8388/es8388.cpp +0 -2
- esphome/components/esp32/__init__.py +203 -60
- esphome/components/esp32/boards.py +17 -0
- esphome/components/esp32/gpio.cpp +0 -1
- esphome/components/esp32/gpio.py +1 -2
- esphome/components/esp32/gpio_esp32_h2.py +2 -7
- esphome/components/esp32/gpio_esp32_p4.py +2 -7
- esphome/components/esp32/post_build.py.script +112 -61
- esphome/components/esp32_ble/__init__.py +41 -2
- esphome/components/esp32_ble/ble.cpp +14 -10
- esphome/components/esp32_ble/ble.h +18 -18
- esphome/components/esp32_ble/ble_advertising.cpp +5 -5
- esphome/components/esp32_ble/ble_advertising.h +7 -5
- esphome/components/esp32_ble/ble_event.h +139 -73
- esphome/components/esp32_ble/ble_scan_result.h +2 -4
- esphome/components/esp32_ble/ble_uuid.cpp +5 -5
- esphome/components/esp32_ble/ble_uuid.h +6 -5
- esphome/components/esp32_ble_beacon/__init__.py +4 -0
- esphome/components/esp32_ble_client/__init__.py +1 -1
- esphome/components/esp32_ble_client/ble_characteristic.cpp +4 -4
- esphome/components/esp32_ble_client/ble_characteristic.h +6 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +155 -104
- esphome/components/esp32_ble_client/ble_client_base.h +17 -6
- esphome/components/esp32_ble_client/ble_descriptor.h +6 -4
- esphome/components/esp32_ble_client/ble_service.cpp +4 -4
- esphome/components/esp32_ble_client/ble_service.h +6 -4
- esphome/components/esp32_ble_server/__init__.py +15 -12
- esphome/components/esp32_ble_tracker/__init__.py +79 -11
- esphome/components/esp32_ble_tracker/automation.h +4 -4
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +264 -261
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +103 -37
- esphome/components/esp32_camera/__init__.py +13 -1
- esphome/components/esp32_camera/esp32_camera.cpp +7 -2
- esphome/components/esp32_camera/esp32_camera.h +1 -0
- esphome/components/esp32_dac/esp32_dac.cpp +3 -19
- esphome/components/esp32_dac/esp32_dac.h +4 -8
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -6
- esphome/components/esp32_rmt_led_strip/light.py +1 -1
- esphome/components/esp32_touch/__init__.py +2 -3
- esphome/components/esp32_touch/esp32_touch.h +9 -6
- esphome/components/esp32_touch/esp32_touch_common.cpp +2 -0
- esphome/components/esp32_touch/esp32_touch_v1.cpp +7 -9
- esphome/components/esp32_touch/esp32_touch_v2.cpp +10 -6
- esphome/components/esp8266/__init__.py +3 -1
- esphome/components/esp8266_pwm/esp8266_pwm.cpp +0 -1
- esphome/components/esphome/ota/__init__.py +1 -2
- esphome/components/esphome/ota/ota_esphome.cpp +150 -77
- esphome/components/esphome/ota/ota_esphome.h +8 -1
- esphome/components/espnow/__init__.py +309 -0
- esphome/components/espnow/automation.h +175 -0
- esphome/components/espnow/espnow_component.cpp +468 -0
- esphome/components/espnow/espnow_component.h +183 -0
- esphome/components/espnow/espnow_err.h +19 -0
- esphome/components/espnow/espnow_packet.h +166 -0
- esphome/components/ethernet/__init__.py +7 -1
- esphome/components/ethernet/esp_eth_phy_jl1101.c +5 -0
- esphome/components/ethernet/ethernet_component.cpp +0 -1
- esphome/components/ethernet/ethernet_component.h +4 -0
- esphome/components/ethernet_info/ethernet_info_text_sensor.h +0 -3
- esphome/components/event/__init__.py +0 -1
- esphome/components/factory_reset/__init__.py +92 -0
- esphome/components/factory_reset/factory_reset.cpp +76 -0
- esphome/components/factory_reset/factory_reset.h +43 -0
- esphome/components/fan/__init__.py +0 -1
- esphome/components/fan/fan_traits.h +16 -0
- esphome/components/fastled_base/fastled_light.cpp +0 -1
- esphome/components/fastled_spi/light.py +1 -3
- esphome/components/fingerprint_grow/fingerprint_grow.cpp +0 -2
- esphome/components/font/__init__.py +9 -1
- esphome/components/fs3000/fs3000.cpp +0 -2
- esphome/components/ft5x06/touchscreen/ft5x06_touchscreen.cpp +0 -2
- esphome/components/ft63x6/ft63x6.cpp +0 -1
- esphome/components/gdk101/gdk101.cpp +0 -1
- esphome/components/gl_r01_i2c/gl_r01_i2c.cpp +0 -1
- esphome/components/gl_r01_i2c/sensor.py +1 -1
- esphome/components/gpio/one_wire/gpio_one_wire.cpp +0 -1
- esphome/components/gpio/switch/gpio_switch.cpp +0 -2
- esphome/components/gpio_expander/cached_gpio.h +24 -15
- esphome/components/gps/__init__.py +6 -2
- esphome/components/gps/gps.cpp +50 -49
- esphome/components/gps/gps.h +4 -8
- esphome/components/gps/time/gps_time.cpp +3 -9
- esphome/components/gps/time/gps_time.h +4 -7
- esphome/components/graph/__init__.py +1 -1
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +0 -1
- esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +0 -1
- esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +21 -12
- esphome/components/gt911/touchscreen/gt911_touchscreen.h +26 -2
- esphome/components/haier/climate.py +5 -10
- esphome/components/haier/haier_base.cpp +0 -1
- esphome/components/hbridge/switch/hbridge_switch.cpp +0 -2
- esphome/components/hdc1080/hdc1080.cpp +0 -2
- esphome/components/heatpumpir/climate.py +2 -2
- esphome/components/hlw8012/hlw8012.cpp +0 -1
- esphome/components/hm3301/hm3301.cpp +0 -1
- esphome/components/hmc5883l/hmc5883l.cpp +0 -1
- esphome/components/homeassistant/__init__.py +1 -0
- esphome/components/homeassistant/number/__init__.py +1 -0
- esphome/components/homeassistant/number/homeassistant_number.cpp +11 -7
- esphome/components/homeassistant/switch/__init__.py +1 -0
- esphome/components/homeassistant/switch/homeassistant_switch.cpp +9 -5
- esphome/components/honeywellabp/honeywellabp.cpp +1 -4
- esphome/components/host/__init__.py +2 -0
- esphome/components/hte501/hte501.cpp +0 -1
- esphome/components/http_request/__init__.py +2 -3
- esphome/components/http_request/http_request_idf.cpp +2 -2
- esphome/components/htu21d/htu21d.cpp +0 -2
- esphome/components/htu31d/htu31d.cpp +0 -2
- esphome/components/hx711/hx711.cpp +0 -1
- esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +0 -1
- esphome/components/hydreon_rgxx/sensor.py +4 -5
- esphome/components/i2c/i2c_bus.h +1 -1
- esphome/components/i2c/i2c_bus_arduino.cpp +1 -2
- esphome/components/i2c/i2c_bus_esp_idf.cpp +192 -17
- esphome/components/i2c/i2c_bus_esp_idf.h +11 -1
- esphome/components/i2s_audio/__init__.py +6 -5
- esphome/components/i2s_audio/i2s_audio.cpp +0 -2
- esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +1 -4
- esphome/components/i2s_audio/microphone/__init__.py +4 -6
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +46 -19
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +4 -3
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +273 -269
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +19 -34
- esphome/components/ili9xxx/display.py +4 -3
- esphome/components/ili9xxx/ili9xxx_display.cpp +0 -2
- esphome/components/image/__init__.py +123 -92
- esphome/components/improv_serial/__init__.py +7 -8
- esphome/components/ina219/ina219.cpp +0 -1
- esphome/components/ina226/ina226.cpp +0 -2
- esphome/components/ina260/ina260.cpp +0 -2
- esphome/components/ina2xx_base/__init__.py +2 -5
- esphome/components/ina2xx_base/ina2xx_base.cpp +0 -2
- esphome/components/ina3221/ina3221.cpp +0 -1
- esphome/components/internal_temperature/internal_temperature.cpp +0 -2
- esphome/components/interval/interval.h +5 -9
- esphome/components/json/__init__.py +1 -1
- esphome/components/kmeteriso/kmeteriso.cpp +0 -2
- esphome/components/lc709203f/lc709203f.cpp +0 -2
- esphome/components/lcd_gpio/display.py +1 -3
- esphome/components/lcd_gpio/gpio_lcd_display.cpp +0 -1
- esphome/components/lcd_pcf8574/pcf8574_display.cpp +0 -1
- esphome/components/ld2410/__init__.py +4 -6
- esphome/components/ld2410/binary_sensor.py +4 -0
- esphome/components/ld2410/ld2410.cpp +56 -100
- esphome/components/ld2410/ld2410.h +17 -15
- esphome/components/ld2410/sensor.py +24 -10
- esphome/components/ld2412/__init__.py +46 -0
- esphome/components/ld2412/binary_sensor.py +70 -0
- esphome/components/ld2412/button/__init__.py +74 -0
- esphome/components/ld2412/button/factory_reset_button.cpp +9 -0
- esphome/components/ld2412/button/factory_reset_button.h +18 -0
- esphome/components/ld2412/button/query_button.cpp +9 -0
- esphome/components/ld2412/button/query_button.h +18 -0
- esphome/components/ld2412/button/restart_button.cpp +9 -0
- esphome/components/ld2412/button/restart_button.h +18 -0
- esphome/components/ld2412/button/start_dynamic_background_correction_button.cpp +11 -0
- esphome/components/ld2412/button/start_dynamic_background_correction_button.h +18 -0
- esphome/components/ld2412/ld2412.cpp +861 -0
- esphome/components/ld2412/ld2412.h +141 -0
- esphome/components/ld2412/number/__init__.py +126 -0
- esphome/components/ld2412/number/gate_threshold_number.cpp +14 -0
- esphome/components/ld2412/number/gate_threshold_number.h +19 -0
- esphome/components/ld2412/number/light_threshold_number.cpp +12 -0
- esphome/components/ld2412/number/light_threshold_number.h +18 -0
- esphome/components/ld2412/number/max_distance_timeout_number.cpp +12 -0
- esphome/components/ld2412/number/max_distance_timeout_number.h +18 -0
- esphome/components/ld2412/select/__init__.py +82 -0
- esphome/components/ld2412/select/baud_rate_select.cpp +12 -0
- esphome/components/ld2412/select/baud_rate_select.h +18 -0
- esphome/components/ld2412/select/distance_resolution_select.cpp +12 -0
- esphome/components/ld2412/select/distance_resolution_select.h +18 -0
- esphome/components/ld2412/select/light_out_control_select.cpp +12 -0
- esphome/components/ld2412/select/light_out_control_select.h +18 -0
- esphome/components/ld2412/sensor.py +124 -0
- esphome/components/ld2412/switch/__init__.py +45 -0
- esphome/components/ld2412/switch/bluetooth_switch.cpp +12 -0
- esphome/components/ld2412/switch/bluetooth_switch.h +18 -0
- esphome/components/ld2412/switch/engineering_mode_switch.cpp +12 -0
- esphome/components/ld2412/switch/engineering_mode_switch.h +18 -0
- esphome/components/ld2412/text_sensor.py +34 -0
- esphome/components/ld2420/ld2420.cpp +0 -1
- esphome/components/ld2450/__init__.py +3 -4
- esphome/components/ld2450/binary_sensor.py +3 -0
- esphome/components/ld2450/ld2450.cpp +77 -165
- esphome/components/ld2450/ld2450.h +26 -54
- esphome/components/ld2450/sensor.py +120 -6
- esphome/components/ld2450/text_sensor.py +5 -4
- esphome/components/ld24xx/__init__.py +1 -0
- esphome/components/ld24xx/ld24xx.h +65 -0
- esphome/components/ledc/ledc_output.cpp +0 -1
- esphome/components/libretiny/__init__.py +2 -0
- esphome/components/light/__init__.py +0 -1
- esphome/components/light/effects.py +70 -45
- esphome/components/light/light_call.cpp +101 -66
- esphome/components/light/light_color_values.h +16 -11
- esphome/components/light/light_json_schema.cpp +46 -44
- esphome/components/light/light_state.cpp +8 -11
- esphome/components/light/light_traits.h +17 -0
- esphome/components/lightwaverf/lightwaverf.cpp +0 -2
- esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +0 -1
- esphome/components/lock/__init__.py +0 -1
- esphome/components/logger/__init__.py +31 -9
- esphome/components/logger/logger.cpp +12 -7
- esphome/components/logger/logger.h +25 -14
- esphome/components/logger/logger_esp32.cpp +2 -7
- esphome/components/logger/logger_esp8266.cpp +2 -4
- esphome/components/logger/logger_host.cpp +2 -4
- esphome/components/logger/logger_libretiny.cpp +2 -4
- esphome/components/logger/logger_rp2040.cpp +2 -4
- esphome/components/logger/logger_zephyr.cpp +86 -0
- esphome/components/logger/select/logger_level_select.cpp +2 -4
- esphome/components/logger/select/logger_level_select.h +2 -4
- esphome/components/logger/task_log_buffer.cpp +2 -4
- esphome/components/logger/task_log_buffer.h +2 -4
- esphome/components/lps22/sensor.py +5 -5
- esphome/components/ltr390/ltr390.cpp +0 -2
- esphome/components/ltr501/ltr501.cpp +0 -1
- esphome/components/ltr_als_ps/ltr_als_ps.cpp +0 -1
- esphome/components/lvgl/__init__.py +14 -13
- esphome/components/lvgl/automation.py +2 -4
- esphome/components/lvgl/defines.py +0 -2
- esphome/components/lvgl/helpers.py +1 -1
- esphome/components/lvgl/lv_validation.py +7 -4
- esphome/components/lvgl/lvgl_esphome.cpp +2 -3
- esphome/components/lvgl/styles.py +2 -2
- esphome/components/lvgl/types.py +1 -1
- esphome/components/lvgl/widgets/__init__.py +2 -2
- esphome/components/lvgl/widgets/arc.py +14 -11
- esphome/components/lvgl/widgets/buttonmatrix.py +1 -1
- esphome/components/lvgl/widgets/qrcode.py +7 -7
- esphome/components/lvgl/widgets/spinner.py +6 -6
- esphome/components/lvgl/widgets/switch.py +2 -2
- esphome/components/lvgl/widgets/tabview.py +3 -3
- esphome/components/lvgl/widgets/tileview.py +15 -7
- esphome/components/m5stack_8angle/m5stack_8angle.cpp +0 -1
- esphome/components/matrix_keypad/__init__.py +4 -3
- esphome/components/max17043/max17043.cpp +0 -2
- esphome/components/max31855/max31855.cpp +1 -4
- esphome/components/max31856/max31856.cpp +0 -4
- esphome/components/max31865/max31865.cpp +0 -1
- esphome/components/max44009/max44009.cpp +0 -1
- esphome/components/max6675/max6675.cpp +1 -4
- esphome/components/max6956/max6956.cpp +0 -1
- esphome/components/max7219/max7219.cpp +0 -1
- esphome/components/max7219digit/display.py +1 -1
- esphome/components/max7219digit/max7219digit.cpp +0 -1
- esphome/components/max9611/max9611.cpp +0 -1
- esphome/components/mcp23008/__init__.py +1 -1
- esphome/components/mcp23008/mcp23008.cpp +0 -1
- esphome/components/mcp23016/mcp23016.cpp +0 -1
- esphome/components/mcp23017/__init__.py +1 -1
- esphome/components/mcp23017/mcp23017.cpp +0 -1
- esphome/components/mcp23s08/__init__.py +1 -1
- esphome/components/mcp23s08/mcp23s08.cpp +0 -1
- esphome/components/mcp23s17/__init__.py +1 -1
- esphome/components/mcp23s17/mcp23s17.cpp +0 -1
- esphome/components/mcp23x08_base/__init__.py +2 -0
- esphome/components/mcp23x08_base/mcp23x08_base.cpp +9 -7
- esphome/components/mcp23x08_base/mcp23x08_base.h +9 -4
- esphome/components/mcp23x17_base/__init__.py +2 -0
- esphome/components/mcp23x17_base/mcp23x17_base.cpp +20 -7
- esphome/components/mcp23x17_base/mcp23x17_base.h +9 -4
- esphome/components/mcp23xxx_base/__init__.py +11 -5
- esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +15 -12
- esphome/components/mcp23xxx_base/mcp23xxx_base.h +8 -7
- esphome/components/mcp3008/mcp3008.cpp +1 -4
- esphome/components/mcp3204/mcp3204.cpp +1 -4
- esphome/components/mcp4461/mcp4461.cpp +0 -1
- esphome/components/mcp4725/mcp4725.cpp +0 -1
- esphome/components/mcp4728/mcp4728.cpp +0 -1
- esphome/components/mcp9600/mcp9600.cpp +0 -2
- esphome/components/mcp9808/mcp9808.cpp +0 -2
- esphome/components/mdns/__init__.py +3 -0
- esphome/components/mdns/mdns_component.cpp +2 -0
- esphome/components/mdns/mdns_component.h +4 -0
- esphome/components/media_player/__init__.py +40 -0
- esphome/components/media_player/automation.h +16 -0
- esphome/components/media_player/media_player.cpp +13 -0
- esphome/components/media_player/media_player.h +50 -3
- esphome/components/micro_wake_word/micro_wake_word.cpp +0 -3
- esphome/components/mics_4514/mics_4514.cpp +1 -6
- esphome/components/midea/ir_transmitter.h +4 -4
- esphome/components/mipi/__init__.py +416 -0
- esphome/components/mipi_dsi/__init__.py +5 -0
- esphome/components/mipi_dsi/display.py +233 -0
- esphome/components/mipi_dsi/mipi_dsi.cpp +379 -0
- esphome/components/mipi_dsi/mipi_dsi.h +123 -0
- esphome/components/mipi_dsi/models/__init__.py +0 -0
- esphome/components/mipi_dsi/models/guition.py +38 -0
- esphome/components/mipi_dsi/models/m5stack.py +57 -0
- esphome/components/mipi_dsi/models/waveshare.py +105 -0
- esphome/components/mipi_rgb/models/lilygo.py +0 -0
- esphome/components/mipi_spi/__init__.py +0 -9
- esphome/components/mipi_spi/display.py +220 -256
- esphome/components/mipi_spi/mipi_spi.cpp +1 -485
- esphome/components/mipi_spi/mipi_spi.h +556 -108
- esphome/components/mipi_spi/models/__init__.py +0 -65
- esphome/components/mipi_spi/models/adafruit.py +30 -0
- esphome/components/mipi_spi/models/amoled.py +41 -5
- esphome/components/mipi_spi/models/ili.py +5 -5
- esphome/components/mipi_spi/models/jc.py +1 -3
- esphome/components/mipi_spi/models/lilygo.py +1 -1
- esphome/components/mipi_spi/models/waveshare.py +16 -1
- esphome/components/mixer/speaker/__init__.py +4 -5
- esphome/components/mlx90393/sensor.py +7 -5
- esphome/components/mlx90393/sensor_mlx90393.cpp +0 -1
- esphome/components/mlx90614/mlx90614.cpp +0 -1
- esphome/components/mmc5603/mmc5603.cpp +0 -1
- esphome/components/mmc5983/mmc5983.cpp +0 -2
- esphome/components/mpl3115a2/mpl3115a2.cpp +0 -2
- esphome/components/mpr121/__init__.py +7 -6
- esphome/components/mpr121/mpr121.cpp +0 -1
- esphome/components/mpu6050/mpu6050.cpp +0 -1
- esphome/components/mpu6886/mpu6886.cpp +0 -1
- esphome/components/mqtt/__init__.py +1 -2
- esphome/components/mqtt/mqtt_button.cpp +1 -1
- esphome/components/mqtt/mqtt_client.cpp +0 -1
- esphome/components/mqtt/mqtt_component.cpp +8 -14
- esphome/components/mqtt/mqtt_component.h +0 -7
- esphome/components/mqtt/mqtt_sensor.cpp +0 -1
- esphome/components/mqtt/mqtt_sensor.h +0 -1
- esphome/components/mqtt/mqtt_text_sensor.cpp +0 -1
- esphome/components/mqtt/mqtt_text_sensor.h +0 -1
- esphome/components/ms5611/ms5611.cpp +0 -1
- esphome/components/ms8607/ms8607.cpp +0 -1
- esphome/components/msa3xx/msa3xx.cpp +0 -2
- esphome/components/my9231/my9231.cpp +0 -2
- esphome/components/nau7802/nau7802.cpp +0 -1
- esphome/components/neopixelbus/light.py +3 -0
- esphome/components/network/util.cpp +29 -0
- esphome/components/nextion/nextion.cpp +2 -2
- esphome/components/nfc/binary_sensor/{binary_sensor.cpp → nfc_binary_sensor.cpp} +1 -1
- esphome/components/npi19/npi19.cpp +0 -2
- esphome/components/nrf52/__init__.py +223 -0
- esphome/components/nrf52/boards.py +34 -0
- esphome/components/nrf52/const.py +18 -0
- esphome/components/nrf52/gpio.py +79 -0
- esphome/components/number/__init__.py +2 -1
- esphome/components/one_wire/__init__.py +1 -2
- esphome/components/one_wire/one_wire.cpp +0 -2
- esphome/components/one_wire/one_wire.h +0 -2
- esphome/components/opentherm/hub.cpp +0 -1
- esphome/components/opentherm/number/__init__.py +2 -2
- esphome/components/openthread/__init__.py +2 -3
- esphome/components/openthread/openthread.cpp +30 -13
- esphome/components/openthread/openthread.h +3 -0
- esphome/components/openthread/openthread_esp.cpp +3 -1
- esphome/components/opt3001/sensor.py +2 -6
- esphome/components/output/__init__.py +38 -0
- esphome/components/output/automation.h +24 -0
- esphome/components/output/switch/output_switch.cpp +0 -2
- esphome/components/packages/__init__.py +1 -2
- esphome/components/packet_transport/__init__.py +4 -3
- esphome/components/pca6416a/pca6416a.cpp +0 -1
- esphome/components/pca9554/pca9554.cpp +0 -1
- esphome/components/pca9685/pca9685_output.cpp +0 -2
- esphome/components/pcf85063/pcf85063.cpp +0 -1
- esphome/components/pcf8563/pcf8563.cpp +0 -1
- esphome/components/pcf8574/pcf8574.cpp +0 -1
- esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +0 -1
- esphome/components/pipsolar/pipsolar.cpp +54 -42
- esphome/components/pipsolar/pipsolar.h +5 -4
- esphome/components/pipsolar/sensor/__init__.py +1 -1
- esphome/components/pm2005/pm2005.cpp +0 -1
- esphome/components/pmsa003i/pmsa003i.cpp +0 -2
- esphome/components/pmwcs3/sensor.py +1 -2
- esphome/components/pn532/pn532.cpp +0 -2
- esphome/components/pn532_spi/pn532_spi.cpp +0 -2
- esphome/components/power_supply/power_supply.cpp +7 -10
- esphome/components/power_supply/power_supply.h +1 -1
- esphome/components/psram/__init__.py +6 -1
- esphome/components/pulse_counter/pulse_counter_sensor.cpp +0 -1
- esphome/components/pulse_counter/sensor.py +9 -6
- esphome/components/pylontech/pylontech.cpp +0 -1
- esphome/components/qmc5883l/qmc5883l.cpp +0 -1
- esphome/components/qmp6988/qmp6988.cpp +0 -2
- esphome/components/qspi_dbi/display.py +2 -3
- esphome/components/qspi_dbi/qspi_dbi.cpp +0 -2
- esphome/components/qwiic_pir/binary_sensor.py +2 -3
- esphome/components/qwiic_pir/qwiic_pir.cpp +0 -2
- esphome/components/rc522/rc522.cpp +9 -31
- esphome/components/rc522_spi/rc522_spi.cpp +0 -1
- esphome/components/remote_base/__init__.py +5 -6
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +0 -1
- esphome/components/remote_receiver/remote_receiver_esp8266.cpp +0 -1
- esphome/components/remote_receiver/remote_receiver_libretiny.cpp +0 -1
- esphome/components/remote_transmitter/__init__.py +26 -0
- esphome/components/remote_transmitter/automation.h +18 -0
- esphome/components/remote_transmitter/remote_transmitter.h +2 -1
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +0 -1
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
- esphome/components/resampler/speaker/__init__.py +4 -5
- esphome/components/rf_bridge/__init__.py +4 -8
- esphome/components/rotary_encoder/rotary_encoder.cpp +0 -2
- esphome/components/rp2040/__init__.py +3 -1
- esphome/components/rp2040_pio_led_strip/led_strip.cpp +0 -2
- esphome/components/rp2040_pio_led_strip/light.py +1 -2
- esphome/components/rp2040_pwm/rp2040_pwm.cpp +1 -5
- esphome/components/rpi_dpi_rgb/display.py +13 -15
- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +0 -3
- esphome/components/runtime_stats/__init__.py +34 -0
- esphome/components/runtime_stats/runtime_stats.cpp +102 -0
- esphome/components/runtime_stats/runtime_stats.h +132 -0
- esphome/components/scd30/scd30.cpp +0 -2
- esphome/components/scd30/sensor.py +1 -2
- esphome/components/scd4x/scd4x.cpp +0 -1
- esphome/components/scd4x/sensor.py +1 -3
- esphome/components/sdl/display.py +3 -1
- esphome/components/sdl/sdl_esphome.cpp +0 -2
- esphome/components/sdp3x/sdp3x.cpp +0 -2
- esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +0 -2
- esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +0 -3
- esphome/components/select/__init__.py +2 -3
- esphome/components/select/select_traits.cpp +1 -1
- esphome/components/select/select_traits.h +1 -1
- esphome/components/sen0321/sen0321.cpp +0 -1
- esphome/components/sen5x/sen5x.cpp +0 -2
- esphome/components/senseair/senseair.cpp +7 -3
- esphome/components/senseair/senseair.h +11 -0
- esphome/components/sensor/__init__.py +36 -4
- esphome/components/sensor/filter.cpp +49 -10
- esphome/components/sensor/filter.h +22 -7
- esphome/components/sensor/sensor.cpp +0 -1
- esphome/components/sensor/sensor.h +0 -9
- esphome/components/sfa30/sfa30.cpp +0 -4
- esphome/components/sgp30/sgp30.cpp +0 -2
- esphome/components/sgp4x/sensor.py +1 -1
- esphome/components/sgp4x/sgp4x.cpp +0 -2
- esphome/components/shelly_dimmer/shelly_dimmer.cpp +0 -2
- esphome/components/sht3xd/sht3xd.cpp +0 -2
- esphome/components/sht4x/sht4x.cpp +0 -2
- esphome/components/shtcx/shtcx.cpp +0 -1
- esphome/components/sim800l/__init__.py +2 -4
- esphome/components/sm16716/sm16716.cpp +0 -1
- esphome/components/sm2135/sm2135.cpp +0 -1
- esphome/components/sm2235/sm2235.cpp +0 -1
- esphome/components/sm2335/sm2335.cpp +0 -1
- esphome/components/sn74hc165/sn74hc165.cpp +0 -1
- esphome/components/sn74hc595/sn74hc595.cpp +0 -1
- esphome/components/sntp/sntp_component.cpp +0 -1
- esphome/components/sound_level/sensor.py +1 -1
- esphome/components/speaker/media_player/__init__.py +21 -33
- esphome/components/speaker/media_player/audio_pipeline.cpp +4 -7
- esphome/components/spi/__init__.py +29 -13
- esphome/components/spi/spi.cpp +0 -2
- esphome/components/spi_device/spi_device.cpp +1 -4
- esphome/components/sprinkler/__init__.py +4 -4
- esphome/components/sps30/sps30.cpp +0 -1
- esphome/components/ssd1306_base/__init__.py +11 -11
- esphome/components/ssd1306_base/ssd1306_base.cpp +1 -1
- esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +0 -1
- esphome/components/ssd1306_spi/ssd1306_spi.cpp +0 -1
- esphome/components/ssd1322_spi/ssd1322_spi.cpp +0 -1
- esphome/components/ssd1325_spi/ssd1325_spi.cpp +0 -1
- esphome/components/ssd1327_i2c/ssd1327_i2c.cpp +0 -1
- esphome/components/ssd1327_spi/ssd1327_spi.cpp +0 -1
- esphome/components/ssd1331_spi/ssd1331_spi.cpp +0 -1
- esphome/components/ssd1351_spi/ssd1351_spi.cpp +0 -1
- esphome/components/st7567_i2c/st7567_i2c.cpp +0 -1
- esphome/components/st7567_spi/st7567_spi.cpp +0 -1
- esphome/components/st7701s/display.py +10 -14
- esphome/components/st7701s/st7701s.cpp +0 -3
- esphome/components/st7735/st7735.cpp +0 -1
- esphome/components/st7789v/st7789v.cpp +0 -1
- esphome/components/st7920/st7920.cpp +0 -1
- esphome/components/status_led/light/status_led_light.cpp +0 -2
- esphome/components/status_led/status_led.cpp +0 -1
- esphome/components/stepper/__init__.py +2 -4
- esphome/components/sts3x/sts3x.cpp +0 -1
- esphome/components/substitutions/__init__.py +10 -16
- esphome/components/substitutions/jinja.py +24 -1
- esphome/components/sun/__init__.py +2 -3
- esphome/components/switch/__init__.py +31 -1
- esphome/components/switch/automation.h +24 -0
- esphome/components/switch/switch.cpp +8 -0
- esphome/components/switch/switch.h +8 -0
- esphome/components/sx126x/sx126x.cpp +0 -2
- esphome/components/sx127x/sx127x.cpp +0 -2
- esphome/components/sx1509/__init__.py +7 -5
- esphome/components/sx1509/output/sx1509_float_output.cpp +1 -1
- esphome/components/sx1509/sx1509.cpp +0 -2
- esphome/components/syslog/esphome_syslog.cpp +1 -1
- esphome/components/tc74/tc74.cpp +0 -1
- esphome/components/tca9548a/tca9548a.cpp +0 -1
- esphome/components/tca9555/tca9555.cpp +0 -1
- esphome/components/tcs34725/tcs34725.cpp +0 -1
- esphome/components/tee501/tee501.cpp +0 -1
- esphome/components/tem3200/tem3200.cpp +0 -2
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +0 -1
- esphome/components/template/cover/template_cover.cpp +0 -1
- esphome/components/template/select/template_select.cpp +0 -1
- esphome/components/template/text/template_text.cpp +0 -2
- esphome/components/template/valve/template_valve.cpp +0 -1
- esphome/components/text/__init__.py +0 -1
- esphome/components/text/text_traits.h +2 -0
- esphome/components/text_sensor/__init__.py +2 -1
- esphome/components/text_sensor/text_sensor.cpp +0 -2
- esphome/components/text_sensor/text_sensor.h +0 -8
- esphome/components/thermostat/climate.py +4 -4
- esphome/components/time/__init__.py +7 -4
- esphome/components/time/real_time_clock.cpp +16 -3
- esphome/components/tlc59208f/tlc59208f_output.cpp +0 -2
- esphome/components/tlc5947/tlc5947.cpp +0 -2
- esphome/components/tlc5971/tlc5971.cpp +0 -2
- esphome/components/tm1621/tm1621.cpp +0 -2
- esphome/components/tm1637/tm1637.cpp +0 -2
- esphome/components/tm1638/tm1638.cpp +0 -2
- esphome/components/tm1651/__init__.py +45 -48
- esphome/components/tm1651/tm1651.cpp +213 -47
- esphome/components/tm1651/tm1651.h +37 -32
- esphome/components/tmp117/tmp117.cpp +0 -2
- esphome/components/tsl2561/tsl2561.cpp +0 -1
- esphome/components/tsl2591/tsl2591.cpp +0 -1
- esphome/components/tt21100/touchscreen/tt21100.cpp +0 -2
- esphome/components/ttp229_bsf/ttp229_bsf.cpp +0 -1
- esphome/components/ttp229_lsf/ttp229_lsf.cpp +0 -1
- esphome/components/tuya/climate/__init__.py +9 -10
- esphome/components/tuya/number/__init__.py +8 -6
- esphome/components/tx20/tx20.cpp +0 -1
- esphome/components/uart/uart_component_esp32_arduino.cpp +0 -1
- esphome/components/uart/uart_component_esp8266.cpp +0 -1
- esphome/components/uart/uart_component_esp_idf.cpp +0 -2
- esphome/components/uart/uart_component_libretiny.cpp +0 -2
- esphome/components/uart/uart_component_rp2040.cpp +0 -2
- esphome/components/udp/__init__.py +1 -1
- esphome/components/ufire_ec/sensor.py +1 -2
- esphome/components/ufire_ec/ufire_ec.cpp +0 -2
- esphome/components/ufire_ise/sensor.py +1 -2
- esphome/components/ufire_ise/ufire_ise.cpp +0 -2
- esphome/components/ultrasonic/ultrasonic_sensor.cpp +0 -1
- esphome/components/update/__init__.py +0 -1
- esphome/components/uptime/sensor/uptime_seconds_sensor.cpp +0 -1
- esphome/components/uptime/sensor/uptime_seconds_sensor.h +0 -2
- esphome/components/usb_host/usb_host_client.cpp +0 -1
- esphome/components/usb_host/usb_host_component.cpp +0 -1
- esphome/components/valve/__init__.py +0 -1
- esphome/components/veml3235/veml3235.cpp +0 -3
- esphome/components/veml7700/veml7700.cpp +0 -2
- esphome/components/version/version_text_sensor.cpp +0 -1
- esphome/components/version/version_text_sensor.h +0 -1
- esphome/components/vl53l0x/vl53l0x_sensor.cpp +0 -4
- esphome/components/voice_assistant/voice_assistant.cpp +9 -8
- esphome/components/web_server/__init__.py +13 -0
- esphome/components/web_server/web_server.cpp +188 -353
- esphome/components/web_server/web_server.h +61 -1
- esphome/components/web_server_base/__init__.py +1 -1
- esphome/components/web_server_base/web_server_base.cpp +2 -0
- esphome/components/web_server_base/web_server_base.h +6 -0
- esphome/components/web_server_idf/web_server_idf.cpp +10 -8
- esphome/components/web_server_idf/web_server_idf.h +2 -0
- esphome/components/weikai_i2c/weikai_i2c.cpp +1 -2
- esphome/components/weikai_spi/weikai_spi.cpp +1 -1
- esphome/components/wifi/__init__.py +17 -43
- esphome/components/wifi/wifi_component.cpp +100 -36
- esphome/components/wifi/wifi_component.h +5 -1
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -0
- esphome/components/wifi/wifi_component_esp_idf.cpp +30 -0
- esphome/components/wifi_info/wifi_info_text_sensor.h +0 -6
- esphome/components/wifi_signal/wifi_signal_sensor.h +0 -1
- esphome/components/wireguard/wireguard.cpp +0 -2
- esphome/components/x9c/x9c.cpp +0 -2
- esphome/components/xgzp68xx/xgzp68xx.cpp +0 -1
- esphome/components/xl9535/xl9535.cpp +0 -2
- esphome/components/zephyr/__init__.py +252 -0
- esphome/components/zephyr/const.py +16 -0
- esphome/components/zephyr/core.cpp +90 -0
- esphome/components/zephyr/gpio.cpp +120 -0
- esphome/components/zephyr/gpio.h +38 -0
- esphome/components/zephyr/pre_build.py.script +4 -0
- esphome/components/zephyr/preferences.cpp +156 -0
- esphome/components/zephyr/preferences.h +13 -0
- esphome/config.py +38 -16
- esphome/config_helpers.py +1 -2
- esphome/config_validation.py +12 -16
- esphome/const.py +26 -1
- esphome/core/__init__.py +92 -51
- esphome/core/application.cpp +75 -21
- esphome/core/application.h +106 -171
- esphome/core/color.h +10 -0
- esphome/core/component.cpp +41 -25
- esphome/core/component.h +9 -6
- esphome/core/component_iterator.cpp +61 -261
- esphome/core/component_iterator.h +15 -0
- esphome/core/config.py +26 -11
- esphome/core/defines.h +40 -2
- esphome/core/entity_base.h +18 -0
- esphome/core/entity_helpers.py +45 -10
- esphome/core/helpers.cpp +8 -15
- esphome/core/helpers.h +60 -6
- esphome/core/lock_free_queue.h +1 -1
- esphome/core/scheduler.cpp +311 -77
- esphome/core/scheduler.h +141 -28
- esphome/cpp_generator.py +2 -6
- esphome/cpp_helpers.py +1 -1
- esphome/dashboard/dashboard.py +2 -3
- esphome/dashboard/dns.py +2 -8
- esphome/dashboard/web_server.py +34 -19
- esphome/espota2.py +1 -4
- esphome/git.py +3 -1
- esphome/helpers.py +23 -4
- esphome/log.py +3 -1
- esphome/mqtt.py +3 -5
- esphome/platformio_api.py +7 -4
- esphome/types.py +12 -0
- esphome/util.py +20 -8
- esphome/voluptuous_schema.py +4 -3
- esphome/vscode.py +1 -2
- esphome/wizard.py +1 -4
- esphome/writer.py +16 -108
- esphome/yaml_util.py +7 -5
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/METADATA +13 -14
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/RECORD +757 -677
- esphome/components/mipi_spi/models/commands.py +0 -82
- /esphome/components/nfc/binary_sensor/{binary_sensor.h → nfc_binary_sensor.h} +0 -0
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/WHEEL +0 -0
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/entry_points.txt +0 -0
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.7.4.dist-info → esphome-2025.8.0.dist-info}/top_level.txt +0 -0
|
@@ -35,13 +35,37 @@
|
|
|
35
35
|
// bt_trace.h
|
|
36
36
|
#undef TAG
|
|
37
37
|
|
|
38
|
-
namespace esphome {
|
|
39
|
-
namespace esp32_ble_tracker {
|
|
38
|
+
namespace esphome::esp32_ble_tracker {
|
|
40
39
|
|
|
41
40
|
static const char *const TAG = "esp32_ble_tracker";
|
|
42
41
|
|
|
43
42
|
ESP32BLETracker *global_esp32_ble_tracker = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
|
44
43
|
|
|
44
|
+
const char *client_state_to_string(ClientState state) {
|
|
45
|
+
switch (state) {
|
|
46
|
+
case ClientState::INIT:
|
|
47
|
+
return "INIT";
|
|
48
|
+
case ClientState::DISCONNECTING:
|
|
49
|
+
return "DISCONNECTING";
|
|
50
|
+
case ClientState::IDLE:
|
|
51
|
+
return "IDLE";
|
|
52
|
+
case ClientState::SEARCHING:
|
|
53
|
+
return "SEARCHING";
|
|
54
|
+
case ClientState::DISCOVERED:
|
|
55
|
+
return "DISCOVERED";
|
|
56
|
+
case ClientState::READY_TO_CONNECT:
|
|
57
|
+
return "READY_TO_CONNECT";
|
|
58
|
+
case ClientState::CONNECTING:
|
|
59
|
+
return "CONNECTING";
|
|
60
|
+
case ClientState::CONNECTED:
|
|
61
|
+
return "CONNECTED";
|
|
62
|
+
case ClientState::ESTABLISHED:
|
|
63
|
+
return "ESTABLISHED";
|
|
64
|
+
default:
|
|
65
|
+
return "UNKNOWN";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
45
69
|
float ESP32BLETracker::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH; }
|
|
46
70
|
|
|
47
71
|
void ESP32BLETracker::setup() {
|
|
@@ -50,13 +74,6 @@ void ESP32BLETracker::setup() {
|
|
|
50
74
|
ESP_LOGE(TAG, "BLE Tracker was marked failed by ESP32BLE");
|
|
51
75
|
return;
|
|
52
76
|
}
|
|
53
|
-
RAMAllocator<BLEScanResult> allocator;
|
|
54
|
-
this->scan_ring_buffer_ = allocator.allocate(SCAN_RESULT_BUFFER_SIZE);
|
|
55
|
-
|
|
56
|
-
if (this->scan_ring_buffer_ == nullptr) {
|
|
57
|
-
ESP_LOGE(TAG, "Could not allocate ring buffer for BLE Tracker!");
|
|
58
|
-
this->mark_failed();
|
|
59
|
-
}
|
|
60
77
|
|
|
61
78
|
global_esp32_ble_tracker = this;
|
|
62
79
|
|
|
@@ -84,118 +101,49 @@ void ESP32BLETracker::loop() {
|
|
|
84
101
|
this->start_scan();
|
|
85
102
|
}
|
|
86
103
|
}
|
|
87
|
-
int connecting = 0;
|
|
88
|
-
int discovered = 0;
|
|
89
|
-
int searching = 0;
|
|
90
|
-
int disconnecting = 0;
|
|
91
|
-
for (auto *client : this->clients_) {
|
|
92
|
-
switch (client->state()) {
|
|
93
|
-
case ClientState::DISCONNECTING:
|
|
94
|
-
disconnecting++;
|
|
95
|
-
break;
|
|
96
|
-
case ClientState::DISCOVERED:
|
|
97
|
-
discovered++;
|
|
98
|
-
break;
|
|
99
|
-
case ClientState::SEARCHING:
|
|
100
|
-
searching++;
|
|
101
|
-
break;
|
|
102
|
-
case ClientState::CONNECTING:
|
|
103
|
-
case ClientState::READY_TO_CONNECT:
|
|
104
|
-
connecting++;
|
|
105
|
-
break;
|
|
106
|
-
default:
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (connecting != connecting_ || discovered != discovered_ || searching != searching_ ||
|
|
111
|
-
disconnecting != disconnecting_) {
|
|
112
|
-
connecting_ = connecting;
|
|
113
|
-
discovered_ = discovered;
|
|
114
|
-
searching_ = searching;
|
|
115
|
-
disconnecting_ = disconnecting;
|
|
116
|
-
ESP_LOGD(TAG, "connecting: %d, discovered: %d, searching: %d, disconnecting: %d", connecting_, discovered_,
|
|
117
|
-
searching_, disconnecting_);
|
|
118
|
-
}
|
|
119
|
-
bool promote_to_connecting = discovered && !searching && !connecting;
|
|
120
104
|
|
|
121
|
-
//
|
|
122
|
-
//
|
|
105
|
+
// Check for scan timeout - moved here from scheduler to avoid false reboots
|
|
106
|
+
// when the loop is blocked
|
|
123
107
|
if (this->scanner_state_ == ScannerState::RUNNING) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
for (auto *client : this->clients_) {
|
|
139
|
-
client->parse_devices(&scan_result, 1);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (this->parse_advertisements_) {
|
|
144
|
-
ESPBTDevice device;
|
|
145
|
-
device.parse_scan_rst(scan_result);
|
|
146
|
-
|
|
147
|
-
bool found = false;
|
|
148
|
-
for (auto *listener : this->listeners_) {
|
|
149
|
-
if (listener->parse_device(device))
|
|
150
|
-
found = true;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
for (auto *client : this->clients_) {
|
|
154
|
-
if (client->parse_device(device)) {
|
|
155
|
-
found = true;
|
|
156
|
-
if (!connecting && client->state() == ClientState::DISCOVERED) {
|
|
157
|
-
promote_to_connecting = true;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (!found && !this->scan_continuous_) {
|
|
163
|
-
this->print_bt_device_info(device);
|
|
108
|
+
switch (this->scan_timeout_state_) {
|
|
109
|
+
case ScanTimeoutState::MONITORING: {
|
|
110
|
+
uint32_t now = App.get_loop_component_start_time();
|
|
111
|
+
uint32_t timeout_ms = this->scan_duration_ * 2000;
|
|
112
|
+
// Robust time comparison that handles rollover correctly
|
|
113
|
+
// This works because unsigned arithmetic wraps around predictably
|
|
114
|
+
if ((now - this->scan_start_time_) > timeout_ms) {
|
|
115
|
+
// First time we've seen the timeout exceeded - wait one more loop iteration
|
|
116
|
+
// This ensures all components have had a chance to process pending events
|
|
117
|
+
// This is because esp32_ble may not have run yet and called
|
|
118
|
+
// gap_scan_event_handler yet when the loop unblocks
|
|
119
|
+
ESP_LOGW(TAG, "Scan timeout exceeded");
|
|
120
|
+
this->scan_timeout_state_ = ScanTimeoutState::EXCEEDED_WAIT;
|
|
164
121
|
}
|
|
122
|
+
break;
|
|
165
123
|
}
|
|
124
|
+
case ScanTimeoutState::EXCEEDED_WAIT:
|
|
125
|
+
// We've waited at least one full loop iteration, and scan is still running
|
|
126
|
+
ESP_LOGE(TAG, "Scan never terminated, rebooting");
|
|
127
|
+
App.reboot();
|
|
128
|
+
break;
|
|
166
129
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// Store with release to ensure reads complete before index update
|
|
171
|
-
this->ring_read_index_.store(read_idx, std::memory_order_release);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Log dropped results periodically
|
|
175
|
-
size_t dropped = this->scan_results_dropped_.exchange(0, std::memory_order_relaxed);
|
|
176
|
-
if (dropped > 0) {
|
|
177
|
-
ESP_LOGW(TAG, "Dropped %zu BLE scan results due to buffer overflow", dropped);
|
|
130
|
+
case ScanTimeoutState::INACTIVE:
|
|
131
|
+
// This case should be unreachable - scanner and timeout states are always synchronized
|
|
132
|
+
break;
|
|
178
133
|
}
|
|
179
134
|
}
|
|
180
|
-
|
|
181
|
-
|
|
135
|
+
|
|
136
|
+
ClientStateCounts counts = this->count_client_states_();
|
|
137
|
+
if (counts != this->client_state_counts_) {
|
|
138
|
+
this->client_state_counts_ = counts;
|
|
139
|
+
ESP_LOGD(TAG, "connecting: %d, discovered: %d, searching: %d, disconnecting: %d",
|
|
140
|
+
this->client_state_counts_.connecting, this->client_state_counts_.discovered,
|
|
141
|
+
this->client_state_counts_.searching, this->client_state_counts_.disconnecting);
|
|
182
142
|
}
|
|
143
|
+
|
|
183
144
|
if (this->scanner_state_ == ScannerState::FAILED ||
|
|
184
145
|
(this->scan_set_param_failed_ && this->scanner_state_ == ScannerState::RUNNING)) {
|
|
185
|
-
this->
|
|
186
|
-
if (this->scan_start_fail_count_ == std::numeric_limits<uint8_t>::max()) {
|
|
187
|
-
ESP_LOGE(TAG, "Scan could not restart after %d attempts, rebooting to restore stack (IDF)",
|
|
188
|
-
std::numeric_limits<uint8_t>::max());
|
|
189
|
-
App.reboot();
|
|
190
|
-
}
|
|
191
|
-
if (this->scan_start_failed_) {
|
|
192
|
-
ESP_LOGE(TAG, "Scan start failed: %d", this->scan_start_failed_);
|
|
193
|
-
this->scan_start_failed_ = ESP_BT_STATUS_SUCCESS;
|
|
194
|
-
}
|
|
195
|
-
if (this->scan_set_param_failed_) {
|
|
196
|
-
ESP_LOGE(TAG, "Scan set param failed: %d", this->scan_set_param_failed_);
|
|
197
|
-
this->scan_set_param_failed_ = ESP_BT_STATUS_SUCCESS;
|
|
198
|
-
}
|
|
146
|
+
this->handle_scanner_failure_();
|
|
199
147
|
}
|
|
200
148
|
/*
|
|
201
149
|
|
|
@@ -210,13 +158,12 @@ void ESP32BLETracker::loop() {
|
|
|
210
158
|
https://github.com/espressif/esp-idf/issues/6688
|
|
211
159
|
|
|
212
160
|
*/
|
|
213
|
-
|
|
161
|
+
bool promote_to_connecting = counts.discovered && !counts.searching && !counts.connecting;
|
|
162
|
+
|
|
163
|
+
if (this->scanner_state_ == ScannerState::IDLE && !counts.connecting && !counts.disconnecting &&
|
|
164
|
+
!promote_to_connecting) {
|
|
214
165
|
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
|
|
215
|
-
|
|
216
|
-
this->coex_prefer_ble_ = false;
|
|
217
|
-
ESP_LOGD(TAG, "Setting coexistence preference to balanced.");
|
|
218
|
-
esp_coex_preference_set(ESP_COEX_PREFER_BALANCE); // Reset to default
|
|
219
|
-
}
|
|
166
|
+
this->update_coex_preference_(false);
|
|
220
167
|
#endif
|
|
221
168
|
if (this->scan_continuous_) {
|
|
222
169
|
this->start_scan_(false); // first = false
|
|
@@ -224,31 +171,13 @@ void ESP32BLETracker::loop() {
|
|
|
224
171
|
}
|
|
225
172
|
// If there is a discovered client and no connecting
|
|
226
173
|
// clients and no clients using the scanner to search for
|
|
227
|
-
// devices, then
|
|
228
|
-
//
|
|
174
|
+
// devices, then promote the discovered client to ready to connect.
|
|
175
|
+
// We check both RUNNING and IDLE states because:
|
|
176
|
+
// - RUNNING: gap_scan_event_handler initiates stop_scan_() but promotion can happen immediately
|
|
177
|
+
// - IDLE: Scanner has already stopped (naturally or by gap_scan_event_handler)
|
|
229
178
|
if (promote_to_connecting &&
|
|
230
179
|
(this->scanner_state_ == ScannerState::RUNNING || this->scanner_state_ == ScannerState::IDLE)) {
|
|
231
|
-
|
|
232
|
-
if (client->state() == ClientState::DISCOVERED) {
|
|
233
|
-
if (this->scanner_state_ == ScannerState::RUNNING) {
|
|
234
|
-
ESP_LOGD(TAG, "Stopping scan to make connection");
|
|
235
|
-
this->stop_scan_();
|
|
236
|
-
} else if (this->scanner_state_ == ScannerState::IDLE) {
|
|
237
|
-
ESP_LOGD(TAG, "Promoting client to connect");
|
|
238
|
-
// We only want to promote one client at a time.
|
|
239
|
-
// once the scanner is fully stopped.
|
|
240
|
-
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
|
|
241
|
-
ESP_LOGD(TAG, "Setting coexistence to Bluetooth to make connection.");
|
|
242
|
-
if (!this->coex_prefer_ble_) {
|
|
243
|
-
this->coex_prefer_ble_ = true;
|
|
244
|
-
esp_coex_preference_set(ESP_COEX_PREFER_BT); // Prioritize Bluetooth
|
|
245
|
-
}
|
|
246
|
-
#endif
|
|
247
|
-
client->set_state(ClientState::READY_TO_CONNECT);
|
|
248
|
-
}
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
180
|
+
this->try_promote_discovered_clients_();
|
|
252
181
|
}
|
|
253
182
|
}
|
|
254
183
|
|
|
@@ -264,18 +193,11 @@ void ESP32BLETracker::ble_before_disabled_event_handler() { this->stop_scan_();
|
|
|
264
193
|
|
|
265
194
|
void ESP32BLETracker::stop_scan_() {
|
|
266
195
|
if (this->scanner_state_ != ScannerState::RUNNING && this->scanner_state_ != ScannerState::FAILED) {
|
|
267
|
-
|
|
268
|
-
ESP_LOGE(TAG, "Scan is already stopped while trying to stop.");
|
|
269
|
-
} else if (this->scanner_state_ == ScannerState::STARTING) {
|
|
270
|
-
ESP_LOGE(TAG, "Scan is starting while trying to stop.");
|
|
271
|
-
} else if (this->scanner_state_ == ScannerState::STOPPING) {
|
|
272
|
-
ESP_LOGE(TAG, "Scan is already stopping while trying to stop.");
|
|
273
|
-
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
|
274
|
-
ESP_LOGE(TAG, "Scan is already stopped while trying to stop.");
|
|
275
|
-
}
|
|
196
|
+
ESP_LOGE(TAG, "Cannot stop scan: %s", this->scanner_state_to_string_(this->scanner_state_));
|
|
276
197
|
return;
|
|
277
198
|
}
|
|
278
|
-
|
|
199
|
+
// Reset timeout state machine when stopping scan
|
|
200
|
+
this->scan_timeout_state_ = ScanTimeoutState::INACTIVE;
|
|
279
201
|
this->set_scanner_state_(ScannerState::STOPPING);
|
|
280
202
|
esp_err_t err = esp_ble_gap_stop_scanning();
|
|
281
203
|
if (err != ESP_OK) {
|
|
@@ -290,17 +212,7 @@ void ESP32BLETracker::start_scan_(bool first) {
|
|
|
290
212
|
return;
|
|
291
213
|
}
|
|
292
214
|
if (this->scanner_state_ != ScannerState::IDLE) {
|
|
293
|
-
|
|
294
|
-
ESP_LOGE(TAG, "Cannot start scan while already starting.");
|
|
295
|
-
} else if (this->scanner_state_ == ScannerState::RUNNING) {
|
|
296
|
-
ESP_LOGE(TAG, "Cannot start scan while already running.");
|
|
297
|
-
} else if (this->scanner_state_ == ScannerState::STOPPING) {
|
|
298
|
-
ESP_LOGE(TAG, "Cannot start scan while already stopping.");
|
|
299
|
-
} else if (this->scanner_state_ == ScannerState::FAILED) {
|
|
300
|
-
ESP_LOGE(TAG, "Cannot start scan while already failed.");
|
|
301
|
-
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
|
302
|
-
ESP_LOGE(TAG, "Cannot start scan while already stopped.");
|
|
303
|
-
}
|
|
215
|
+
this->log_unexpected_state_("start scan", ScannerState::IDLE);
|
|
304
216
|
return;
|
|
305
217
|
}
|
|
306
218
|
this->set_scanner_state_(ScannerState::STARTING);
|
|
@@ -309,18 +221,19 @@ void ESP32BLETracker::start_scan_(bool first) {
|
|
|
309
221
|
for (auto *listener : this->listeners_)
|
|
310
222
|
listener->on_scan_end();
|
|
311
223
|
}
|
|
224
|
+
#ifdef USE_ESP32_BLE_DEVICE
|
|
312
225
|
this->already_discovered_.clear();
|
|
226
|
+
#endif
|
|
313
227
|
this->scan_params_.scan_type = this->scan_active_ ? BLE_SCAN_TYPE_ACTIVE : BLE_SCAN_TYPE_PASSIVE;
|
|
314
228
|
this->scan_params_.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
|
|
315
229
|
this->scan_params_.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL;
|
|
316
230
|
this->scan_params_.scan_interval = this->scan_interval_;
|
|
317
231
|
this->scan_params_.scan_window = this->scan_window_;
|
|
318
232
|
|
|
319
|
-
// Start timeout
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
});
|
|
233
|
+
// Start timeout monitoring in loop() instead of using scheduler
|
|
234
|
+
// This prevents false reboots when the loop is blocked
|
|
235
|
+
this->scan_start_time_ = App.get_loop_component_start_time();
|
|
236
|
+
this->scan_timeout_state_ = ScanTimeoutState::MONITORING;
|
|
324
237
|
|
|
325
238
|
esp_err_t err = esp_ble_gap_set_scan_params(&this->scan_params_);
|
|
326
239
|
if (err != ESP_OK) {
|
|
@@ -334,21 +247,6 @@ void ESP32BLETracker::start_scan_(bool first) {
|
|
|
334
247
|
}
|
|
335
248
|
}
|
|
336
249
|
|
|
337
|
-
void ESP32BLETracker::end_of_scan_() {
|
|
338
|
-
// The lock must be held when calling this function.
|
|
339
|
-
if (this->scanner_state_ != ScannerState::STOPPED) {
|
|
340
|
-
ESP_LOGE(TAG, "end_of_scan_ called while scanner is not stopped.");
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
ESP_LOGD(TAG, "End of scan, set scanner state to IDLE.");
|
|
344
|
-
this->already_discovered_.clear();
|
|
345
|
-
this->cancel_timeout("scan");
|
|
346
|
-
|
|
347
|
-
for (auto *listener : this->listeners_)
|
|
348
|
-
listener->on_scan_end();
|
|
349
|
-
this->set_scanner_state_(ScannerState::IDLE);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
250
|
void ESP32BLETracker::register_client(ESPBTClient *client) {
|
|
353
251
|
client->app_id = ++this->app_id_;
|
|
354
252
|
this->clients_.push_back(client);
|
|
@@ -381,6 +279,8 @@ void ESP32BLETracker::recalculate_advertisement_parser_types() {
|
|
|
381
279
|
}
|
|
382
280
|
|
|
383
281
|
void ESP32BLETracker::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
|
|
282
|
+
// Note: This handler is called from the main loop context, not directly from the BT task.
|
|
283
|
+
// The esp32_ble component queues events via enqueue_ble_event() and processes them in loop().
|
|
384
284
|
switch (event) {
|
|
385
285
|
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
|
|
386
286
|
this->gap_scan_set_param_complete_(param->scan_param_cmpl);
|
|
@@ -401,51 +301,32 @@ void ESP32BLETracker::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_ga
|
|
|
401
301
|
}
|
|
402
302
|
|
|
403
303
|
void ESP32BLETracker::gap_scan_event_handler(const BLEScanResult &scan_result) {
|
|
304
|
+
// Note: This handler is called from the main loop context via esp32_ble's event queue.
|
|
305
|
+
// We process advertisements immediately instead of buffering them.
|
|
404
306
|
ESP_LOGV(TAG, "gap_scan_result - event %d", scan_result.search_evt);
|
|
405
307
|
|
|
406
308
|
if (scan_result.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) {
|
|
407
|
-
//
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
//
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
// Load consumer's index with acquire to see their latest updates
|
|
416
|
-
uint8_t read_idx = this->ring_read_index_.load(std::memory_order_acquire);
|
|
417
|
-
|
|
418
|
-
// Check if buffer is full
|
|
419
|
-
if (next_write_idx != read_idx) {
|
|
420
|
-
// Write to ring buffer
|
|
421
|
-
this->scan_ring_buffer_[write_idx] = scan_result;
|
|
422
|
-
|
|
423
|
-
// Store with release to ensure the write is visible before index update
|
|
424
|
-
this->ring_write_index_.store(next_write_idx, std::memory_order_release);
|
|
425
|
-
} else {
|
|
426
|
-
// Buffer full, track dropped results
|
|
427
|
-
this->scan_results_dropped_.fetch_add(1, std::memory_order_relaxed);
|
|
309
|
+
// Process the scan result immediately
|
|
310
|
+
bool found_discovered_client = this->process_scan_result_(scan_result);
|
|
311
|
+
|
|
312
|
+
// If we found a discovered client that needs promotion, stop scanning
|
|
313
|
+
// This replaces the promote_to_connecting logic from loop()
|
|
314
|
+
if (found_discovered_client && this->scanner_state_ == ScannerState::RUNNING) {
|
|
315
|
+
ESP_LOGD(TAG, "Found discovered client, stopping scan for connection");
|
|
316
|
+
this->stop_scan_();
|
|
428
317
|
}
|
|
429
318
|
} else if (scan_result.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) {
|
|
430
319
|
// Scan finished on its own
|
|
431
320
|
if (this->scanner_state_ != ScannerState::RUNNING) {
|
|
432
|
-
|
|
433
|
-
ESP_LOGE(TAG, "Scan was not running when scan completed.");
|
|
434
|
-
} else if (this->scanner_state_ == ScannerState::STARTING) {
|
|
435
|
-
ESP_LOGE(TAG, "Scan was not started when scan completed.");
|
|
436
|
-
} else if (this->scanner_state_ == ScannerState::FAILED) {
|
|
437
|
-
ESP_LOGE(TAG, "Scan was in failed state when scan completed.");
|
|
438
|
-
} else if (this->scanner_state_ == ScannerState::IDLE) {
|
|
439
|
-
ESP_LOGE(TAG, "Scan was idle when scan completed.");
|
|
440
|
-
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
|
441
|
-
ESP_LOGE(TAG, "Scan was stopped when scan completed.");
|
|
442
|
-
}
|
|
321
|
+
this->log_unexpected_state_("scan complete", ScannerState::RUNNING);
|
|
443
322
|
}
|
|
444
|
-
|
|
323
|
+
// Scan completed naturally, perform cleanup and transition to IDLE
|
|
324
|
+
this->cleanup_scan_state_(false);
|
|
445
325
|
}
|
|
446
326
|
}
|
|
447
327
|
|
|
448
328
|
void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t::ble_scan_param_cmpl_evt_param ¶m) {
|
|
329
|
+
// Called from main loop context via gap_event_handler after being queued from BT task
|
|
449
330
|
ESP_LOGV(TAG, "gap_scan_set_param_complete - status %d", param.status);
|
|
450
331
|
if (param.status == ESP_BT_STATUS_DONE) {
|
|
451
332
|
this->scan_set_param_failed_ = ESP_BT_STATUS_SUCCESS;
|
|
@@ -455,20 +336,11 @@ void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t:
|
|
|
455
336
|
}
|
|
456
337
|
|
|
457
338
|
void ESP32BLETracker::gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param ¶m) {
|
|
339
|
+
// Called from main loop context via gap_event_handler after being queued from BT task
|
|
458
340
|
ESP_LOGV(TAG, "gap_scan_start_complete - status %d", param.status);
|
|
459
341
|
this->scan_start_failed_ = param.status;
|
|
460
342
|
if (this->scanner_state_ != ScannerState::STARTING) {
|
|
461
|
-
|
|
462
|
-
ESP_LOGE(TAG, "Scan was already running when start complete.");
|
|
463
|
-
} else if (this->scanner_state_ == ScannerState::STOPPING) {
|
|
464
|
-
ESP_LOGE(TAG, "Scan was stopping when start complete.");
|
|
465
|
-
} else if (this->scanner_state_ == ScannerState::FAILED) {
|
|
466
|
-
ESP_LOGE(TAG, "Scan was in failed state when start complete.");
|
|
467
|
-
} else if (this->scanner_state_ == ScannerState::IDLE) {
|
|
468
|
-
ESP_LOGE(TAG, "Scan was idle when start complete.");
|
|
469
|
-
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
|
470
|
-
ESP_LOGE(TAG, "Scan was stopped when start complete.");
|
|
471
|
-
}
|
|
343
|
+
this->log_unexpected_state_("start complete", ScannerState::STARTING);
|
|
472
344
|
}
|
|
473
345
|
if (param.status == ESP_BT_STATUS_SUCCESS) {
|
|
474
346
|
this->scan_start_fail_count_ = 0;
|
|
@@ -482,21 +354,15 @@ void ESP32BLETracker::gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble
|
|
|
482
354
|
}
|
|
483
355
|
|
|
484
356
|
void ESP32BLETracker::gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param ¶m) {
|
|
357
|
+
// Called from main loop context via gap_event_handler after being queued from BT task
|
|
358
|
+
// This allows us to safely transition to IDLE state and perform cleanup without race conditions
|
|
485
359
|
ESP_LOGV(TAG, "gap_scan_stop_complete - status %d", param.status);
|
|
486
360
|
if (this->scanner_state_ != ScannerState::STOPPING) {
|
|
487
|
-
|
|
488
|
-
ESP_LOGE(TAG, "Scan was not running when stop complete.");
|
|
489
|
-
} else if (this->scanner_state_ == ScannerState::STARTING) {
|
|
490
|
-
ESP_LOGE(TAG, "Scan was not started when stop complete.");
|
|
491
|
-
} else if (this->scanner_state_ == ScannerState::FAILED) {
|
|
492
|
-
ESP_LOGE(TAG, "Scan was in failed state when stop complete.");
|
|
493
|
-
} else if (this->scanner_state_ == ScannerState::IDLE) {
|
|
494
|
-
ESP_LOGE(TAG, "Scan was idle when stop complete.");
|
|
495
|
-
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
|
496
|
-
ESP_LOGE(TAG, "Scan was stopped when stop complete.");
|
|
497
|
-
}
|
|
361
|
+
this->log_unexpected_state_("stop complete", ScannerState::STOPPING);
|
|
498
362
|
}
|
|
499
|
-
|
|
363
|
+
|
|
364
|
+
// Perform cleanup and transition to IDLE
|
|
365
|
+
this->cleanup_scan_state_(true);
|
|
500
366
|
}
|
|
501
367
|
|
|
502
368
|
void ESP32BLETracker::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
|
@@ -511,6 +377,7 @@ void ESP32BLETracker::set_scanner_state_(ScannerState state) {
|
|
|
511
377
|
this->scanner_state_callbacks_.call(state);
|
|
512
378
|
}
|
|
513
379
|
|
|
380
|
+
#ifdef USE_ESP32_BLE_DEVICE
|
|
514
381
|
ESPBLEiBeacon::ESPBLEiBeacon(const uint8_t *data) { memcpy(&this->beacon_data_, data, sizeof(beacon_data_)); }
|
|
515
382
|
optional<ESPBLEiBeacon> ESPBLEiBeacon::from_manufacturer_data(const ServiceData &data) {
|
|
516
383
|
if (!data.uuid.contains(0x4C, 0x00))
|
|
@@ -751,13 +618,16 @@ void ESPBTDevice::parse_adv_(const uint8_t *payload, uint8_t len) {
|
|
|
751
618
|
}
|
|
752
619
|
}
|
|
753
620
|
}
|
|
621
|
+
|
|
754
622
|
std::string ESPBTDevice::address_str() const {
|
|
755
623
|
char mac[24];
|
|
756
624
|
snprintf(mac, sizeof(mac), "%02X:%02X:%02X:%02X:%02X:%02X", this->address_[0], this->address_[1], this->address_[2],
|
|
757
625
|
this->address_[3], this->address_[4], this->address_[5]);
|
|
758
626
|
return mac;
|
|
759
627
|
}
|
|
628
|
+
|
|
760
629
|
uint64_t ESPBTDevice::address_uint64() const { return esp32_ble::ble_addr_to_uint64(this->address_); }
|
|
630
|
+
#endif // USE_ESP32_BLE_DEVICE
|
|
761
631
|
|
|
762
632
|
void ESP32BLETracker::dump_config() {
|
|
763
633
|
ESP_LOGCONFIG(TAG, "BLE Tracker:");
|
|
@@ -769,33 +639,16 @@ void ESP32BLETracker::dump_config() {
|
|
|
769
639
|
" Continuous Scanning: %s",
|
|
770
640
|
this->scan_duration_, this->scan_interval_ * 0.625f, this->scan_window_ * 0.625f,
|
|
771
641
|
this->scan_active_ ? "ACTIVE" : "PASSIVE", YESNO(this->scan_continuous_));
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
case ScannerState::STARTING:
|
|
777
|
-
ESP_LOGCONFIG(TAG, " Scanner State: STARTING");
|
|
778
|
-
break;
|
|
779
|
-
case ScannerState::RUNNING:
|
|
780
|
-
ESP_LOGCONFIG(TAG, " Scanner State: RUNNING");
|
|
781
|
-
break;
|
|
782
|
-
case ScannerState::STOPPING:
|
|
783
|
-
ESP_LOGCONFIG(TAG, " Scanner State: STOPPING");
|
|
784
|
-
break;
|
|
785
|
-
case ScannerState::STOPPED:
|
|
786
|
-
ESP_LOGCONFIG(TAG, " Scanner State: STOPPED");
|
|
787
|
-
break;
|
|
788
|
-
case ScannerState::FAILED:
|
|
789
|
-
ESP_LOGCONFIG(TAG, " Scanner State: FAILED");
|
|
790
|
-
break;
|
|
791
|
-
}
|
|
792
|
-
ESP_LOGCONFIG(TAG, " Connecting: %d, discovered: %d, searching: %d, disconnecting: %d", connecting_, discovered_,
|
|
793
|
-
searching_, disconnecting_);
|
|
642
|
+
ESP_LOGCONFIG(TAG, " Scanner State: %s", this->scanner_state_to_string_(this->scanner_state_));
|
|
643
|
+
ESP_LOGCONFIG(TAG, " Connecting: %d, discovered: %d, searching: %d, disconnecting: %d",
|
|
644
|
+
this->client_state_counts_.connecting, this->client_state_counts_.discovered,
|
|
645
|
+
this->client_state_counts_.searching, this->client_state_counts_.disconnecting);
|
|
794
646
|
if (this->scan_start_fail_count_) {
|
|
795
647
|
ESP_LOGCONFIG(TAG, " Scan Start Fail Count: %d", this->scan_start_fail_count_);
|
|
796
648
|
}
|
|
797
649
|
}
|
|
798
650
|
|
|
651
|
+
#ifdef USE_ESP32_BLE_DEVICE
|
|
799
652
|
void ESP32BLETracker::print_bt_device_info(const ESPBTDevice &device) {
|
|
800
653
|
const uint64_t address = device.address_uint64();
|
|
801
654
|
for (auto &disc : this->already_discovered_) {
|
|
@@ -867,7 +720,157 @@ bool ESPBTDevice::resolve_irk(const uint8_t *irk) const {
|
|
|
867
720
|
ecb_ciphertext[13] == ((addr64 >> 16) & 0xff);
|
|
868
721
|
}
|
|
869
722
|
|
|
870
|
-
|
|
871
|
-
|
|
723
|
+
bool ESP32BLETracker::has_connecting_clients_() const {
|
|
724
|
+
for (auto *client : this->clients_) {
|
|
725
|
+
auto state = client->state();
|
|
726
|
+
if (state == ClientState::CONNECTING || state == ClientState::READY_TO_CONNECT) {
|
|
727
|
+
return true;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
return false;
|
|
731
|
+
}
|
|
732
|
+
#endif // USE_ESP32_BLE_DEVICE
|
|
733
|
+
|
|
734
|
+
bool ESP32BLETracker::process_scan_result_(const BLEScanResult &scan_result) {
|
|
735
|
+
bool found_discovered_client = false;
|
|
736
|
+
|
|
737
|
+
// Process raw advertisements
|
|
738
|
+
if (this->raw_advertisements_) {
|
|
739
|
+
for (auto *listener : this->listeners_) {
|
|
740
|
+
listener->parse_devices(&scan_result, 1);
|
|
741
|
+
}
|
|
742
|
+
for (auto *client : this->clients_) {
|
|
743
|
+
client->parse_devices(&scan_result, 1);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Process parsed advertisements
|
|
748
|
+
if (this->parse_advertisements_) {
|
|
749
|
+
#ifdef USE_ESP32_BLE_DEVICE
|
|
750
|
+
ESPBTDevice device;
|
|
751
|
+
device.parse_scan_rst(scan_result);
|
|
752
|
+
|
|
753
|
+
bool found = false;
|
|
754
|
+
for (auto *listener : this->listeners_) {
|
|
755
|
+
if (listener->parse_device(device))
|
|
756
|
+
found = true;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
for (auto *client : this->clients_) {
|
|
760
|
+
if (client->parse_device(device)) {
|
|
761
|
+
found = true;
|
|
762
|
+
// Check if this client is discovered and needs promotion
|
|
763
|
+
if (client->state() == ClientState::DISCOVERED) {
|
|
764
|
+
// Only check for connecting clients if we found a discovered client
|
|
765
|
+
// This matches the original logic: !connecting && client->state() == DISCOVERED
|
|
766
|
+
if (!this->has_connecting_clients_()) {
|
|
767
|
+
found_discovered_client = true;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
if (!found && !this->scan_continuous_) {
|
|
774
|
+
this->print_bt_device_info(device);
|
|
775
|
+
}
|
|
776
|
+
#endif // USE_ESP32_BLE_DEVICE
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
return found_discovered_client;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
void ESP32BLETracker::cleanup_scan_state_(bool is_stop_complete) {
|
|
783
|
+
ESP_LOGD(TAG, "Scan %scomplete, set scanner state to IDLE.", is_stop_complete ? "stop " : "");
|
|
784
|
+
#ifdef USE_ESP32_BLE_DEVICE
|
|
785
|
+
this->already_discovered_.clear();
|
|
786
|
+
#endif
|
|
787
|
+
// Reset timeout state machine instead of cancelling scheduler timeout
|
|
788
|
+
this->scan_timeout_state_ = ScanTimeoutState::INACTIVE;
|
|
789
|
+
|
|
790
|
+
for (auto *listener : this->listeners_)
|
|
791
|
+
listener->on_scan_end();
|
|
792
|
+
|
|
793
|
+
this->set_scanner_state_(ScannerState::IDLE);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
void ESP32BLETracker::handle_scanner_failure_() {
|
|
797
|
+
this->stop_scan_();
|
|
798
|
+
if (this->scan_start_fail_count_ == std::numeric_limits<uint8_t>::max()) {
|
|
799
|
+
ESP_LOGE(TAG, "Scan could not restart after %d attempts, rebooting to restore stack (IDF)",
|
|
800
|
+
std::numeric_limits<uint8_t>::max());
|
|
801
|
+
App.reboot();
|
|
802
|
+
}
|
|
803
|
+
if (this->scan_start_failed_) {
|
|
804
|
+
ESP_LOGE(TAG, "Scan start failed: %d", this->scan_start_failed_);
|
|
805
|
+
this->scan_start_failed_ = ESP_BT_STATUS_SUCCESS;
|
|
806
|
+
}
|
|
807
|
+
if (this->scan_set_param_failed_) {
|
|
808
|
+
ESP_LOGE(TAG, "Scan set param failed: %d", this->scan_set_param_failed_);
|
|
809
|
+
this->scan_set_param_failed_ = ESP_BT_STATUS_SUCCESS;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
void ESP32BLETracker::try_promote_discovered_clients_() {
|
|
814
|
+
// Only promote the first discovered client to avoid multiple simultaneous connections
|
|
815
|
+
for (auto *client : this->clients_) {
|
|
816
|
+
if (client->state() != ClientState::DISCOVERED) {
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
if (this->scanner_state_ == ScannerState::RUNNING) {
|
|
821
|
+
ESP_LOGD(TAG, "Stopping scan to make connection");
|
|
822
|
+
this->stop_scan_();
|
|
823
|
+
// Don't wait for scan stop complete - promote immediately.
|
|
824
|
+
// This is safe because ESP-IDF processes BLE commands sequentially through its internal mailbox queue.
|
|
825
|
+
// This guarantees that the stop scan command will be fully processed before any subsequent connect command,
|
|
826
|
+
// preventing race conditions or overlapping operations.
|
|
827
|
+
}
|
|
872
828
|
|
|
829
|
+
ESP_LOGD(TAG, "Promoting client to connect");
|
|
830
|
+
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
|
|
831
|
+
this->update_coex_preference_(true);
|
|
873
832
|
#endif
|
|
833
|
+
client->set_state(ClientState::READY_TO_CONNECT);
|
|
834
|
+
break;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
const char *ESP32BLETracker::scanner_state_to_string_(ScannerState state) const {
|
|
839
|
+
switch (state) {
|
|
840
|
+
case ScannerState::IDLE:
|
|
841
|
+
return "IDLE";
|
|
842
|
+
case ScannerState::STARTING:
|
|
843
|
+
return "STARTING";
|
|
844
|
+
case ScannerState::RUNNING:
|
|
845
|
+
return "RUNNING";
|
|
846
|
+
case ScannerState::STOPPING:
|
|
847
|
+
return "STOPPING";
|
|
848
|
+
case ScannerState::FAILED:
|
|
849
|
+
return "FAILED";
|
|
850
|
+
default:
|
|
851
|
+
return "UNKNOWN";
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
void ESP32BLETracker::log_unexpected_state_(const char *operation, ScannerState expected_state) const {
|
|
856
|
+
ESP_LOGE(TAG, "Unexpected state: %s on %s, expected: %s", this->scanner_state_to_string_(this->scanner_state_),
|
|
857
|
+
operation, this->scanner_state_to_string_(expected_state));
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
|
|
861
|
+
void ESP32BLETracker::update_coex_preference_(bool force_ble) {
|
|
862
|
+
if (force_ble && !this->coex_prefer_ble_) {
|
|
863
|
+
ESP_LOGD(TAG, "Setting coexistence to Bluetooth to make connection.");
|
|
864
|
+
this->coex_prefer_ble_ = true;
|
|
865
|
+
esp_coex_preference_set(ESP_COEX_PREFER_BT); // Prioritize Bluetooth
|
|
866
|
+
} else if (!force_ble && this->coex_prefer_ble_) {
|
|
867
|
+
ESP_LOGD(TAG, "Setting coexistence preference to balanced.");
|
|
868
|
+
this->coex_prefer_ble_ = false;
|
|
869
|
+
esp_coex_preference_set(ESP_COEX_PREFER_BALANCE); // Reset to default
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
#endif
|
|
873
|
+
|
|
874
|
+
} // namespace esphome::esp32_ble_tracker
|
|
875
|
+
|
|
876
|
+
#endif // USE_ESP32
|