esphome 2024.12.4__py3-none-any.whl → 2025.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +16 -3
- esphome/components/adc/__init__.py +17 -11
- esphome/components/adc/adc_sensor.h +17 -0
- esphome/components/adc/adc_sensor_common.cpp +55 -0
- esphome/components/adc/adc_sensor_esp32.cpp +8 -5
- esphome/components/adc/adc_sensor_esp8266.cpp +10 -6
- esphome/components/adc/adc_sensor_libretiny.cpp +11 -6
- esphome/components/adc/adc_sensor_rp2040.cpp +13 -10
- esphome/components/adc/sensor.py +9 -3
- esphome/components/ads1115/ads1115.cpp +56 -7
- esphome/components/ads1115/ads1115.h +13 -1
- esphome/components/ads1115/sensor/__init__.py +16 -0
- esphome/components/ads1115/sensor/ads1115_sensor.cpp +2 -1
- esphome/components/ads1115/sensor/ads1115_sensor.h +2 -0
- esphome/components/animation/__init__.py +23 -261
- esphome/components/animation/animation.cpp +2 -2
- esphome/components/animation/animation.h +2 -1
- esphome/components/api/api_pb2.cpp +14 -0
- esphome/components/api/api_pb2.h +1 -0
- esphome/components/api/client.py +8 -3
- esphome/components/audio/__init__.py +112 -0
- esphome/components/audio/audio.cpp +67 -0
- esphome/components/audio/audio.h +125 -7
- esphome/components/audio/audio_decoder.cpp +361 -0
- esphome/components/audio/audio_decoder.h +135 -0
- esphome/components/audio/audio_reader.cpp +308 -0
- esphome/components/audio/audio_reader.h +85 -0
- esphome/components/audio/audio_resampler.cpp +159 -0
- esphome/components/audio/audio_resampler.h +101 -0
- esphome/components/audio/audio_transfer_buffer.cpp +165 -0
- esphome/components/audio/audio_transfer_buffer.h +139 -0
- esphome/components/audio_adc/__init__.py +41 -0
- esphome/components/audio_adc/audio_adc.h +17 -0
- esphome/components/audio_adc/automation.h +23 -0
- esphome/components/bk72xx/__init__.py +1 -0
- esphome/components/ble_client/ble_client.cpp +1 -2
- esphome/components/ble_client/sensor/__init__.py +1 -1
- esphome/components/ble_client/text_sensor/__init__.py +1 -1
- esphome/components/bluetooth_proxy/bluetooth_connection.cpp +5 -0
- esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -0
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +5 -0
- esphome/components/ch422g/ch422g.h +2 -0
- esphome/components/climate/__init__.py +1 -1
- esphome/components/climate_ir/climate_ir.cpp +2 -1
- esphome/components/coolix/coolix.cpp +2 -1
- esphome/components/cse7766/cse7766.cpp +8 -16
- esphome/components/custom/__init__.py +0 -3
- esphome/components/custom/binary_sensor/__init__.py +2 -28
- esphome/components/custom/climate/__init__.py +2 -27
- esphome/components/custom/cover/__init__.py +2 -27
- esphome/components/custom/light/__init__.py +2 -27
- esphome/components/custom/output/__init__.py +2 -58
- esphome/components/custom/sensor/__init__.py +2 -24
- esphome/components/custom/switch/__init__.py +2 -24
- esphome/components/custom/text_sensor/__init__.py +2 -29
- esphome/components/custom_component/__init__.py +3 -27
- esphome/components/daly_bms/daly_bms.cpp +6 -0
- esphome/components/daly_bms/daly_bms.h +2 -0
- esphome/components/daly_bms/sensor.py +6 -0
- esphome/components/debug/debug_component.cpp +4 -0
- esphome/components/debug/debug_component.h +14 -0
- esphome/components/debug/debug_esp32.cpp +154 -74
- esphome/components/dfplayer/dfplayer.cpp +15 -2
- esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp +2 -1
- esphome/components/dht/dht.cpp +4 -2
- esphome/components/dht/sensor.py +1 -1
- esphome/components/display/__init__.py +18 -5
- esphome/components/display/display.cpp +16 -3
- esphome/components/display/rect.cpp +2 -1
- esphome/components/es7210/__init__.py +0 -0
- esphome/components/es7210/audio_adc.py +51 -0
- esphome/components/es7210/es7210.cpp +228 -0
- esphome/components/es7210/es7210.h +62 -0
- esphome/components/es7210/es7210_const.h +129 -0
- esphome/components/es7243e/__init__.py +0 -0
- esphome/components/es7243e/audio_adc.py +34 -0
- esphome/components/es7243e/es7243e.cpp +125 -0
- esphome/components/es7243e/es7243e.h +37 -0
- esphome/components/es7243e/es7243e_const.h +54 -0
- esphome/components/es8156/__init__.py +0 -0
- esphome/components/es8156/audio_dac.py +27 -0
- esphome/components/es8156/es8156.cpp +87 -0
- esphome/components/es8156/es8156.h +51 -0
- esphome/components/es8156/es8156_const.h +68 -0
- esphome/components/es8311/audio_dac.py +1 -2
- esphome/components/esp32/__init__.py +1 -0
- esphome/components/esp32/core.cpp +5 -1
- esphome/components/esp32/gpio.h +2 -0
- esphome/components/esp32_ble/__init__.py +39 -0
- esphome/components/esp32_ble/queue.h +4 -4
- esphome/components/esp32_ble_client/ble_client_base.cpp +46 -0
- esphome/components/esp32_ble_client/ble_client_base.h +2 -0
- esphome/components/esp32_ble_server/__init__.py +582 -12
- esphome/components/esp32_ble_server/ble_characteristic.cpp +48 -60
- esphome/components/esp32_ble_server/ble_characteristic.h +24 -17
- esphome/components/esp32_ble_server/ble_descriptor.cpp +21 -9
- esphome/components/esp32_ble_server/ble_descriptor.h +17 -6
- esphome/components/esp32_ble_server/ble_server.cpp +62 -67
- esphome/components/esp32_ble_server/ble_server.h +28 -32
- esphome/components/esp32_ble_server/ble_server_automations.cpp +77 -0
- esphome/components/esp32_ble_server/ble_server_automations.h +115 -0
- esphome/components/esp32_ble_server/ble_service.cpp +17 -15
- esphome/components/esp32_ble_server/ble_service.h +10 -14
- esphome/components/esp32_ble_tracker/__init__.py +6 -39
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +33 -10
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +8 -4
- esphome/components/esp32_dac/esp32_dac.cpp +16 -7
- esphome/components/esp32_dac/esp32_dac.h +8 -0
- esphome/components/esp32_dac/output.py +16 -4
- esphome/components/esp32_improv/__init__.py +2 -8
- esphome/components/esp32_improv/esp32_improv_component.cpp +21 -20
- esphome/components/esp32_improv/esp32_improv_component.h +3 -4
- esphome/components/esp32_rmt/__init__.py +28 -3
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +73 -6
- esphome/components/esp32_rmt_led_strip/led_strip.h +21 -3
- esphome/components/esp32_rmt_led_strip/light.py +72 -7
- esphome/components/esp32_touch/esp32_touch.cpp +5 -0
- esphome/components/esp8266/__init__.py +1 -0
- esphome/components/esp8266/gpio.h +1 -0
- esphome/components/ethernet/__init__.py +10 -10
- esphome/components/event/event.cpp +4 -2
- esphome/components/event/event.h +2 -0
- esphome/components/event_emitter/__init__.py +5 -0
- esphome/components/event_emitter/event_emitter.cpp +14 -0
- esphome/components/event_emitter/event_emitter.h +63 -0
- esphome/components/font/__init__.py +1 -1
- esphome/components/gcja5/gcja5.cpp +2 -1
- esphome/components/graph/graph.cpp +4 -9
- esphome/components/haier/haier_base.cpp +2 -1
- esphome/components/haier/hon_climate.cpp +2 -1
- esphome/components/heatpumpir/heatpumpir.cpp +2 -1
- esphome/components/host/__init__.py +1 -0
- esphome/components/host/gpio.h +1 -0
- esphome/components/http_request/http_request.h +2 -2
- esphome/components/http_request/http_request_arduino.cpp +1 -1
- esphome/components/http_request/http_request_idf.cpp +1 -1
- esphome/components/i2c/i2c_bus_esp_idf.cpp +4 -0
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +7 -5
- esphome/components/i2s_audio/speaker/__init__.py +53 -6
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +92 -46
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -0
- esphome/components/ili9xxx/display.py +29 -11
- esphome/components/ili9xxx/ili9xxx_display.cpp +2 -5
- esphome/components/ili9xxx/ili9xxx_display.h +2 -1
- esphome/components/image/__init__.py +443 -255
- esphome/components/image/image.cpp +115 -61
- esphome/components/image/image.h +15 -24
- esphome/components/json/json_util.cpp +8 -34
- esphome/components/libretiny/__init__.py +1 -0
- esphome/components/libretiny/gpio_arduino.h +1 -0
- esphome/components/light/light_color_values.h +1 -1
- esphome/components/logger/__init__.py +45 -9
- esphome/components/logger/logger.cpp +16 -14
- esphome/components/logger/logger.h +11 -7
- esphome/components/logger/select/__init__.py +29 -0
- esphome/components/logger/select/logger_level_select.cpp +27 -0
- esphome/components/logger/select/logger_level_select.h +15 -0
- esphome/components/lvgl/__init__.py +96 -73
- esphome/components/lvgl/automation.py +39 -7
- esphome/components/lvgl/defines.py +8 -2
- esphome/components/lvgl/lvgl_esphome.cpp +8 -15
- esphome/components/lvgl/lvgl_esphome.h +20 -5
- esphome/components/lvgl/schemas.py +25 -14
- esphome/components/lvgl/trigger.py +27 -3
- esphome/components/lvgl/widgets/dropdown.py +1 -1
- esphome/components/lvgl/widgets/keyboard.py +8 -1
- esphome/components/lvgl/widgets/meter.py +2 -1
- esphome/components/lvgl/widgets/msgbox.py +1 -1
- esphome/components/lvgl/widgets/obj.py +1 -12
- esphome/components/lvgl/widgets/page.py +37 -2
- esphome/components/lvgl/widgets/tabview.py +1 -1
- esphome/components/max6956/max6956.h +2 -0
- esphome/components/mcp23016/mcp23016.h +2 -0
- esphome/components/mcp23xxx_base/mcp23xxx_base.h +2 -0
- esphome/components/mdns/__init__.py +1 -1
- esphome/components/media_player/__init__.py +37 -8
- esphome/components/media_player/automation.h +11 -2
- esphome/components/media_player/media_player.cpp +8 -0
- esphome/components/media_player/media_player.h +8 -4
- esphome/components/micronova/switch/micronova_switch.cpp +4 -2
- esphome/components/midea/ac_automations.h +3 -1
- esphome/components/midea/air_conditioner.cpp +7 -5
- esphome/components/midea/air_conditioner.h +1 -1
- esphome/components/midea/climate.py +4 -2
- esphome/components/midea/ir_transmitter.h +36 -5
- esphome/components/mixer/__init__.py +0 -0
- esphome/components/mixer/speaker/__init__.py +172 -0
- esphome/components/mixer/speaker/automation.h +19 -0
- esphome/components/mixer/speaker/mixer_speaker.cpp +624 -0
- esphome/components/mixer/speaker/mixer_speaker.h +207 -0
- esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp +7 -13
- esphome/components/mpr121/mpr121.h +2 -0
- esphome/components/mqtt/__init__.py +1 -1
- esphome/components/mqtt/mqtt_client.cpp +7 -1
- esphome/components/mqtt/mqtt_client.h +1 -1
- esphome/components/mqtt/mqtt_climate.cpp +2 -2
- esphome/components/network/ip_address.h +2 -0
- esphome/components/nextion/automation.h +17 -0
- esphome/components/nextion/display.py +42 -17
- esphome/components/nextion/nextion.cpp +4 -10
- esphome/components/nextion/nextion.h +89 -82
- esphome/components/nextion/nextion_commands.cpp +10 -10
- esphome/components/ntc/sensor.py +2 -4
- esphome/components/online_image/__init__.py +98 -46
- esphome/components/online_image/bmp_image.cpp +101 -0
- esphome/components/online_image/bmp_image.h +40 -0
- esphome/components/online_image/image_decoder.cpp +31 -2
- esphome/components/online_image/image_decoder.h +24 -15
- esphome/components/online_image/jpeg_image.cpp +92 -0
- esphome/components/online_image/jpeg_image.h +34 -0
- esphome/components/online_image/online_image.cpp +118 -58
- esphome/components/online_image/online_image.h +39 -9
- esphome/components/online_image/png_image.cpp +7 -3
- esphome/components/online_image/png_image.h +2 -1
- esphome/components/opentherm/__init__.py +73 -7
- esphome/components/opentherm/automation.h +25 -0
- esphome/components/opentherm/const.py +1 -0
- esphome/components/opentherm/generate.py +39 -6
- esphome/components/opentherm/hub.cpp +117 -79
- esphome/components/opentherm/hub.h +31 -15
- esphome/components/opentherm/opentherm.cpp +47 -23
- esphome/components/opentherm/opentherm.h +27 -6
- esphome/components/opentherm/opentherm_macros.h +11 -0
- esphome/components/opentherm/schema.py +78 -1
- esphome/components/opentherm/validate.py +7 -2
- esphome/components/pca6416a/pca6416a.h +2 -0
- esphome/components/pca9554/pca9554.h +2 -0
- esphome/components/pcf8574/pcf8574.h +2 -0
- esphome/components/preferences/__init__.py +2 -4
- esphome/components/preferences/syncer.h +10 -3
- esphome/components/prometheus/prometheus_handler.cpp +313 -0
- esphome/components/prometheus/prometheus_handler.h +48 -7
- esphome/components/psram/psram.cpp +8 -1
- esphome/components/pulse_counter/pulse_counter_sensor.cpp +14 -9
- esphome/components/pulse_counter/pulse_counter_sensor.h +4 -4
- esphome/components/pulse_meter/pulse_meter_sensor.cpp +2 -0
- esphome/components/qspi_dbi/__init__.py +3 -0
- esphome/components/qspi_dbi/display.py +74 -47
- esphome/components/qspi_dbi/models.py +245 -2
- esphome/components/qspi_dbi/qspi_dbi.cpp +9 -16
- esphome/components/qspi_dbi/qspi_dbi.h +2 -2
- esphome/components/remote_base/__init__.py +77 -25
- esphome/components/remote_base/remote_base.cpp +1 -1
- esphome/components/remote_base/remote_base.h +20 -2
- esphome/components/remote_base/toto_protocol.cpp +100 -0
- esphome/components/remote_base/toto_protocol.h +45 -0
- esphome/components/remote_receiver/__init__.py +55 -10
- esphome/components/remote_receiver/remote_receiver.h +36 -3
- esphome/components/remote_receiver/remote_receiver_esp32.cpp +145 -6
- esphome/components/remote_transmitter/__init__.py +62 -4
- esphome/components/remote_transmitter/remote_transmitter.h +21 -2
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +140 -4
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +3 -3
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +3 -3
- esphome/components/resampler/__init__.py +0 -0
- esphome/components/resampler/speaker/__init__.py +103 -0
- esphome/components/resampler/speaker/resampler_speaker.cpp +318 -0
- esphome/components/resampler/speaker/resampler_speaker.h +107 -0
- esphome/components/resistance/resistance_sensor.h +2 -3
- esphome/components/resistance/sensor.py +2 -9
- esphome/components/rotary_encoder/rotary_encoder.cpp +8 -4
- esphome/components/rp2040/__init__.py +1 -0
- esphome/components/rp2040/gpio.h +1 -0
- esphome/components/rtl87xx/__init__.py +2 -0
- esphome/components/scd30/sensor.py +1 -1
- esphome/components/sdl/binary_sensor.py +270 -0
- esphome/components/sdl/sdl_esphome.cpp +16 -0
- esphome/components/sdl/sdl_esphome.h +9 -0
- esphome/components/seeed_mr60bha2/binary_sensor.py +25 -0
- esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +26 -2
- esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +9 -20
- esphome/components/seeed_mr60bha2/sensor.py +9 -1
- esphome/components/sn74hc165/sn74hc165.h +3 -0
- esphome/components/sn74hc595/sn74hc595.h +3 -0
- esphome/components/speaker/__init__.py +5 -4
- esphome/components/speaker/media_player/__init__.py +458 -0
- esphome/components/speaker/media_player/audio_pipeline.cpp +568 -0
- esphome/components/speaker/media_player/audio_pipeline.h +159 -0
- esphome/components/speaker/media_player/automation.h +26 -0
- esphome/components/speaker/media_player/speaker_media_player.cpp +577 -0
- esphome/components/speaker/media_player/speaker_media_player.h +160 -0
- esphome/components/speaker/speaker.h +20 -0
- esphome/components/spi/__init__.py +1 -5
- esphome/components/spi/spi.cpp +7 -1
- esphome/components/spi/spi.h +21 -2
- esphome/components/spi_led_strip/light.py +3 -5
- esphome/components/spi_led_strip/spi_led_strip.cpp +67 -0
- esphome/components/spi_led_strip/spi_led_strip.h +8 -60
- esphome/components/sprinkler/sprinkler.cpp +3 -1
- esphome/components/sx1509/sx1509_gpio_pin.h +2 -0
- esphome/components/tca9555/tca9555.h +2 -0
- esphome/components/toshiba/toshiba.cpp +2 -1
- esphome/components/tuya/light/tuya_light.cpp +4 -2
- esphome/components/uart/uart_component_esp32_arduino.cpp +2 -2
- esphome/components/uart/uart_component_esp_idf.cpp +2 -2
- esphome/components/udp/__init__.py +8 -2
- esphome/components/udp/udp_component.cpp +25 -56
- esphome/components/udp/udp_component.h +3 -0
- esphome/components/uponor_smatrix/sensor/__init__.py +14 -4
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +5 -0
- esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.h +1 -0
- esphome/components/uptime/text_sensor/__init__.py +19 -0
- esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +63 -0
- esphome/components/uptime/text_sensor/uptime_text_sensor.h +25 -0
- esphome/components/voice_assistant/voice_assistant.cpp +24 -14
- esphome/components/voice_assistant/voice_assistant.h +8 -0
- esphome/components/waveshare_epaper/display.py +22 -1
- esphome/components/waveshare_epaper/waveshare_213v3.cpp +9 -3
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +1155 -44
- esphome/components/waveshare_epaper/waveshare_epaper.h +208 -7
- esphome/components/web_server/web_server.cpp +28 -6
- esphome/components/weikai/weikai.h +2 -0
- esphome/components/wifi/__init__.py +6 -6
- esphome/components/wifi/wifi_component.cpp +1 -1
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -1
- esphome/components/wireguard/__init__.py +2 -2
- esphome/components/xl9535/xl9535.h +2 -0
- esphome/components/xxtea/__init__.py +3 -0
- esphome/components/xxtea/xxtea.cpp +46 -0
- esphome/components/xxtea/xxtea.h +26 -0
- esphome/components/yashima/yashima.cpp +2 -1
- esphome/config.py +9 -5
- esphome/config_validation.py +55 -17
- esphome/const.py +7 -10
- esphome/core/__init__.py +6 -13
- esphome/core/base_automation.h +1 -0
- esphome/core/config.py +59 -72
- esphome/core/defines.h +9 -1
- esphome/core/gpio.h +7 -0
- esphome/core/helpers.cpp +19 -15
- esphome/core/helpers.h +57 -8
- esphome/core/log.h +9 -7
- esphome/cpp_generator.py +2 -2
- esphome/dashboard/web_server.py +1 -1
- esphome/espota2.py +3 -2
- esphome/loader.py +12 -4
- esphome/log.py +5 -7
- esphome/yaml_util.py +2 -2
- {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/METADATA +14 -9
- {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/RECORD +349 -300
- esphome/components/custom/binary_sensor/custom_binary_sensor.cpp +0 -16
- esphome/components/custom/binary_sensor/custom_binary_sensor.h +0 -26
- esphome/components/custom/climate/custom_climate.h +0 -22
- esphome/components/custom/cover/custom_cover.h +0 -21
- esphome/components/custom/light/custom_light_output.h +0 -24
- esphome/components/custom/output/custom_output.h +0 -37
- esphome/components/custom/sensor/custom_sensor.cpp +0 -16
- esphome/components/custom/sensor/custom_sensor.h +0 -24
- esphome/components/custom/switch/custom_switch.cpp +0 -16
- esphome/components/custom/switch/custom_switch.h +0 -24
- esphome/components/custom/text_sensor/custom_text_sensor.cpp +0 -16
- esphome/components/custom/text_sensor/custom_text_sensor.h +0 -26
- esphome/components/custom_component/custom_component.h +0 -28
- esphome/components/esp32_ble_server/ble_2901.cpp +0 -18
- esphome/components/esp32_ble_server/ble_2901.h +0 -19
- esphome/components/resistance_sampler/__init__.py +0 -6
- esphome/components/resistance_sampler/resistance_sampler.h +0 -10
- esphome/components/uptime/{sensor.py → sensor/__init__.py} +3 -3
- /esphome/components/uptime/{uptime_seconds_sensor.cpp → sensor/uptime_seconds_sensor.cpp} +0 -0
- /esphome/components/uptime/{uptime_seconds_sensor.h → sensor/uptime_seconds_sensor.h} +0 -0
- /esphome/components/uptime/{uptime_timestamp_sensor.cpp → sensor/uptime_timestamp_sensor.cpp} +0 -0
- /esphome/components/uptime/{uptime_timestamp_sensor.h → sensor/uptime_timestamp_sensor.h} +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/LICENSE +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/WHEEL +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/entry_points.txt +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
#pragma once
|
2
|
+
#include <unordered_map>
|
3
|
+
#include <vector>
|
4
|
+
#include <functional>
|
5
|
+
#include <limits>
|
6
|
+
|
7
|
+
#include "esphome/core/log.h"
|
8
|
+
|
9
|
+
namespace esphome {
|
10
|
+
namespace event_emitter {
|
11
|
+
|
12
|
+
using EventEmitterListenerID = uint32_t;
|
13
|
+
void raise_event_emitter_full_error();
|
14
|
+
|
15
|
+
// EventEmitter class that can emit events with a specific name (it is highly recommended to use an enum class for this)
|
16
|
+
// and a list of arguments. Supports multiple listeners for each event.
|
17
|
+
template<typename EvtType, typename... Args> class EventEmitter {
|
18
|
+
public:
|
19
|
+
EventEmitterListenerID on(EvtType event, std::function<void(Args...)> listener) {
|
20
|
+
EventEmitterListenerID listener_id = get_next_id_(event);
|
21
|
+
listeners_[event][listener_id] = listener;
|
22
|
+
return listener_id;
|
23
|
+
}
|
24
|
+
|
25
|
+
void off(EvtType event, EventEmitterListenerID id) {
|
26
|
+
if (listeners_.count(event) == 0)
|
27
|
+
return;
|
28
|
+
listeners_[event].erase(id);
|
29
|
+
}
|
30
|
+
|
31
|
+
protected:
|
32
|
+
void emit_(EvtType event, Args... args) {
|
33
|
+
if (listeners_.count(event) == 0)
|
34
|
+
return;
|
35
|
+
for (const auto &listener : listeners_[event]) {
|
36
|
+
listener.second(args...);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
EventEmitterListenerID get_next_id_(EvtType event) {
|
41
|
+
// Check if the map is full
|
42
|
+
if (listeners_[event].size() == std::numeric_limits<EventEmitterListenerID>::max()) {
|
43
|
+
// Raise an error if the map is full
|
44
|
+
raise_event_emitter_full_error();
|
45
|
+
off(event, 0);
|
46
|
+
return 0;
|
47
|
+
}
|
48
|
+
// Get the next ID for the given event.
|
49
|
+
EventEmitterListenerID next_id = (current_id_ + 1) % std::numeric_limits<EventEmitterListenerID>::max();
|
50
|
+
while (listeners_[event].count(next_id) > 0) {
|
51
|
+
next_id = (next_id + 1) % std::numeric_limits<EventEmitterListenerID>::max();
|
52
|
+
}
|
53
|
+
current_id_ = next_id;
|
54
|
+
return current_id_;
|
55
|
+
}
|
56
|
+
|
57
|
+
private:
|
58
|
+
std::unordered_map<EvtType, std::unordered_map<EventEmitterListenerID, std::function<void(Args...)>>> listeners_;
|
59
|
+
EventEmitterListenerID current_id_ = 0;
|
60
|
+
};
|
61
|
+
|
62
|
+
} // namespace event_emitter
|
63
|
+
} // namespace esphome
|
@@ -97,8 +97,9 @@ void GCJA5Component::parse_data_() {
|
|
97
97
|
if (this->rx_message_[0] != 0x02 || this->rx_message_[31] != 0x03 || !this->calculate_checksum_()) {
|
98
98
|
ESP_LOGVV(TAG, "Discarding bad packet - failed checks.");
|
99
99
|
return;
|
100
|
-
} else
|
100
|
+
} else {
|
101
101
|
ESP_LOGVV(TAG, "Good packet found.");
|
102
|
+
}
|
102
103
|
|
103
104
|
this->have_good_data_ = true;
|
104
105
|
uint8_t status = this->rx_message_[29];
|
@@ -4,9 +4,6 @@
|
|
4
4
|
#include "esphome/core/log.h"
|
5
5
|
#include "esphome/core/hal.h"
|
6
6
|
#include <algorithm>
|
7
|
-
#include <sstream>
|
8
|
-
#include <iostream> // std::cout, std::fixed
|
9
|
-
#include <iomanip>
|
10
7
|
namespace esphome {
|
11
8
|
namespace graph {
|
12
9
|
|
@@ -231,9 +228,8 @@ void GraphLegend::init(Graph *g) {
|
|
231
228
|
ESP_LOGI(TAGL, " %s %d %d", txtstr.c_str(), fw, fh);
|
232
229
|
|
233
230
|
if (this->values_ != VALUE_POSITION_TYPE_NONE) {
|
234
|
-
std::
|
235
|
-
|
236
|
-
std::string valstr = ss.str();
|
231
|
+
std::string valstr =
|
232
|
+
value_accuracy_to_string(trace->sensor_->get_state(), trace->sensor_->get_accuracy_decimals());
|
237
233
|
if (this->units_) {
|
238
234
|
valstr += trace->sensor_->get_unit_of_measurement();
|
239
235
|
}
|
@@ -368,9 +364,8 @@ void Graph::draw_legend(display::Display *buff, uint16_t x_offset, uint16_t y_of
|
|
368
364
|
if (legend_->values_ != VALUE_POSITION_TYPE_NONE) {
|
369
365
|
int xv = x + legend_->xv_;
|
370
366
|
int yv = y + legend_->yv_;
|
371
|
-
std::
|
372
|
-
|
373
|
-
std::string valstr = ss.str();
|
367
|
+
std::string valstr =
|
368
|
+
value_accuracy_to_string(trace->sensor_->get_state(), trace->sensor_->get_accuracy_decimals());
|
374
369
|
if (legend_->units_) {
|
375
370
|
valstr += trace->sensor_->get_unit_of_measurement();
|
376
371
|
}
|
esphome/components/host/gpio.h
CHANGED
@@ -21,6 +21,7 @@ class HostGPIOPin : public InternalGPIOPin {
|
|
21
21
|
void detach_interrupt() const override;
|
22
22
|
ISRInternalGPIOPin to_isr() const override;
|
23
23
|
uint8_t get_pin() const override { return pin_; }
|
24
|
+
gpio::Flags get_flags() const override { return flags_; }
|
24
25
|
bool is_inverted() const override { return inverted_; }
|
25
26
|
|
26
27
|
protected:
|
@@ -96,7 +96,7 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::start(std::string url, std::s
|
|
96
96
|
container->client_.setUserAgent(this->useragent_);
|
97
97
|
}
|
98
98
|
for (const auto &header : headers) {
|
99
|
-
container->client_.addHeader(header.name, header.value, false, true);
|
99
|
+
container->client_.addHeader(header.name.c_str(), header.value.c_str(), false, true);
|
100
100
|
}
|
101
101
|
|
102
102
|
// returned needed headers must be collected before the requests
|
@@ -84,7 +84,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::start(std::string url, std::strin
|
|
84
84
|
container->set_secure(secure);
|
85
85
|
|
86
86
|
for (const auto &header : headers) {
|
87
|
-
esp_http_client_set_header(client, header.name, header.value);
|
87
|
+
esp_http_client_set_header(client, header.name.c_str(), header.value.c_str());
|
88
88
|
}
|
89
89
|
|
90
90
|
const int body_len = body.length();
|
@@ -39,6 +39,10 @@ void IDFI2CBus::setup() {
|
|
39
39
|
conf.scl_io_num = scl_pin_;
|
40
40
|
conf.scl_pullup_en = scl_pullup_enabled_;
|
41
41
|
conf.master.clk_speed = frequency_;
|
42
|
+
#ifdef USE_ESP32_VARIANT_ESP32S2
|
43
|
+
// workaround for https://github.com/esphome/issues/issues/6718
|
44
|
+
conf.clk_flags = I2C_SCLK_SRC_FLAG_AWARE_DFS;
|
45
|
+
#endif
|
42
46
|
esp_err_t err = i2c_param_config(port_, &conf);
|
43
47
|
if (err != ESP_OK) {
|
44
48
|
ESP_LOGW(TAG, "i2c_param_config failed: %s", esp_err_to_name(err));
|
@@ -25,11 +25,13 @@ void I2SAudioMicrophone::setup() {
|
|
25
25
|
}
|
26
26
|
} else
|
27
27
|
#endif
|
28
|
-
|
29
|
-
if (this->
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
{
|
29
|
+
if (this->pdm_) {
|
30
|
+
if (this->parent_->get_port() != I2S_NUM_0) {
|
31
|
+
ESP_LOGE(TAG, "PDM only works on I2S0!");
|
32
|
+
this->mark_failed();
|
33
|
+
return;
|
34
|
+
}
|
33
35
|
}
|
34
36
|
}
|
35
37
|
}
|
@@ -1,13 +1,25 @@
|
|
1
1
|
from esphome import pins
|
2
2
|
import esphome.codegen as cg
|
3
|
-
from esphome.components import esp32, speaker
|
3
|
+
from esphome.components import audio, esp32, speaker
|
4
4
|
import esphome.config_validation as cv
|
5
|
-
from esphome.const import
|
5
|
+
from esphome.const import (
|
6
|
+
CONF_BITS_PER_SAMPLE,
|
7
|
+
CONF_BUFFER_DURATION,
|
8
|
+
CONF_CHANNEL,
|
9
|
+
CONF_ID,
|
10
|
+
CONF_MODE,
|
11
|
+
CONF_NEVER,
|
12
|
+
CONF_NUM_CHANNELS,
|
13
|
+
CONF_SAMPLE_RATE,
|
14
|
+
CONF_TIMEOUT,
|
15
|
+
)
|
6
16
|
|
7
17
|
from .. import (
|
8
18
|
CONF_I2S_DOUT_PIN,
|
19
|
+
CONF_I2S_MODE,
|
9
20
|
CONF_LEFT,
|
10
21
|
CONF_MONO,
|
22
|
+
CONF_PRIMARY,
|
11
23
|
CONF_RIGHT,
|
12
24
|
CONF_STEREO,
|
13
25
|
I2SAudioOut,
|
@@ -24,10 +36,8 @@ I2SAudioSpeaker = i2s_audio_ns.class_(
|
|
24
36
|
"I2SAudioSpeaker", cg.Component, speaker.Speaker, I2SAudioOut
|
25
37
|
)
|
26
38
|
|
27
|
-
CONF_BUFFER_DURATION = "buffer_duration"
|
28
39
|
CONF_DAC_TYPE = "dac_type"
|
29
40
|
CONF_I2S_COMM_FMT = "i2s_comm_fmt"
|
30
|
-
CONF_NEVER = "never"
|
31
41
|
|
32
42
|
i2s_dac_mode_t = cg.global_ns.enum("i2s_dac_mode_t")
|
33
43
|
INTERNAL_DAC_OPTIONS = {
|
@@ -53,7 +63,41 @@ I2C_COMM_FMT_OPTIONS = {
|
|
53
63
|
NO_INTERNAL_DAC_VARIANTS = [esp32.const.VARIANT_ESP32S2]
|
54
64
|
|
55
65
|
|
56
|
-
def
|
66
|
+
def _set_num_channels_from_config(config):
|
67
|
+
if config[CONF_CHANNEL] in (CONF_MONO, CONF_LEFT, CONF_RIGHT):
|
68
|
+
config[CONF_NUM_CHANNELS] = 1
|
69
|
+
else:
|
70
|
+
config[CONF_NUM_CHANNELS] = 2
|
71
|
+
|
72
|
+
return config
|
73
|
+
|
74
|
+
|
75
|
+
def _set_stream_limits(config):
|
76
|
+
if config[CONF_I2S_MODE] == CONF_PRIMARY:
|
77
|
+
# Primary mode has modifiable stream settings
|
78
|
+
audio.set_stream_limits(
|
79
|
+
min_bits_per_sample=8,
|
80
|
+
max_bits_per_sample=32,
|
81
|
+
min_channels=1,
|
82
|
+
max_channels=2,
|
83
|
+
min_sample_rate=16000,
|
84
|
+
max_sample_rate=48000,
|
85
|
+
)(config)
|
86
|
+
else:
|
87
|
+
# Secondary mode has unmodifiable max bits per sample and min/max sample rates
|
88
|
+
audio.set_stream_limits(
|
89
|
+
min_bits_per_sample=8,
|
90
|
+
max_bits_per_sample=config.get(CONF_BITS_PER_SAMPLE),
|
91
|
+
min_channels=1,
|
92
|
+
max_channels=2,
|
93
|
+
min_sample_rate=config.get(CONF_SAMPLE_RATE),
|
94
|
+
max_sample_rate=config.get(CONF_SAMPLE_RATE),
|
95
|
+
)
|
96
|
+
|
97
|
+
return config
|
98
|
+
|
99
|
+
|
100
|
+
def _validate_esp32_variant(config):
|
57
101
|
if config[CONF_DAC_TYPE] != "internal":
|
58
102
|
return config
|
59
103
|
variant = esp32.get_esp32_variant()
|
@@ -85,6 +129,7 @@ BASE_SCHEMA = (
|
|
85
129
|
.extend(cv.COMPONENT_SCHEMA)
|
86
130
|
)
|
87
131
|
|
132
|
+
|
88
133
|
CONFIG_SCHEMA = cv.All(
|
89
134
|
cv.typed_schema(
|
90
135
|
{
|
@@ -106,7 +151,9 @@ CONFIG_SCHEMA = cv.All(
|
|
106
151
|
},
|
107
152
|
key=CONF_DAC_TYPE,
|
108
153
|
),
|
109
|
-
|
154
|
+
_validate_esp32_variant,
|
155
|
+
_set_num_channels_from_config,
|
156
|
+
_set_stream_limits,
|
110
157
|
)
|
111
158
|
|
112
159
|
|
@@ -148,9 +148,11 @@ void I2SAudioSpeaker::loop() {
|
|
148
148
|
this->status_set_error("Failed to adjust I2S bus to match the incoming audio");
|
149
149
|
ESP_LOGE(TAG,
|
150
150
|
"Incompatible audio format: sample rate = %" PRIu32 ", channels = %" PRIu8 ", bits per sample = %" PRIu8,
|
151
|
-
this->audio_stream_info_.
|
152
|
-
this->audio_stream_info_.
|
151
|
+
this->audio_stream_info_.get_sample_rate(), this->audio_stream_info_.get_channels(),
|
152
|
+
this->audio_stream_info_.get_bits_per_sample());
|
153
153
|
}
|
154
|
+
|
155
|
+
xEventGroupClearBits(this->event_group_, ALL_ERR_ESP_BITS);
|
154
156
|
}
|
155
157
|
|
156
158
|
void I2SAudioSpeaker::set_volume(float volume) {
|
@@ -201,6 +203,12 @@ size_t I2SAudioSpeaker::play(const uint8_t *data, size_t length, TickType_t tick
|
|
201
203
|
this->start();
|
202
204
|
}
|
203
205
|
|
206
|
+
if ((this->state_ != speaker::STATE_RUNNING) || (this->audio_ring_buffer_.use_count() == 1)) {
|
207
|
+
// Unable to write data to a running speaker, so delay the max amount of time so it can get ready
|
208
|
+
vTaskDelay(ticks_to_wait);
|
209
|
+
ticks_to_wait = 0;
|
210
|
+
}
|
211
|
+
|
204
212
|
size_t bytes_written = 0;
|
205
213
|
if ((this->state_ == speaker::STATE_RUNNING) && (this->audio_ring_buffer_.use_count() == 1)) {
|
206
214
|
// Only one owner of the ring buffer (the speaker task), so the ring buffer is allocated and no other components are
|
@@ -223,6 +231,8 @@ bool I2SAudioSpeaker::has_buffered_data() const {
|
|
223
231
|
|
224
232
|
void I2SAudioSpeaker::speaker_task(void *params) {
|
225
233
|
I2SAudioSpeaker *this_speaker = (I2SAudioSpeaker *) params;
|
234
|
+
this_speaker->task_created_ = true;
|
235
|
+
|
226
236
|
uint32_t event_group_bits =
|
227
237
|
xEventGroupWaitBits(this_speaker->event_group_,
|
228
238
|
SpeakerEventGroupBits::COMMAND_START | SpeakerEventGroupBits::COMMAND_STOP |
|
@@ -240,19 +250,20 @@ void I2SAudioSpeaker::speaker_task(void *params) {
|
|
240
250
|
|
241
251
|
audio::AudioStreamInfo audio_stream_info = this_speaker->audio_stream_info_;
|
242
252
|
|
243
|
-
const uint32_t
|
244
|
-
|
253
|
+
const uint32_t dma_buffers_duration_ms = DMA_BUFFER_DURATION_MS * DMA_BUFFERS_COUNT;
|
254
|
+
// Ensure ring buffer duration is at least the duration of all DMA buffers
|
255
|
+
const uint32_t ring_buffer_duration = std::max(dma_buffers_duration_ms, this_speaker->buffer_duration_ms_);
|
245
256
|
|
246
|
-
|
257
|
+
// The DMA buffers may have more bits per sample, so calculate buffer sizes based in the input audio stream info
|
258
|
+
const size_t data_buffer_size = audio_stream_info.ms_to_bytes(dma_buffers_duration_ms);
|
259
|
+
const size_t ring_buffer_size = audio_stream_info.ms_to_bytes(ring_buffer_duration);
|
247
260
|
|
248
|
-
|
249
|
-
const size_t ring_buffer_size =
|
250
|
-
std::max((uint32_t) dma_buffers_size, this_speaker->buffer_duration_ms_ * bytes_per_ms);
|
261
|
+
const size_t single_dma_buffer_input_size = data_buffer_size / DMA_BUFFERS_COUNT;
|
251
262
|
|
252
|
-
if (this_speaker->send_esp_err_to_event_group_(this_speaker->allocate_buffers_(
|
263
|
+
if (this_speaker->send_esp_err_to_event_group_(this_speaker->allocate_buffers_(data_buffer_size, ring_buffer_size))) {
|
253
264
|
// Failed to allocate buffers
|
254
265
|
xEventGroupSetBits(this_speaker->event_group_, SpeakerEventGroupBits::ERR_ESP_NO_MEM);
|
255
|
-
this_speaker->delete_task_(
|
266
|
+
this_speaker->delete_task_(data_buffer_size);
|
256
267
|
}
|
257
268
|
|
258
269
|
if (!this_speaker->send_esp_err_to_event_group_(this_speaker->start_i2s_driver_(audio_stream_info))) {
|
@@ -262,20 +273,25 @@ void I2SAudioSpeaker::speaker_task(void *params) {
|
|
262
273
|
uint32_t last_data_received_time = millis();
|
263
274
|
bool tx_dma_underflow = false;
|
264
275
|
|
265
|
-
|
276
|
+
this_speaker->accumulated_frames_written_ = 0;
|
277
|
+
|
278
|
+
// Keep looping if paused, there is no timeout configured, or data was received more recently than the configured
|
279
|
+
// timeout
|
280
|
+
while (this_speaker->pause_state_ || !this_speaker->timeout_.has_value() ||
|
266
281
|
(millis() - last_data_received_time) <= this_speaker->timeout_.value()) {
|
267
282
|
event_group_bits = xEventGroupGetBits(this_speaker->event_group_);
|
268
283
|
|
269
284
|
if (event_group_bits & SpeakerEventGroupBits::COMMAND_STOP) {
|
285
|
+
xEventGroupClearBits(this_speaker->event_group_, SpeakerEventGroupBits::COMMAND_STOP);
|
270
286
|
break;
|
271
287
|
}
|
272
288
|
if (event_group_bits & SpeakerEventGroupBits::COMMAND_STOP_GRACEFULLY) {
|
289
|
+
xEventGroupClearBits(this_speaker->event_group_, SpeakerEventGroupBits::COMMAND_STOP_GRACEFULLY);
|
273
290
|
stop_gracefully = true;
|
274
291
|
}
|
275
292
|
|
276
293
|
if (this_speaker->audio_stream_info_ != audio_stream_info) {
|
277
|
-
// Audio stream info
|
278
|
-
|
294
|
+
// Audio stream info changed, stop the speaker task so it will restart with the proper settings.
|
279
295
|
break;
|
280
296
|
}
|
281
297
|
|
@@ -286,33 +302,64 @@ void I2SAudioSpeaker::speaker_task(void *params) {
|
|
286
302
|
}
|
287
303
|
}
|
288
304
|
|
289
|
-
|
290
|
-
|
305
|
+
if (this_speaker->pause_state_) {
|
306
|
+
// Pause state is accessed atomically, so thread safe
|
307
|
+
// Delay so the task can yields, then skip transferring audio data
|
308
|
+
delay(TASK_DELAY_MS);
|
309
|
+
continue;
|
310
|
+
}
|
311
|
+
|
312
|
+
size_t bytes_read = this_speaker->audio_ring_buffer_->read((void *) this_speaker->data_buffer_, data_buffer_size,
|
291
313
|
pdMS_TO_TICKS(TASK_DELAY_MS));
|
292
314
|
|
293
315
|
if (bytes_read > 0) {
|
294
|
-
|
295
|
-
|
296
|
-
if ((audio_stream_info.bits_per_sample == 16) && (this_speaker->q15_volume_factor_ < INT16_MAX)) {
|
316
|
+
if ((audio_stream_info.get_bits_per_sample() == 16) && (this_speaker->q15_volume_factor_ < INT16_MAX)) {
|
297
317
|
// Scale samples by the volume factor in place
|
298
318
|
q15_multiplication((int16_t *) this_speaker->data_buffer_, (int16_t *) this_speaker->data_buffer_,
|
299
319
|
bytes_read / sizeof(int16_t), this_speaker->q15_volume_factor_);
|
300
320
|
}
|
301
321
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
}
|
322
|
+
// Write the audio data to a single DMA buffer at a time to reduce latency for the audio duration played
|
323
|
+
// callback.
|
324
|
+
const uint32_t batches = (bytes_read + single_dma_buffer_input_size - 1) / single_dma_buffer_input_size;
|
325
|
+
|
326
|
+
for (uint32_t i = 0; i < batches; ++i) {
|
327
|
+
size_t bytes_written = 0;
|
328
|
+
size_t bytes_to_write = std::min(single_dma_buffer_input_size, bytes_read);
|
310
329
|
|
311
|
-
|
312
|
-
|
330
|
+
if (audio_stream_info.get_bits_per_sample() == (uint8_t) this_speaker->bits_per_sample_) {
|
331
|
+
i2s_write(this_speaker->parent_->get_port(), this_speaker->data_buffer_ + i * single_dma_buffer_input_size,
|
332
|
+
bytes_to_write, &bytes_written, pdMS_TO_TICKS(DMA_BUFFER_DURATION_MS * 5));
|
333
|
+
} else if (audio_stream_info.get_bits_per_sample() < (uint8_t) this_speaker->bits_per_sample_) {
|
334
|
+
i2s_write_expand(this_speaker->parent_->get_port(),
|
335
|
+
this_speaker->data_buffer_ + i * single_dma_buffer_input_size, bytes_to_write,
|
336
|
+
audio_stream_info.get_bits_per_sample(), this_speaker->bits_per_sample_, &bytes_written,
|
337
|
+
pdMS_TO_TICKS(DMA_BUFFER_DURATION_MS * 5));
|
338
|
+
}
|
339
|
+
|
340
|
+
uint32_t write_timestamp = micros();
|
341
|
+
|
342
|
+
if (bytes_written != bytes_to_write) {
|
343
|
+
xEventGroupSetBits(this_speaker->event_group_, SpeakerEventGroupBits::ERR_ESP_INVALID_SIZE);
|
344
|
+
}
|
345
|
+
|
346
|
+
bytes_read -= bytes_written;
|
347
|
+
|
348
|
+
this_speaker->accumulated_frames_written_ += audio_stream_info.bytes_to_frames(bytes_written);
|
349
|
+
const uint32_t new_playback_ms =
|
350
|
+
audio_stream_info.frames_to_milliseconds_with_remainder(&this_speaker->accumulated_frames_written_);
|
351
|
+
const uint32_t remainder_us =
|
352
|
+
audio_stream_info.frames_to_microseconds(this_speaker->accumulated_frames_written_);
|
353
|
+
|
354
|
+
uint32_t pending_frames =
|
355
|
+
audio_stream_info.bytes_to_frames(bytes_read + this_speaker->audio_ring_buffer_->available());
|
356
|
+
const uint32_t pending_ms = audio_stream_info.frames_to_milliseconds_with_remainder(&pending_frames);
|
357
|
+
|
358
|
+
this_speaker->audio_output_callback_(new_playback_ms, remainder_us, pending_ms, write_timestamp);
|
359
|
+
|
360
|
+
tx_dma_underflow = false;
|
361
|
+
last_data_received_time = millis();
|
313
362
|
}
|
314
|
-
tx_dma_underflow = false;
|
315
|
-
last_data_received_time = millis();
|
316
363
|
} else {
|
317
364
|
// No data received
|
318
365
|
if (stop_gracefully && tx_dma_underflow) {
|
@@ -328,7 +375,7 @@ void I2SAudioSpeaker::speaker_task(void *params) {
|
|
328
375
|
this_speaker->parent_->unlock();
|
329
376
|
}
|
330
377
|
|
331
|
-
this_speaker->delete_task_(
|
378
|
+
this_speaker->delete_task_(data_buffer_size);
|
332
379
|
}
|
333
380
|
|
334
381
|
void I2SAudioSpeaker::start() {
|
@@ -337,16 +384,15 @@ void I2SAudioSpeaker::start() {
|
|
337
384
|
if ((this->state_ == speaker::STATE_STARTING) || (this->state_ == speaker::STATE_RUNNING))
|
338
385
|
return;
|
339
386
|
|
340
|
-
if (this->speaker_task_handle_ == nullptr) {
|
387
|
+
if (!this->task_created_ && (this->speaker_task_handle_ == nullptr)) {
|
341
388
|
xTaskCreate(I2SAudioSpeaker::speaker_task, "speaker_task", TASK_STACK_SIZE, (void *) this, TASK_PRIORITY,
|
342
389
|
&this->speaker_task_handle_);
|
343
|
-
}
|
344
390
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
391
|
+
if (this->speaker_task_handle_ != nullptr) {
|
392
|
+
xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::COMMAND_START);
|
393
|
+
} else {
|
394
|
+
xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::ERR_TASK_FAILED_TO_START);
|
395
|
+
}
|
350
396
|
}
|
351
397
|
}
|
352
398
|
|
@@ -416,12 +462,12 @@ esp_err_t I2SAudioSpeaker::allocate_buffers_(size_t data_buffer_size, size_t rin
|
|
416
462
|
}
|
417
463
|
|
418
464
|
esp_err_t I2SAudioSpeaker::start_i2s_driver_(audio::AudioStreamInfo &audio_stream_info) {
|
419
|
-
if ((this->i2s_mode_ & I2S_MODE_SLAVE) && (this->sample_rate_ != audio_stream_info.
|
420
|
-
//
|
465
|
+
if ((this->i2s_mode_ & I2S_MODE_SLAVE) && (this->sample_rate_ != audio_stream_info.get_sample_rate())) { // NOLINT
|
466
|
+
// Can't reconfigure I2S bus, so the sample rate must match the configured value
|
421
467
|
return ESP_ERR_NOT_SUPPORTED;
|
422
468
|
}
|
423
469
|
|
424
|
-
if ((i2s_bits_per_sample_t) audio_stream_info.
|
470
|
+
if ((i2s_bits_per_sample_t) audio_stream_info.get_bits_per_sample() > this->bits_per_sample_) {
|
425
471
|
// Currently can't handle the case when the incoming audio has more bits per sample than the configured value
|
426
472
|
return ESP_ERR_NOT_SUPPORTED;
|
427
473
|
}
|
@@ -432,21 +478,21 @@ esp_err_t I2SAudioSpeaker::start_i2s_driver_(audio::AudioStreamInfo &audio_strea
|
|
432
478
|
|
433
479
|
i2s_channel_fmt_t channel = this->channel_;
|
434
480
|
|
435
|
-
if (audio_stream_info.
|
481
|
+
if (audio_stream_info.get_channels() == 1) {
|
436
482
|
if (this->channel_ == I2S_CHANNEL_FMT_ONLY_LEFT) {
|
437
483
|
channel = I2S_CHANNEL_FMT_ONLY_LEFT;
|
438
484
|
} else {
|
439
485
|
channel = I2S_CHANNEL_FMT_ONLY_RIGHT;
|
440
486
|
}
|
441
|
-
} else if (audio_stream_info.
|
487
|
+
} else if (audio_stream_info.get_channels() == 2) {
|
442
488
|
channel = I2S_CHANNEL_FMT_RIGHT_LEFT;
|
443
489
|
}
|
444
490
|
|
445
|
-
int dma_buffer_length = DMA_BUFFER_DURATION_MS
|
491
|
+
int dma_buffer_length = audio_stream_info.ms_to_frames(DMA_BUFFER_DURATION_MS);
|
446
492
|
|
447
493
|
i2s_driver_config_t config = {
|
448
494
|
.mode = (i2s_mode_t) (this->i2s_mode_ | I2S_MODE_TX),
|
449
|
-
.sample_rate = audio_stream_info.
|
495
|
+
.sample_rate = audio_stream_info.get_sample_rate(),
|
450
496
|
.bits_per_sample = this->bits_per_sample_,
|
451
497
|
.channel_format = channel,
|
452
498
|
.communication_format = this->i2s_comm_fmt_,
|
@@ -504,7 +550,7 @@ esp_err_t I2SAudioSpeaker::start_i2s_driver_(audio::AudioStreamInfo &audio_strea
|
|
504
550
|
}
|
505
551
|
|
506
552
|
void I2SAudioSpeaker::delete_task_(size_t buffer_size) {
|
507
|
-
this->audio_ring_buffer_.reset(); // Releases
|
553
|
+
this->audio_ring_buffer_.reset(); // Releases ownership of the shared_ptr
|
508
554
|
|
509
555
|
if (this->data_buffer_ != nullptr) {
|
510
556
|
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
@@ -40,6 +40,9 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp
|
|
40
40
|
void stop() override;
|
41
41
|
void finish() override;
|
42
42
|
|
43
|
+
void set_pause_state(bool pause_state) override { this->pause_state_ = pause_state; }
|
44
|
+
bool get_pause_state() const override { return this->pause_state_; }
|
45
|
+
|
43
46
|
/// @brief Plays the provided audio data.
|
44
47
|
/// Starts the speaker task, if necessary. Writes the audio data to the ring buffer.
|
45
48
|
/// @param data Audio data in the format set by the parent speaker classes ``set_audio_stream_info`` method.
|
@@ -121,13 +124,18 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp
|
|
121
124
|
uint8_t dout_pin_;
|
122
125
|
|
123
126
|
bool task_created_{false};
|
127
|
+
bool pause_state_{false};
|
124
128
|
|
125
129
|
int16_t q15_volume_factor_{INT16_MAX};
|
126
130
|
|
131
|
+
size_t bytes_written_{0};
|
132
|
+
|
127
133
|
#if SOC_I2S_SUPPORTS_DAC
|
128
134
|
i2s_dac_mode_t internal_dac_mode_{I2S_DAC_CHANNEL_DISABLE};
|
129
135
|
#endif
|
130
136
|
i2s_comm_format_t i2s_comm_fmt_;
|
137
|
+
|
138
|
+
uint32_t accumulated_frames_written_{0};
|
131
139
|
};
|
132
140
|
|
133
141
|
} // namespace i2s_audio
|