esphome 2025.4.1__py3-none-any.whl → 2025.5.0b2__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/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 +77 -10
- esphome/components/api/api_connection.h +6 -1
- esphome/components/api/api_frame_helper.cpp +98 -130
- esphome/components/api/api_frame_helper.h +12 -2
- 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 +38 -9
- esphome/components/as3935_i2c/as3935_i2c.h +0 -3
- 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/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/binary_sensor/binary_sensor.cpp +6 -10
- esphome/components/binary_sensor/binary_sensor.h +1 -1
- esphome/components/binary_sensor/filter.cpp +21 -21
- esphome/components/binary_sensor/filter.h +10 -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 +135 -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/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/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/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/debug/debug_component.cpp +5 -0
- 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/display/rect.cpp +4 -9
- esphome/components/display/rect.h +1 -1
- esphome/components/emmeti/climate.py +2 -9
- esphome/components/endstop/cover.py +17 -16
- 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 -8
- esphome/components/esp32_ble/ble.h +5 -3
- 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_can/esp32_can.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/esp8266/gpio.cpp +69 -8
- 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/fujitsu_general/climate.py +2 -9
- 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 +11 -2
- esphome/components/gps/gps.cpp +11 -8
- esphome/components/gps/gps.h +9 -6
- 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/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/hlw8012/hlw8012.cpp +1 -1
- esphome/components/hm3301/hm3301.h +1 -1
- 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/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/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 +21 -0
- esphome/components/logger/logger.cpp +125 -95
- esphome/components/logger/logger.h +160 -35
- 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/lv_validation.py +10 -1
- esphome/components/lvgl/lvgl_esphome.cpp +5 -1
- esphome/components/lvgl/schemas.py +14 -14
- esphome/components/lvgl/text/__init__.py +1 -2
- esphome/components/lvgl/widgets/arc.py +7 -6
- esphome/components/lvgl/widgets/buttonmatrix.py +3 -3
- esphome/components/lvgl/widgets/checkbox.py +2 -2
- esphome/components/lvgl/widgets/dropdown.py +2 -1
- esphome/components/lvgl/widgets/img.py +15 -12
- esphome/components/mapping/__init__.py +134 -0
- esphome/components/max7219digit/max7219digit.cpp +27 -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 +40 -6
- 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/mqtt/__init__.py +1 -1
- esphome/components/mqtt/mqtt_client.cpp +5 -1
- 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/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 +193 -229
- 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/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/scd30/sensor.py +2 -3
- esphome/components/scd4x/sensor.py +4 -5
- esphome/components/sdp3x/sensor.py +2 -1
- esphome/components/select/__init__.py +19 -20
- esphome/components/sen5x/sensor.py +1 -1
- esphome/components/sensor/__init__.py +158 -14
- esphome/components/sensor/filter.cpp +23 -0
- esphome/components/sensor/filter.h +22 -0
- esphome/components/sgp4x/sensor.py +1 -1
- esphome/components/sht4x/sht4x.cpp +43 -22
- esphome/components/sht4x/sht4x.h +1 -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/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/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/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/tt21100/touchscreen/tt21100.cpp +1 -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/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/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_validation.py +38 -58
- esphome/const.py +15 -1
- esphome/core/__init__.py +2 -0
- esphome/core/application.cpp +1 -0
- esphome/core/application.h +4 -0
- esphome/core/automation.h +4 -3
- esphome/core/component.cpp +19 -3
- esphome/core/component.h +5 -0
- esphome/core/defines.h +23 -17
- esphome/core/macros.h +4 -0
- esphome/core/scheduler.cpp +3 -0
- esphome/cpp_generator.py +6 -2
- esphome/dashboard/web_server.py +3 -3
- esphome/helpers.py +39 -0
- esphome/loader.py +4 -0
- esphome/mqtt.py +21 -8
- esphome/platformio_api.py +1 -1
- esphome/schema_extractors.py +0 -1
- esphome/vscode.py +15 -0
- esphome/wizard.py +2 -2
- esphome/zeroconf.py +7 -3
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/METADATA +10 -11
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/RECORD +411 -352
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/WHEEL +1 -1
- esphome/components/esp32_ble/const_esp32c6.h +0 -74
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/entry_points.txt +0 -0
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.4.1.dist-info → esphome-2025.5.0b2.dist-info}/top_level.txt +0 -0
@@ -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)
|
@@ -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_) {
|
@@ -154,6 +154,21 @@ enum class ClientState {
|
|
154
154
|
ESTABLISHED,
|
155
155
|
};
|
156
156
|
|
157
|
+
enum class ScannerState {
|
158
|
+
// Scanner is idle, init state, set from the main loop when processing STOPPED
|
159
|
+
IDLE,
|
160
|
+
// Scanner is starting, set from the main loop only
|
161
|
+
STARTING,
|
162
|
+
// Scanner is running, set from the ESP callback only
|
163
|
+
RUNNING,
|
164
|
+
// Scanner failed to start, set from the ESP callback only
|
165
|
+
FAILED,
|
166
|
+
// Scanner is stopping, set from the main loop only
|
167
|
+
STOPPING,
|
168
|
+
// Scanner is stopped, set from the ESP callback only
|
169
|
+
STOPPED,
|
170
|
+
};
|
171
|
+
|
157
172
|
enum class ConnectionType {
|
158
173
|
// The default connection type, we hold all the services in ram
|
159
174
|
// for the duration of the connection.
|
@@ -203,6 +218,7 @@ class ESP32BLETracker : public Component,
|
|
203
218
|
void set_scan_interval(uint32_t scan_interval) { scan_interval_ = scan_interval; }
|
204
219
|
void set_scan_window(uint32_t scan_window) { scan_window_ = scan_window; }
|
205
220
|
void set_scan_active(bool scan_active) { scan_active_ = scan_active; }
|
221
|
+
bool get_scan_active() const { return scan_active_; }
|
206
222
|
void set_scan_continuous(bool scan_continuous) { scan_continuous_ = scan_continuous; }
|
207
223
|
|
208
224
|
/// Setup the FreeRTOS task and the Bluetooth stack.
|
@@ -226,6 +242,11 @@ class ESP32BLETracker : public Component,
|
|
226
242
|
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
|
227
243
|
void ble_before_disabled_event_handler() override;
|
228
244
|
|
245
|
+
void add_scanner_state_callback(std::function<void(ScannerState)> &&callback) {
|
246
|
+
this->scanner_state_callbacks_.add(std::move(callback));
|
247
|
+
}
|
248
|
+
ScannerState get_scanner_state() const { return this->scanner_state_; }
|
249
|
+
|
229
250
|
protected:
|
230
251
|
void stop_scan_();
|
231
252
|
/// Start a single scan by setting up the parameters and doing some esp-idf calls.
|
@@ -240,6 +261,8 @@ class ESP32BLETracker : public Component,
|
|
240
261
|
void gap_scan_start_complete_(const esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param ¶m);
|
241
262
|
/// Called when a `ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT` event is received.
|
242
263
|
void gap_scan_stop_complete_(const esp_ble_gap_cb_param_t::ble_scan_stop_cmpl_evt_param ¶m);
|
264
|
+
/// Called to set the scanner state. Will also call callbacks to let listeners know when state is changed.
|
265
|
+
void set_scanner_state_(ScannerState state);
|
243
266
|
|
244
267
|
int app_id_{0};
|
245
268
|
|
@@ -257,17 +280,17 @@ class ESP32BLETracker : public Component,
|
|
257
280
|
uint8_t scan_start_fail_count_{0};
|
258
281
|
bool scan_continuous_;
|
259
282
|
bool scan_active_;
|
260
|
-
|
283
|
+
ScannerState scanner_state_{ScannerState::IDLE};
|
284
|
+
CallbackManager<void(ScannerState)> scanner_state_callbacks_;
|
261
285
|
bool ble_was_disabled_{true};
|
262
286
|
bool raw_advertisements_{false};
|
263
287
|
bool parse_advertisements_{false};
|
264
288
|
SemaphoreHandle_t scan_result_lock_;
|
265
|
-
SemaphoreHandle_t scan_end_lock_;
|
266
289
|
size_t scan_result_index_{0};
|
267
290
|
#ifdef USE_PSRAM
|
268
291
|
const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 32;
|
269
292
|
#else
|
270
|
-
const static u_int8_t SCAN_RESULT_BUFFER_SIZE =
|
293
|
+
const static u_int8_t SCAN_RESULT_BUFFER_SIZE = 20;
|
271
294
|
#endif // USE_PSRAM
|
272
295
|
esp_ble_gap_cb_param_t::ble_scan_result_evt_param *scan_result_buffer_;
|
273
296
|
esp_bt_status_t scan_start_failed_{ESP_BT_STATUS_SUCCESS};
|
@@ -276,6 +299,9 @@ class ESP32BLETracker : public Component,
|
|
276
299
|
int discovered_{0};
|
277
300
|
int searching_{0};
|
278
301
|
int disconnecting_{0};
|
302
|
+
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
|
303
|
+
bool coex_prefer_ble_{false};
|
304
|
+
#endif
|
279
305
|
};
|
280
306
|
|
281
307
|
// NOLINTNEXTLINE
|
@@ -17,7 +17,7 @@ static const char *const TAG = "esp32_can";
|
|
17
17
|
static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config) {
|
18
18
|
switch (bitrate) {
|
19
19
|
#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C3) || \
|
20
|
-
defined(USE_ESP32_VARIANT_ESP32C6) || defined(
|
20
|
+
defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32H2)
|
21
21
|
case canbus::CAN_1KBPS:
|
22
22
|
*t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_1KBITS();
|
23
23
|
return true;
|
@@ -58,7 +58,7 @@ void ESP32RMTLEDStripLightOutput::setup() {
|
|
58
58
|
channel.flags.io_loop_back = 0;
|
59
59
|
channel.flags.io_od_mode = 0;
|
60
60
|
channel.flags.invert_out = 0;
|
61
|
-
channel.flags.with_dma =
|
61
|
+
channel.flags.with_dma = this->use_dma_;
|
62
62
|
channel.intr_priority = 0;
|
63
63
|
if (rmt_new_tx_channel(&channel, &this->channel_) != ESP_OK) {
|
64
64
|
ESP_LOGE(TAG, "Channel creation failed");
|