esphome 2024.12.3__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.
Files changed (366) hide show
  1. esphome/__main__.py +16 -3
  2. esphome/components/adc/__init__.py +17 -11
  3. esphome/components/adc/adc_sensor.h +17 -0
  4. esphome/components/adc/adc_sensor_common.cpp +55 -0
  5. esphome/components/adc/adc_sensor_esp32.cpp +8 -5
  6. esphome/components/adc/adc_sensor_esp8266.cpp +10 -6
  7. esphome/components/adc/adc_sensor_libretiny.cpp +11 -6
  8. esphome/components/adc/adc_sensor_rp2040.cpp +13 -10
  9. esphome/components/adc/sensor.py +9 -3
  10. esphome/components/ads1115/ads1115.cpp +56 -7
  11. esphome/components/ads1115/ads1115.h +13 -1
  12. esphome/components/ads1115/sensor/__init__.py +16 -0
  13. esphome/components/ads1115/sensor/ads1115_sensor.cpp +2 -1
  14. esphome/components/ads1115/sensor/ads1115_sensor.h +2 -0
  15. esphome/components/animation/__init__.py +23 -261
  16. esphome/components/animation/animation.cpp +2 -2
  17. esphome/components/animation/animation.h +2 -1
  18. esphome/components/api/api_pb2.cpp +14 -0
  19. esphome/components/api/api_pb2.h +1 -0
  20. esphome/components/api/client.py +8 -3
  21. esphome/components/audio/__init__.py +112 -0
  22. esphome/components/audio/audio.cpp +67 -0
  23. esphome/components/audio/audio.h +125 -7
  24. esphome/components/audio/audio_decoder.cpp +361 -0
  25. esphome/components/audio/audio_decoder.h +135 -0
  26. esphome/components/audio/audio_reader.cpp +308 -0
  27. esphome/components/audio/audio_reader.h +85 -0
  28. esphome/components/audio/audio_resampler.cpp +159 -0
  29. esphome/components/audio/audio_resampler.h +101 -0
  30. esphome/components/audio/audio_transfer_buffer.cpp +165 -0
  31. esphome/components/audio/audio_transfer_buffer.h +139 -0
  32. esphome/components/audio_adc/__init__.py +41 -0
  33. esphome/components/audio_adc/audio_adc.h +17 -0
  34. esphome/components/audio_adc/automation.h +23 -0
  35. esphome/components/bk72xx/__init__.py +1 -0
  36. esphome/components/ble_client/ble_client.cpp +1 -2
  37. esphome/components/ble_client/sensor/__init__.py +1 -1
  38. esphome/components/ble_client/text_sensor/__init__.py +1 -1
  39. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +5 -0
  40. esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -0
  41. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +5 -0
  42. esphome/components/ch422g/ch422g.h +2 -0
  43. esphome/components/climate/__init__.py +1 -1
  44. esphome/components/climate_ir/climate_ir.cpp +2 -1
  45. esphome/components/coolix/coolix.cpp +2 -1
  46. esphome/components/cse7766/cse7766.cpp +8 -16
  47. esphome/components/custom/__init__.py +0 -3
  48. esphome/components/custom/binary_sensor/__init__.py +2 -28
  49. esphome/components/custom/climate/__init__.py +2 -27
  50. esphome/components/custom/cover/__init__.py +2 -27
  51. esphome/components/custom/light/__init__.py +2 -27
  52. esphome/components/custom/output/__init__.py +2 -58
  53. esphome/components/custom/sensor/__init__.py +2 -24
  54. esphome/components/custom/switch/__init__.py +2 -24
  55. esphome/components/custom/text_sensor/__init__.py +2 -29
  56. esphome/components/custom_component/__init__.py +3 -27
  57. esphome/components/daly_bms/daly_bms.cpp +6 -0
  58. esphome/components/daly_bms/daly_bms.h +2 -0
  59. esphome/components/daly_bms/sensor.py +6 -0
  60. esphome/components/debug/debug_component.cpp +4 -0
  61. esphome/components/debug/debug_component.h +14 -0
  62. esphome/components/debug/debug_esp32.cpp +154 -74
  63. esphome/components/dfplayer/dfplayer.cpp +15 -2
  64. esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp +2 -1
  65. esphome/components/dht/dht.cpp +4 -2
  66. esphome/components/dht/sensor.py +1 -1
  67. esphome/components/display/__init__.py +18 -5
  68. esphome/components/display/display.cpp +16 -3
  69. esphome/components/display/rect.cpp +2 -1
  70. esphome/components/es7210/__init__.py +0 -0
  71. esphome/components/es7210/audio_adc.py +51 -0
  72. esphome/components/es7210/es7210.cpp +228 -0
  73. esphome/components/es7210/es7210.h +62 -0
  74. esphome/components/es7210/es7210_const.h +129 -0
  75. esphome/components/es7243e/__init__.py +0 -0
  76. esphome/components/es7243e/audio_adc.py +34 -0
  77. esphome/components/es7243e/es7243e.cpp +125 -0
  78. esphome/components/es7243e/es7243e.h +37 -0
  79. esphome/components/es7243e/es7243e_const.h +54 -0
  80. esphome/components/es8156/__init__.py +0 -0
  81. esphome/components/es8156/audio_dac.py +27 -0
  82. esphome/components/es8156/es8156.cpp +87 -0
  83. esphome/components/es8156/es8156.h +51 -0
  84. esphome/components/es8156/es8156_const.h +68 -0
  85. esphome/components/es8311/audio_dac.py +1 -2
  86. esphome/components/esp32/__init__.py +1 -0
  87. esphome/components/esp32/core.cpp +5 -1
  88. esphome/components/esp32/gpio.h +2 -0
  89. esphome/components/esp32_ble/__init__.py +39 -0
  90. esphome/components/esp32_ble/queue.h +4 -4
  91. esphome/components/esp32_ble_client/ble_client_base.cpp +46 -0
  92. esphome/components/esp32_ble_client/ble_client_base.h +2 -0
  93. esphome/components/esp32_ble_server/__init__.py +582 -12
  94. esphome/components/esp32_ble_server/ble_characteristic.cpp +48 -60
  95. esphome/components/esp32_ble_server/ble_characteristic.h +24 -17
  96. esphome/components/esp32_ble_server/ble_descriptor.cpp +21 -9
  97. esphome/components/esp32_ble_server/ble_descriptor.h +17 -6
  98. esphome/components/esp32_ble_server/ble_server.cpp +62 -67
  99. esphome/components/esp32_ble_server/ble_server.h +28 -32
  100. esphome/components/esp32_ble_server/ble_server_automations.cpp +77 -0
  101. esphome/components/esp32_ble_server/ble_server_automations.h +115 -0
  102. esphome/components/esp32_ble_server/ble_service.cpp +17 -15
  103. esphome/components/esp32_ble_server/ble_service.h +10 -14
  104. esphome/components/esp32_ble_tracker/__init__.py +6 -39
  105. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +33 -10
  106. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +8 -4
  107. esphome/components/esp32_dac/esp32_dac.cpp +16 -7
  108. esphome/components/esp32_dac/esp32_dac.h +8 -0
  109. esphome/components/esp32_dac/output.py +16 -4
  110. esphome/components/esp32_improv/__init__.py +2 -8
  111. esphome/components/esp32_improv/esp32_improv_component.cpp +21 -20
  112. esphome/components/esp32_improv/esp32_improv_component.h +3 -4
  113. esphome/components/esp32_rmt/__init__.py +28 -3
  114. esphome/components/esp32_rmt_led_strip/led_strip.cpp +73 -6
  115. esphome/components/esp32_rmt_led_strip/led_strip.h +21 -3
  116. esphome/components/esp32_rmt_led_strip/light.py +72 -7
  117. esphome/components/esp32_touch/esp32_touch.cpp +5 -0
  118. esphome/components/esp8266/__init__.py +1 -0
  119. esphome/components/esp8266/gpio.h +1 -0
  120. esphome/components/ethernet/__init__.py +10 -10
  121. esphome/components/event/event.cpp +4 -2
  122. esphome/components/event/event.h +2 -0
  123. esphome/components/event_emitter/__init__.py +5 -0
  124. esphome/components/event_emitter/event_emitter.cpp +14 -0
  125. esphome/components/event_emitter/event_emitter.h +63 -0
  126. esphome/components/font/__init__.py +1 -1
  127. esphome/components/gcja5/gcja5.cpp +2 -1
  128. esphome/components/graph/graph.cpp +4 -9
  129. esphome/components/haier/haier_base.cpp +2 -1
  130. esphome/components/haier/hon_climate.cpp +2 -1
  131. esphome/components/heatpumpir/heatpumpir.cpp +2 -1
  132. esphome/components/host/__init__.py +1 -0
  133. esphome/components/host/gpio.h +1 -0
  134. esphome/components/http_request/http_request.h +2 -2
  135. esphome/components/http_request/http_request_arduino.cpp +1 -1
  136. esphome/components/http_request/http_request_idf.cpp +1 -1
  137. esphome/components/i2c/i2c_bus_esp_idf.cpp +4 -0
  138. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +7 -5
  139. esphome/components/i2s_audio/speaker/__init__.py +53 -6
  140. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +92 -46
  141. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -0
  142. esphome/components/ili9xxx/display.py +29 -11
  143. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -5
  144. esphome/components/ili9xxx/ili9xxx_display.h +2 -1
  145. esphome/components/image/__init__.py +443 -255
  146. esphome/components/image/image.cpp +115 -61
  147. esphome/components/image/image.h +15 -24
  148. esphome/components/json/json_util.cpp +8 -34
  149. esphome/components/libretiny/__init__.py +1 -0
  150. esphome/components/libretiny/gpio_arduino.h +1 -0
  151. esphome/components/light/light_color_values.h +1 -1
  152. esphome/components/logger/__init__.py +45 -9
  153. esphome/components/logger/logger.cpp +16 -14
  154. esphome/components/logger/logger.h +11 -7
  155. esphome/components/logger/select/__init__.py +29 -0
  156. esphome/components/logger/select/logger_level_select.cpp +27 -0
  157. esphome/components/logger/select/logger_level_select.h +15 -0
  158. esphome/components/lvgl/__init__.py +96 -73
  159. esphome/components/lvgl/automation.py +39 -7
  160. esphome/components/lvgl/defines.py +8 -2
  161. esphome/components/lvgl/lvgl_esphome.cpp +8 -15
  162. esphome/components/lvgl/lvgl_esphome.h +20 -5
  163. esphome/components/lvgl/schemas.py +25 -14
  164. esphome/components/lvgl/trigger.py +27 -3
  165. esphome/components/lvgl/widgets/dropdown.py +1 -1
  166. esphome/components/lvgl/widgets/keyboard.py +8 -1
  167. esphome/components/lvgl/widgets/meter.py +2 -1
  168. esphome/components/lvgl/widgets/msgbox.py +1 -1
  169. esphome/components/lvgl/widgets/obj.py +1 -12
  170. esphome/components/lvgl/widgets/page.py +37 -2
  171. esphome/components/lvgl/widgets/tabview.py +1 -1
  172. esphome/components/max6956/max6956.h +2 -0
  173. esphome/components/mcp23016/mcp23016.h +2 -0
  174. esphome/components/mcp23xxx_base/mcp23xxx_base.h +2 -0
  175. esphome/components/mdns/__init__.py +1 -1
  176. esphome/components/media_player/__init__.py +37 -8
  177. esphome/components/media_player/automation.h +11 -2
  178. esphome/components/media_player/media_player.cpp +8 -0
  179. esphome/components/media_player/media_player.h +8 -4
  180. esphome/components/micronova/switch/micronova_switch.cpp +4 -2
  181. esphome/components/midea/ac_automations.h +3 -1
  182. esphome/components/midea/air_conditioner.cpp +7 -5
  183. esphome/components/midea/air_conditioner.h +1 -1
  184. esphome/components/midea/climate.py +4 -2
  185. esphome/components/midea/ir_transmitter.h +36 -5
  186. esphome/components/mixer/__init__.py +0 -0
  187. esphome/components/mixer/speaker/__init__.py +172 -0
  188. esphome/components/mixer/speaker/automation.h +19 -0
  189. esphome/components/mixer/speaker/mixer_speaker.cpp +624 -0
  190. esphome/components/mixer/speaker/mixer_speaker.h +207 -0
  191. esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp +7 -13
  192. esphome/components/mpr121/mpr121.h +2 -0
  193. esphome/components/mqtt/__init__.py +1 -1
  194. esphome/components/mqtt/mqtt_client.cpp +7 -1
  195. esphome/components/mqtt/mqtt_client.h +1 -1
  196. esphome/components/mqtt/mqtt_climate.cpp +2 -2
  197. esphome/components/network/ip_address.h +2 -0
  198. esphome/components/nextion/automation.h +17 -0
  199. esphome/components/nextion/display.py +42 -17
  200. esphome/components/nextion/nextion.cpp +4 -10
  201. esphome/components/nextion/nextion.h +89 -82
  202. esphome/components/nextion/nextion_commands.cpp +10 -10
  203. esphome/components/ntc/sensor.py +2 -4
  204. esphome/components/online_image/__init__.py +98 -46
  205. esphome/components/online_image/bmp_image.cpp +101 -0
  206. esphome/components/online_image/bmp_image.h +40 -0
  207. esphome/components/online_image/image_decoder.cpp +31 -2
  208. esphome/components/online_image/image_decoder.h +24 -15
  209. esphome/components/online_image/jpeg_image.cpp +92 -0
  210. esphome/components/online_image/jpeg_image.h +34 -0
  211. esphome/components/online_image/online_image.cpp +118 -58
  212. esphome/components/online_image/online_image.h +39 -9
  213. esphome/components/online_image/png_image.cpp +7 -3
  214. esphome/components/online_image/png_image.h +2 -1
  215. esphome/components/opentherm/__init__.py +73 -7
  216. esphome/components/opentherm/automation.h +25 -0
  217. esphome/components/opentherm/const.py +1 -0
  218. esphome/components/opentherm/generate.py +39 -6
  219. esphome/components/opentherm/hub.cpp +117 -79
  220. esphome/components/opentherm/hub.h +31 -15
  221. esphome/components/opentherm/opentherm.cpp +47 -23
  222. esphome/components/opentherm/opentherm.h +27 -6
  223. esphome/components/opentherm/opentherm_macros.h +11 -0
  224. esphome/components/opentherm/schema.py +78 -1
  225. esphome/components/opentherm/validate.py +7 -2
  226. esphome/components/pca6416a/pca6416a.h +2 -0
  227. esphome/components/pca9554/pca9554.h +2 -0
  228. esphome/components/pcf8574/pcf8574.h +2 -0
  229. esphome/components/preferences/__init__.py +2 -4
  230. esphome/components/preferences/syncer.h +10 -3
  231. esphome/components/prometheus/prometheus_handler.cpp +313 -0
  232. esphome/components/prometheus/prometheus_handler.h +48 -7
  233. esphome/components/psram/psram.cpp +8 -1
  234. esphome/components/pulse_counter/pulse_counter_sensor.cpp +14 -9
  235. esphome/components/pulse_counter/pulse_counter_sensor.h +4 -4
  236. esphome/components/pulse_meter/pulse_meter_sensor.cpp +2 -0
  237. esphome/components/qspi_dbi/__init__.py +3 -0
  238. esphome/components/qspi_dbi/display.py +74 -47
  239. esphome/components/qspi_dbi/models.py +245 -2
  240. esphome/components/qspi_dbi/qspi_dbi.cpp +9 -16
  241. esphome/components/qspi_dbi/qspi_dbi.h +2 -2
  242. esphome/components/remote_base/__init__.py +77 -25
  243. esphome/components/remote_base/remote_base.cpp +1 -1
  244. esphome/components/remote_base/remote_base.h +20 -2
  245. esphome/components/remote_base/toto_protocol.cpp +100 -0
  246. esphome/components/remote_base/toto_protocol.h +45 -0
  247. esphome/components/remote_receiver/__init__.py +55 -10
  248. esphome/components/remote_receiver/remote_receiver.h +36 -3
  249. esphome/components/remote_receiver/remote_receiver_esp32.cpp +145 -6
  250. esphome/components/remote_transmitter/__init__.py +62 -4
  251. esphome/components/remote_transmitter/remote_transmitter.h +21 -2
  252. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +140 -4
  253. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +3 -3
  254. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +3 -3
  255. esphome/components/resampler/__init__.py +0 -0
  256. esphome/components/resampler/speaker/__init__.py +103 -0
  257. esphome/components/resampler/speaker/resampler_speaker.cpp +318 -0
  258. esphome/components/resampler/speaker/resampler_speaker.h +107 -0
  259. esphome/components/resistance/resistance_sensor.h +2 -3
  260. esphome/components/resistance/sensor.py +2 -9
  261. esphome/components/rotary_encoder/rotary_encoder.cpp +8 -4
  262. esphome/components/rp2040/__init__.py +1 -0
  263. esphome/components/rp2040/gpio.h +1 -0
  264. esphome/components/rtl87xx/__init__.py +2 -0
  265. esphome/components/scd30/sensor.py +1 -1
  266. esphome/components/sdl/binary_sensor.py +270 -0
  267. esphome/components/sdl/sdl_esphome.cpp +16 -0
  268. esphome/components/sdl/sdl_esphome.h +9 -0
  269. esphome/components/seeed_mr60bha2/binary_sensor.py +25 -0
  270. esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +26 -2
  271. esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +9 -20
  272. esphome/components/seeed_mr60bha2/sensor.py +9 -1
  273. esphome/components/sn74hc165/sn74hc165.h +3 -0
  274. esphome/components/sn74hc595/sn74hc595.h +3 -0
  275. esphome/components/speaker/__init__.py +5 -4
  276. esphome/components/speaker/media_player/__init__.py +458 -0
  277. esphome/components/speaker/media_player/audio_pipeline.cpp +568 -0
  278. esphome/components/speaker/media_player/audio_pipeline.h +159 -0
  279. esphome/components/speaker/media_player/automation.h +26 -0
  280. esphome/components/speaker/media_player/speaker_media_player.cpp +577 -0
  281. esphome/components/speaker/media_player/speaker_media_player.h +160 -0
  282. esphome/components/speaker/speaker.h +20 -0
  283. esphome/components/spi/__init__.py +1 -5
  284. esphome/components/spi/spi.cpp +7 -1
  285. esphome/components/spi/spi.h +21 -2
  286. esphome/components/spi_led_strip/light.py +3 -5
  287. esphome/components/spi_led_strip/spi_led_strip.cpp +67 -0
  288. esphome/components/spi_led_strip/spi_led_strip.h +8 -60
  289. esphome/components/sprinkler/sprinkler.cpp +3 -1
  290. esphome/components/sx1509/sx1509_gpio_pin.h +2 -0
  291. esphome/components/tca9555/tca9555.h +2 -0
  292. esphome/components/toshiba/toshiba.cpp +2 -1
  293. esphome/components/tuya/light/tuya_light.cpp +4 -2
  294. esphome/components/uart/uart_component_esp32_arduino.cpp +2 -2
  295. esphome/components/uart/uart_component_esp_idf.cpp +2 -2
  296. esphome/components/udp/__init__.py +8 -2
  297. esphome/components/udp/udp_component.cpp +25 -56
  298. esphome/components/udp/udp_component.h +3 -0
  299. esphome/components/uponor_smatrix/sensor/__init__.py +14 -4
  300. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +5 -0
  301. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.h +1 -0
  302. esphome/components/uptime/text_sensor/__init__.py +19 -0
  303. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +63 -0
  304. esphome/components/uptime/text_sensor/uptime_text_sensor.h +25 -0
  305. esphome/components/voice_assistant/voice_assistant.cpp +24 -14
  306. esphome/components/voice_assistant/voice_assistant.h +8 -0
  307. esphome/components/waveshare_epaper/display.py +22 -1
  308. esphome/components/waveshare_epaper/waveshare_213v3.cpp +9 -3
  309. esphome/components/waveshare_epaper/waveshare_epaper.cpp +1155 -44
  310. esphome/components/waveshare_epaper/waveshare_epaper.h +208 -7
  311. esphome/components/web_server/web_server.cpp +28 -6
  312. esphome/components/weikai/weikai.h +2 -0
  313. esphome/components/wifi/__init__.py +6 -6
  314. esphome/components/wifi/wifi_component.cpp +1 -1
  315. esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -1
  316. esphome/components/wireguard/__init__.py +2 -2
  317. esphome/components/xl9535/xl9535.h +2 -0
  318. esphome/components/xxtea/__init__.py +3 -0
  319. esphome/components/xxtea/xxtea.cpp +46 -0
  320. esphome/components/xxtea/xxtea.h +26 -0
  321. esphome/components/yashima/yashima.cpp +2 -1
  322. esphome/config.py +9 -5
  323. esphome/config_validation.py +55 -17
  324. esphome/const.py +7 -10
  325. esphome/core/__init__.py +6 -13
  326. esphome/core/base_automation.h +1 -0
  327. esphome/core/config.py +59 -72
  328. esphome/core/defines.h +9 -1
  329. esphome/core/gpio.h +7 -0
  330. esphome/core/helpers.cpp +19 -15
  331. esphome/core/helpers.h +57 -8
  332. esphome/core/log.h +9 -7
  333. esphome/cpp_generator.py +2 -2
  334. esphome/dashboard/web_server.py +1 -1
  335. esphome/espota2.py +3 -2
  336. esphome/loader.py +12 -4
  337. esphome/log.py +5 -7
  338. esphome/yaml_util.py +2 -2
  339. {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/METADATA +14 -9
  340. {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/RECORD +349 -300
  341. esphome/components/custom/binary_sensor/custom_binary_sensor.cpp +0 -16
  342. esphome/components/custom/binary_sensor/custom_binary_sensor.h +0 -26
  343. esphome/components/custom/climate/custom_climate.h +0 -22
  344. esphome/components/custom/cover/custom_cover.h +0 -21
  345. esphome/components/custom/light/custom_light_output.h +0 -24
  346. esphome/components/custom/output/custom_output.h +0 -37
  347. esphome/components/custom/sensor/custom_sensor.cpp +0 -16
  348. esphome/components/custom/sensor/custom_sensor.h +0 -24
  349. esphome/components/custom/switch/custom_switch.cpp +0 -16
  350. esphome/components/custom/switch/custom_switch.h +0 -24
  351. esphome/components/custom/text_sensor/custom_text_sensor.cpp +0 -16
  352. esphome/components/custom/text_sensor/custom_text_sensor.h +0 -26
  353. esphome/components/custom_component/custom_component.h +0 -28
  354. esphome/components/esp32_ble_server/ble_2901.cpp +0 -18
  355. esphome/components/esp32_ble_server/ble_2901.h +0 -19
  356. esphome/components/resistance_sampler/__init__.py +0 -6
  357. esphome/components/resistance_sampler/resistance_sampler.h +0 -10
  358. esphome/components/uptime/{sensor.py → sensor/__init__.py} +3 -3
  359. /esphome/components/uptime/{uptime_seconds_sensor.cpp → sensor/uptime_seconds_sensor.cpp} +0 -0
  360. /esphome/components/uptime/{uptime_seconds_sensor.h → sensor/uptime_seconds_sensor.h} +0 -0
  361. /esphome/components/uptime/{uptime_timestamp_sensor.cpp → sensor/uptime_timestamp_sensor.cpp} +0 -0
  362. /esphome/components/uptime/{uptime_timestamp_sensor.h → sensor/uptime_timestamp_sensor.h} +0 -0
  363. {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/LICENSE +0 -0
  364. {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/WHEEL +0 -0
  365. {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/entry_points.txt +0 -0
  366. {esphome-2024.12.3.dist-info → esphome-2025.2.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,9 @@
1
1
  #pragma once
2
2
  #include "esphome/core/component.h"
3
3
  #include "esphome/core/defines.h"
4
+ #ifdef USE_BINARY_SENSOR
5
+ #include "esphome/components/binary_sensor/binary_sensor.h"
6
+ #endif
4
7
  #ifdef USE_SENSOR
5
8
  #include "esphome/components/sensor/sensor.h"
6
9
  #endif
@@ -12,37 +15,23 @@
12
15
 
13
16
  namespace esphome {
14
17
  namespace seeed_mr60bha2 {
15
-
16
- static const uint8_t DATA_BUF_MAX_SIZE = 12;
17
- static const uint8_t FRAME_BUF_MAX_SIZE = 21;
18
- static const uint8_t LEN_TO_HEAD_CKSUM = 8;
19
- static const uint8_t LEN_TO_DATA_FRAME = 9;
20
-
21
18
  static const uint8_t FRAME_HEADER_BUFFER = 0x01;
22
19
  static const uint16_t BREATH_RATE_TYPE_BUFFER = 0x0A14;
20
+ static const uint16_t PEOPLE_EXIST_TYPE_BUFFER = 0x0F09;
23
21
  static const uint16_t HEART_RATE_TYPE_BUFFER = 0x0A15;
24
22
  static const uint16_t DISTANCE_TYPE_BUFFER = 0x0A16;
25
-
26
- enum FrameLocation {
27
- LOCATE_FRAME_HEADER,
28
- LOCATE_ID_FRAME1,
29
- LOCATE_ID_FRAME2,
30
- LOCATE_LENGTH_FRAME_H,
31
- LOCATE_LENGTH_FRAME_L,
32
- LOCATE_TYPE_FRAME1,
33
- LOCATE_TYPE_FRAME2,
34
- LOCATE_HEAD_CKSUM_FRAME, // Header checksum: [from the first byte to the previous byte of the HEAD_CKSUM bit]
35
- LOCATE_DATA_FRAME,
36
- LOCATE_DATA_CKSUM_FRAME, // Data checksum: [from the first to the previous byte of the DATA_CKSUM bit]
37
- LOCATE_PROCESS_FRAME,
38
- };
23
+ static const uint16_t PRINT_CLOUD_BUFFER = 0x0A04;
39
24
 
40
25
  class MR60BHA2Component : public Component,
41
26
  public uart::UARTDevice { // The class name must be the name defined by text_sensor.py
27
+ #ifdef USE_BINARY_SENSOR
28
+ SUB_BINARY_SENSOR(has_target);
29
+ #endif
42
30
  #ifdef USE_SENSOR
43
31
  SUB_SENSOR(breath_rate);
44
32
  SUB_SENSOR(heart_rate);
45
33
  SUB_SENSOR(distance);
34
+ SUB_SENSOR(num_targets);
46
35
  #endif
47
36
 
48
37
  public:
@@ -7,6 +7,7 @@ from esphome.const import (
7
7
  ICON_HEART_PULSE,
8
8
  ICON_PULSE,
9
9
  ICON_SIGNAL,
10
+ ICON_COUNTER,
10
11
  STATE_CLASS_MEASUREMENT,
11
12
  UNIT_BEATS_PER_MINUTE,
12
13
  UNIT_CENTIMETER,
@@ -18,12 +19,13 @@ DEPENDENCIES = ["seeed_mr60bha2"]
18
19
 
19
20
  CONF_BREATH_RATE = "breath_rate"
20
21
  CONF_HEART_RATE = "heart_rate"
22
+ CONF_NUM_TARGETS = "num_targets"
21
23
 
22
24
  CONFIG_SCHEMA = cv.Schema(
23
25
  {
24
26
  cv.GenerateID(CONF_MR60BHA2_ID): cv.use_id(MR60BHA2Component),
25
27
  cv.Optional(CONF_BREATH_RATE): sensor.sensor_schema(
26
- accuracy_decimals=2,
28
+ accuracy_decimals=0,
27
29
  state_class=STATE_CLASS_MEASUREMENT,
28
30
  icon=ICON_PULSE,
29
31
  ),
@@ -40,6 +42,9 @@ CONFIG_SCHEMA = cv.Schema(
40
42
  accuracy_decimals=2,
41
43
  icon=ICON_SIGNAL,
42
44
  ),
45
+ cv.Optional(CONF_NUM_TARGETS): sensor.sensor_schema(
46
+ icon=ICON_COUNTER,
47
+ ),
43
48
  }
44
49
  )
45
50
 
@@ -55,3 +60,6 @@ async def to_code(config):
55
60
  if distance_config := config.get(CONF_DISTANCE):
56
61
  sens = await sensor.new_sensor(distance_config)
57
62
  cg.add(mr60bha2_component.set_distance_sensor(sens))
63
+ if num_targets_config := config.get(CONF_NUM_TARGETS):
64
+ sens = await sensor.new_sensor(num_targets_config)
65
+ cg.add(mr60bha2_component.set_num_targets_sensor(sens))
@@ -52,6 +52,9 @@ class SN74HC165GPIOPin : public GPIOPin, public Parented<SN74HC165Component> {
52
52
  void set_pin(uint16_t pin) { pin_ = pin; }
53
53
  void set_inverted(bool inverted) { inverted_ = inverted; }
54
54
 
55
+ /// Always returns `gpio::Flags::FLAG_INPUT`.
56
+ gpio::Flags get_flags() const override { return gpio::Flags::FLAG_INPUT; }
57
+
55
58
  protected:
56
59
  uint16_t pin_;
57
60
  bool inverted_;
@@ -59,6 +59,9 @@ class SN74HC595GPIOPin : public GPIOPin, public Parented<SN74HC595Component> {
59
59
  void set_pin(uint16_t pin) { pin_ = pin; }
60
60
  void set_inverted(bool inverted) { inverted_ = inverted; }
61
61
 
62
+ /// Always returns `gpio::Flags::FLAG_OUTPUT`.
63
+ gpio::Flags get_flags() const override { return gpio::Flags::FLAG_OUTPUT; }
64
+
62
65
  protected:
63
66
  uint16_t pin_;
64
67
  bool inverted_;
@@ -1,7 +1,6 @@
1
1
  from esphome import automation
2
- from esphome.automation import maybe_simple_id
3
2
  import esphome.codegen as cg
4
- from esphome.components import audio_dac
3
+ from esphome.components import audio, audio_dac
5
4
  import esphome.config_validation as cv
6
5
  from esphome.const import CONF_DATA, CONF_ID, CONF_VOLUME
7
6
  from esphome.core import CORE
@@ -54,13 +53,15 @@ async def register_speaker(var, config):
54
53
  await setup_speaker_core_(var, config)
55
54
 
56
55
 
57
- SPEAKER_SCHEMA = cv.Schema(
56
+ SPEAKER_SCHEMA = cv.Schema.extend(audio.AUDIO_COMPONENT_SCHEMA).extend(
58
57
  {
59
58
  cv.Optional(CONF_AUDIO_DAC): cv.use_id(audio_dac.AudioDac),
60
59
  }
61
60
  )
62
61
 
63
- SPEAKER_AUTOMATION_SCHEMA = maybe_simple_id({cv.GenerateID(): cv.use_id(Speaker)})
62
+ SPEAKER_AUTOMATION_SCHEMA = automation.maybe_simple_id(
63
+ {cv.GenerateID(): cv.use_id(Speaker)}
64
+ )
64
65
 
65
66
 
66
67
  async def speaker_action(config, action_id, template_arg, args):
@@ -0,0 +1,458 @@
1
+ """Speaker Media Player Setup."""
2
+
3
+ import hashlib
4
+ import logging
5
+ from pathlib import Path
6
+
7
+ from esphome import automation, external_files
8
+ import esphome.codegen as cg
9
+ from esphome.components import audio, esp32, media_player, speaker
10
+ import esphome.config_validation as cv
11
+ from esphome.const import (
12
+ CONF_BUFFER_SIZE,
13
+ CONF_FILE,
14
+ CONF_FILES,
15
+ CONF_FORMAT,
16
+ CONF_ID,
17
+ CONF_NUM_CHANNELS,
18
+ CONF_PATH,
19
+ CONF_RAW_DATA_ID,
20
+ CONF_SAMPLE_RATE,
21
+ CONF_SPEAKER,
22
+ CONF_TASK_STACK_IN_PSRAM,
23
+ CONF_TYPE,
24
+ CONF_URL,
25
+ )
26
+ from esphome.core import CORE, HexInt
27
+ from esphome.core.entity_helpers import inherit_property_from
28
+ from esphome.external_files import download_content
29
+
30
+ _LOGGER = logging.getLogger(__name__)
31
+
32
+ AUTO_LOAD = ["audio", "psram"]
33
+
34
+ CODEOWNERS = ["@kahrendt", "@synesthesiam"]
35
+ DOMAIN = "media_player"
36
+
37
+ TYPE_LOCAL = "local"
38
+ TYPE_WEB = "web"
39
+
40
+ CONF_ANNOUNCEMENT = "announcement"
41
+ CONF_ANNOUNCEMENT_PIPELINE = "announcement_pipeline"
42
+ CONF_CODEC_SUPPORT_ENABLED = "codec_support_enabled"
43
+ CONF_ENQUEUE = "enqueue"
44
+ CONF_MEDIA_FILE = "media_file"
45
+ CONF_MEDIA_PIPELINE = "media_pipeline"
46
+ CONF_ON_MUTE = "on_mute"
47
+ CONF_ON_UNMUTE = "on_unmute"
48
+ CONF_ON_VOLUME = "on_volume"
49
+ CONF_STREAM = "stream"
50
+ CONF_VOLUME_INCREMENT = "volume_increment"
51
+ CONF_VOLUME_MIN = "volume_min"
52
+ CONF_VOLUME_MAX = "volume_max"
53
+
54
+
55
+ speaker_ns = cg.esphome_ns.namespace("speaker")
56
+ SpeakerMediaPlayer = speaker_ns.class_(
57
+ "SpeakerMediaPlayer",
58
+ media_player.MediaPlayer,
59
+ cg.Component,
60
+ )
61
+
62
+ AudioPipeline = speaker_ns.class_("AudioPipeline")
63
+ AudioPipelineType = speaker_ns.enum("AudioPipelineType", is_class=True)
64
+ AUDIO_PIPELINE_TYPE_ENUM = {
65
+ "MEDIA": AudioPipelineType.MEDIA,
66
+ "ANNOUNCEMENT": AudioPipelineType.ANNOUNCEMENT,
67
+ }
68
+
69
+ PlayOnDeviceMediaAction = speaker_ns.class_(
70
+ "PlayOnDeviceMediaAction",
71
+ automation.Action,
72
+ cg.Parented.template(SpeakerMediaPlayer),
73
+ )
74
+ StopStreamAction = speaker_ns.class_(
75
+ "StopStreamAction", automation.Action, cg.Parented.template(SpeakerMediaPlayer)
76
+ )
77
+
78
+
79
+ def _compute_local_file_path(value: dict) -> Path:
80
+ url = value[CONF_URL]
81
+ h = hashlib.new("sha256")
82
+ h.update(url.encode())
83
+ key = h.hexdigest()[:8]
84
+ base_dir = external_files.compute_local_file_dir(DOMAIN)
85
+ _LOGGER.debug("_compute_local_file_path: base_dir=%s", base_dir / key)
86
+ return base_dir / key
87
+
88
+
89
+ def _download_web_file(value):
90
+ url = value[CONF_URL]
91
+ path = _compute_local_file_path(value)
92
+
93
+ download_content(url, path)
94
+ _LOGGER.debug("download_web_file: path=%s", path)
95
+ return value
96
+
97
+
98
+ # Returns a media_player.MediaPlayerSupportedFormat struct with the configured
99
+ # format, sample rate, number of channels, purpose, and bytes per sample
100
+ def _get_supported_format_struct(pipeline, type):
101
+ args = [
102
+ media_player.MediaPlayerSupportedFormat,
103
+ ]
104
+
105
+ if pipeline[CONF_FORMAT] == "FLAC":
106
+ args.append(("format", "flac"))
107
+ elif pipeline[CONF_FORMAT] == "MP3":
108
+ args.append(("format", "mp3"))
109
+ elif pipeline[CONF_FORMAT] == "WAV":
110
+ args.append(("format", "wav"))
111
+
112
+ args.append(("sample_rate", pipeline[CONF_SAMPLE_RATE]))
113
+ args.append(("num_channels", pipeline[CONF_NUM_CHANNELS]))
114
+
115
+ if type == "MEDIA":
116
+ args.append(
117
+ (
118
+ "purpose",
119
+ media_player.MEDIA_PLAYER_FORMAT_PURPOSE_ENUM["default"],
120
+ )
121
+ )
122
+ elif type == "ANNOUNCEMENT":
123
+ args.append(
124
+ (
125
+ "purpose",
126
+ media_player.MEDIA_PLAYER_FORMAT_PURPOSE_ENUM["announcement"],
127
+ )
128
+ )
129
+ if pipeline[CONF_FORMAT] != "MP3":
130
+ args.append(("sample_bytes", 2))
131
+
132
+ return cg.StructInitializer(*args)
133
+
134
+
135
+ def _file_schema(value):
136
+ if isinstance(value, str):
137
+ return _validate_file_shorthand(value)
138
+ return TYPED_FILE_SCHEMA(value)
139
+
140
+
141
+ def _read_audio_file_and_type(file_config):
142
+ conf_file = file_config[CONF_FILE]
143
+ file_source = conf_file[CONF_TYPE]
144
+ if file_source == TYPE_LOCAL:
145
+ path = CORE.relative_config_path(conf_file[CONF_PATH])
146
+ elif file_source == TYPE_WEB:
147
+ path = _compute_local_file_path(conf_file)
148
+ else:
149
+ raise cv.Invalid("Unsupported file source.")
150
+
151
+ with open(path, "rb") as f:
152
+ data = f.read()
153
+
154
+ import puremagic
155
+
156
+ file_type: str = puremagic.from_string(data)
157
+ if file_type.startswith("."):
158
+ file_type = file_type[1:]
159
+
160
+ media_file_type = audio.AUDIO_FILE_TYPE_ENUM["NONE"]
161
+ if file_type in ("wav"):
162
+ media_file_type = audio.AUDIO_FILE_TYPE_ENUM["WAV"]
163
+ elif file_type in ("mp3", "mpeg", "mpga"):
164
+ media_file_type = audio.AUDIO_FILE_TYPE_ENUM["MP3"]
165
+ elif file_type in ("flac"):
166
+ media_file_type = audio.AUDIO_FILE_TYPE_ENUM["FLAC"]
167
+
168
+ return data, media_file_type
169
+
170
+
171
+ def _validate_file_shorthand(value):
172
+ value = cv.string_strict(value)
173
+ if value.startswith("http://") or value.startswith("https://"):
174
+ return _file_schema(
175
+ {
176
+ CONF_TYPE: TYPE_WEB,
177
+ CONF_URL: value,
178
+ }
179
+ )
180
+ return _file_schema(
181
+ {
182
+ CONF_TYPE: TYPE_LOCAL,
183
+ CONF_PATH: value,
184
+ }
185
+ )
186
+
187
+
188
+ def _validate_pipeline(config):
189
+ # Inherit transcoder settings from speaker if not manually set
190
+ inherit_property_from(CONF_NUM_CHANNELS, CONF_SPEAKER)(config)
191
+ inherit_property_from(CONF_SAMPLE_RATE, CONF_SPEAKER)(config)
192
+
193
+ # Validate the transcoder settings is compatible with the speaker
194
+ audio.final_validate_audio_schema(
195
+ "speaker media_player",
196
+ audio_device=CONF_SPEAKER,
197
+ bits_per_sample=16,
198
+ channels=config.get(CONF_NUM_CHANNELS),
199
+ sample_rate=config.get(CONF_SAMPLE_RATE),
200
+ )(config)
201
+
202
+ return config
203
+
204
+
205
+ def _validate_repeated_speaker(config):
206
+ if (announcement_config := config.get(CONF_ANNOUNCEMENT_PIPELINE)) and (
207
+ media_config := config.get(CONF_MEDIA_PIPELINE)
208
+ ):
209
+ if announcement_config[CONF_SPEAKER] == media_config[CONF_SPEAKER]:
210
+ raise cv.Invalid(
211
+ "The announcement and media pipelines cannot use the same speaker. Use the `mixer` speaker component to create two source speakers."
212
+ )
213
+
214
+ return config
215
+
216
+
217
+ def _validate_supported_local_file(config):
218
+ for file_config in config.get(CONF_FILES, []):
219
+ _, media_file_type = _read_audio_file_and_type(file_config)
220
+ if str(media_file_type) == str(audio.AUDIO_FILE_TYPE_ENUM["NONE"]):
221
+ raise cv.Invalid("Unsupported local media file.")
222
+ if not config[CONF_CODEC_SUPPORT_ENABLED] and str(media_file_type) != str(
223
+ audio.AUDIO_FILE_TYPE_ENUM["WAV"]
224
+ ):
225
+ # Only wav files are supported
226
+ raise cv.Invalid(
227
+ f"Unsupported local media file type, set {CONF_CODEC_SUPPORT_ENABLED} to true or convert the media file to wav"
228
+ )
229
+
230
+ return config
231
+
232
+
233
+ LOCAL_SCHEMA = cv.Schema(
234
+ {
235
+ cv.Required(CONF_PATH): cv.file_,
236
+ }
237
+ )
238
+
239
+ WEB_SCHEMA = cv.All(
240
+ {
241
+ cv.Required(CONF_URL): cv.url,
242
+ },
243
+ _download_web_file,
244
+ )
245
+
246
+
247
+ TYPED_FILE_SCHEMA = cv.typed_schema(
248
+ {
249
+ TYPE_LOCAL: LOCAL_SCHEMA,
250
+ TYPE_WEB: WEB_SCHEMA,
251
+ },
252
+ )
253
+
254
+
255
+ MEDIA_FILE_TYPE_SCHEMA = cv.Schema(
256
+ {
257
+ cv.Required(CONF_ID): cv.declare_id(audio.AudioFile),
258
+ cv.Required(CONF_FILE): _file_schema,
259
+ cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8),
260
+ }
261
+ )
262
+
263
+ PIPELINE_SCHEMA = cv.Schema(
264
+ {
265
+ cv.GenerateID(): cv.declare_id(AudioPipeline),
266
+ cv.Required(CONF_SPEAKER): cv.use_id(speaker.Speaker),
267
+ cv.Optional(CONF_FORMAT, default="FLAC"): cv.enum(audio.AUDIO_FILE_TYPE_ENUM),
268
+ cv.Optional(CONF_SAMPLE_RATE): cv.int_range(min=1),
269
+ cv.Optional(CONF_NUM_CHANNELS): cv.int_range(1, 2),
270
+ }
271
+ )
272
+
273
+ CONFIG_SCHEMA = cv.All(
274
+ media_player.MEDIA_PLAYER_SCHEMA.extend(
275
+ {
276
+ cv.GenerateID(): cv.declare_id(SpeakerMediaPlayer),
277
+ cv.Required(CONF_ANNOUNCEMENT_PIPELINE): PIPELINE_SCHEMA,
278
+ cv.Optional(CONF_MEDIA_PIPELINE): PIPELINE_SCHEMA,
279
+ cv.Optional(CONF_BUFFER_SIZE, default=1000000): cv.int_range(
280
+ min=4000, max=4000000
281
+ ),
282
+ cv.Optional(CONF_CODEC_SUPPORT_ENABLED, default=True): cv.boolean,
283
+ cv.Optional(CONF_FILES): cv.ensure_list(MEDIA_FILE_TYPE_SCHEMA),
284
+ cv.Optional(CONF_TASK_STACK_IN_PSRAM, default=False): cv.boolean,
285
+ cv.Optional(CONF_VOLUME_INCREMENT, default=0.05): cv.percentage,
286
+ cv.Optional(CONF_VOLUME_MAX, default=1.0): cv.percentage,
287
+ cv.Optional(CONF_VOLUME_MIN, default=0.0): cv.percentage,
288
+ cv.Optional(CONF_ON_MUTE): automation.validate_automation(single=True),
289
+ cv.Optional(CONF_ON_UNMUTE): automation.validate_automation(single=True),
290
+ cv.Optional(CONF_ON_VOLUME): automation.validate_automation(single=True),
291
+ }
292
+ ),
293
+ cv.only_with_esp_idf,
294
+ _validate_repeated_speaker,
295
+ )
296
+
297
+
298
+ FINAL_VALIDATE_SCHEMA = cv.All(
299
+ cv.Schema(
300
+ {
301
+ cv.Optional(CONF_ANNOUNCEMENT_PIPELINE): _validate_pipeline,
302
+ cv.Optional(CONF_MEDIA_PIPELINE): _validate_pipeline,
303
+ },
304
+ extra=cv.ALLOW_EXTRA,
305
+ ),
306
+ _validate_supported_local_file,
307
+ )
308
+
309
+
310
+ async def to_code(config):
311
+ if config[CONF_CODEC_SUPPORT_ENABLED]:
312
+ # Compile all supported audio codecs and optimize the wifi settings
313
+
314
+ cg.add_define("USE_AUDIO_FLAC_SUPPORT", True)
315
+ cg.add_define("USE_AUDIO_MP3_SUPPORT", True)
316
+
317
+ # Wifi settings based on https://github.com/espressif/esp-adf/issues/297#issuecomment-783811702
318
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM", 16)
319
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM", 512)
320
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_STATIC_TX_BUFFER", True)
321
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_TX_BUFFER_TYPE", 0)
322
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM", 8)
323
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM", 32)
324
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED", True)
325
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_TX_BA_WIN", 16)
326
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED", True)
327
+ esp32.add_idf_sdkconfig_option("CONFIG_ESP32_WIFI_RX_BA_WIN", 32)
328
+ esp32.add_idf_sdkconfig_option("CONFIG_LWIP_MAX_ACTIVE_TCP", 16)
329
+ esp32.add_idf_sdkconfig_option("CONFIG_LWIP_MAX_LISTENING_TCP", 16)
330
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_MAXRTX", 12)
331
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_SYNMAXRTX", 6)
332
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_MSS", 1436)
333
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_MSL", 60000)
334
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_SND_BUF_DEFAULT", 65535)
335
+ esp32.add_idf_sdkconfig_option(
336
+ "CONFIG_TCP_WND_DEFAULT", 65535
337
+ ) # Adjusted from referenced settings to avoid compilation error
338
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_RECVMBOX_SIZE", 512)
339
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_QUEUE_OOSEQ", True)
340
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_OVERSIZE_MSS", True)
341
+ esp32.add_idf_sdkconfig_option("CONFIG_LWIP_WND_SCALE", True)
342
+ esp32.add_idf_sdkconfig_option("CONFIG_TCP_RCV_SCALE", 3)
343
+ esp32.add_idf_sdkconfig_option("CONFIG_LWIP_TCPIP_RECVMBOX_SIZE", 512)
344
+
345
+ # Allocate wifi buffers in PSRAM
346
+ esp32.add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True)
347
+
348
+ var = cg.new_Pvariable(config[CONF_ID])
349
+ await cg.register_component(var, config)
350
+ await media_player.register_media_player(var, config)
351
+
352
+ cg.add_define("USE_OTA_STATE_CALLBACK")
353
+
354
+ cg.add(var.set_buffer_size(config[CONF_BUFFER_SIZE]))
355
+
356
+ cg.add(var.set_task_stack_in_psram(config[CONF_TASK_STACK_IN_PSRAM]))
357
+ if config[CONF_TASK_STACK_IN_PSRAM]:
358
+ esp32.add_idf_sdkconfig_option(
359
+ "CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY", True
360
+ )
361
+
362
+ cg.add(var.set_volume_increment(config[CONF_VOLUME_INCREMENT]))
363
+ cg.add(var.set_volume_max(config[CONF_VOLUME_MAX]))
364
+ cg.add(var.set_volume_min(config[CONF_VOLUME_MIN]))
365
+
366
+ announcement_pipeline_config = config[CONF_ANNOUNCEMENT_PIPELINE]
367
+ spkr = await cg.get_variable(announcement_pipeline_config[CONF_SPEAKER])
368
+ cg.add(var.set_announcement_speaker(spkr))
369
+ if announcement_pipeline_config[CONF_FORMAT] != "NONE":
370
+ cg.add(
371
+ var.set_announcement_format(
372
+ _get_supported_format_struct(
373
+ announcement_pipeline_config, "ANNOUNCEMENT"
374
+ )
375
+ )
376
+ )
377
+
378
+ if media_pipeline_config := config.get(CONF_MEDIA_PIPELINE):
379
+ spkr = await cg.get_variable(media_pipeline_config[CONF_SPEAKER])
380
+ cg.add(var.set_media_speaker(spkr))
381
+ if media_pipeline_config[CONF_FORMAT] != "NONE":
382
+ cg.add(
383
+ var.set_media_format(
384
+ _get_supported_format_struct(media_pipeline_config, "MEDIA")
385
+ )
386
+ )
387
+
388
+ if on_mute := config.get(CONF_ON_MUTE):
389
+ await automation.build_automation(
390
+ var.get_mute_trigger(),
391
+ [],
392
+ on_mute,
393
+ )
394
+ if on_unmute := config.get(CONF_ON_UNMUTE):
395
+ await automation.build_automation(
396
+ var.get_unmute_trigger(),
397
+ [],
398
+ on_unmute,
399
+ )
400
+ if on_volume := config.get(CONF_ON_VOLUME):
401
+ await automation.build_automation(
402
+ var.get_volume_trigger(),
403
+ [(cg.float_, "x")],
404
+ on_volume,
405
+ )
406
+
407
+ for file_config in config.get(CONF_FILES, []):
408
+ data, media_file_type = _read_audio_file_and_type(file_config)
409
+
410
+ rhs = [HexInt(x) for x in data]
411
+ prog_arr = cg.progmem_array(file_config[CONF_RAW_DATA_ID], rhs)
412
+
413
+ media_files_struct = cg.StructInitializer(
414
+ audio.AudioFile,
415
+ (
416
+ "data",
417
+ prog_arr,
418
+ ),
419
+ (
420
+ "length",
421
+ len(rhs),
422
+ ),
423
+ (
424
+ "file_type",
425
+ media_file_type,
426
+ ),
427
+ )
428
+
429
+ cg.new_Pvariable(
430
+ file_config[CONF_ID],
431
+ media_files_struct,
432
+ )
433
+
434
+
435
+ @automation.register_action(
436
+ "media_player.speaker.play_on_device_media_file",
437
+ PlayOnDeviceMediaAction,
438
+ cv.maybe_simple_value(
439
+ {
440
+ cv.GenerateID(): cv.use_id(SpeakerMediaPlayer),
441
+ cv.Required(CONF_MEDIA_FILE): cv.use_id(audio.AudioFile),
442
+ cv.Optional(CONF_ANNOUNCEMENT, default=False): cv.templatable(cv.boolean),
443
+ cv.Optional(CONF_ENQUEUE, default=False): cv.templatable(cv.boolean),
444
+ },
445
+ key=CONF_MEDIA_FILE,
446
+ ),
447
+ )
448
+ async def play_on_device_media_media_action(config, action_id, template_arg, args):
449
+ var = cg.new_Pvariable(action_id, template_arg)
450
+ await cg.register_parented(var, config[CONF_ID])
451
+ media_file = await cg.get_variable(config[CONF_MEDIA_FILE])
452
+ announcement = await cg.templatable(config[CONF_ANNOUNCEMENT], args, cg.bool_)
453
+ enqueue = await cg.templatable(config[CONF_ENQUEUE], args, cg.bool_)
454
+
455
+ cg.add(var.set_audio_file(media_file))
456
+ cg.add(var.set_announcement(announcement))
457
+ cg.add(var.set_enqueue(enqueue))
458
+ return var