esphome 2024.12.4__py3-none-any.whl → 2025.2.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +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/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/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 +2 -1
- esphome/components/display/__init__.py +18 -5
- esphome/components/display/display.cpp +2 -1
- 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_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/gcja5/gcja5.cpp +2 -1
- 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 +43 -7
- esphome/components/logger/logger.cpp +16 -11
- 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/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 +28 -2
- esphome/components/online_image/image_decoder.h +24 -15
- esphome/components/online_image/jpeg_image.cpp +90 -0
- esphome/components/online_image/jpeg_image.h +34 -0
- esphome/components/online_image/online_image.cpp +112 -53
- esphome/components/online_image/online_image.h +24 -7
- 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/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 +57 -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/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.0b1.dist-info}/METADATA +12 -7
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/RECORD +338 -289
- 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.0b1.dist-info}/LICENSE +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/WHEEL +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/entry_points.txt +0 -0
- {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
from esphome.components import audio, esp32, speaker
|
3
|
+
import esphome.config_validation as cv
|
4
|
+
from esphome.const import (
|
5
|
+
CONF_BITS_PER_SAMPLE,
|
6
|
+
CONF_BUFFER_DURATION,
|
7
|
+
CONF_FILTERS,
|
8
|
+
CONF_ID,
|
9
|
+
CONF_NUM_CHANNELS,
|
10
|
+
CONF_OUTPUT_SPEAKER,
|
11
|
+
CONF_SAMPLE_RATE,
|
12
|
+
CONF_TASK_STACK_IN_PSRAM,
|
13
|
+
PLATFORM_ESP32,
|
14
|
+
)
|
15
|
+
from esphome.core.entity_helpers import inherit_property_from
|
16
|
+
|
17
|
+
AUTO_LOAD = ["audio"]
|
18
|
+
CODEOWNERS = ["@kahrendt"]
|
19
|
+
|
20
|
+
resampler_ns = cg.esphome_ns.namespace("resampler")
|
21
|
+
ResamplerSpeaker = resampler_ns.class_(
|
22
|
+
"ResamplerSpeaker", cg.Component, speaker.Speaker
|
23
|
+
)
|
24
|
+
|
25
|
+
CONF_TAPS = "taps"
|
26
|
+
|
27
|
+
|
28
|
+
def _set_stream_limits(config):
|
29
|
+
audio.set_stream_limits(
|
30
|
+
min_bits_per_sample=16,
|
31
|
+
max_bits_per_sample=32,
|
32
|
+
)(config)
|
33
|
+
|
34
|
+
return config
|
35
|
+
|
36
|
+
|
37
|
+
def _validate_audio_compatability(config):
|
38
|
+
inherit_property_from(CONF_BITS_PER_SAMPLE, CONF_OUTPUT_SPEAKER)(config)
|
39
|
+
inherit_property_from(CONF_NUM_CHANNELS, CONF_OUTPUT_SPEAKER)(config)
|
40
|
+
inherit_property_from(CONF_SAMPLE_RATE, CONF_OUTPUT_SPEAKER)(config)
|
41
|
+
|
42
|
+
audio.final_validate_audio_schema(
|
43
|
+
"source_speaker",
|
44
|
+
audio_device=CONF_OUTPUT_SPEAKER,
|
45
|
+
bits_per_sample=config.get(CONF_BITS_PER_SAMPLE),
|
46
|
+
channels=config.get(CONF_NUM_CHANNELS),
|
47
|
+
sample_rate=config.get(CONF_SAMPLE_RATE),
|
48
|
+
)(config)
|
49
|
+
|
50
|
+
|
51
|
+
def _validate_taps(taps):
|
52
|
+
value = cv.int_range(min=16, max=128)(taps)
|
53
|
+
if value % 4 != 0:
|
54
|
+
raise cv.Invalid("Number of taps must be divisible by 4")
|
55
|
+
return value
|
56
|
+
|
57
|
+
|
58
|
+
CONFIG_SCHEMA = cv.All(
|
59
|
+
speaker.SPEAKER_SCHEMA.extend(
|
60
|
+
{
|
61
|
+
cv.GenerateID(): cv.declare_id(ResamplerSpeaker),
|
62
|
+
cv.Required(CONF_OUTPUT_SPEAKER): cv.use_id(speaker.Speaker),
|
63
|
+
cv.Optional(
|
64
|
+
CONF_BUFFER_DURATION, default="100ms"
|
65
|
+
): cv.positive_time_period_milliseconds,
|
66
|
+
cv.SplitDefault(CONF_TASK_STACK_IN_PSRAM, esp32_idf=False): cv.All(
|
67
|
+
cv.boolean, cv.only_with_esp_idf
|
68
|
+
),
|
69
|
+
cv.Optional(CONF_FILTERS, default=16): cv.int_range(min=2, max=1024),
|
70
|
+
cv.Optional(CONF_TAPS, default=16): _validate_taps,
|
71
|
+
}
|
72
|
+
).extend(cv.COMPONENT_SCHEMA),
|
73
|
+
cv.only_on([PLATFORM_ESP32]),
|
74
|
+
_set_stream_limits,
|
75
|
+
)
|
76
|
+
|
77
|
+
|
78
|
+
FINAL_VALIDATE_SCHEMA = _validate_audio_compatability
|
79
|
+
|
80
|
+
|
81
|
+
async def to_code(config):
|
82
|
+
var = cg.new_Pvariable(config[CONF_ID])
|
83
|
+
await cg.register_component(var, config)
|
84
|
+
await speaker.register_speaker(var, config)
|
85
|
+
|
86
|
+
output_spkr = await cg.get_variable(config[CONF_OUTPUT_SPEAKER])
|
87
|
+
cg.add(var.set_output_speaker(output_spkr))
|
88
|
+
|
89
|
+
cg.add(var.set_buffer_duration(config[CONF_BUFFER_DURATION]))
|
90
|
+
|
91
|
+
if task_stack_in_psram := config.get(CONF_TASK_STACK_IN_PSRAM):
|
92
|
+
cg.add(var.set_task_stack_in_psram(task_stack_in_psram))
|
93
|
+
if task_stack_in_psram:
|
94
|
+
if config[CONF_TASK_STACK_IN_PSRAM]:
|
95
|
+
esp32.add_idf_sdkconfig_option(
|
96
|
+
"CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY", True
|
97
|
+
)
|
98
|
+
|
99
|
+
cg.add(var.set_target_bits_per_sample(config[CONF_BITS_PER_SAMPLE]))
|
100
|
+
cg.add(var.set_target_sample_rate(config[CONF_SAMPLE_RATE]))
|
101
|
+
|
102
|
+
cg.add(var.set_filters(config[CONF_FILTERS]))
|
103
|
+
cg.add(var.set_taps(config[CONF_TAPS]))
|
@@ -0,0 +1,318 @@
|
|
1
|
+
#include "resampler_speaker.h"
|
2
|
+
|
3
|
+
#ifdef USE_ESP32
|
4
|
+
|
5
|
+
#include "esphome/components/audio/audio_resampler.h"
|
6
|
+
|
7
|
+
#include "esphome/core/helpers.h"
|
8
|
+
#include "esphome/core/log.h"
|
9
|
+
|
10
|
+
#include <algorithm>
|
11
|
+
#include <cstring>
|
12
|
+
|
13
|
+
namespace esphome {
|
14
|
+
namespace resampler {
|
15
|
+
|
16
|
+
static const UBaseType_t RESAMPLER_TASK_PRIORITY = 1;
|
17
|
+
|
18
|
+
static const uint32_t TRANSFER_BUFFER_DURATION_MS = 50;
|
19
|
+
|
20
|
+
static const uint32_t TASK_DELAY_MS = 20;
|
21
|
+
static const uint32_t TASK_STACK_SIZE = 3072;
|
22
|
+
|
23
|
+
static const char *const TAG = "resampler_speaker";
|
24
|
+
|
25
|
+
enum ResamplingEventGroupBits : uint32_t {
|
26
|
+
COMMAND_STOP = (1 << 0), // stops the resampler task
|
27
|
+
STATE_STARTING = (1 << 10),
|
28
|
+
STATE_RUNNING = (1 << 11),
|
29
|
+
STATE_STOPPING = (1 << 12),
|
30
|
+
STATE_STOPPED = (1 << 13),
|
31
|
+
ERR_ESP_NO_MEM = (1 << 19),
|
32
|
+
ERR_ESP_NOT_SUPPORTED = (1 << 20),
|
33
|
+
ERR_ESP_FAIL = (1 << 21),
|
34
|
+
ALL_BITS = 0x00FFFFFF, // All valid FreeRTOS event group bits
|
35
|
+
};
|
36
|
+
|
37
|
+
void ResamplerSpeaker::setup() {
|
38
|
+
this->event_group_ = xEventGroupCreate();
|
39
|
+
|
40
|
+
if (this->event_group_ == nullptr) {
|
41
|
+
ESP_LOGE(TAG, "Failed to create event group");
|
42
|
+
this->mark_failed();
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
|
46
|
+
this->output_speaker_->add_audio_output_callback(
|
47
|
+
[this](uint32_t new_playback_ms, uint32_t remainder_us, uint32_t pending_ms, uint32_t write_timestamp) {
|
48
|
+
int32_t adjustment = this->playback_differential_ms_;
|
49
|
+
this->playback_differential_ms_ -= adjustment;
|
50
|
+
int32_t adjusted_playback_ms = static_cast<int32_t>(new_playback_ms) + adjustment;
|
51
|
+
this->audio_output_callback_(adjusted_playback_ms, remainder_us, pending_ms, write_timestamp);
|
52
|
+
});
|
53
|
+
}
|
54
|
+
|
55
|
+
void ResamplerSpeaker::loop() {
|
56
|
+
uint32_t event_group_bits = xEventGroupGetBits(this->event_group_);
|
57
|
+
|
58
|
+
if (event_group_bits & ResamplingEventGroupBits::STATE_STARTING) {
|
59
|
+
ESP_LOGD(TAG, "Starting resampler task");
|
60
|
+
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::STATE_STARTING);
|
61
|
+
}
|
62
|
+
|
63
|
+
if (event_group_bits & ResamplingEventGroupBits::ERR_ESP_NO_MEM) {
|
64
|
+
this->status_set_error("Resampler task failed to allocate the internal buffers");
|
65
|
+
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ERR_ESP_NO_MEM);
|
66
|
+
this->state_ = speaker::STATE_STOPPING;
|
67
|
+
}
|
68
|
+
if (event_group_bits & ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED) {
|
69
|
+
this->status_set_error("Cannot resample due to an unsupported audio stream");
|
70
|
+
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED);
|
71
|
+
this->state_ = speaker::STATE_STOPPING;
|
72
|
+
}
|
73
|
+
if (event_group_bits & ResamplingEventGroupBits::ERR_ESP_FAIL) {
|
74
|
+
this->status_set_error("Resampler task failed");
|
75
|
+
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ERR_ESP_FAIL);
|
76
|
+
this->state_ = speaker::STATE_STOPPING;
|
77
|
+
}
|
78
|
+
|
79
|
+
if (event_group_bits & ResamplingEventGroupBits::STATE_RUNNING) {
|
80
|
+
ESP_LOGD(TAG, "Started resampler task");
|
81
|
+
this->status_clear_error();
|
82
|
+
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::STATE_RUNNING);
|
83
|
+
}
|
84
|
+
if (event_group_bits & ResamplingEventGroupBits::STATE_STOPPING) {
|
85
|
+
ESP_LOGD(TAG, "Stopping resampler task");
|
86
|
+
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::STATE_STOPPING);
|
87
|
+
}
|
88
|
+
if (event_group_bits & ResamplingEventGroupBits::STATE_STOPPED) {
|
89
|
+
if (this->delete_task_() == ESP_OK) {
|
90
|
+
ESP_LOGD(TAG, "Stopped resampler task");
|
91
|
+
xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ALL_BITS);
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
switch (this->state_) {
|
96
|
+
case speaker::STATE_STARTING: {
|
97
|
+
esp_err_t err = this->start_();
|
98
|
+
if (err == ESP_OK) {
|
99
|
+
this->status_clear_error();
|
100
|
+
this->state_ = speaker::STATE_RUNNING;
|
101
|
+
} else {
|
102
|
+
switch (err) {
|
103
|
+
case ESP_ERR_INVALID_STATE:
|
104
|
+
this->status_set_error("Failed to start resampler: resampler task failed to start");
|
105
|
+
break;
|
106
|
+
case ESP_ERR_NO_MEM:
|
107
|
+
this->status_set_error("Failed to start resampler: not enough memory for task stack");
|
108
|
+
default:
|
109
|
+
this->status_set_error("Failed to start resampler");
|
110
|
+
break;
|
111
|
+
}
|
112
|
+
|
113
|
+
this->state_ = speaker::STATE_STOPPING;
|
114
|
+
}
|
115
|
+
break;
|
116
|
+
}
|
117
|
+
case speaker::STATE_RUNNING:
|
118
|
+
if (this->output_speaker_->is_stopped()) {
|
119
|
+
this->state_ = speaker::STATE_STOPPING;
|
120
|
+
}
|
121
|
+
|
122
|
+
break;
|
123
|
+
case speaker::STATE_STOPPING:
|
124
|
+
this->stop_();
|
125
|
+
this->state_ = speaker::STATE_STOPPED;
|
126
|
+
break;
|
127
|
+
case speaker::STATE_STOPPED:
|
128
|
+
break;
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
size_t ResamplerSpeaker::play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) {
|
133
|
+
if (this->is_stopped()) {
|
134
|
+
this->start();
|
135
|
+
}
|
136
|
+
|
137
|
+
size_t bytes_written = 0;
|
138
|
+
if ((this->output_speaker_->is_running()) && (!this->requires_resampling_())) {
|
139
|
+
bytes_written = this->output_speaker_->play(data, length, ticks_to_wait);
|
140
|
+
} else {
|
141
|
+
if (this->ring_buffer_.use_count() == 1) {
|
142
|
+
std::shared_ptr<RingBuffer> temp_ring_buffer = this->ring_buffer_.lock();
|
143
|
+
bytes_written = temp_ring_buffer->write_without_replacement(data, length, ticks_to_wait);
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
return bytes_written;
|
148
|
+
}
|
149
|
+
|
150
|
+
void ResamplerSpeaker::start() { this->state_ = speaker::STATE_STARTING; }
|
151
|
+
|
152
|
+
esp_err_t ResamplerSpeaker::start_() {
|
153
|
+
this->target_stream_info_ = audio::AudioStreamInfo(
|
154
|
+
this->target_bits_per_sample_, this->audio_stream_info_.get_channels(), this->target_sample_rate_);
|
155
|
+
|
156
|
+
this->output_speaker_->set_audio_stream_info(this->target_stream_info_);
|
157
|
+
this->output_speaker_->start();
|
158
|
+
|
159
|
+
if (this->requires_resampling_()) {
|
160
|
+
// Start the resampler task to handle converting sample rates
|
161
|
+
return this->start_task_();
|
162
|
+
}
|
163
|
+
|
164
|
+
return ESP_OK;
|
165
|
+
}
|
166
|
+
|
167
|
+
esp_err_t ResamplerSpeaker::start_task_() {
|
168
|
+
if (this->task_stack_buffer_ == nullptr) {
|
169
|
+
if (this->task_stack_in_psram_) {
|
170
|
+
RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL);
|
171
|
+
this->task_stack_buffer_ = stack_allocator.allocate(TASK_STACK_SIZE);
|
172
|
+
} else {
|
173
|
+
RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL);
|
174
|
+
this->task_stack_buffer_ = stack_allocator.allocate(TASK_STACK_SIZE);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
if (this->task_stack_buffer_ == nullptr) {
|
179
|
+
return ESP_ERR_NO_MEM;
|
180
|
+
}
|
181
|
+
|
182
|
+
if (this->task_handle_ == nullptr) {
|
183
|
+
this->task_handle_ = xTaskCreateStatic(resample_task, "sample", TASK_STACK_SIZE, (void *) this,
|
184
|
+
RESAMPLER_TASK_PRIORITY, this->task_stack_buffer_, &this->task_stack_);
|
185
|
+
}
|
186
|
+
|
187
|
+
if (this->task_handle_ == nullptr) {
|
188
|
+
return ESP_ERR_INVALID_STATE;
|
189
|
+
}
|
190
|
+
|
191
|
+
return ESP_OK;
|
192
|
+
}
|
193
|
+
|
194
|
+
void ResamplerSpeaker::stop() { this->state_ = speaker::STATE_STOPPING; }
|
195
|
+
|
196
|
+
void ResamplerSpeaker::stop_() {
|
197
|
+
if (this->task_handle_ != nullptr) {
|
198
|
+
xEventGroupSetBits(this->event_group_, ResamplingEventGroupBits::COMMAND_STOP);
|
199
|
+
}
|
200
|
+
this->output_speaker_->stop();
|
201
|
+
}
|
202
|
+
|
203
|
+
esp_err_t ResamplerSpeaker::delete_task_() {
|
204
|
+
if (!this->task_created_) {
|
205
|
+
this->task_handle_ = nullptr;
|
206
|
+
|
207
|
+
if (this->task_stack_buffer_ != nullptr) {
|
208
|
+
if (this->task_stack_in_psram_) {
|
209
|
+
RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL);
|
210
|
+
stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE);
|
211
|
+
} else {
|
212
|
+
RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL);
|
213
|
+
stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE);
|
214
|
+
}
|
215
|
+
|
216
|
+
this->task_stack_buffer_ = nullptr;
|
217
|
+
}
|
218
|
+
|
219
|
+
return ESP_OK;
|
220
|
+
}
|
221
|
+
|
222
|
+
return ESP_ERR_INVALID_STATE;
|
223
|
+
}
|
224
|
+
|
225
|
+
void ResamplerSpeaker::finish() { this->output_speaker_->finish(); }
|
226
|
+
|
227
|
+
bool ResamplerSpeaker::has_buffered_data() const {
|
228
|
+
bool has_ring_buffer_data = false;
|
229
|
+
if (this->requires_resampling_() && (this->ring_buffer_.use_count() > 0)) {
|
230
|
+
has_ring_buffer_data = (this->ring_buffer_.lock()->available() > 0);
|
231
|
+
}
|
232
|
+
return (has_ring_buffer_data || this->output_speaker_->has_buffered_data());
|
233
|
+
}
|
234
|
+
|
235
|
+
void ResamplerSpeaker::set_mute_state(bool mute_state) {
|
236
|
+
this->mute_state_ = mute_state;
|
237
|
+
this->output_speaker_->set_mute_state(mute_state);
|
238
|
+
}
|
239
|
+
|
240
|
+
void ResamplerSpeaker::set_volume(float volume) {
|
241
|
+
this->volume_ = volume;
|
242
|
+
this->output_speaker_->set_volume(volume);
|
243
|
+
}
|
244
|
+
|
245
|
+
bool ResamplerSpeaker::requires_resampling_() const {
|
246
|
+
return (this->audio_stream_info_.get_sample_rate() != this->target_sample_rate_) ||
|
247
|
+
(this->audio_stream_info_.get_bits_per_sample() != this->target_bits_per_sample_);
|
248
|
+
}
|
249
|
+
|
250
|
+
void ResamplerSpeaker::resample_task(void *params) {
|
251
|
+
ResamplerSpeaker *this_resampler = (ResamplerSpeaker *) params;
|
252
|
+
|
253
|
+
this_resampler->task_created_ = true;
|
254
|
+
xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STARTING);
|
255
|
+
|
256
|
+
std::unique_ptr<audio::AudioResampler> resampler =
|
257
|
+
make_unique<audio::AudioResampler>(this_resampler->audio_stream_info_.ms_to_bytes(TRANSFER_BUFFER_DURATION_MS),
|
258
|
+
this_resampler->target_stream_info_.ms_to_bytes(TRANSFER_BUFFER_DURATION_MS));
|
259
|
+
|
260
|
+
esp_err_t err = resampler->start(this_resampler->audio_stream_info_, this_resampler->target_stream_info_,
|
261
|
+
this_resampler->taps_, this_resampler->filters_);
|
262
|
+
|
263
|
+
if (err == ESP_OK) {
|
264
|
+
std::shared_ptr<RingBuffer> temp_ring_buffer =
|
265
|
+
RingBuffer::create(this_resampler->audio_stream_info_.ms_to_bytes(this_resampler->buffer_duration_ms_));
|
266
|
+
|
267
|
+
if (temp_ring_buffer.use_count() == 0) {
|
268
|
+
err = ESP_ERR_NO_MEM;
|
269
|
+
} else {
|
270
|
+
this_resampler->ring_buffer_ = temp_ring_buffer;
|
271
|
+
resampler->add_source(this_resampler->ring_buffer_);
|
272
|
+
|
273
|
+
this_resampler->output_speaker_->set_audio_stream_info(this_resampler->target_stream_info_);
|
274
|
+
resampler->add_sink(this_resampler->output_speaker_);
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
278
|
+
if (err == ESP_OK) {
|
279
|
+
xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_RUNNING);
|
280
|
+
} else if (err == ESP_ERR_NO_MEM) {
|
281
|
+
xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_NO_MEM);
|
282
|
+
} else if (err == ESP_ERR_NOT_SUPPORTED) {
|
283
|
+
xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED);
|
284
|
+
}
|
285
|
+
|
286
|
+
this_resampler->playback_differential_ms_ = 0;
|
287
|
+
while (err == ESP_OK) {
|
288
|
+
uint32_t event_bits = xEventGroupGetBits(this_resampler->event_group_);
|
289
|
+
|
290
|
+
if (event_bits & ResamplingEventGroupBits::COMMAND_STOP) {
|
291
|
+
break;
|
292
|
+
}
|
293
|
+
|
294
|
+
// Stop gracefully if the decoder is done
|
295
|
+
int32_t ms_differential = 0;
|
296
|
+
audio::AudioResamplerState resampler_state = resampler->resample(false, &ms_differential);
|
297
|
+
|
298
|
+
this_resampler->playback_differential_ms_ += ms_differential;
|
299
|
+
|
300
|
+
if (resampler_state == audio::AudioResamplerState::FINISHED) {
|
301
|
+
break;
|
302
|
+
} else if (resampler_state == audio::AudioResamplerState::FAILED) {
|
303
|
+
xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_FAIL);
|
304
|
+
break;
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
308
|
+
xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STOPPING);
|
309
|
+
resampler.reset();
|
310
|
+
xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STOPPED);
|
311
|
+
this_resampler->task_created_ = false;
|
312
|
+
vTaskDelete(nullptr);
|
313
|
+
}
|
314
|
+
|
315
|
+
} // namespace resampler
|
316
|
+
} // namespace esphome
|
317
|
+
|
318
|
+
#endif
|
@@ -0,0 +1,107 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#ifdef USE_ESP32
|
4
|
+
|
5
|
+
#include "esphome/components/audio/audio.h"
|
6
|
+
#include "esphome/components/audio/audio_transfer_buffer.h"
|
7
|
+
#include "esphome/components/speaker/speaker.h"
|
8
|
+
|
9
|
+
#include "esphome/core/component.h"
|
10
|
+
|
11
|
+
#include <freertos/event_groups.h>
|
12
|
+
#include <freertos/FreeRTOS.h>
|
13
|
+
|
14
|
+
namespace esphome {
|
15
|
+
namespace resampler {
|
16
|
+
|
17
|
+
class ResamplerSpeaker : public Component, public speaker::Speaker {
|
18
|
+
public:
|
19
|
+
float get_setup_priority() const override { return esphome::setup_priority::DATA; }
|
20
|
+
void setup() override;
|
21
|
+
void loop() override;
|
22
|
+
|
23
|
+
size_t play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) override;
|
24
|
+
size_t play(const uint8_t *data, size_t length) override { return this->play(data, length, 0); }
|
25
|
+
|
26
|
+
void start() override;
|
27
|
+
void stop() override;
|
28
|
+
void finish() override;
|
29
|
+
|
30
|
+
void set_pause_state(bool pause_state) override { this->output_speaker_->set_pause_state(pause_state); }
|
31
|
+
bool get_pause_state() const override { return this->output_speaker_->get_pause_state(); }
|
32
|
+
|
33
|
+
bool has_buffered_data() const override;
|
34
|
+
|
35
|
+
/// @brief Mute state changes are passed to the parent's output speaker
|
36
|
+
void set_mute_state(bool mute_state) override;
|
37
|
+
|
38
|
+
/// @brief Volume state changes are passed to the parent's output speaker
|
39
|
+
void set_volume(float volume) override;
|
40
|
+
|
41
|
+
void set_output_speaker(speaker::Speaker *speaker) { this->output_speaker_ = speaker; }
|
42
|
+
void set_task_stack_in_psram(bool task_stack_in_psram) { this->task_stack_in_psram_ = task_stack_in_psram; }
|
43
|
+
|
44
|
+
void set_target_bits_per_sample(uint8_t target_bits_per_sample) {
|
45
|
+
this->target_bits_per_sample_ = target_bits_per_sample;
|
46
|
+
}
|
47
|
+
void set_target_sample_rate(uint32_t target_sample_rate) { this->target_sample_rate_ = target_sample_rate; }
|
48
|
+
|
49
|
+
void set_filters(uint16_t filters) { this->filters_ = filters; }
|
50
|
+
void set_taps(uint16_t taps) { this->taps_ = taps; }
|
51
|
+
|
52
|
+
void set_buffer_duration(uint32_t buffer_duration_ms) { this->buffer_duration_ms_ = buffer_duration_ms; }
|
53
|
+
|
54
|
+
protected:
|
55
|
+
/// @brief Starts the output speaker after setting the resampled stream info. If resampling is required, it starts the
|
56
|
+
/// task.
|
57
|
+
/// @return ESP_OK if resampling is required
|
58
|
+
/// return value of start_task_() if resampling is required
|
59
|
+
esp_err_t start_();
|
60
|
+
|
61
|
+
/// @brief Starts the resampler task after allocating the task stack
|
62
|
+
/// @return ESP_OK if successful,
|
63
|
+
/// ESP_ERR_NO_MEM if the task stack couldn't be allocated
|
64
|
+
/// ESP_ERR_INVALID_STATE if the task wasn't created
|
65
|
+
esp_err_t start_task_();
|
66
|
+
|
67
|
+
/// @brief Stops the output speaker. If the resampling task is running, it sends the stop command.
|
68
|
+
void stop_();
|
69
|
+
|
70
|
+
/// @brief Deallocates the task stack and resets the pointers.
|
71
|
+
/// @return ESP_OK if successful
|
72
|
+
/// ESP_ERR_INVALID_STATE if the task hasn't stopped itself
|
73
|
+
esp_err_t delete_task_();
|
74
|
+
|
75
|
+
inline bool requires_resampling_() const;
|
76
|
+
static void resample_task(void *params);
|
77
|
+
|
78
|
+
EventGroupHandle_t event_group_{nullptr};
|
79
|
+
|
80
|
+
std::weak_ptr<RingBuffer> ring_buffer_;
|
81
|
+
|
82
|
+
speaker::Speaker *output_speaker_{nullptr};
|
83
|
+
|
84
|
+
bool task_stack_in_psram_{false};
|
85
|
+
bool task_created_{false};
|
86
|
+
|
87
|
+
TaskHandle_t task_handle_{nullptr};
|
88
|
+
StaticTask_t task_stack_;
|
89
|
+
StackType_t *task_stack_buffer_{nullptr};
|
90
|
+
|
91
|
+
audio::AudioStreamInfo target_stream_info_;
|
92
|
+
|
93
|
+
uint16_t taps_;
|
94
|
+
uint16_t filters_;
|
95
|
+
|
96
|
+
uint8_t target_bits_per_sample_;
|
97
|
+
uint32_t target_sample_rate_;
|
98
|
+
|
99
|
+
uint32_t buffer_duration_ms_;
|
100
|
+
|
101
|
+
int32_t playback_differential_ms_{0};
|
102
|
+
};
|
103
|
+
|
104
|
+
} // namespace resampler
|
105
|
+
} // namespace esphome
|
106
|
+
|
107
|
+
#endif
|
@@ -1,8 +1,7 @@
|
|
1
1
|
#pragma once
|
2
2
|
|
3
|
-
#include "esphome/components/resistance_sampler/resistance_sampler.h"
|
4
|
-
#include "esphome/components/sensor/sensor.h"
|
5
3
|
#include "esphome/core/component.h"
|
4
|
+
#include "esphome/components/sensor/sensor.h"
|
6
5
|
|
7
6
|
namespace esphome {
|
8
7
|
namespace resistance {
|
@@ -12,7 +11,7 @@ enum ResistanceConfiguration {
|
|
12
11
|
DOWNSTREAM,
|
13
12
|
};
|
14
13
|
|
15
|
-
class ResistanceSensor : public Component, public sensor::Sensor
|
14
|
+
class ResistanceSensor : public Component, public sensor::Sensor {
|
16
15
|
public:
|
17
16
|
void set_sensor(Sensor *sensor) { sensor_ = sensor; }
|
18
17
|
void set_configuration(ResistanceConfiguration configuration) { configuration_ = configuration; }
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import esphome.codegen as cg
|
2
2
|
import esphome.config_validation as cv
|
3
|
-
from esphome.components import sensor
|
3
|
+
from esphome.components import sensor
|
4
4
|
from esphome.const import (
|
5
5
|
CONF_REFERENCE_VOLTAGE,
|
6
6
|
CONF_SENSOR,
|
@@ -9,15 +9,8 @@ from esphome.const import (
|
|
9
9
|
ICON_FLASH,
|
10
10
|
)
|
11
11
|
|
12
|
-
AUTO_LOAD = ["resistance_sampler"]
|
13
|
-
|
14
12
|
resistance_ns = cg.esphome_ns.namespace("resistance")
|
15
|
-
ResistanceSensor = resistance_ns.class_(
|
16
|
-
"ResistanceSensor",
|
17
|
-
cg.Component,
|
18
|
-
sensor.Sensor,
|
19
|
-
resistance_sampler.ResistanceSampler,
|
20
|
-
)
|
13
|
+
ResistanceSensor = resistance_ns.class_("ResistanceSensor", cg.Component, sensor.Sensor)
|
21
14
|
|
22
15
|
CONF_CONFIGURATION = "configuration"
|
23
16
|
CONF_RESISTOR = "resistor"
|
@@ -93,13 +93,17 @@ void IRAM_ATTR HOT RotaryEncoderSensorStore::gpio_intr(RotaryEncoderSensorStore
|
|
93
93
|
int8_t rotation_dir = 0;
|
94
94
|
uint16_t new_state = STATE_LOOKUP_TABLE[input_state];
|
95
95
|
if ((new_state & arg->resolution & STATE_HAS_INCREMENTED) != 0) {
|
96
|
-
if (arg->counter < arg->max_value)
|
97
|
-
arg->counter
|
96
|
+
if (arg->counter < arg->max_value) {
|
97
|
+
auto x = arg->counter + 1;
|
98
|
+
arg->counter = x;
|
99
|
+
}
|
98
100
|
rotation_dir = 1;
|
99
101
|
}
|
100
102
|
if ((new_state & arg->resolution & STATE_HAS_DECREMENTED) != 0) {
|
101
|
-
if (arg->counter > arg->min_value)
|
102
|
-
arg->counter
|
103
|
+
if (arg->counter > arg->min_value) {
|
104
|
+
auto x = arg->counter - 1;
|
105
|
+
arg->counter = x;
|
106
|
+
}
|
103
107
|
rotation_dir = -1;
|
104
108
|
}
|
105
109
|
|
esphome/components/rp2040/gpio.h
CHANGED
@@ -22,6 +22,7 @@ class RP2040GPIOPin : public InternalGPIOPin {
|
|
22
22
|
void detach_interrupt() const override;
|
23
23
|
ISRInternalGPIOPin to_isr() const override;
|
24
24
|
uint8_t get_pin() const override { return pin_; }
|
25
|
+
gpio::Flags get_flags() const override { return flags_; }
|
25
26
|
bool is_inverted() const override { return inverted_; }
|
26
27
|
|
27
28
|
protected:
|