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.
Files changed (355) 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/audio/__init__.py +112 -0
  21. esphome/components/audio/audio.cpp +67 -0
  22. esphome/components/audio/audio.h +125 -7
  23. esphome/components/audio/audio_decoder.cpp +361 -0
  24. esphome/components/audio/audio_decoder.h +135 -0
  25. esphome/components/audio/audio_reader.cpp +308 -0
  26. esphome/components/audio/audio_reader.h +85 -0
  27. esphome/components/audio/audio_resampler.cpp +159 -0
  28. esphome/components/audio/audio_resampler.h +101 -0
  29. esphome/components/audio/audio_transfer_buffer.cpp +165 -0
  30. esphome/components/audio/audio_transfer_buffer.h +139 -0
  31. esphome/components/audio_adc/__init__.py +41 -0
  32. esphome/components/audio_adc/audio_adc.h +17 -0
  33. esphome/components/audio_adc/automation.h +23 -0
  34. esphome/components/bk72xx/__init__.py +1 -0
  35. esphome/components/ble_client/ble_client.cpp +1 -2
  36. esphome/components/ble_client/sensor/__init__.py +1 -1
  37. esphome/components/ble_client/text_sensor/__init__.py +1 -1
  38. esphome/components/bluetooth_proxy/bluetooth_connection.cpp +5 -0
  39. esphome/components/bluetooth_proxy/bluetooth_connection.h +1 -0
  40. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +5 -0
  41. esphome/components/ch422g/ch422g.h +2 -0
  42. esphome/components/climate/__init__.py +1 -1
  43. esphome/components/climate_ir/climate_ir.cpp +2 -1
  44. esphome/components/coolix/coolix.cpp +2 -1
  45. esphome/components/custom/__init__.py +0 -3
  46. esphome/components/custom/binary_sensor/__init__.py +2 -28
  47. esphome/components/custom/climate/__init__.py +2 -27
  48. esphome/components/custom/cover/__init__.py +2 -27
  49. esphome/components/custom/light/__init__.py +2 -27
  50. esphome/components/custom/output/__init__.py +2 -58
  51. esphome/components/custom/sensor/__init__.py +2 -24
  52. esphome/components/custom/switch/__init__.py +2 -24
  53. esphome/components/custom/text_sensor/__init__.py +2 -29
  54. esphome/components/custom_component/__init__.py +3 -27
  55. esphome/components/daly_bms/daly_bms.cpp +6 -0
  56. esphome/components/daly_bms/daly_bms.h +2 -0
  57. esphome/components/daly_bms/sensor.py +6 -0
  58. esphome/components/debug/debug_component.cpp +4 -0
  59. esphome/components/debug/debug_component.h +14 -0
  60. esphome/components/debug/debug_esp32.cpp +154 -74
  61. esphome/components/dfplayer/dfplayer.cpp +15 -2
  62. esphome/components/dfrobot_sen0395/dfrobot_sen0395.cpp +2 -1
  63. esphome/components/dht/dht.cpp +2 -1
  64. esphome/components/display/__init__.py +18 -5
  65. esphome/components/display/display.cpp +2 -1
  66. esphome/components/display/rect.cpp +2 -1
  67. esphome/components/es7210/__init__.py +0 -0
  68. esphome/components/es7210/audio_adc.py +51 -0
  69. esphome/components/es7210/es7210.cpp +228 -0
  70. esphome/components/es7210/es7210.h +62 -0
  71. esphome/components/es7210/es7210_const.h +129 -0
  72. esphome/components/es7243e/__init__.py +0 -0
  73. esphome/components/es7243e/audio_adc.py +34 -0
  74. esphome/components/es7243e/es7243e.cpp +125 -0
  75. esphome/components/es7243e/es7243e.h +37 -0
  76. esphome/components/es7243e/es7243e_const.h +54 -0
  77. esphome/components/es8156/__init__.py +0 -0
  78. esphome/components/es8156/audio_dac.py +27 -0
  79. esphome/components/es8156/es8156.cpp +87 -0
  80. esphome/components/es8156/es8156.h +51 -0
  81. esphome/components/es8156/es8156_const.h +68 -0
  82. esphome/components/es8311/audio_dac.py +1 -2
  83. esphome/components/esp32/__init__.py +1 -0
  84. esphome/components/esp32/core.cpp +5 -1
  85. esphome/components/esp32/gpio.h +2 -0
  86. esphome/components/esp32_ble/__init__.py +39 -0
  87. esphome/components/esp32_ble/queue.h +4 -4
  88. esphome/components/esp32_ble_client/ble_client_base.cpp +46 -0
  89. esphome/components/esp32_ble_client/ble_client_base.h +2 -0
  90. esphome/components/esp32_ble_server/__init__.py +582 -12
  91. esphome/components/esp32_ble_server/ble_characteristic.cpp +48 -60
  92. esphome/components/esp32_ble_server/ble_characteristic.h +24 -17
  93. esphome/components/esp32_ble_server/ble_descriptor.cpp +21 -9
  94. esphome/components/esp32_ble_server/ble_descriptor.h +17 -6
  95. esphome/components/esp32_ble_server/ble_server.cpp +62 -67
  96. esphome/components/esp32_ble_server/ble_server.h +28 -32
  97. esphome/components/esp32_ble_server/ble_server_automations.cpp +77 -0
  98. esphome/components/esp32_ble_server/ble_server_automations.h +115 -0
  99. esphome/components/esp32_ble_server/ble_service.cpp +17 -15
  100. esphome/components/esp32_ble_server/ble_service.h +10 -14
  101. esphome/components/esp32_ble_tracker/__init__.py +6 -39
  102. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +33 -10
  103. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +8 -4
  104. esphome/components/esp32_improv/__init__.py +2 -8
  105. esphome/components/esp32_improv/esp32_improv_component.cpp +21 -20
  106. esphome/components/esp32_improv/esp32_improv_component.h +3 -4
  107. esphome/components/esp32_rmt/__init__.py +28 -3
  108. esphome/components/esp32_rmt_led_strip/led_strip.cpp +73 -6
  109. esphome/components/esp32_rmt_led_strip/led_strip.h +21 -3
  110. esphome/components/esp32_rmt_led_strip/light.py +72 -7
  111. esphome/components/esp32_touch/esp32_touch.cpp +5 -0
  112. esphome/components/esp8266/__init__.py +1 -0
  113. esphome/components/esp8266/gpio.h +1 -0
  114. esphome/components/ethernet/__init__.py +10 -10
  115. esphome/components/event/event.cpp +4 -2
  116. esphome/components/event/event.h +2 -0
  117. esphome/components/event_emitter/__init__.py +5 -0
  118. esphome/components/event_emitter/event_emitter.cpp +14 -0
  119. esphome/components/event_emitter/event_emitter.h +63 -0
  120. esphome/components/gcja5/gcja5.cpp +2 -1
  121. esphome/components/haier/haier_base.cpp +2 -1
  122. esphome/components/haier/hon_climate.cpp +2 -1
  123. esphome/components/heatpumpir/heatpumpir.cpp +2 -1
  124. esphome/components/host/__init__.py +1 -0
  125. esphome/components/host/gpio.h +1 -0
  126. esphome/components/http_request/http_request.h +2 -2
  127. esphome/components/http_request/http_request_arduino.cpp +1 -1
  128. esphome/components/http_request/http_request_idf.cpp +1 -1
  129. esphome/components/i2c/i2c_bus_esp_idf.cpp +4 -0
  130. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +7 -5
  131. esphome/components/i2s_audio/speaker/__init__.py +53 -6
  132. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +92 -46
  133. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -0
  134. esphome/components/ili9xxx/display.py +29 -11
  135. esphome/components/ili9xxx/ili9xxx_display.cpp +2 -5
  136. esphome/components/ili9xxx/ili9xxx_display.h +2 -1
  137. esphome/components/image/__init__.py +443 -255
  138. esphome/components/image/image.cpp +115 -61
  139. esphome/components/image/image.h +15 -24
  140. esphome/components/json/json_util.cpp +8 -34
  141. esphome/components/libretiny/__init__.py +1 -0
  142. esphome/components/libretiny/gpio_arduino.h +1 -0
  143. esphome/components/light/light_color_values.h +1 -1
  144. esphome/components/logger/__init__.py +43 -7
  145. esphome/components/logger/logger.cpp +16 -11
  146. esphome/components/logger/logger.h +11 -7
  147. esphome/components/logger/select/__init__.py +29 -0
  148. esphome/components/logger/select/logger_level_select.cpp +27 -0
  149. esphome/components/logger/select/logger_level_select.h +15 -0
  150. esphome/components/lvgl/__init__.py +96 -73
  151. esphome/components/lvgl/automation.py +39 -7
  152. esphome/components/lvgl/defines.py +8 -2
  153. esphome/components/lvgl/lvgl_esphome.cpp +8 -15
  154. esphome/components/lvgl/lvgl_esphome.h +20 -5
  155. esphome/components/lvgl/schemas.py +25 -14
  156. esphome/components/lvgl/trigger.py +27 -3
  157. esphome/components/lvgl/widgets/dropdown.py +1 -1
  158. esphome/components/lvgl/widgets/keyboard.py +8 -1
  159. esphome/components/lvgl/widgets/meter.py +2 -1
  160. esphome/components/lvgl/widgets/msgbox.py +1 -1
  161. esphome/components/lvgl/widgets/obj.py +1 -12
  162. esphome/components/lvgl/widgets/page.py +37 -2
  163. esphome/components/lvgl/widgets/tabview.py +1 -1
  164. esphome/components/max6956/max6956.h +2 -0
  165. esphome/components/mcp23016/mcp23016.h +2 -0
  166. esphome/components/mcp23xxx_base/mcp23xxx_base.h +2 -0
  167. esphome/components/mdns/__init__.py +1 -1
  168. esphome/components/media_player/__init__.py +37 -8
  169. esphome/components/media_player/automation.h +11 -2
  170. esphome/components/media_player/media_player.cpp +8 -0
  171. esphome/components/media_player/media_player.h +8 -4
  172. esphome/components/micronova/switch/micronova_switch.cpp +4 -2
  173. esphome/components/midea/ac_automations.h +3 -1
  174. esphome/components/midea/air_conditioner.cpp +7 -5
  175. esphome/components/midea/air_conditioner.h +1 -1
  176. esphome/components/midea/climate.py +4 -2
  177. esphome/components/midea/ir_transmitter.h +36 -5
  178. esphome/components/mixer/__init__.py +0 -0
  179. esphome/components/mixer/speaker/__init__.py +172 -0
  180. esphome/components/mixer/speaker/automation.h +19 -0
  181. esphome/components/mixer/speaker/mixer_speaker.cpp +624 -0
  182. esphome/components/mixer/speaker/mixer_speaker.h +207 -0
  183. esphome/components/mpr121/mpr121.h +2 -0
  184. esphome/components/mqtt/__init__.py +1 -1
  185. esphome/components/mqtt/mqtt_client.cpp +7 -1
  186. esphome/components/mqtt/mqtt_client.h +1 -1
  187. esphome/components/mqtt/mqtt_climate.cpp +2 -2
  188. esphome/components/network/ip_address.h +2 -0
  189. esphome/components/nextion/automation.h +17 -0
  190. esphome/components/nextion/display.py +42 -17
  191. esphome/components/nextion/nextion.cpp +4 -10
  192. esphome/components/nextion/nextion.h +89 -82
  193. esphome/components/nextion/nextion_commands.cpp +10 -10
  194. esphome/components/ntc/sensor.py +2 -4
  195. esphome/components/online_image/__init__.py +98 -46
  196. esphome/components/online_image/bmp_image.cpp +101 -0
  197. esphome/components/online_image/bmp_image.h +40 -0
  198. esphome/components/online_image/image_decoder.cpp +28 -2
  199. esphome/components/online_image/image_decoder.h +24 -15
  200. esphome/components/online_image/jpeg_image.cpp +90 -0
  201. esphome/components/online_image/jpeg_image.h +34 -0
  202. esphome/components/online_image/online_image.cpp +112 -53
  203. esphome/components/online_image/online_image.h +24 -7
  204. esphome/components/online_image/png_image.cpp +7 -3
  205. esphome/components/online_image/png_image.h +2 -1
  206. esphome/components/opentherm/__init__.py +73 -7
  207. esphome/components/opentherm/automation.h +25 -0
  208. esphome/components/opentherm/const.py +1 -0
  209. esphome/components/opentherm/generate.py +39 -6
  210. esphome/components/opentherm/hub.cpp +117 -79
  211. esphome/components/opentherm/hub.h +31 -15
  212. esphome/components/opentherm/opentherm.cpp +47 -23
  213. esphome/components/opentherm/opentherm.h +27 -6
  214. esphome/components/opentherm/opentherm_macros.h +11 -0
  215. esphome/components/opentherm/schema.py +78 -1
  216. esphome/components/opentherm/validate.py +7 -2
  217. esphome/components/pca6416a/pca6416a.h +2 -0
  218. esphome/components/pca9554/pca9554.h +2 -0
  219. esphome/components/pcf8574/pcf8574.h +2 -0
  220. esphome/components/preferences/__init__.py +2 -4
  221. esphome/components/preferences/syncer.h +10 -3
  222. esphome/components/prometheus/prometheus_handler.cpp +313 -0
  223. esphome/components/prometheus/prometheus_handler.h +48 -7
  224. esphome/components/psram/psram.cpp +8 -1
  225. esphome/components/pulse_counter/pulse_counter_sensor.cpp +14 -9
  226. esphome/components/pulse_counter/pulse_counter_sensor.h +4 -4
  227. esphome/components/pulse_meter/pulse_meter_sensor.cpp +2 -0
  228. esphome/components/qspi_dbi/__init__.py +3 -0
  229. esphome/components/qspi_dbi/display.py +74 -47
  230. esphome/components/qspi_dbi/models.py +245 -2
  231. esphome/components/qspi_dbi/qspi_dbi.cpp +9 -16
  232. esphome/components/qspi_dbi/qspi_dbi.h +2 -2
  233. esphome/components/remote_base/__init__.py +77 -25
  234. esphome/components/remote_base/remote_base.cpp +1 -1
  235. esphome/components/remote_base/remote_base.h +20 -2
  236. esphome/components/remote_base/toto_protocol.cpp +100 -0
  237. esphome/components/remote_base/toto_protocol.h +45 -0
  238. esphome/components/remote_receiver/__init__.py +55 -10
  239. esphome/components/remote_receiver/remote_receiver.h +36 -3
  240. esphome/components/remote_receiver/remote_receiver_esp32.cpp +145 -6
  241. esphome/components/remote_transmitter/__init__.py +62 -4
  242. esphome/components/remote_transmitter/remote_transmitter.h +21 -2
  243. esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +140 -4
  244. esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +3 -3
  245. esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +3 -3
  246. esphome/components/resampler/__init__.py +0 -0
  247. esphome/components/resampler/speaker/__init__.py +103 -0
  248. esphome/components/resampler/speaker/resampler_speaker.cpp +318 -0
  249. esphome/components/resampler/speaker/resampler_speaker.h +107 -0
  250. esphome/components/resistance/resistance_sensor.h +2 -3
  251. esphome/components/resistance/sensor.py +2 -9
  252. esphome/components/rotary_encoder/rotary_encoder.cpp +8 -4
  253. esphome/components/rp2040/__init__.py +1 -0
  254. esphome/components/rp2040/gpio.h +1 -0
  255. esphome/components/rtl87xx/__init__.py +2 -0
  256. esphome/components/sdl/binary_sensor.py +270 -0
  257. esphome/components/sdl/sdl_esphome.cpp +16 -0
  258. esphome/components/sdl/sdl_esphome.h +9 -0
  259. esphome/components/seeed_mr60bha2/binary_sensor.py +25 -0
  260. esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +26 -2
  261. esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +9 -20
  262. esphome/components/seeed_mr60bha2/sensor.py +9 -1
  263. esphome/components/sn74hc165/sn74hc165.h +3 -0
  264. esphome/components/sn74hc595/sn74hc595.h +3 -0
  265. esphome/components/speaker/__init__.py +5 -4
  266. esphome/components/speaker/media_player/__init__.py +458 -0
  267. esphome/components/speaker/media_player/audio_pipeline.cpp +568 -0
  268. esphome/components/speaker/media_player/audio_pipeline.h +159 -0
  269. esphome/components/speaker/media_player/automation.h +26 -0
  270. esphome/components/speaker/media_player/speaker_media_player.cpp +577 -0
  271. esphome/components/speaker/media_player/speaker_media_player.h +160 -0
  272. esphome/components/speaker/speaker.h +20 -0
  273. esphome/components/spi/__init__.py +1 -5
  274. esphome/components/spi/spi.cpp +7 -1
  275. esphome/components/spi/spi.h +21 -2
  276. esphome/components/spi_led_strip/light.py +3 -5
  277. esphome/components/spi_led_strip/spi_led_strip.cpp +67 -0
  278. esphome/components/spi_led_strip/spi_led_strip.h +8 -60
  279. esphome/components/sprinkler/sprinkler.cpp +3 -1
  280. esphome/components/sx1509/sx1509_gpio_pin.h +2 -0
  281. esphome/components/tca9555/tca9555.h +2 -0
  282. esphome/components/toshiba/toshiba.cpp +2 -1
  283. esphome/components/tuya/light/tuya_light.cpp +4 -2
  284. esphome/components/uart/uart_component_esp32_arduino.cpp +2 -2
  285. esphome/components/uart/uart_component_esp_idf.cpp +2 -2
  286. esphome/components/udp/__init__.py +8 -2
  287. esphome/components/udp/udp_component.cpp +25 -56
  288. esphome/components/udp/udp_component.h +3 -0
  289. esphome/components/uponor_smatrix/sensor/__init__.py +14 -4
  290. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +5 -0
  291. esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.h +1 -0
  292. esphome/components/uptime/text_sensor/__init__.py +19 -0
  293. esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +63 -0
  294. esphome/components/uptime/text_sensor/uptime_text_sensor.h +25 -0
  295. esphome/components/voice_assistant/voice_assistant.cpp +24 -14
  296. esphome/components/voice_assistant/voice_assistant.h +8 -0
  297. esphome/components/waveshare_epaper/display.py +22 -1
  298. esphome/components/waveshare_epaper/waveshare_213v3.cpp +9 -3
  299. esphome/components/waveshare_epaper/waveshare_epaper.cpp +1155 -44
  300. esphome/components/waveshare_epaper/waveshare_epaper.h +208 -7
  301. esphome/components/web_server/web_server.cpp +28 -6
  302. esphome/components/weikai/weikai.h +2 -0
  303. esphome/components/wifi/__init__.py +6 -6
  304. esphome/components/wifi/wifi_component.cpp +1 -1
  305. esphome/components/wifi/wifi_component_esp32_arduino.cpp +30 -1
  306. esphome/components/wireguard/__init__.py +2 -2
  307. esphome/components/xl9535/xl9535.h +2 -0
  308. esphome/components/xxtea/__init__.py +3 -0
  309. esphome/components/xxtea/xxtea.cpp +46 -0
  310. esphome/components/xxtea/xxtea.h +26 -0
  311. esphome/components/yashima/yashima.cpp +2 -1
  312. esphome/config.py +9 -5
  313. esphome/config_validation.py +55 -17
  314. esphome/const.py +7 -10
  315. esphome/core/__init__.py +6 -13
  316. esphome/core/base_automation.h +1 -0
  317. esphome/core/config.py +57 -72
  318. esphome/core/defines.h +9 -1
  319. esphome/core/gpio.h +7 -0
  320. esphome/core/helpers.cpp +19 -15
  321. esphome/core/helpers.h +57 -8
  322. esphome/core/log.h +9 -7
  323. esphome/cpp_generator.py +2 -2
  324. esphome/espota2.py +3 -2
  325. esphome/loader.py +12 -4
  326. esphome/log.py +5 -7
  327. esphome/yaml_util.py +2 -2
  328. {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/METADATA +12 -7
  329. {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/RECORD +338 -289
  330. esphome/components/custom/binary_sensor/custom_binary_sensor.cpp +0 -16
  331. esphome/components/custom/binary_sensor/custom_binary_sensor.h +0 -26
  332. esphome/components/custom/climate/custom_climate.h +0 -22
  333. esphome/components/custom/cover/custom_cover.h +0 -21
  334. esphome/components/custom/light/custom_light_output.h +0 -24
  335. esphome/components/custom/output/custom_output.h +0 -37
  336. esphome/components/custom/sensor/custom_sensor.cpp +0 -16
  337. esphome/components/custom/sensor/custom_sensor.h +0 -24
  338. esphome/components/custom/switch/custom_switch.cpp +0 -16
  339. esphome/components/custom/switch/custom_switch.h +0 -24
  340. esphome/components/custom/text_sensor/custom_text_sensor.cpp +0 -16
  341. esphome/components/custom/text_sensor/custom_text_sensor.h +0 -26
  342. esphome/components/custom_component/custom_component.h +0 -28
  343. esphome/components/esp32_ble_server/ble_2901.cpp +0 -18
  344. esphome/components/esp32_ble_server/ble_2901.h +0 -19
  345. esphome/components/resistance_sampler/__init__.py +0 -6
  346. esphome/components/resistance_sampler/resistance_sampler.h +0 -10
  347. esphome/components/uptime/{sensor.py → sensor/__init__.py} +3 -3
  348. /esphome/components/uptime/{uptime_seconds_sensor.cpp → sensor/uptime_seconds_sensor.cpp} +0 -0
  349. /esphome/components/uptime/{uptime_seconds_sensor.h → sensor/uptime_seconds_sensor.h} +0 -0
  350. /esphome/components/uptime/{uptime_timestamp_sensor.cpp → sensor/uptime_timestamp_sensor.cpp} +0 -0
  351. /esphome/components/uptime/{uptime_timestamp_sensor.h → sensor/uptime_timestamp_sensor.h} +0 -0
  352. {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/LICENSE +0 -0
  353. {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/WHEEL +0 -0
  354. {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/entry_points.txt +0 -0
  355. {esphome-2024.12.4.dist-info → esphome-2025.2.0b1.dist-info}/top_level.txt +0 -0
@@ -10,19 +10,19 @@ static const char *const TAG = "nextion";
10
10
  // Sleep safe commands
11
11
  void Nextion::soft_reset() { this->send_command_("rest"); }
12
12
 
13
- void Nextion::set_wake_up_page(uint8_t page_id) {
14
- this->add_no_result_to_queue_with_set_internal_("wake_up_page", "wup", page_id, true);
13
+ void Nextion::set_wake_up_page(uint8_t wake_up_page) {
14
+ this->wake_up_page_ = wake_up_page;
15
+ this->add_no_result_to_queue_with_set_internal_("wake_up_page", "wup", wake_up_page, true);
15
16
  }
16
17
 
17
- void Nextion::set_start_up_page(uint8_t page_id) { this->start_up_page_ = page_id; }
18
-
19
- void Nextion::set_touch_sleep_timeout(uint16_t timeout) {
20
- if (timeout < 3) {
18
+ void Nextion::set_touch_sleep_timeout(uint32_t touch_sleep_timeout) {
19
+ if (touch_sleep_timeout < 3) {
21
20
  ESP_LOGD(TAG, "Sleep timeout out of bounds, range 3-65535");
22
21
  return;
23
22
  }
24
23
 
25
- this->add_no_result_to_queue_with_set_internal_("touch_sleep_timeout", "thsp", timeout, true);
24
+ this->touch_sleep_timeout_ = touch_sleep_timeout;
25
+ this->add_no_result_to_queue_with_set_internal_("touch_sleep_timeout", "thsp", touch_sleep_timeout, true);
26
26
  }
27
27
 
28
28
  void Nextion::sleep(bool sleep) {
@@ -54,7 +54,6 @@ bool Nextion::set_protocol_reparse_mode(bool active_mode) {
54
54
  this->ignore_is_setup_ = false;
55
55
  return all_commands_sent;
56
56
  }
57
- void Nextion::set_exit_reparse_on_start(bool exit_reparse) { this->exit_reparse_on_start_ = exit_reparse; }
58
57
 
59
58
  // Set Colors - Background
60
59
  void Nextion::set_component_background_color(const char *component, uint16_t color) {
@@ -191,8 +190,9 @@ void Nextion::set_backlight_brightness(float brightness) {
191
190
  this->add_no_result_to_queue_with_printf_("backlight_brightness", "dim=%d", static_cast<int>(brightness * 100));
192
191
  }
193
192
 
194
- void Nextion::set_auto_wake_on_touch(bool auto_wake) {
195
- this->add_no_result_to_queue_with_set("auto_wake_on_touch", "thup", auto_wake ? 1 : 0);
193
+ void Nextion::set_auto_wake_on_touch(bool auto_wake_on_touch) {
194
+ this->auto_wake_on_touch_ = auto_wake_on_touch;
195
+ this->add_no_result_to_queue_with_set("auto_wake_on_touch", "thup", auto_wake_on_touch ? 1 : 0);
196
196
  }
197
197
 
198
198
  // General Component
@@ -2,7 +2,7 @@ from math import log
2
2
 
3
3
  import esphome.config_validation as cv
4
4
  import esphome.codegen as cg
5
- from esphome.components import sensor, resistance_sampler
5
+ from esphome.components import sensor
6
6
  from esphome.const import (
7
7
  CONF_CALIBRATION,
8
8
  CONF_REFERENCE_RESISTANCE,
@@ -15,8 +15,6 @@ from esphome.const import (
15
15
  UNIT_CELSIUS,
16
16
  )
17
17
 
18
- AUTO_LOAD = ["resistance_sampler"]
19
-
20
18
  ntc_ns = cg.esphome_ns.namespace("ntc")
21
19
  NTC = ntc_ns.class_("NTC", cg.Component, sensor.Sensor)
22
20
 
@@ -126,7 +124,7 @@ CONFIG_SCHEMA = (
126
124
  )
127
125
  .extend(
128
126
  {
129
- cv.Required(CONF_SENSOR): cv.use_id(resistance_sampler.ResistanceSampler),
127
+ cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor),
130
128
  cv.Required(CONF_CALIBRATION): process_calibration,
131
129
  }
132
130
  )
@@ -4,14 +4,18 @@ from esphome import automation
4
4
  import esphome.codegen as cg
5
5
  from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent
6
6
  from esphome.components.image import (
7
- CONF_USE_TRANSPARENCY,
8
- IMAGE_TYPE,
7
+ CONF_INVERT_ALPHA,
8
+ CONF_TRANSPARENCY,
9
+ IMAGE_SCHEMA,
9
10
  Image_,
10
- validate_cross_dependencies,
11
+ get_image_type_enum,
12
+ get_transparency_enum,
11
13
  )
12
14
  import esphome.config_validation as cv
13
15
  from esphome.const import (
14
16
  CONF_BUFFER_SIZE,
17
+ CONF_DITHER,
18
+ CONF_FILE,
15
19
  CONF_FORMAT,
16
20
  CONF_ID,
17
21
  CONF_ON_ERROR,
@@ -23,7 +27,7 @@ from esphome.const import (
23
27
 
24
28
  AUTO_LOAD = ["image"]
25
29
  DEPENDENCIES = ["display", "http_request"]
26
- CODEOWNERS = ["@guillempages"]
30
+ CODEOWNERS = ["@guillempages", "@clydebarrow"]
27
31
  MULTI_CONF = True
28
32
 
29
33
  CONF_ON_DOWNLOAD_FINISHED = "on_download_finished"
@@ -35,9 +39,54 @@ online_image_ns = cg.esphome_ns.namespace("online_image")
35
39
 
36
40
  ImageFormat = online_image_ns.enum("ImageFormat")
37
41
 
38
- FORMAT_PNG = "PNG"
39
42
 
40
- IMAGE_FORMAT = {FORMAT_PNG: ImageFormat.PNG} # Add new supported formats here
43
+ class Format:
44
+ def __init__(self, image_type):
45
+ self.image_type = image_type
46
+
47
+ @property
48
+ def enum(self):
49
+ return getattr(ImageFormat, self.image_type)
50
+
51
+ def actions(self):
52
+ pass
53
+
54
+
55
+ class BMPFormat(Format):
56
+ def __init__(self):
57
+ super().__init__("BMP")
58
+
59
+ def actions(self):
60
+ cg.add_define("USE_ONLINE_IMAGE_BMP_SUPPORT")
61
+
62
+
63
+ class JPEGFormat(Format):
64
+ def __init__(self):
65
+ super().__init__("JPEG")
66
+
67
+ def actions(self):
68
+ cg.add_define("USE_ONLINE_IMAGE_JPEG_SUPPORT")
69
+ cg.add_library("JPEGDEC", None, "https://github.com/bitbank2/JPEGDEC#ca1e0f2")
70
+
71
+
72
+ class PNGFormat(Format):
73
+ def __init__(self):
74
+ super().__init__("PNG")
75
+
76
+ def actions(self):
77
+ cg.add_define("USE_ONLINE_IMAGE_PNG_SUPPORT")
78
+ cg.add_library("pngle", "1.0.2")
79
+
80
+
81
+ IMAGE_FORMATS = {
82
+ x.image_type: x
83
+ for x in (
84
+ BMPFormat(),
85
+ JPEGFormat(),
86
+ PNGFormat(),
87
+ )
88
+ }
89
+ IMAGE_FORMATS.update({"JPG": IMAGE_FORMATS["JPEG"]})
41
90
 
42
91
  OnlineImage = online_image_ns.class_("OnlineImage", cg.PollingComponent, Image_)
43
92
 
@@ -57,48 +106,54 @@ DownloadErrorTrigger = online_image_ns.class_(
57
106
  "DownloadErrorTrigger", automation.Trigger.template()
58
107
  )
59
108
 
60
- ONLINE_IMAGE_SCHEMA = cv.Schema(
61
- {
62
- cv.Required(CONF_ID): cv.declare_id(OnlineImage),
63
- cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent),
64
- #
65
- # Common image options
66
- #
67
- cv.Optional(CONF_RESIZE): cv.dimensions,
68
- cv.Optional(CONF_TYPE, default="BINARY"): cv.enum(IMAGE_TYPE, upper=True),
69
- # Not setting default here on purpose; the default depends on the image type,
70
- # and thus will be set in the "validate_cross_dependencies" validator.
71
- cv.Optional(CONF_USE_TRANSPARENCY): cv.boolean,
72
- #
73
- # Online Image specific options
74
- #
75
- cv.Required(CONF_URL): cv.url,
76
- cv.Required(CONF_FORMAT): cv.enum(IMAGE_FORMAT, upper=True),
77
- cv.Optional(CONF_PLACEHOLDER): cv.use_id(Image_),
78
- cv.Optional(CONF_BUFFER_SIZE, default=2048): cv.int_range(256, 65536),
79
- cv.Optional(CONF_ON_DOWNLOAD_FINISHED): automation.validate_automation(
80
- {
81
- cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DownloadFinishedTrigger),
82
- }
83
- ),
84
- cv.Optional(CONF_ON_ERROR): automation.validate_automation(
85
- {
86
- cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DownloadErrorTrigger),
87
- }
88
- ),
109
+
110
+ def remove_options(*options):
111
+ return {
112
+ cv.Optional(option): cv.invalid(
113
+ f"{option} is an invalid option for online_image"
114
+ )
115
+ for option in options
89
116
  }
90
- ).extend(cv.polling_component_schema("never"))
117
+
118
+
119
+ ONLINE_IMAGE_SCHEMA = (
120
+ IMAGE_SCHEMA.extend(remove_options(CONF_FILE, CONF_INVERT_ALPHA, CONF_DITHER))
121
+ .extend(
122
+ {
123
+ cv.Required(CONF_ID): cv.declare_id(OnlineImage),
124
+ cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent),
125
+ # Online Image specific options
126
+ cv.Required(CONF_URL): cv.url,
127
+ cv.Required(CONF_FORMAT): cv.one_of(*IMAGE_FORMATS, upper=True),
128
+ cv.Optional(CONF_PLACEHOLDER): cv.use_id(Image_),
129
+ cv.Optional(CONF_BUFFER_SIZE, default=65536): cv.int_range(256, 65536),
130
+ cv.Optional(CONF_ON_DOWNLOAD_FINISHED): automation.validate_automation(
131
+ {
132
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
133
+ DownloadFinishedTrigger
134
+ ),
135
+ }
136
+ ),
137
+ cv.Optional(CONF_ON_ERROR): automation.validate_automation(
138
+ {
139
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DownloadErrorTrigger),
140
+ }
141
+ ),
142
+ }
143
+ )
144
+ .extend(cv.polling_component_schema("never"))
145
+ )
91
146
 
92
147
  CONFIG_SCHEMA = cv.Schema(
93
148
  cv.All(
94
149
  ONLINE_IMAGE_SCHEMA,
95
- validate_cross_dependencies,
96
150
  cv.require_framework_version(
97
151
  # esp8266 not supported yet; if enabled in the future, minimum version of 2.7.0 is needed
98
152
  # esp8266_arduino=cv.Version(2, 7, 0),
99
153
  esp32_arduino=cv.Version(0, 0, 0),
100
154
  esp_idf=cv.Version(4, 0, 0),
101
155
  rp2040_arduino=cv.Version(0, 0, 0),
156
+ host=cv.Version(0, 0, 0),
102
157
  ),
103
158
  )
104
159
  )
@@ -132,29 +187,26 @@ async def online_image_action_to_code(config, action_id, template_arg, args):
132
187
 
133
188
 
134
189
  async def to_code(config):
135
- format = config[CONF_FORMAT]
136
- if format in [FORMAT_PNG]:
137
- cg.add_define("USE_ONLINE_IMAGE_PNG_SUPPORT")
138
- cg.add_library("pngle", "1.0.2")
190
+ image_format = IMAGE_FORMATS[config[CONF_FORMAT]]
191
+ image_format.actions()
139
192
 
140
193
  url = config[CONF_URL]
141
194
  width, height = config.get(CONF_RESIZE, (0, 0))
142
- transparent = config[CONF_USE_TRANSPARENCY]
195
+ transparent = get_transparency_enum(config[CONF_TRANSPARENCY])
143
196
 
144
197
  var = cg.new_Pvariable(
145
198
  config[CONF_ID],
146
199
  url,
147
200
  width,
148
201
  height,
149
- format,
150
- config[CONF_TYPE],
202
+ image_format.enum,
203
+ get_image_type_enum(config[CONF_TYPE]),
204
+ transparent,
151
205
  config[CONF_BUFFER_SIZE],
152
206
  )
153
207
  await cg.register_component(var, config)
154
208
  await cg.register_parented(var, config[CONF_HTTP_REQUEST_ID])
155
209
 
156
- cg.add(var.set_transparency(transparent))
157
-
158
210
  if placeholder_id := config.get(CONF_PLACEHOLDER):
159
211
  placeholder = await cg.get_variable(placeholder_id)
160
212
  cg.add(var.set_placeholder(placeholder))
@@ -0,0 +1,101 @@
1
+ #include "bmp_image.h"
2
+
3
+ #ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
4
+
5
+ #include "esphome/components/display/display.h"
6
+ #include "esphome/core/helpers.h"
7
+ #include "esphome/core/log.h"
8
+
9
+ namespace esphome {
10
+ namespace online_image {
11
+
12
+ static const char *const TAG = "online_image.bmp";
13
+
14
+ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) {
15
+ size_t index = 0;
16
+ if (this->current_index_ == 0 && index == 0 && size > 14) {
17
+ /**
18
+ * BMP file format:
19
+ * 0-1: Signature (BM)
20
+ * 2-5: File size
21
+ * 6-9: Reserved
22
+ * 10-13: Pixel data offset
23
+ *
24
+ * Integer values are stored in little-endian format.
25
+ */
26
+
27
+ // Check if the file is a BMP image
28
+ if (buffer[0] != 'B' || buffer[1] != 'M') {
29
+ ESP_LOGE(TAG, "Not a BMP file");
30
+ return DECODE_ERROR_INVALID_TYPE;
31
+ }
32
+
33
+ this->download_size_ = encode_uint32(buffer[5], buffer[4], buffer[3], buffer[2]);
34
+ this->data_offset_ = encode_uint32(buffer[13], buffer[12], buffer[11], buffer[10]);
35
+
36
+ this->current_index_ = 14;
37
+ index = 14;
38
+ }
39
+ if (this->current_index_ == 14 && index == 14 && size > this->data_offset_) {
40
+ /**
41
+ * BMP DIB header:
42
+ * 14-17: DIB header size
43
+ * 18-21: Image width
44
+ * 22-25: Image height
45
+ * 26-27: Number of color planes
46
+ * 28-29: Bits per pixel
47
+ * 30-33: Compression method
48
+ * 34-37: Image data size
49
+ * 38-41: Horizontal resolution
50
+ * 42-45: Vertical resolution
51
+ * 46-49: Number of colors in the color table
52
+ */
53
+
54
+ this->width_ = encode_uint32(buffer[21], buffer[20], buffer[19], buffer[18]);
55
+ this->height_ = encode_uint32(buffer[25], buffer[24], buffer[23], buffer[22]);
56
+ this->bits_per_pixel_ = encode_uint16(buffer[29], buffer[28]);
57
+ this->compression_method_ = encode_uint32(buffer[33], buffer[32], buffer[31], buffer[30]);
58
+ this->image_data_size_ = encode_uint32(buffer[37], buffer[36], buffer[35], buffer[34]);
59
+ this->color_table_entries_ = encode_uint32(buffer[49], buffer[48], buffer[47], buffer[46]);
60
+
61
+ switch (this->bits_per_pixel_) {
62
+ case 1:
63
+ this->width_bytes_ = (this->width_ % 8 == 0) ? (this->width_ / 8) : (this->width_ / 8 + 1);
64
+ break;
65
+ default:
66
+ ESP_LOGE(TAG, "Unsupported bits per pixel: %d", this->bits_per_pixel_);
67
+ return DECODE_ERROR_UNSUPPORTED_FORMAT;
68
+ }
69
+
70
+ if (this->compression_method_ != 0) {
71
+ ESP_LOGE(TAG, "Unsupported compression method: %d", this->compression_method_);
72
+ return DECODE_ERROR_UNSUPPORTED_FORMAT;
73
+ }
74
+
75
+ if (!this->set_size(this->width_, this->height_)) {
76
+ return DECODE_ERROR_OUT_OF_MEMORY;
77
+ }
78
+ this->current_index_ = this->data_offset_;
79
+ index = this->data_offset_;
80
+ }
81
+ while (index < size) {
82
+ size_t paint_index = this->current_index_ - this->data_offset_;
83
+
84
+ uint8_t current_byte = buffer[index];
85
+ for (uint8_t i = 0; i < 8; i++) {
86
+ size_t x = (paint_index * 8) % this->width_ + i;
87
+ size_t y = (this->height_ - 1) - (paint_index / this->width_bytes_);
88
+ Color c = (current_byte & (1 << (7 - i))) ? display::COLOR_ON : display::COLOR_OFF;
89
+ this->draw(x, y, 1, 1, c);
90
+ }
91
+ this->current_index_++;
92
+ index++;
93
+ }
94
+ this->decoded_bytes_ += size;
95
+ return size;
96
+ };
97
+
98
+ } // namespace online_image
99
+ } // namespace esphome
100
+
101
+ #endif // USE_ONLINE_IMAGE_BMP_SUPPORT
@@ -0,0 +1,40 @@
1
+ #pragma once
2
+
3
+ #include "esphome/core/defines.h"
4
+ #ifdef USE_ONLINE_IMAGE_BMP_SUPPORT
5
+
6
+ #include "image_decoder.h"
7
+
8
+ namespace esphome {
9
+ namespace online_image {
10
+
11
+ /**
12
+ * @brief Image decoder specialization for PNG images.
13
+ */
14
+ class BmpDecoder : public ImageDecoder {
15
+ public:
16
+ /**
17
+ * @brief Construct a new BMP Decoder object.
18
+ *
19
+ * @param display The image to decode the stream into.
20
+ */
21
+ BmpDecoder(OnlineImage *image) : ImageDecoder(image) {}
22
+
23
+ int HOT decode(uint8_t *buffer, size_t size) override;
24
+
25
+ protected:
26
+ size_t current_index_{0};
27
+ ssize_t width_{0};
28
+ ssize_t height_{0};
29
+ uint16_t bits_per_pixel_{0};
30
+ uint32_t compression_method_{0};
31
+ uint32_t image_data_size_{0};
32
+ uint32_t color_table_entries_{0};
33
+ size_t width_bytes_{0};
34
+ size_t data_offset_{0};
35
+ };
36
+
37
+ } // namespace online_image
38
+ } // namespace esphome
39
+
40
+ #endif // USE_ONLINE_IMAGE_BMP_SUPPORT
@@ -8,10 +8,11 @@ namespace online_image {
8
8
 
9
9
  static const char *const TAG = "online_image.decoder";
10
10
 
11
- void ImageDecoder::set_size(int width, int height) {
12
- this->image_->resize_(width, height);
11
+ bool ImageDecoder::set_size(int width, int height) {
12
+ bool resized = this->image_->resize_(width, height);
13
13
  this->x_scale_ = static_cast<double>(this->image_->buffer_width_) / width;
14
14
  this->y_scale_ = static_cast<double>(this->image_->buffer_height_) / height;
15
+ return resized;
15
16
  }
16
17
 
17
18
  void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
@@ -24,6 +25,15 @@ void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
24
25
  }
25
26
  }
26
27
 
28
+ DownloadBuffer::DownloadBuffer(size_t size) : size_(size) {
29
+ this->buffer_ = this->allocator_.allocate(size);
30
+ this->reset();
31
+ if (!this->buffer_) {
32
+ ESP_LOGE(TAG, "Initial allocation of download buffer failed!");
33
+ this->size_ = 0;
34
+ }
35
+ }
36
+
27
37
  uint8_t *DownloadBuffer::data(size_t offset) {
28
38
  if (offset > this->size_) {
29
39
  ESP_LOGE(TAG, "Tried to access beyond download buffer bounds!!!");
@@ -40,5 +50,21 @@ size_t DownloadBuffer::read(size_t len) {
40
50
  return this->unread_;
41
51
  }
42
52
 
53
+ size_t DownloadBuffer::resize(size_t size) {
54
+ if (this->size_ == size) {
55
+ return size;
56
+ }
57
+ this->allocator_.deallocate(this->buffer_, this->size_);
58
+ this->buffer_ = this->allocator_.allocate(size);
59
+ this->reset();
60
+ if (this->buffer_) {
61
+ this->size_ = size;
62
+ return size;
63
+ } else {
64
+ this->size_ = 0;
65
+ return 0;
66
+ }
67
+ }
68
+
43
69
  } // namespace online_image
44
70
  } // namespace esphome
@@ -1,10 +1,15 @@
1
1
  #pragma once
2
- #include "esphome/core/defines.h"
3
2
  #include "esphome/core/color.h"
4
3
 
5
4
  namespace esphome {
6
5
  namespace online_image {
7
6
 
7
+ enum DecodeError : int {
8
+ DECODE_ERROR_INVALID_TYPE = -1,
9
+ DECODE_ERROR_UNSUPPORTED_FORMAT = -2,
10
+ DECODE_ERROR_OUT_OF_MEMORY = -3,
11
+ };
12
+
8
13
  class OnlineImage;
9
14
 
10
15
  /**
@@ -23,9 +28,13 @@ class ImageDecoder {
23
28
  /**
24
29
  * @brief Initialize the decoder.
25
30
  *
26
- * @param download_size The total number of bytes that need to be download for the image.
31
+ * @param download_size The total number of bytes that need to be downloaded for the image.
32
+ * @return int Returns 0 on success, a {@see DecodeError} value in case of an error.
27
33
  */
28
- virtual void prepare(uint32_t download_size) { this->download_size_ = download_size; }
34
+ virtual int prepare(size_t download_size) {
35
+ this->download_size_ = download_size;
36
+ return 0;
37
+ }
29
38
 
30
39
  /**
31
40
  * @brief Decode a part of the image. It will try reading from the buffer.
@@ -38,7 +47,7 @@ class ImageDecoder {
38
47
  * @return int The amount of bytes read. It can be 0 if the buffer does not have enough content to meaningfully
39
48
  * decode anything, or negative in case of a decoding error.
40
49
  */
41
- virtual int decode(uint8_t *buffer, size_t size);
50
+ virtual int decode(uint8_t *buffer, size_t size) = 0;
42
51
 
43
52
  /**
44
53
  * @brief Request the image to be resized once the actual dimensions are known.
@@ -46,11 +55,12 @@ class ImageDecoder {
46
55
  *
47
56
  * @param width The image's width.
48
57
  * @param height The image's height.
58
+ * @return true if the image was resized, false otherwise.
49
59
  */
50
- void set_size(int width, int height);
60
+ bool set_size(int width, int height);
51
61
 
52
62
  /**
53
- * @brief Draw a rectangle on the display_buffer using the defined color.
63
+ * @brief Fill a rectangle on the display_buffer using the defined color.
54
64
  * Will check the given coordinates for out-of-bounds, and clip the rectangle accordingly.
55
65
  * In case of binary displays, the color will be converted to binary as well.
56
66
  * Called by the callback functions, to be able to access the parent Image class.
@@ -59,7 +69,7 @@ class ImageDecoder {
59
69
  * @param y The top-most coordinate of the rectangle.
60
70
  * @param w The width of the rectangle.
61
71
  * @param h The height of the rectangle.
62
- * @param color The color to draw the rectangle with.
72
+ * @param color The fill color
63
73
  */
64
74
  void draw(int x, int y, int w, int h, const Color &color);
65
75
 
@@ -67,20 +77,17 @@ class ImageDecoder {
67
77
 
68
78
  protected:
69
79
  OnlineImage *image_;
70
- // Initializing to 1, to ensure it is different than initial "decoded_bytes_".
80
+ // Initializing to 1, to ensure it is distinguishable from initial "decoded_bytes_".
71
81
  // Will be overwritten anyway once the download size is known.
72
- uint32_t download_size_ = 1;
73
- uint32_t decoded_bytes_ = 0;
82
+ size_t download_size_ = 1;
83
+ size_t decoded_bytes_ = 0;
74
84
  double x_scale_ = 1.0;
75
85
  double y_scale_ = 1.0;
76
86
  };
77
87
 
78
88
  class DownloadBuffer {
79
89
  public:
80
- DownloadBuffer(size_t size) : size_(size) {
81
- this->buffer_ = this->allocator_.allocate(size);
82
- this->reset();
83
- }
90
+ DownloadBuffer(size_t size);
84
91
 
85
92
  virtual ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); }
86
93
 
@@ -100,8 +107,10 @@ class DownloadBuffer {
100
107
 
101
108
  void reset() { this->unread_ = 0; }
102
109
 
110
+ size_t resize(size_t size);
111
+
103
112
  protected:
104
- ExternalRAMAllocator<uint8_t> allocator_;
113
+ RAMAllocator<uint8_t> allocator_{};
105
114
  uint8_t *buffer_;
106
115
  size_t size_;
107
116
  /** Total number of downloaded bytes not yet read. */
@@ -0,0 +1,90 @@
1
+ #include "jpeg_image.h"
2
+ #ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
3
+
4
+ #include "esphome/components/display/display_buffer.h"
5
+ #include "esphome/core/application.h"
6
+ #include "esphome/core/helpers.h"
7
+ #include "esphome/core/log.h"
8
+
9
+ #include "online_image.h"
10
+ static const char *const TAG = "online_image.jpeg";
11
+
12
+ namespace esphome {
13
+ namespace online_image {
14
+
15
+ /**
16
+ * @brief Callback method that will be called by the JPEGDEC engine when a chunk
17
+ * of the image is decoded.
18
+ *
19
+ * @param jpeg The JPEGDRAW object, including the context data.
20
+ */
21
+ static int draw_callback(JPEGDRAW *jpeg) {
22
+ ImageDecoder *decoder = (ImageDecoder *) jpeg->pUser;
23
+
24
+ // Some very big images take too long to decode, so feed the watchdog on each callback
25
+ // to avoid crashing.
26
+ App.feed_wdt();
27
+ size_t position = 0;
28
+ for (size_t y = 0; y < jpeg->iHeight; y++) {
29
+ for (size_t x = 0; x < jpeg->iWidth; x++) {
30
+ auto rg = decode_value(jpeg->pPixels[position++]);
31
+ auto ba = decode_value(jpeg->pPixels[position++]);
32
+ Color color(rg[1], rg[0], ba[1], ba[0]);
33
+
34
+ if (!decoder) {
35
+ ESP_LOGE(TAG, "Decoder pointer is null!");
36
+ return 0;
37
+ }
38
+ decoder->draw(jpeg->x + x, jpeg->y + y, 1, 1, color);
39
+ }
40
+ }
41
+ return 1;
42
+ }
43
+
44
+ int JpegDecoder::prepare(size_t download_size) {
45
+ ImageDecoder::prepare(download_size);
46
+ auto size = this->image_->resize_download_buffer(download_size);
47
+ if (size < download_size) {
48
+ ESP_LOGE(TAG, "Download buffer resize failed!");
49
+ return DECODE_ERROR_OUT_OF_MEMORY;
50
+ }
51
+ return 0;
52
+ }
53
+
54
+ int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
55
+ if (size < this->download_size_) {
56
+ ESP_LOGV(TAG, "Download not complete. Size: %d/%d", size, this->download_size_);
57
+ return 0;
58
+ }
59
+
60
+ if (!this->jpeg_.openRAM(buffer, size, draw_callback)) {
61
+ ESP_LOGE(TAG, "Could not open image for decoding.");
62
+ return DECODE_ERROR_INVALID_TYPE;
63
+ }
64
+ auto jpeg_type = this->jpeg_.getJPEGType();
65
+ if (jpeg_type == JPEG_MODE_INVALID) {
66
+ ESP_LOGE(TAG, "Unsupported JPEG image");
67
+ return DECODE_ERROR_INVALID_TYPE;
68
+ } else if (jpeg_type == JPEG_MODE_PROGRESSIVE) {
69
+ ESP_LOGE(TAG, "Progressive JPEG images not supported");
70
+ return DECODE_ERROR_INVALID_TYPE;
71
+ }
72
+ ESP_LOGD(TAG, "Image size: %d x %d, bpp: %d", this->jpeg_.getWidth(), this->jpeg_.getHeight(), this->jpeg_.getBpp());
73
+
74
+ this->jpeg_.setUserPointer(this);
75
+ this->jpeg_.setPixelType(RGB8888);
76
+ this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight());
77
+ if (!this->jpeg_.decode(0, 0, 0)) {
78
+ ESP_LOGE(TAG, "Error while decoding.");
79
+ this->jpeg_.close();
80
+ return DECODE_ERROR_UNSUPPORTED_FORMAT;
81
+ }
82
+ this->decoded_bytes_ = size;
83
+ this->jpeg_.close();
84
+ return size;
85
+ }
86
+
87
+ } // namespace online_image
88
+ } // namespace esphome
89
+
90
+ #endif // USE_ONLINE_IMAGE_JPEG_SUPPORT