esphome 2025.4.2__py3-none-any.whl → 2025.5.0b3__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 +16 -14
- esphome/components/ac_dimmer/ac_dimmer.cpp +3 -2
- esphome/components/adc/__init__.py +51 -34
- esphome/components/airthings_wave_base/__init__.py +1 -1
- esphome/components/alarm_control_panel/__init__.py +37 -2
- esphome/components/am43/cover/__init__.py +4 -5
- esphome/components/analog_threshold/analog_threshold_binary_sensor.cpp +6 -4
- esphome/components/analog_threshold/analog_threshold_binary_sensor.h +4 -5
- esphome/components/analog_threshold/binary_sensor.py +10 -8
- esphome/components/anova/climate.py +4 -5
- esphome/components/api/__init__.py +25 -8
- esphome/components/api/api_connection.cpp +81 -13
- esphome/components/api/api_connection.h +13 -1
- esphome/components/api/api_frame_helper.cpp +232 -177
- esphome/components/api/api_frame_helper.h +61 -8
- esphome/components/api/api_noise_context.h +13 -4
- esphome/components/api/api_pb2.cpp +1422 -1
- esphome/components/api/api_pb2.h +255 -1
- esphome/components/api/api_pb2_service.cpp +162 -49
- esphome/components/api/api_pb2_service.h +90 -51
- esphome/components/api/api_pb2_size.h +361 -0
- esphome/components/api/api_server.cpp +110 -34
- esphome/components/api/api_server.h +8 -0
- esphome/components/api/proto.h +86 -17
- esphome/components/as7341/as7341.h +1 -1
- esphome/components/atm90e32/__init__.py +1 -0
- esphome/components/atm90e32/atm90e32.cpp +576 -199
- esphome/components/atm90e32/atm90e32.h +128 -31
- esphome/components/atm90e32/atm90e32_reg.h +4 -2
- esphome/components/atm90e32/button/__init__.py +62 -10
- esphome/components/atm90e32/button/atm90e32_button.cpp +63 -4
- esphome/components/atm90e32/button/atm90e32_button.h +36 -4
- esphome/components/atm90e32/number/__init__.py +130 -0
- esphome/components/atm90e32/number/atm90e32_number.h +16 -0
- esphome/components/atm90e32/sensor.py +21 -4
- esphome/components/atm90e32/text_sensor/__init__.py +48 -0
- esphome/components/audio/__init__.py +96 -49
- esphome/components/audio/audio.h +48 -0
- esphome/components/audio/audio_decoder.cpp +1 -1
- esphome/components/audio/audio_resampler.cpp +2 -0
- esphome/components/audio/audio_resampler.h +1 -0
- esphome/components/ballu/climate.py +2 -9
- esphome/components/bang_bang/climate.py +5 -6
- esphome/components/bedjet/bedjet_hub.cpp +1 -0
- esphome/components/bedjet/climate/__init__.py +3 -8
- esphome/components/bedjet/fan/__init__.py +2 -11
- esphome/components/binary/fan/__init__.py +13 -16
- esphome/components/binary_sensor/__init__.py +13 -10
- esphome/components/bl0906/constants.h +16 -16
- esphome/components/ble_client/text_sensor/__init__.py +3 -5
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +4 -6
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +136 -21
- esphome/components/bluetooth_proxy/bluetooth_proxy.h +7 -0
- esphome/components/button/__init__.py +11 -8
- esphome/components/canbus/canbus.cpp +3 -0
- esphome/components/canbus/canbus.h +16 -0
- esphome/components/ccs811/sensor.py +9 -6
- esphome/components/climate/__init__.py +35 -2
- esphome/components/climate/climate_mode.h +1 -1
- esphome/components/climate/climate_traits.h +63 -57
- esphome/components/climate_ir/__init__.py +57 -17
- esphome/components/climate_ir_lg/climate.py +2 -5
- esphome/components/climate_ir_lg/climate_ir_lg.cpp +7 -7
- esphome/components/climate_ir_lg/climate_ir_lg.h +1 -1
- esphome/components/color/__init__.py +2 -0
- esphome/components/const/__init__.py +5 -0
- esphome/components/coolix/climate.py +2 -9
- esphome/components/copy/cover/__init__.py +10 -9
- esphome/components/copy/fan/__init__.py +11 -9
- esphome/components/copy/lock/__init__.py +11 -9
- esphome/components/copy/text/__init__.py +9 -6
- esphome/components/cover/__init__.py +37 -2
- esphome/components/cse7766/cse7766.cpp +2 -1
- esphome/components/cst226/binary_sensor/__init__.py +28 -0
- esphome/components/cst226/binary_sensor/cs226_button.h +22 -0
- esphome/components/cst226/binary_sensor/cstt6_button.cpp +19 -0
- esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +27 -5
- esphome/components/cst226/touchscreen/cst226_touchscreen.h +10 -10
- esphome/components/current_based/cover.py +37 -36
- esphome/components/current_based/current_based_cover.cpp +2 -1
- esphome/components/daikin/climate.py +2 -9
- esphome/components/daikin/daikin.cpp +15 -9
- esphome/components/daikin/daikin.h +5 -5
- esphome/components/daikin_arc/climate.py +2 -7
- esphome/components/daikin_brc/climate.py +3 -5
- esphome/components/dallas_temp/dallas_temp.cpp +17 -24
- esphome/components/dallas_temp/dallas_temp.h +0 -1
- esphome/components/daly_bms/daly_bms.cpp +2 -1
- esphome/components/debug/debug_component.cpp +6 -1
- esphome/components/debug/debug_component.h +6 -0
- esphome/components/debug/debug_esp32.cpp +109 -254
- esphome/components/debug/sensor.py +14 -0
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +13 -1
- esphome/components/delonghi/climate.py +2 -9
- esphome/components/demo/__init__.py +18 -20
- esphome/components/dfrobot_sen0395/switch/__init__.py +21 -22
- esphome/components/dps310/sensor.py +6 -6
- esphome/components/ee895/sensor.py +9 -9
- esphome/components/emmeti/climate.py +2 -9
- esphome/components/endstop/cover.py +17 -16
- esphome/components/endstop/endstop_cover.cpp +2 -1
- esphome/components/ens160_base/__init__.py +12 -9
- esphome/components/esp32/__init__.py +60 -3
- esphome/components/esp32/core.cpp +11 -5
- esphome/components/esp32/gpio.cpp +86 -24
- esphome/components/esp32/gpio.py +15 -16
- esphome/components/esp32/gpio_esp32.py +1 -2
- esphome/components/esp32/gpio_esp32_c2.py +1 -1
- esphome/components/esp32/gpio_esp32_c3.py +1 -1
- esphome/components/esp32/gpio_esp32_c6.py +1 -1
- esphome/components/esp32/gpio_esp32_h2.py +1 -1
- esphome/components/esp32_ble/ble.cpp +1 -0
- esphome/components/esp32_ble/ble.h +5 -3
- esphome/components/esp32_ble/ble_advertising.cpp +2 -1
- esphome/components/esp32_ble/ble_advertising.h +1 -0
- esphome/components/esp32_ble_server/__init__.py +3 -0
- esphome/components/esp32_ble_tracker/__init__.py +7 -1
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +192 -118
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +29 -3
- esphome/components/esp32_camera/esp32_camera.cpp +2 -1
- esphome/components/esp32_camera/esp32_camera.h +1 -1
- esphome/components/esp32_can/esp32_can.cpp +1 -1
- esphome/components/esp32_improv/esp32_improv_component.cpp +1 -1
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +1 -1
- esphome/components/esp32_rmt_led_strip/led_strip.h +7 -5
- esphome/components/esp32_rmt_led_strip/light.py +9 -1
- esphome/components/esp32_touch/esp32_touch.cpp +1 -1
- esphome/components/esp8266/gpio.cpp +69 -8
- esphome/components/ethernet/ethernet_component.cpp +1 -1
- esphome/components/event/__init__.py +13 -10
- esphome/components/factory_reset/switch/__init__.py +7 -21
- esphome/components/fan/__init__.py +52 -5
- esphome/components/fastled_base/__init__.py +1 -4
- esphome/components/fastled_base/fastled_light.cpp +1 -1
- esphome/components/feedback/cover.py +38 -33
- esphome/components/feedback/feedback_cover.cpp +2 -1
- esphome/components/fujitsu_general/climate.py +2 -9
- esphome/components/gcja5/gcja5.cpp +2 -1
- esphome/components/gpio/one_wire/gpio_one_wire.cpp +45 -43
- esphome/components/gpio/one_wire/gpio_one_wire.h +2 -1
- esphome/components/gpio_expander/cached_gpio.h +22 -7
- esphome/components/gps/__init__.py +47 -17
- esphome/components/gps/gps.cpp +42 -23
- esphome/components/gps/gps.h +17 -13
- esphome/components/graph/__init__.py +1 -2
- esphome/components/gree/climate.py +4 -6
- esphome/components/gree/gree.cpp +16 -2
- esphome/components/gree/gree.h +2 -2
- esphome/components/growatt_solar/growatt_solar.cpp +2 -1
- esphome/components/haier/climate.py +37 -34
- esphome/components/hbridge/fan/__init__.py +19 -17
- esphome/components/he60r/cover.py +4 -5
- esphome/components/heatpumpir/climate.py +3 -6
- esphome/components/hitachi_ac344/climate.py +2 -9
- esphome/components/hitachi_ac424/climate.py +2 -9
- esphome/components/hm3301/hm3301.h +1 -1
- esphome/components/hte501/sensor.py +6 -6
- esphome/components/http_request/__init__.py +39 -6
- esphome/components/http_request/http_request.cpp +20 -0
- esphome/components/http_request/http_request.h +57 -15
- esphome/components/http_request/http_request_arduino.cpp +22 -6
- esphome/components/http_request/http_request_arduino.h +4 -3
- esphome/components/http_request/http_request_host.cpp +141 -0
- esphome/components/http_request/http_request_host.h +37 -0
- esphome/components/http_request/http_request_idf.cpp +35 -3
- esphome/components/http_request/http_request_idf.h +10 -3
- esphome/components/http_request/httplib.h +9691 -0
- esphome/components/http_request/update/__init__.py +11 -8
- esphome/components/hyt271/sensor.py +6 -6
- esphome/components/i2c/i2c.h +4 -0
- esphome/components/i2c/i2c_bus_esp_idf.cpp +1 -1
- esphome/components/i2s_audio/__init__.py +131 -22
- esphome/components/i2s_audio/i2s_audio.h +44 -4
- esphome/components/i2s_audio/media_player/__init__.py +19 -9
- esphome/components/i2s_audio/microphone/__init__.py +63 -5
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +351 -61
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +40 -6
- esphome/components/i2s_audio/speaker/__init__.py +31 -5
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +155 -19
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +17 -4
- esphome/components/ili9xxx/ili9xxx_init.h +1 -1
- esphome/components/image/__init__.py +37 -17
- esphome/components/image/image.cpp +25 -8
- esphome/components/internal_temperature/internal_temperature.cpp +6 -4
- esphome/components/key_collector/__init__.py +35 -0
- esphome/components/key_collector/key_collector.cpp +8 -0
- esphome/components/key_collector/key_collector.h +10 -0
- esphome/components/kuntze/kuntze.cpp +2 -1
- esphome/components/ld2410/ld2410.h +1 -1
- esphome/components/ld2450/ld2450.h +1 -1
- esphome/components/light/__init__.py +57 -0
- esphome/components/lock/__init__.py +51 -4
- esphome/components/lock/automation.h +2 -13
- esphome/components/logger/__init__.py +22 -0
- esphome/components/logger/logger.cpp +154 -103
- esphome/components/logger/logger.h +211 -36
- esphome/components/logger/task_log_buffer.cpp +138 -0
- esphome/components/logger/task_log_buffer.h +69 -0
- esphome/components/lvgl/__init__.py +13 -5
- esphome/components/lvgl/automation.py +50 -1
- esphome/components/lvgl/defines.py +0 -1
- esphome/components/lvgl/lvgl_esphome.cpp +5 -1
- esphome/components/lvgl/text/__init__.py +1 -2
- esphome/components/mapping/__init__.py +134 -0
- esphome/components/matrix_keypad/matrix_keypad.cpp +2 -1
- esphome/components/max7219digit/max7219digit.cpp +28 -27
- esphome/components/mdns/__init__.py +11 -5
- esphome/components/mdns/mdns_component.cpp +11 -5
- esphome/components/mdns/mdns_component.h +3 -2
- esphome/components/mdns/mdns_esp32.cpp +4 -3
- esphome/components/mdns/mdns_esp8266.cpp +4 -2
- esphome/components/mdns/mdns_libretiny.cpp +4 -2
- esphome/components/mdns/mdns_rp2040.cpp +4 -2
- esphome/components/media_player/__init__.py +33 -1
- esphome/components/mhz19/sensor.py +11 -7
- esphome/components/micro_wake_word/__init__.py +99 -31
- esphome/components/micro_wake_word/automation.h +54 -0
- esphome/components/micro_wake_word/micro_wake_word.cpp +331 -319
- esphome/components/micro_wake_word/micro_wake_word.h +58 -105
- esphome/components/micro_wake_word/preprocessor_settings.h +19 -2
- esphome/components/micro_wake_word/streaming_model.cpp +158 -41
- esphome/components/micro_wake_word/streaming_model.h +85 -13
- esphome/components/microphone/__init__.py +139 -9
- esphome/components/microphone/automation.h +14 -2
- esphome/components/microphone/microphone.cpp +21 -0
- esphome/components/microphone/microphone.h +14 -5
- esphome/components/microphone/microphone_source.cpp +95 -0
- esphome/components/microphone/microphone_source.h +80 -0
- esphome/components/mics_4514/sensor.py +25 -14
- esphome/components/midea/climate.py +3 -4
- esphome/components/midea_ir/climate.py +3 -5
- esphome/components/mipi_spi/__init__.py +15 -0
- esphome/components/mipi_spi/display.py +474 -0
- esphome/components/mipi_spi/mipi_spi.cpp +481 -0
- esphome/components/mipi_spi/mipi_spi.h +171 -0
- esphome/components/mipi_spi/models/__init__.py +65 -0
- esphome/components/mipi_spi/models/amoled.py +72 -0
- esphome/components/mipi_spi/models/commands.py +82 -0
- esphome/components/mipi_spi/models/cyd.py +10 -0
- esphome/components/mipi_spi/models/ili.py +749 -0
- esphome/components/mipi_spi/models/jc.py +260 -0
- esphome/components/mipi_spi/models/lanbon.py +15 -0
- esphome/components/mipi_spi/models/lilygo.py +60 -0
- esphome/components/mipi_spi/models/waveshare.py +139 -0
- esphome/components/mitsubishi/climate.py +2 -5
- esphome/components/mitsubishi/mitsubishi.cpp +9 -9
- esphome/components/mixer/speaker/mixer_speaker.cpp +12 -22
- esphome/components/mixer/speaker/mixer_speaker.h +1 -3
- esphome/components/mlx90393/sensor.py +5 -0
- esphome/components/mlx90393/sensor_mlx90393.cpp +195 -13
- esphome/components/mlx90393/sensor_mlx90393.h +21 -4
- esphome/components/modbus/modbus.cpp +2 -1
- esphome/components/mqtt/__init__.py +1 -1
- esphome/components/mqtt/mqtt_client.cpp +6 -2
- esphome/components/mqtt/mqtt_const.h +4 -0
- esphome/components/mqtt/mqtt_fan.cpp +39 -0
- esphome/components/mqtt/mqtt_fan.h +2 -0
- esphome/components/ms5611/sensor.py +6 -6
- esphome/components/ms8607/sensor.py +3 -3
- esphome/components/network/__init__.py +1 -1
- esphome/components/nextion/base_component.py +17 -16
- esphome/components/nextion/display.py +11 -2
- esphome/components/nextion/nextion.cpp +39 -1
- esphome/components/nextion/nextion.h +50 -0
- esphome/components/noblex/climate.py +2 -9
- esphome/components/number/__init__.py +12 -9
- esphome/components/one_wire/one_wire_bus.cpp +14 -10
- esphome/components/one_wire/one_wire_bus.h +14 -8
- esphome/components/online_image/bmp_image.cpp +48 -11
- esphome/components/online_image/bmp_image.h +2 -0
- esphome/components/opentherm/binary_sensor/__init__.py +2 -4
- esphome/components/opentherm/number/__init__.py +11 -20
- esphome/components/opentherm/sensor/__init__.py +3 -3
- esphome/components/opentherm/switch/__init__.py +3 -5
- esphome/components/output/lock/__init__.py +11 -9
- esphome/components/packages/__init__.py +33 -31
- esphome/components/packet_transport/__init__.py +201 -0
- esphome/components/packet_transport/binary_sensor.py +19 -0
- esphome/components/packet_transport/packet_transport.cpp +534 -0
- esphome/components/packet_transport/packet_transport.h +154 -0
- esphome/components/packet_transport/sensor.py +19 -0
- esphome/components/pca9685/pca9685_output.cpp +2 -1
- esphome/components/pid/climate.py +2 -4
- esphome/components/pm2005/__init__.py +1 -0
- esphome/components/pm2005/pm2005.cpp +123 -0
- esphome/components/pm2005/pm2005.h +46 -0
- esphome/components/pm2005/sensor.py +86 -0
- esphome/components/pmsa003i/pmsa003i.cpp +43 -16
- esphome/components/pmsa003i/pmsa003i.h +25 -25
- esphome/components/pmsx003/pmsx003.cpp +195 -230
- esphome/components/pmsx003/pmsx003.h +51 -33
- esphome/components/pmsx003/sensor.py +21 -11
- esphome/components/pn7150/pn7150.h +2 -2
- esphome/components/pn7160/pn7160.h +2 -2
- esphome/components/prometheus/prometheus_handler.cpp +174 -0
- esphome/components/prometheus/prometheus_handler.h +17 -0
- esphome/components/psram/__init__.py +7 -5
- esphome/components/pulse_meter/pulse_meter_sensor.cpp +32 -12
- esphome/components/pulse_meter/pulse_meter_sensor.h +5 -5
- esphome/components/pzem004t/pzem004t.cpp +2 -1
- esphome/components/qspi_dbi/__init__.py +0 -1
- esphome/components/qspi_dbi/display.py +2 -1
- esphome/components/qspi_dbi/models.py +1 -2
- esphome/components/remote_base/__init__.py +91 -0
- esphome/components/remote_base/beo4_protocol.cpp +153 -0
- esphome/components/remote_base/beo4_protocol.h +43 -0
- esphome/components/remote_base/gobox_protocol.cpp +131 -0
- esphome/components/remote_base/gobox_protocol.h +54 -0
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +16 -9
- esphome/components/resampler/speaker/resampler_speaker.cpp +12 -10
- esphome/components/resampler/speaker/resampler_speaker.h +1 -1
- esphome/components/rf_bridge/rf_bridge.cpp +2 -1
- esphome/components/scd30/sensor.py +2 -3
- esphome/components/scd4x/sensor.py +4 -5
- esphome/components/sdp3x/sensor.py +2 -1
- esphome/components/sds011/sds011.cpp +2 -1
- esphome/components/select/__init__.py +19 -20
- esphome/components/sen5x/sen5x.cpp +55 -36
- esphome/components/sen5x/sensor.py +1 -1
- esphome/components/senseair/sensor.py +3 -3
- esphome/components/sensor/__init__.py +158 -14
- esphome/components/sensor/filter.cpp +23 -0
- esphome/components/sensor/filter.h +22 -0
- esphome/components/sgp30/sensor.py +14 -16
- esphome/components/sgp4x/sensor.py +1 -1
- esphome/components/sht4x/sht4x.cpp +43 -22
- esphome/components/sht4x/sht4x.h +1 -1
- esphome/components/shtcx/sensor.py +6 -6
- esphome/components/slow_pwm/slow_pwm_output.cpp +2 -1
- esphome/components/sml/text_sensor/__init__.py +4 -6
- esphome/components/sound_level/__init__.py +0 -0
- esphome/components/sound_level/sensor.py +97 -0
- esphome/components/sound_level/sound_level.cpp +194 -0
- esphome/components/sound_level/sound_level.h +73 -0
- esphome/components/speaker/media_player/__init__.py +4 -8
- esphome/components/speaker/media_player/speaker_media_player.cpp +0 -18
- esphome/components/speaker/media_player/speaker_media_player.h +0 -11
- esphome/components/speaker/speaker.h +4 -7
- esphome/components/speed/fan/__init__.py +17 -16
- esphome/components/spi/spi.h +11 -1
- esphome/components/sprinkler/__init__.py +18 -19
- esphome/components/sprinkler/sprinkler.cpp +6 -5
- esphome/components/switch/__init__.py +32 -42
- esphome/components/syslog/__init__.py +41 -0
- esphome/components/syslog/esphome_syslog.cpp +49 -0
- esphome/components/syslog/esphome_syslog.h +27 -0
- esphome/components/t6615/sensor.py +3 -3
- esphome/components/t6615/t6615.cpp +2 -1
- esphome/components/tca9555/tca9555.cpp +11 -6
- esphome/components/tcl112/climate.py +2 -9
- esphome/components/template/alarm_control_panel/__init__.py +7 -6
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +21 -17
- esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +2 -1
- esphome/components/template/cover/__init__.py +27 -21
- esphome/components/template/fan/__init__.py +14 -12
- esphome/components/template/lock/__init__.py +20 -25
- esphome/components/template/lock/automation.h +18 -0
- esphome/components/template/text/__init__.py +4 -3
- esphome/components/template/valve/__init__.py +32 -21
- esphome/components/template/valve/automation.h +24 -0
- esphome/components/text/__init__.py +32 -1
- esphome/components/text_sensor/__init__.py +24 -29
- esphome/components/thermostat/climate.py +5 -5
- esphome/components/time_based/cover.py +17 -16
- esphome/components/time_based/time_based_cover.cpp +2 -1
- esphome/components/tm1638/switch/__init__.py +10 -7
- esphome/components/tormatic/cover.py +4 -5
- esphome/components/toshiba/climate.py +3 -5
- esphome/components/touchscreen/touchscreen.cpp +3 -1
- esphome/components/tuya/climate/__init__.py +5 -6
- esphome/components/tuya/cover/__init__.py +6 -11
- esphome/components/tuya/select/__init__.py +15 -5
- esphome/components/tuya/select/tuya_select.cpp +6 -1
- esphome/components/tuya/select/tuya_select.h +5 -1
- esphome/components/uart/packet_transport/__init__.py +20 -0
- esphome/components/uart/packet_transport/uart_transport.cpp +88 -0
- esphome/components/uart/packet_transport/uart_transport.h +41 -0
- esphome/components/uart/switch/uart_switch.cpp +2 -1
- esphome/components/udp/__init__.py +126 -128
- esphome/components/udp/automation.h +40 -0
- esphome/components/udp/binary_sensor.py +3 -25
- esphome/components/udp/packet_transport/__init__.py +29 -0
- esphome/components/udp/packet_transport/udp_transport.cpp +36 -0
- esphome/components/udp/packet_transport/udp_transport.h +28 -0
- esphome/components/udp/sensor.py +3 -25
- esphome/components/udp/udp_component.cpp +26 -470
- esphome/components/udp/udp_component.h +21 -128
- esphome/components/update/__init__.py +31 -1
- esphome/components/uponor_smatrix/climate/__init__.py +4 -9
- esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +2 -1
- esphome/components/uponor_smatrix/uponor_smatrix.cpp +2 -1
- esphome/components/uptime/text_sensor/__init__.py +47 -7
- esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +12 -7
- esphome/components/uptime/text_sensor/uptime_text_sensor.h +19 -0
- esphome/components/valve/__init__.py +34 -3
- esphome/components/valve/automation.h +1 -19
- esphome/components/vl53l0x/sensor.py +11 -0
- esphome/components/vl53l0x/vl53l0x_sensor.cpp +5 -1
- esphome/components/vl53l0x/vl53l0x_sensor.h +2 -1
- esphome/components/voice_assistant/__init__.py +36 -10
- esphome/components/voice_assistant/voice_assistant.cpp +170 -144
- esphome/components/voice_assistant/voice_assistant.h +26 -25
- esphome/components/waveshare_epaper/display.py +6 -0
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +439 -37
- esphome/components/waveshare_epaper/waveshare_epaper.h +60 -11
- esphome/components/whirlpool/climate.py +3 -5
- esphome/components/whynter/climate.py +3 -5
- esphome/components/xpt2046/touchscreen/xpt2046.cpp +1 -1
- esphome/components/yashima/climate.py +6 -6
- esphome/components/zhlt01/climate.py +2 -7
- esphome/config.py +13 -13
- esphome/config_validation.py +38 -58
- esphome/const.py +15 -1
- esphome/core/__init__.py +2 -0
- esphome/core/application.cpp +23 -10
- esphome/core/application.h +9 -1
- esphome/core/automation.h +4 -3
- esphome/core/component.cpp +28 -7
- esphome/core/component.h +10 -1
- esphome/core/defines.h +23 -17
- esphome/core/macros.h +4 -0
- esphome/core/scheduler.cpp +7 -1
- esphome/cpp_generator.py +6 -2
- esphome/dashboard/web_server.py +3 -3
- esphome/helpers.py +39 -0
- esphome/loader.py +4 -0
- esphome/log.py +15 -19
- esphome/mqtt.py +23 -10
- esphome/platformio_api.py +1 -1
- esphome/schema_extractors.py +0 -1
- esphome/voluptuous_schema.py +3 -1
- esphome/vscode.py +15 -0
- esphome/wizard.py +47 -37
- esphome/zeroconf.py +7 -3
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/METADATA +10 -11
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/RECORD +440 -380
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/WHEEL +1 -1
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/entry_points.txt +0 -0
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.4.2.dist-info → esphome-2025.5.0b3.dist-info}/top_level.txt +0 -0
@@ -36,7 +36,7 @@ def esp32_c6_validate_supports(value):
|
|
36
36
|
is_input = mode[CONF_INPUT]
|
37
37
|
|
38
38
|
if num < 0 or num > 23:
|
39
|
-
raise cv.Invalid(f"Invalid pin number: {
|
39
|
+
raise cv.Invalid(f"Invalid pin number: {num} (must be 0-23)")
|
40
40
|
if is_input:
|
41
41
|
# All ESP32 pins support input mode
|
42
42
|
pass
|
@@ -45,7 +45,7 @@ def esp32_h2_validate_supports(value):
|
|
45
45
|
is_input = mode[CONF_INPUT]
|
46
46
|
|
47
47
|
if num < 0 or num > 27:
|
48
|
-
raise cv.Invalid(f"Invalid pin number: {
|
48
|
+
raise cv.Invalid(f"Invalid pin number: {num} (must be 0-27)")
|
49
49
|
if is_input:
|
50
50
|
# All ESP32 pins support input mode
|
51
51
|
pass
|
@@ -95,6 +95,7 @@ class ESP32BLE : public Component {
|
|
95
95
|
void advertising_start();
|
96
96
|
void advertising_set_service_data(const std::vector<uint8_t> &data);
|
97
97
|
void advertising_set_manufacturer_data(const std::vector<uint8_t> &data);
|
98
|
+
void advertising_set_appearance(uint16_t appearance) { this->appearance_ = appearance; }
|
98
99
|
void advertising_add_service_uuid(ESPBTUUID uuid);
|
99
100
|
void advertising_remove_service_uuid(ESPBTUUID uuid);
|
100
101
|
void advertising_register_raw_advertisement_callback(std::function<void(bool)> &&callback);
|
@@ -128,11 +129,12 @@ class ESP32BLE : public Component {
|
|
128
129
|
BLEComponentState state_{BLE_COMPONENT_STATE_OFF};
|
129
130
|
|
130
131
|
Queue<BLEEvent> ble_events_;
|
131
|
-
BLEAdvertising *advertising_;
|
132
|
+
BLEAdvertising *advertising_{};
|
132
133
|
esp_ble_io_cap_t io_cap_{ESP_IO_CAP_NONE};
|
133
|
-
uint32_t advertising_cycle_time_;
|
134
|
-
bool enable_on_boot_;
|
134
|
+
uint32_t advertising_cycle_time_{};
|
135
|
+
bool enable_on_boot_{};
|
135
136
|
optional<std::string> name_;
|
137
|
+
uint16_t appearance_{0};
|
136
138
|
};
|
137
139
|
|
138
140
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
@@ -6,6 +6,7 @@
|
|
6
6
|
#include <cstring>
|
7
7
|
#include "ble_uuid.h"
|
8
8
|
#include "esphome/core/log.h"
|
9
|
+
#include "esphome/core/application.h"
|
9
10
|
|
10
11
|
namespace esphome {
|
11
12
|
namespace esp32_ble {
|
@@ -143,7 +144,7 @@ void BLEAdvertising::loop() {
|
|
143
144
|
if (this->raw_advertisements_callbacks_.empty()) {
|
144
145
|
return;
|
145
146
|
}
|
146
|
-
const uint32_t now =
|
147
|
+
const uint32_t now = App.get_loop_component_start_time();
|
147
148
|
if (now - this->last_advertisement_time_ > this->advertising_cycle_time_) {
|
148
149
|
this->stop();
|
149
150
|
this->current_adv_index_ += 1;
|
@@ -32,6 +32,7 @@ class BLEAdvertising {
|
|
32
32
|
void set_scan_response(bool scan_response) { this->scan_response_ = scan_response; }
|
33
33
|
void set_min_preferred_interval(uint16_t interval) { this->advertising_data_.min_interval = interval; }
|
34
34
|
void set_manufacturer_data(const std::vector<uint8_t> &data);
|
35
|
+
void set_appearance(uint16_t appearance) { this->advertising_data_.appearance = appearance; }
|
35
36
|
void set_service_data(const std::vector<uint8_t> &data);
|
36
37
|
void register_raw_advertisement_callback(std::function<void(bool)> &&callback);
|
37
38
|
|
@@ -32,6 +32,7 @@ DEPENDENCIES = ["esp32"]
|
|
32
32
|
DOMAIN = "esp32_ble_server"
|
33
33
|
|
34
34
|
CONF_ADVERTISE = "advertise"
|
35
|
+
CONF_APPEARANCE = "appearance"
|
35
36
|
CONF_BROADCAST = "broadcast"
|
36
37
|
CONF_CHARACTERISTICS = "characteristics"
|
37
38
|
CONF_DESCRIPTION = "description"
|
@@ -421,6 +422,7 @@ CONFIG_SCHEMA = cv.Schema(
|
|
421
422
|
cv.GenerateID(): cv.declare_id(BLEServer),
|
422
423
|
cv.GenerateID(esp32_ble.CONF_BLE_ID): cv.use_id(esp32_ble.ESP32BLE),
|
423
424
|
cv.Optional(CONF_MANUFACTURER): value_schema("string", templatable=False),
|
425
|
+
cv.Optional(CONF_APPEARANCE, default=0): cv.uint16_t,
|
424
426
|
cv.Optional(CONF_MODEL): value_schema("string", templatable=False),
|
425
427
|
cv.Optional(CONF_FIRMWARE_VERSION): value_schema("string", templatable=False),
|
426
428
|
cv.Optional(CONF_MANUFACTURER_DATA): cv.Schema([cv.uint8_t]),
|
@@ -531,6 +533,7 @@ async def to_code(config):
|
|
531
533
|
cg.add(parent.register_gatts_event_handler(var))
|
532
534
|
cg.add(parent.register_ble_status_event_handler(var))
|
533
535
|
cg.add(var.set_parent(parent))
|
536
|
+
cg.add(parent.advertising_set_appearance(config[CONF_APPEARANCE]))
|
534
537
|
if CONF_MANUFACTURER_DATA in config:
|
535
538
|
cg.add(var.set_manufacturer_data(config[CONF_MANUFACTURER_DATA]))
|
536
539
|
for service_config in config[CONF_SERVICES]:
|
@@ -17,6 +17,7 @@ from esphome.components.esp32_ble import (
|
|
17
17
|
import esphome.config_validation as cv
|
18
18
|
from esphome.const import (
|
19
19
|
CONF_ACTIVE,
|
20
|
+
CONF_CONTINUOUS,
|
20
21
|
CONF_DURATION,
|
21
22
|
CONF_ID,
|
22
23
|
CONF_INTERVAL,
|
@@ -42,8 +43,8 @@ CONF_MAX_CONNECTIONS = "max_connections"
|
|
42
43
|
CONF_ESP32_BLE_ID = "esp32_ble_id"
|
43
44
|
CONF_SCAN_PARAMETERS = "scan_parameters"
|
44
45
|
CONF_WINDOW = "window"
|
45
|
-
CONF_CONTINUOUS = "continuous"
|
46
46
|
CONF_ON_SCAN_END = "on_scan_end"
|
47
|
+
CONF_SOFTWARE_COEXISTENCE = "software_coexistence"
|
47
48
|
|
48
49
|
DEFAULT_MAX_CONNECTIONS = 3
|
49
50
|
IDF_MAX_CONNECTIONS = 9
|
@@ -203,6 +204,7 @@ CONFIG_SCHEMA = cv.All(
|
|
203
204
|
cv.Optional(CONF_ON_SCAN_END): automation.validate_automation(
|
204
205
|
{cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(BLEEndOfScanTrigger)}
|
205
206
|
),
|
207
|
+
cv.OnlyWith(CONF_SOFTWARE_COEXISTENCE, "wifi", default=True): bool,
|
206
208
|
}
|
207
209
|
).extend(cv.COMPONENT_SCHEMA),
|
208
210
|
)
|
@@ -310,6 +312,8 @@ async def to_code(config):
|
|
310
312
|
|
311
313
|
if CORE.using_esp_idf:
|
312
314
|
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
315
|
+
if config.get(CONF_SOFTWARE_COEXISTENCE):
|
316
|
+
add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", True)
|
313
317
|
# https://github.com/espressif/esp-idf/issues/4101
|
314
318
|
# https://github.com/espressif/esp-idf/issues/2503
|
315
319
|
# Match arduino CONFIG_BTU_TASK_STACK_SIZE
|
@@ -331,6 +335,8 @@ async def to_code(config):
|
|
331
335
|
|
332
336
|
cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts
|
333
337
|
cg.add_define("USE_ESP32_BLE_CLIENT")
|
338
|
+
if config.get(CONF_SOFTWARE_COEXISTENCE):
|
339
|
+
cg.add_define("USE_ESP32_BLE_SOFTWARE_COEXISTENCE")
|
334
340
|
|
335
341
|
|
336
342
|
ESP32_BLE_START_SCAN_ACTION_SCHEMA = cv.Schema(
|
@@ -21,6 +21,10 @@
|
|
21
21
|
#include "esphome/components/ota/ota_backend.h"
|
22
22
|
#endif
|
23
23
|
|
24
|
+
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
|
25
|
+
#include <esp_coexist.h>
|
26
|
+
#endif
|
27
|
+
|
24
28
|
#ifdef USE_ARDUINO
|
25
29
|
#include <esp32-hal-bt.h>
|
26
30
|
#endif
|
@@ -57,7 +61,6 @@ void ESP32BLETracker::setup() {
|
|
57
61
|
|
58
62
|
global_esp32_ble_tracker = this;
|
59
63
|
this->scan_result_lock_ = xSemaphoreCreateMutex();
|
60
|
-
this->scan_end_lock_ = xSemaphoreCreateMutex();
|
61
64
|
|
62
65
|
#ifdef USE_OTA
|
63
66
|
ota::get_global_ota_callback()->add_on_state_callback(
|
@@ -117,119 +120,119 @@ void ESP32BLETracker::loop() {
|
|
117
120
|
}
|
118
121
|
bool promote_to_connecting = discovered && !searching && !connecting;
|
119
122
|
|
120
|
-
if (
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
123
|
+
if (this->scanner_state_ == ScannerState::RUNNING &&
|
124
|
+
this->scan_result_index_ && // if it looks like we have a scan result we will take the lock
|
125
|
+
xSemaphoreTake(this->scan_result_lock_, 0)) {
|
126
|
+
uint32_t index = this->scan_result_index_;
|
127
|
+
if (index >= ESP32BLETracker::SCAN_RESULT_BUFFER_SIZE) {
|
128
|
+
ESP_LOGW(TAG, "Too many BLE events to process. Some devices may not show up.");
|
129
|
+
}
|
127
130
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
}
|
132
|
-
for (auto *client : this->clients_) {
|
133
|
-
client->parse_devices(this->scan_result_buffer_, this->scan_result_index_);
|
134
|
-
}
|
131
|
+
if (this->raw_advertisements_) {
|
132
|
+
for (auto *listener : this->listeners_) {
|
133
|
+
listener->parse_devices(this->scan_result_buffer_, this->scan_result_index_);
|
135
134
|
}
|
135
|
+
for (auto *client : this->clients_) {
|
136
|
+
client->parse_devices(this->scan_result_buffer_, this->scan_result_index_);
|
137
|
+
}
|
138
|
+
}
|
136
139
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
140
|
+
if (this->parse_advertisements_) {
|
141
|
+
for (size_t i = 0; i < index; i++) {
|
142
|
+
ESPBTDevice device;
|
143
|
+
device.parse_scan_rst(this->scan_result_buffer_[i]);
|
141
144
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
145
|
+
bool found = false;
|
146
|
+
for (auto *listener : this->listeners_) {
|
147
|
+
if (listener->parse_device(device))
|
148
|
+
found = true;
|
149
|
+
}
|
147
150
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
}
|
151
|
+
for (auto *client : this->clients_) {
|
152
|
+
if (client->parse_device(device)) {
|
153
|
+
found = true;
|
154
|
+
if (!connecting && client->state() == ClientState::DISCOVERED) {
|
155
|
+
promote_to_connecting = true;
|
154
156
|
}
|
155
157
|
}
|
158
|
+
}
|
156
159
|
|
157
|
-
|
158
|
-
|
159
|
-
}
|
160
|
+
if (!found && !this->scan_continuous_) {
|
161
|
+
this->print_bt_device_info(device);
|
160
162
|
}
|
161
163
|
}
|
162
|
-
this->scan_result_index_ = 0;
|
163
|
-
xSemaphoreGive(this->scan_result_lock_);
|
164
164
|
}
|
165
|
+
this->scan_result_index_ = 0;
|
166
|
+
xSemaphoreGive(this->scan_result_lock_);
|
167
|
+
}
|
168
|
+
if (this->scanner_state_ == ScannerState::STOPPED) {
|
169
|
+
this->end_of_scan_(); // Change state to IDLE
|
170
|
+
}
|
171
|
+
if (this->scanner_state_ == ScannerState::FAILED ||
|
172
|
+
(this->scan_set_param_failed_ && this->scanner_state_ == ScannerState::RUNNING)) {
|
173
|
+
this->stop_scan_();
|
174
|
+
if (this->scan_start_fail_count_ == std::numeric_limits<uint8_t>::max()) {
|
175
|
+
ESP_LOGE(TAG, "ESP-IDF BLE scan could not restart after %d attempts, rebooting to restore BLE stack...",
|
176
|
+
std::numeric_limits<uint8_t>::max());
|
177
|
+
App.reboot();
|
178
|
+
}
|
179
|
+
if (this->scan_start_failed_) {
|
180
|
+
ESP_LOGE(TAG, "Scan start failed: %d", this->scan_start_failed_);
|
181
|
+
this->scan_start_failed_ = ESP_BT_STATUS_SUCCESS;
|
182
|
+
}
|
183
|
+
if (this->scan_set_param_failed_) {
|
184
|
+
ESP_LOGE(TAG, "Scan set param failed: %d", this->scan_set_param_failed_);
|
185
|
+
this->scan_set_param_failed_ = ESP_BT_STATUS_SUCCESS;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
/*
|
165
189
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
- we are connecting to a device
|
171
|
-
- we are disconnecting from a device
|
190
|
+
Avoid starting the scanner if:
|
191
|
+
- we are already scanning
|
192
|
+
- we are connecting to a device
|
193
|
+
- we are disconnecting from a device
|
172
194
|
|
173
|
-
|
174
|
-
|
195
|
+
Otherwise the scanner could fail to ever start again
|
196
|
+
and our only way to recover is to reboot.
|
175
197
|
|
176
|
-
|
198
|
+
https://github.com/espressif/esp-idf/issues/6688
|
177
199
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
xSemaphoreGive(this->scan_end_lock_);
|
186
|
-
}
|
187
|
-
} else if (!this->scanner_idle_) {
|
188
|
-
this->end_of_scan_();
|
189
|
-
return;
|
190
|
-
}
|
200
|
+
*/
|
201
|
+
if (this->scanner_state_ == ScannerState::IDLE && !connecting && !disconnecting && !promote_to_connecting) {
|
202
|
+
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
|
203
|
+
if (this->coex_prefer_ble_) {
|
204
|
+
this->coex_prefer_ble_ = false;
|
205
|
+
ESP_LOGD(TAG, "Setting coexistence preference to balanced.");
|
206
|
+
esp_coex_preference_set(ESP_COEX_PREFER_BALANCE); // Reset to default
|
191
207
|
}
|
192
|
-
|
193
|
-
if (this->
|
194
|
-
|
195
|
-
ESP_LOGE(TAG, "ESP-IDF BLE scan could not restart after %d attempts, rebooting to restore BLE stack...",
|
196
|
-
std::numeric_limits<uint8_t>::max());
|
197
|
-
App.reboot();
|
198
|
-
}
|
199
|
-
if (xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
200
|
-
xSemaphoreGive(this->scan_end_lock_);
|
201
|
-
} else {
|
202
|
-
ESP_LOGD(TAG, "Stopping scan after failure...");
|
203
|
-
this->stop_scan_();
|
204
|
-
}
|
205
|
-
if (this->scan_start_failed_) {
|
206
|
-
ESP_LOGE(TAG, "Scan start failed: %d", this->scan_start_failed_);
|
207
|
-
this->scan_start_failed_ = ESP_BT_STATUS_SUCCESS;
|
208
|
-
}
|
209
|
-
if (this->scan_set_param_failed_) {
|
210
|
-
ESP_LOGE(TAG, "Scan set param failed: %d", this->scan_set_param_failed_);
|
211
|
-
this->scan_set_param_failed_ = ESP_BT_STATUS_SUCCESS;
|
212
|
-
}
|
208
|
+
#endif
|
209
|
+
if (this->scan_continuous_) {
|
210
|
+
this->start_scan_(false); // first = false
|
213
211
|
}
|
214
212
|
}
|
215
|
-
|
216
213
|
// If there is a discovered client and no connecting
|
217
214
|
// clients and no clients using the scanner to search for
|
218
215
|
// devices, then stop scanning and promote the discovered
|
219
216
|
// client to ready to connect.
|
220
|
-
if (promote_to_connecting
|
217
|
+
if (promote_to_connecting &&
|
218
|
+
(this->scanner_state_ == ScannerState::RUNNING || this->scanner_state_ == ScannerState::IDLE)) {
|
221
219
|
for (auto *client : this->clients_) {
|
222
220
|
if (client->state() == ClientState::DISCOVERED) {
|
223
|
-
if (
|
224
|
-
|
225
|
-
|
226
|
-
|
221
|
+
if (this->scanner_state_ == ScannerState::RUNNING) {
|
222
|
+
ESP_LOGD(TAG, "Stopping scan to make connection...");
|
223
|
+
this->stop_scan_();
|
224
|
+
} else if (this->scanner_state_ == ScannerState::IDLE) {
|
225
|
+
ESP_LOGD(TAG, "Promoting client to connect...");
|
227
226
|
// We only want to promote one client at a time.
|
228
227
|
// once the scanner is fully stopped.
|
228
|
+
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
|
229
|
+
ESP_LOGD(TAG, "Setting coexistence to Bluetooth to make connection.");
|
230
|
+
if (!this->coex_prefer_ble_) {
|
231
|
+
this->coex_prefer_ble_ = true;
|
232
|
+
esp_coex_preference_set(ESP_COEX_PREFER_BT); // Prioritize Bluetooth
|
233
|
+
}
|
234
|
+
#endif
|
229
235
|
client->set_state(ClientState::READY_TO_CONNECT);
|
230
|
-
} else {
|
231
|
-
ESP_LOGD(TAG, "Pausing scan to make connection...");
|
232
|
-
this->stop_scan_();
|
233
236
|
}
|
234
237
|
break;
|
235
238
|
}
|
@@ -237,13 +240,7 @@ void ESP32BLETracker::loop() {
|
|
237
240
|
}
|
238
241
|
}
|
239
242
|
|
240
|
-
void ESP32BLETracker::start_scan() {
|
241
|
-
if (xSemaphoreTake(this->scan_end_lock_, 0L)) {
|
242
|
-
this->start_scan_(true);
|
243
|
-
} else {
|
244
|
-
ESP_LOGW(TAG, "Scan requested when a scan is already in progress. Ignoring.");
|
245
|
-
}
|
246
|
-
}
|
243
|
+
void ESP32BLETracker::start_scan() { this->start_scan_(true); }
|
247
244
|
|
248
245
|
void ESP32BLETracker::stop_scan() {
|
249
246
|
ESP_LOGD(TAG, "Stopping scan.");
|
@@ -251,16 +248,23 @@ void ESP32BLETracker::stop_scan() {
|
|
251
248
|
this->stop_scan_();
|
252
249
|
}
|
253
250
|
|
254
|
-
void ESP32BLETracker::ble_before_disabled_event_handler() {
|
255
|
-
this->stop_scan_();
|
256
|
-
xSemaphoreGive(this->scan_end_lock_);
|
257
|
-
}
|
251
|
+
void ESP32BLETracker::ble_before_disabled_event_handler() { this->stop_scan_(); }
|
258
252
|
|
259
253
|
void ESP32BLETracker::stop_scan_() {
|
260
|
-
this->
|
261
|
-
|
254
|
+
if (this->scanner_state_ != ScannerState::RUNNING && this->scanner_state_ != ScannerState::FAILED) {
|
255
|
+
if (this->scanner_state_ == ScannerState::IDLE) {
|
256
|
+
ESP_LOGE(TAG, "Scan is already stopped while trying to stop.");
|
257
|
+
} else if (this->scanner_state_ == ScannerState::STARTING) {
|
258
|
+
ESP_LOGE(TAG, "Scan is starting while trying to stop.");
|
259
|
+
} else if (this->scanner_state_ == ScannerState::STOPPING) {
|
260
|
+
ESP_LOGE(TAG, "Scan is already stopping while trying to stop.");
|
261
|
+
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
262
|
+
ESP_LOGE(TAG, "Scan is already stopped while trying to stop.");
|
263
|
+
}
|
262
264
|
return;
|
263
265
|
}
|
266
|
+
this->cancel_timeout("scan");
|
267
|
+
this->set_scanner_state_(ScannerState::STOPPING);
|
264
268
|
esp_err_t err = esp_ble_gap_stop_scanning();
|
265
269
|
if (err != ESP_OK) {
|
266
270
|
ESP_LOGE(TAG, "esp_ble_gap_stop_scanning failed: %d", err);
|
@@ -273,13 +277,22 @@ void ESP32BLETracker::start_scan_(bool first) {
|
|
273
277
|
ESP_LOGW(TAG, "Cannot start scan while ESP32BLE is disabled.");
|
274
278
|
return;
|
275
279
|
}
|
276
|
-
|
277
|
-
|
278
|
-
|
280
|
+
if (this->scanner_state_ != ScannerState::IDLE) {
|
281
|
+
if (this->scanner_state_ == ScannerState::STARTING) {
|
282
|
+
ESP_LOGE(TAG, "Cannot start scan while already starting.");
|
283
|
+
} else if (this->scanner_state_ == ScannerState::RUNNING) {
|
284
|
+
ESP_LOGE(TAG, "Cannot start scan while already running.");
|
285
|
+
} else if (this->scanner_state_ == ScannerState::STOPPING) {
|
286
|
+
ESP_LOGE(TAG, "Cannot start scan while already stopping.");
|
287
|
+
} else if (this->scanner_state_ == ScannerState::FAILED) {
|
288
|
+
ESP_LOGE(TAG, "Cannot start scan while already failed.");
|
289
|
+
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
290
|
+
ESP_LOGE(TAG, "Cannot start scan while already stopped.");
|
291
|
+
}
|
279
292
|
return;
|
280
293
|
}
|
281
|
-
|
282
|
-
ESP_LOGD(TAG, "Starting scan
|
294
|
+
this->set_scanner_state_(ScannerState::STARTING);
|
295
|
+
ESP_LOGD(TAG, "Starting scan, set scanner state to STARTING.");
|
283
296
|
if (!first) {
|
284
297
|
for (auto *listener : this->listeners_)
|
285
298
|
listener->on_scan_end();
|
@@ -307,24 +320,21 @@ void ESP32BLETracker::start_scan_(bool first) {
|
|
307
320
|
ESP_LOGE(TAG, "esp_ble_gap_start_scanning failed: %d", err);
|
308
321
|
return;
|
309
322
|
}
|
310
|
-
this->scanner_idle_ = false;
|
311
323
|
}
|
312
324
|
|
313
325
|
void ESP32BLETracker::end_of_scan_() {
|
314
326
|
// The lock must be held when calling this function.
|
315
|
-
if (
|
316
|
-
ESP_LOGE(TAG, "end_of_scan_ called
|
327
|
+
if (this->scanner_state_ != ScannerState::STOPPED) {
|
328
|
+
ESP_LOGE(TAG, "end_of_scan_ called while scanner is not stopped.");
|
317
329
|
return;
|
318
330
|
}
|
319
|
-
|
320
|
-
ESP_LOGD(TAG, "End of scan.");
|
321
|
-
this->scanner_idle_ = true;
|
331
|
+
ESP_LOGD(TAG, "End of scan, set scanner state to IDLE.");
|
322
332
|
this->already_discovered_.clear();
|
323
|
-
xSemaphoreGive(this->scan_end_lock_);
|
324
333
|
this->cancel_timeout("scan");
|
325
334
|
|
326
335
|
for (auto *listener : this->listeners_)
|
327
336
|
listener->on_scan_end();
|
337
|
+
this->set_scanner_state_(ScannerState::IDLE);
|
328
338
|
}
|
329
339
|
|
330
340
|
void ESP32BLETracker::register_client(ESPBTClient *client) {
|
@@ -392,32 +402,73 @@ void ESP32BLETracker::gap_scan_set_param_complete_(const esp_ble_gap_cb_param_t:
|
|
392
402
|
void ESP32BLETracker::gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param ¶m) {
|
393
403
|
ESP_LOGV(TAG, "gap_scan_start_complete - status %d", param.status);
|
394
404
|
this->scan_start_failed_ = param.status;
|
405
|
+
if (this->scanner_state_ != ScannerState::STARTING) {
|
406
|
+
if (this->scanner_state_ == ScannerState::RUNNING) {
|
407
|
+
ESP_LOGE(TAG, "Scan was already running when start complete.");
|
408
|
+
} else if (this->scanner_state_ == ScannerState::STOPPING) {
|
409
|
+
ESP_LOGE(TAG, "Scan was stopping when start complete.");
|
410
|
+
} else if (this->scanner_state_ == ScannerState::FAILED) {
|
411
|
+
ESP_LOGE(TAG, "Scan was in failed state when start complete.");
|
412
|
+
} else if (this->scanner_state_ == ScannerState::IDLE) {
|
413
|
+
ESP_LOGE(TAG, "Scan was idle when start complete.");
|
414
|
+
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
415
|
+
ESP_LOGE(TAG, "Scan was stopped when start complete.");
|
416
|
+
}
|
417
|
+
}
|
395
418
|
if (param.status == ESP_BT_STATUS_SUCCESS) {
|
396
419
|
this->scan_start_fail_count_ = 0;
|
420
|
+
this->set_scanner_state_(ScannerState::RUNNING);
|
397
421
|
} else {
|
422
|
+
this->set_scanner_state_(ScannerState::FAILED);
|
398
423
|
if (this->scan_start_fail_count_ != std::numeric_limits<uint8_t>::max()) {
|
399
424
|
this->scan_start_fail_count_++;
|
400
425
|
}
|
401
|
-
xSemaphoreGive(this->scan_end_lock_);
|
402
426
|
}
|
403
427
|
}
|
404
428
|
|
405
429
|
void ESP32BLETracker::gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param ¶m) {
|
406
430
|
ESP_LOGV(TAG, "gap_scan_stop_complete - status %d", param.status);
|
407
|
-
|
431
|
+
if (this->scanner_state_ != ScannerState::STOPPING) {
|
432
|
+
if (this->scanner_state_ == ScannerState::RUNNING) {
|
433
|
+
ESP_LOGE(TAG, "Scan was not running when stop complete.");
|
434
|
+
} else if (this->scanner_state_ == ScannerState::STARTING) {
|
435
|
+
ESP_LOGE(TAG, "Scan was not started when stop complete.");
|
436
|
+
} else if (this->scanner_state_ == ScannerState::FAILED) {
|
437
|
+
ESP_LOGE(TAG, "Scan was in failed state when stop complete.");
|
438
|
+
} else if (this->scanner_state_ == ScannerState::IDLE) {
|
439
|
+
ESP_LOGE(TAG, "Scan was idle when stop complete.");
|
440
|
+
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
441
|
+
ESP_LOGE(TAG, "Scan was stopped when stop complete.");
|
442
|
+
}
|
443
|
+
}
|
444
|
+
this->set_scanner_state_(ScannerState::STOPPED);
|
408
445
|
}
|
409
446
|
|
410
447
|
void ESP32BLETracker::gap_scan_result_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m) {
|
411
448
|
ESP_LOGV(TAG, "gap_scan_result - event %d", param.search_evt);
|
412
449
|
if (param.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) {
|
413
|
-
if (xSemaphoreTake(this->scan_result_lock_,
|
450
|
+
if (xSemaphoreTake(this->scan_result_lock_, 0)) {
|
414
451
|
if (this->scan_result_index_ < ESP32BLETracker::SCAN_RESULT_BUFFER_SIZE) {
|
415
452
|
this->scan_result_buffer_[this->scan_result_index_++] = param;
|
416
453
|
}
|
417
454
|
xSemaphoreGive(this->scan_result_lock_);
|
418
455
|
}
|
419
456
|
} else if (param.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) {
|
420
|
-
|
457
|
+
// Scan finished on its own
|
458
|
+
if (this->scanner_state_ != ScannerState::RUNNING) {
|
459
|
+
if (this->scanner_state_ == ScannerState::STOPPING) {
|
460
|
+
ESP_LOGE(TAG, "Scan was not running when scan completed.");
|
461
|
+
} else if (this->scanner_state_ == ScannerState::STARTING) {
|
462
|
+
ESP_LOGE(TAG, "Scan was not started when scan completed.");
|
463
|
+
} else if (this->scanner_state_ == ScannerState::FAILED) {
|
464
|
+
ESP_LOGE(TAG, "Scan was in failed state when scan completed.");
|
465
|
+
} else if (this->scanner_state_ == ScannerState::IDLE) {
|
466
|
+
ESP_LOGE(TAG, "Scan was idle when scan completed.");
|
467
|
+
} else if (this->scanner_state_ == ScannerState::STOPPED) {
|
468
|
+
ESP_LOGE(TAG, "Scan was stopped when scan completed.");
|
469
|
+
}
|
470
|
+
}
|
471
|
+
this->set_scanner_state_(ScannerState::STOPPED);
|
421
472
|
}
|
422
473
|
}
|
423
474
|
|
@@ -428,6 +479,11 @@ void ESP32BLETracker::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_i
|
|
428
479
|
}
|
429
480
|
}
|
430
481
|
|
482
|
+
void ESP32BLETracker::set_scanner_state_(ScannerState state) {
|
483
|
+
this->scanner_state_ = state;
|
484
|
+
this->scanner_state_callbacks_.call(state);
|
485
|
+
}
|
486
|
+
|
431
487
|
ESPBLEiBeacon::ESPBLEiBeacon(const uint8_t *data) { memcpy(&this->beacon_data_, data, sizeof(beacon_data_)); }
|
432
488
|
optional<ESPBLEiBeacon> ESPBLEiBeacon::from_manufacturer_data(const ServiceData &data) {
|
433
489
|
if (!data.uuid.contains(0x4C, 0x00))
|
@@ -680,8 +736,26 @@ void ESP32BLETracker::dump_config() {
|
|
680
736
|
ESP_LOGCONFIG(TAG, " Scan Window: %.1f ms", this->scan_window_ * 0.625f);
|
681
737
|
ESP_LOGCONFIG(TAG, " Scan Type: %s", this->scan_active_ ? "ACTIVE" : "PASSIVE");
|
682
738
|
ESP_LOGCONFIG(TAG, " Continuous Scanning: %s", YESNO(this->scan_continuous_));
|
683
|
-
|
684
|
-
|
739
|
+
switch (this->scanner_state_) {
|
740
|
+
case ScannerState::IDLE:
|
741
|
+
ESP_LOGCONFIG(TAG, " Scanner State: IDLE");
|
742
|
+
break;
|
743
|
+
case ScannerState::STARTING:
|
744
|
+
ESP_LOGCONFIG(TAG, " Scanner State: STARTING");
|
745
|
+
break;
|
746
|
+
case ScannerState::RUNNING:
|
747
|
+
ESP_LOGCONFIG(TAG, " Scanner State: RUNNING");
|
748
|
+
break;
|
749
|
+
case ScannerState::STOPPING:
|
750
|
+
ESP_LOGCONFIG(TAG, " Scanner State: STOPPING");
|
751
|
+
break;
|
752
|
+
case ScannerState::STOPPED:
|
753
|
+
ESP_LOGCONFIG(TAG, " Scanner State: STOPPED");
|
754
|
+
break;
|
755
|
+
case ScannerState::FAILED:
|
756
|
+
ESP_LOGCONFIG(TAG, " Scanner State: FAILED");
|
757
|
+
break;
|
758
|
+
}
|
685
759
|
ESP_LOGCONFIG(TAG, " Connecting: %d, discovered: %d, searching: %d, disconnecting: %d", connecting_, discovered_,
|
686
760
|
searching_, disconnecting_);
|
687
761
|
if (this->scan_start_fail_count_) {
|