esphome 2024.7.3__py3-none-any.whl → 2024.8.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 (350) hide show
  1. esphome/__main__.py +15 -81
  2. esphome/automation.py +1 -1
  3. esphome/codegen.py +53 -53
  4. esphome/components/ade7953/sensor.py +1 -1
  5. esphome/components/ade7953_spi/ade7953_spi.cpp +1 -1
  6. esphome/components/airthings_wave_plus/airthings_wave_plus.cpp +5 -2
  7. esphome/components/airthings_wave_plus/airthings_wave_plus.h +2 -0
  8. esphome/components/airthings_wave_plus/sensor.py +12 -0
  9. esphome/components/alarm_control_panel/__init__.py +75 -66
  10. esphome/components/apds9306/__init__.py +4 -0
  11. esphome/components/apds9306/apds9306.cpp +151 -0
  12. esphome/components/apds9306/apds9306.h +66 -0
  13. esphome/components/apds9306/sensor.py +95 -0
  14. esphome/components/api/__init__.py +80 -52
  15. esphome/components/api/api_connection.cpp +14 -1
  16. esphome/components/api/api_pb2.cpp +33 -4
  17. esphome/components/api/api_pb2.h +8 -1
  18. esphome/components/api/api_server.cpp +10 -0
  19. esphome/components/api/api_server.h +3 -0
  20. esphome/components/atm90e32/__init__.py +7 -0
  21. esphome/components/atm90e32/atm90e32.cpp +68 -16
  22. esphome/components/atm90e32/atm90e32.h +20 -7
  23. esphome/components/atm90e32/atm90e32_reg.h +2 -0
  24. esphome/components/atm90e32/button/__init__.py +43 -0
  25. esphome/components/atm90e32/button/atm90e32_button.cpp +20 -0
  26. esphome/components/atm90e32/button/atm90e32_button.h +27 -0
  27. esphome/components/atm90e32/sensor.py +15 -11
  28. esphome/components/bedjet/bedjet_codec.h +1 -1
  29. esphome/components/binary/light/binary_light_output.h +3 -2
  30. esphome/components/binary_sensor/__init__.py +5 -5
  31. esphome/components/ble_client/__init__.py +3 -3
  32. esphome/components/ble_client/output/__init__.py +1 -1
  33. esphome/components/ble_client/sensor/__init__.py +4 -3
  34. esphome/components/ble_client/switch/__init__.py +2 -1
  35. esphome/components/ble_client/text_sensor/__init__.py +4 -3
  36. esphome/components/ble_presence/binary_sensor.py +3 -3
  37. esphome/components/ble_rssi/sensor.py +2 -2
  38. esphome/components/ble_scanner/text_sensor.py +1 -1
  39. esphome/components/bluetooth_proxy/__init__.py +3 -3
  40. esphome/components/bme68x_bsec2/__init__.py +196 -0
  41. esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +523 -0
  42. esphome/components/bme68x_bsec2/bme68x_bsec2.h +163 -0
  43. esphome/components/bme68x_bsec2/sensor.py +130 -0
  44. esphome/components/bme68x_bsec2/text_sensor.py +33 -0
  45. esphome/components/bme68x_bsec2_i2c/__init__.py +28 -0
  46. esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.cpp +53 -0
  47. esphome/components/bme68x_bsec2_i2c/bme68x_bsec2_i2c.h +28 -0
  48. esphome/components/bmp3xx/sensor.py +1 -1
  49. esphome/components/button/__init__.py +4 -4
  50. esphome/components/climate/__init__.py +5 -5
  51. esphome/components/climate/climate.h +1 -1
  52. esphome/components/cover/__init__.py +8 -8
  53. esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +11 -7
  54. esphome/components/cst226/touchscreen/cst226_touchscreen.h +1 -1
  55. esphome/components/datetime/__init__.py +11 -13
  56. esphome/components/demo/demo_sensor.h +3 -2
  57. esphome/components/display/display.cpp +31 -0
  58. esphome/components/display/display.h +3 -0
  59. esphome/components/display_menu_base/__init__.py +14 -13
  60. esphome/components/ens160/sensor.py +1 -1
  61. esphome/components/esp32/__init__.py +22 -10
  62. esphome/components/esp32/boards.py +1 -1
  63. esphome/components/esp32/gpio.py +12 -13
  64. esphome/components/esp32/gpio_esp32.py +1 -2
  65. esphome/components/esp32/gpio_esp32_c2.py +1 -2
  66. esphome/components/esp32/gpio_esp32_c3.py +1 -5
  67. esphome/components/esp32/gpio_esp32_c6.py +1 -2
  68. esphome/components/esp32/gpio_esp32_h2.py +1 -2
  69. esphome/components/esp32/gpio_esp32_s2.py +1 -2
  70. esphome/components/esp32/gpio_esp32_s3.py +1 -6
  71. esphome/components/esp32_ble/__init__.py +20 -3
  72. esphome/components/esp32_ble/ble.cpp +9 -1
  73. esphome/components/esp32_ble/ble.h +9 -0
  74. esphome/components/esp32_ble/ble_advertising.cpp +42 -9
  75. esphome/components/esp32_ble/ble_advertising.h +21 -1
  76. esphome/components/esp32_ble_beacon/__init__.py +17 -7
  77. esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +45 -113
  78. esphome/components/esp32_ble_beacon/esp32_ble_beacon.h +17 -19
  79. esphome/components/esp32_ble_client/__init__.py +0 -1
  80. esphome/components/esp32_ble_server/__init__.py +2 -3
  81. esphome/components/esp32_ble_tracker/__init__.py +2 -2
  82. esphome/components/esp32_improv/__init__.py +2 -4
  83. esphome/components/ethernet/__init__.py +17 -17
  84. esphome/components/ethernet_info/text_sensor.py +2 -2
  85. esphome/components/event/__init__.py +5 -5
  86. esphome/components/fan/__init__.py +14 -14
  87. esphome/components/fan/fan.cpp +2 -2
  88. esphome/components/fingerprint_grow/fingerprint_grow.cpp +1 -1
  89. esphome/components/fingerprint_grow/fingerprint_grow.h +1 -1
  90. esphome/components/graphical_display_menu/__init__.py +11 -8
  91. esphome/components/haier/haier_base.h +2 -2
  92. esphome/components/homeassistant/__init__.py +8 -1
  93. esphome/components/homeassistant/number/__init__.py +33 -0
  94. esphome/components/homeassistant/number/homeassistant_number.cpp +100 -0
  95. esphome/components/homeassistant/number/homeassistant_number.h +31 -0
  96. esphome/components/homeassistant/switch/__init__.py +30 -0
  97. esphome/components/homeassistant/switch/homeassistant_switch.cpp +59 -0
  98. esphome/components/homeassistant/switch/homeassistant_switch.h +22 -0
  99. esphome/components/host/__init__.py +3 -7
  100. esphome/components/http_request/__init__.py +12 -1
  101. esphome/components/http_request/http_request_arduino.cpp +2 -2
  102. esphome/components/http_request/http_request_idf.cpp +11 -2
  103. esphome/components/http_request/http_request_idf.h +10 -0
  104. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  105. esphome/components/http_request/update/http_request_update.cpp +2 -2
  106. esphome/components/http_request/update/http_request_update.h +2 -1
  107. esphome/components/hx711/hx711.cpp +10 -1
  108. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +1 -1
  109. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +11 -2
  110. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +2 -0
  111. esphome/components/ili9xxx/ili9xxx_defines.h +3 -1
  112. esphome/components/ili9xxx/ili9xxx_display.cpp +9 -22
  113. esphome/components/ili9xxx/ili9xxx_display.h +5 -7
  114. esphome/components/ili9xxx/ili9xxx_init.h +4 -4
  115. esphome/components/improv_base/__init__.py +2 -3
  116. esphome/components/improv_serial/__init__.py +4 -10
  117. esphome/components/improv_serial/improv_serial_component.cpp +4 -0
  118. esphome/components/jsn_sr04t/jsn_sr04t.cpp +18 -1
  119. esphome/components/jsn_sr04t/jsn_sr04t.h +7 -1
  120. esphome/components/jsn_sr04t/sensor.py +13 -0
  121. esphome/components/kalman_combinator/sensor.py +1 -1
  122. esphome/components/light/__init__.py +16 -15
  123. esphome/components/light/addressable_light_effect.h +12 -8
  124. esphome/components/light/automation.h +16 -1
  125. esphome/components/light/automation.py +21 -0
  126. esphome/components/light/base_light_effects.h +5 -5
  127. esphome/components/light/esp_color_correction.h +8 -8
  128. esphome/components/light/types.py +7 -0
  129. esphome/components/lock/__init__.py +3 -3
  130. esphome/components/logger/__init__.py +15 -18
  131. esphome/components/lvgl/__init__.py +346 -0
  132. esphome/components/lvgl/automation.py +226 -0
  133. esphome/components/lvgl/binary_sensor/__init__.py +43 -0
  134. esphome/components/lvgl/defines.py +508 -0
  135. esphome/components/lvgl/encoders.py +77 -0
  136. esphome/components/lvgl/font.cpp +76 -0
  137. esphome/components/lvgl/helpers.py +49 -0
  138. esphome/components/lvgl/light/__init__.py +32 -0
  139. esphome/components/lvgl/light/lvgl_light.h +48 -0
  140. esphome/components/lvgl/lv_validation.py +303 -0
  141. esphome/components/lvgl/lvcode.py +349 -0
  142. esphome/components/lvgl/lvgl_esphome.cpp +407 -0
  143. esphome/components/lvgl/lvgl_esphome.h +274 -0
  144. esphome/components/lvgl/lvgl_hal.h +21 -0
  145. esphome/components/lvgl/number/__init__.py +66 -0
  146. esphome/components/lvgl/number/lvgl_number.h +34 -0
  147. esphome/components/lvgl/schemas.py +436 -0
  148. esphome/components/lvgl/select/__init__.py +55 -0
  149. esphome/components/lvgl/select/lvgl_select.h +62 -0
  150. esphome/components/lvgl/sensor/__init__.py +47 -0
  151. esphome/components/lvgl/styles.py +58 -0
  152. esphome/components/lvgl/switch/__init__.py +56 -0
  153. esphome/components/lvgl/switch/lvgl_switch.h +34 -0
  154. esphome/components/lvgl/text/__init__.py +50 -0
  155. esphome/components/lvgl/text/lvgl_text.h +34 -0
  156. esphome/components/lvgl/text_sensor/__init__.py +42 -0
  157. esphome/components/lvgl/touchscreens.py +45 -0
  158. esphome/components/lvgl/trigger.py +74 -0
  159. esphome/components/lvgl/types.py +191 -0
  160. esphome/components/lvgl/widgets/__init__.py +419 -0
  161. esphome/components/lvgl/widgets/animimg.py +117 -0
  162. esphome/components/lvgl/widgets/arc.py +78 -0
  163. esphome/components/lvgl/widgets/button.py +20 -0
  164. esphome/components/lvgl/widgets/buttonmatrix.py +275 -0
  165. esphome/components/lvgl/widgets/checkbox.py +27 -0
  166. esphome/components/lvgl/widgets/dropdown.py +76 -0
  167. esphome/components/lvgl/widgets/img.py +85 -0
  168. esphome/components/lvgl/widgets/keyboard.py +49 -0
  169. esphome/components/lvgl/widgets/label.py +42 -0
  170. esphome/components/lvgl/widgets/led.py +29 -0
  171. esphome/components/lvgl/widgets/line.py +50 -0
  172. esphome/components/lvgl/widgets/lv_bar.py +55 -0
  173. esphome/components/lvgl/widgets/meter.py +302 -0
  174. esphome/components/lvgl/widgets/msgbox.py +134 -0
  175. esphome/components/lvgl/widgets/obj.py +28 -0
  176. esphome/components/lvgl/widgets/page.py +113 -0
  177. esphome/components/lvgl/widgets/roller.py +77 -0
  178. esphome/components/lvgl/widgets/slider.py +63 -0
  179. esphome/components/lvgl/widgets/spinbox.py +178 -0
  180. esphome/components/lvgl/widgets/spinner.py +43 -0
  181. esphome/components/lvgl/widgets/switch.py +20 -0
  182. esphome/components/lvgl/widgets/tabview.py +114 -0
  183. esphome/components/lvgl/widgets/textarea.py +66 -0
  184. esphome/components/lvgl/widgets/tileview.py +128 -0
  185. esphome/components/m5stack_8angle/__init__.py +33 -0
  186. esphome/components/m5stack_8angle/binary_sensor/__init__.py +30 -0
  187. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +17 -0
  188. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.h +19 -0
  189. esphome/components/m5stack_8angle/light/__init__.py +31 -0
  190. esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +45 -0
  191. esphome/components/m5stack_8angle/light/m5stack_8angle_light.h +37 -0
  192. esphome/components/m5stack_8angle/m5stack_8angle.cpp +74 -0
  193. esphome/components/m5stack_8angle/m5stack_8angle.h +34 -0
  194. esphome/components/m5stack_8angle/sensor/__init__.py +66 -0
  195. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +24 -0
  196. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.h +27 -0
  197. esphome/components/matrix_keypad/matrix_keypad.cpp +2 -0
  198. esphome/components/max31856/sensor.py +5 -5
  199. esphome/components/media_player/__init__.py +3 -5
  200. esphome/components/media_player/automation.h +31 -27
  201. esphome/components/micro_wake_word/__init__.py +20 -25
  202. esphome/components/microphone/microphone.h +4 -1
  203. esphome/components/modbus_controller/__init__.py +26 -2
  204. esphome/components/modbus_controller/automation.h +19 -0
  205. esphome/components/modbus_controller/const.py +1 -0
  206. esphome/components/modbus_controller/modbus_controller.cpp +8 -0
  207. esphome/components/modbus_controller/modbus_controller.h +3 -0
  208. esphome/components/mqtt/__init__.py +20 -9
  209. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +128 -0
  210. esphome/components/mqtt/mqtt_alarm_control_panel.h +39 -0
  211. esphome/components/mqtt/mqtt_backend.h +3 -1
  212. esphome/components/mqtt/mqtt_backend_esp32.cpp +4 -1
  213. esphome/components/mqtt/mqtt_backend_esp32.h +3 -1
  214. esphome/components/mqtt/mqtt_backend_esp8266.h +3 -1
  215. esphome/components/mqtt/mqtt_backend_libretiny.h +3 -1
  216. esphome/components/mqtt/mqtt_client.cpp +16 -3
  217. esphome/components/mqtt/mqtt_client.h +5 -1
  218. esphome/components/mqtt/mqtt_component.cpp +32 -4
  219. esphome/components/mqtt/mqtt_const.h +2 -0
  220. esphome/components/network/__init__.py +15 -12
  221. esphome/components/network/ip_address.h +3 -0
  222. esphome/components/network/util.cpp +2 -1
  223. esphome/components/network/util.h +3 -1
  224. esphome/components/nextion/base_component.py +5 -8
  225. esphome/components/number/__init__.py +7 -8
  226. esphome/components/online_image/__init__.py +167 -0
  227. esphome/components/online_image/image_decoder.cpp +44 -0
  228. esphome/components/online_image/image_decoder.h +112 -0
  229. esphome/components/online_image/online_image.cpp +283 -0
  230. esphome/components/online_image/online_image.h +195 -0
  231. esphome/components/online_image/png_image.cpp +68 -0
  232. esphome/components/online_image/png_image.h +33 -0
  233. esphome/components/ota/__init__.py +8 -4
  234. esphome/components/pid/pid_climate.h +2 -0
  235. esphome/components/remote_base/pronto_protocol.cpp +0 -3
  236. esphome/components/remote_transmitter/remote_transmitter.h +1 -1
  237. esphome/components/rgbct/rgbct_light_output.h +3 -2
  238. esphome/components/rgbw/rgbw_light_output.h +3 -2
  239. esphome/components/rgbww/rgbww_light_output.h +3 -2
  240. esphome/components/rp2040_pio_led_strip/led_strip.cpp +31 -5
  241. esphome/components/rp2040_pio_led_strip/led_strip.h +5 -0
  242. esphome/components/rtttl/rtttl.cpp +108 -21
  243. esphome/components/rtttl/rtttl.h +15 -6
  244. esphome/components/select/__init__.py +7 -7
  245. esphome/components/sensor/__init__.py +29 -10
  246. esphome/components/sensor/filter.cpp +8 -0
  247. esphome/components/sensor/filter.h +9 -0
  248. esphome/components/sml/sml_parser.cpp +48 -22
  249. esphome/components/socket/socket.cpp +11 -14
  250. esphome/components/speaker/__init__.py +14 -5
  251. esphome/components/speaker/automation.h +10 -0
  252. esphome/components/speaker/speaker.h +9 -0
  253. esphome/components/spi/spi.cpp +0 -6
  254. esphome/components/spi/spi.h +2 -19
  255. esphome/components/spi_led_strip/spi_led_strip.h +5 -4
  256. esphome/components/sprinkler/sprinkler.cpp +2 -2
  257. esphome/components/sprinkler/sprinkler.h +1 -1
  258. esphome/components/switch/__init__.py +3 -3
  259. esphome/components/text/__init__.py +5 -5
  260. esphome/components/text_sensor/__init__.py +7 -7
  261. esphome/components/time/__init__.py +8 -8
  262. esphome/components/touchscreen/binary_sensor/__init__.py +24 -10
  263. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp +3 -2
  264. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h +4 -2
  265. esphome/components/uart/uart_component_host.cpp +6 -2
  266. esphome/components/update/__init__.py +33 -15
  267. esphome/components/update/automation.h +23 -0
  268. esphome/components/update/update_entity.h +3 -1
  269. esphome/components/valve/__init__.py +3 -3
  270. esphome/components/voice_assistant/__init__.py +7 -8
  271. esphome/components/wake_on_lan/wake_on_lan.cpp +2 -0
  272. esphome/components/wake_on_lan/wake_on_lan.h +3 -1
  273. esphome/components/watchdog/__init__.py +1 -0
  274. esphome/components/{http_request → watchdog}/watchdog.cpp +0 -2
  275. esphome/components/{http_request → watchdog}/watchdog.h +0 -2
  276. esphome/components/waveshare_epaper/waveshare_epaper.cpp +5 -5
  277. esphome/components/web_server/server_index_v3.h +3615 -3603
  278. esphome/components/web_server/web_server.cpp +0 -209
  279. esphome/components/web_server/web_server.h +1 -1
  280. esphome/components/web_server/web_server_v1.cpp +217 -0
  281. esphome/components/web_server_base/web_server_base.h +1 -0
  282. esphome/components/wifi/__init__.py +15 -14
  283. esphome/components/wifi/wifi_component.cpp +2 -0
  284. esphome/components/wifi/wifi_component.h +7 -1
  285. esphome/components/wifi/wifi_component_esp32_arduino.cpp +5 -2
  286. esphome/components/wifi/wifi_component_esp8266.cpp +2 -0
  287. esphome/components/wifi/wifi_component_esp_idf.cpp +43 -7
  288. esphome/components/wifi/wifi_component_libretiny.cpp +2 -0
  289. esphome/components/wifi/wifi_component_pico_w.cpp +2 -0
  290. esphome/components/wifi/wpa2_eap.py +6 -7
  291. esphome/components/wifi_info/text_sensor.py +3 -3
  292. esphome/components/wifi_info/wifi_info_text_sensor.cpp +2 -0
  293. esphome/components/wifi_info/wifi_info_text_sensor.h +2 -0
  294. esphome/components/wifi_signal/sensor.py +1 -1
  295. esphome/components/wifi_signal/wifi_signal_sensor.cpp +2 -0
  296. esphome/components/wifi_signal/wifi_signal_sensor.h +2 -1
  297. esphome/components/xiaomi_ble/xiaomi_ble.cpp +20 -3
  298. esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
  299. esphome/components/xiaomi_lywsd02mmc/__init__.py +0 -0
  300. esphome/components/xiaomi_lywsd02mmc/sensor.py +77 -0
  301. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp +73 -0
  302. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +37 -0
  303. esphome/config.py +17 -19
  304. esphome/config_validation.py +55 -23
  305. esphome/const.py +25 -9
  306. esphome/core/__init__.py +17 -14
  307. esphome/core/application.h +42 -21
  308. esphome/core/automation.h +5 -3
  309. esphome/core/base_automation.h +3 -2
  310. esphome/core/bytebuffer.cpp +134 -0
  311. esphome/core/bytebuffer.h +96 -0
  312. esphome/core/color.h +24 -16
  313. esphome/core/config.py +3 -3
  314. esphome/core/defines.h +14 -1
  315. esphome/core/entity_base.h +2 -2
  316. esphome/core/entity_helpers.py +1 -2
  317. esphome/core/gpio.h +0 -18
  318. esphome/core/helpers.h +1 -1
  319. esphome/core/optional.h +15 -16
  320. esphome/coroutine.py +1 -1
  321. esphome/cpp_generator.py +1 -1
  322. esphome/cpp_helpers.py +3 -5
  323. esphome/dashboard/core.py +3 -3
  324. esphome/dashboard/dashboard.py +3 -3
  325. esphome/dashboard/entries.py +1 -1
  326. esphome/dashboard/util/file.py +1 -1
  327. esphome/dashboard/web_server.py +3 -3
  328. esphome/external_files.py +5 -3
  329. esphome/final_validate.py +2 -2
  330. esphome/git.py +4 -4
  331. esphome/helpers.py +5 -5
  332. esphome/loader.py +15 -10
  333. esphome/mqtt.py +4 -8
  334. esphome/pins.py +6 -6
  335. esphome/platformio_api.py +5 -5
  336. esphome/storage_json.py +2 -1
  337. esphome/types.py +1 -1
  338. esphome/util.py +2 -3
  339. esphome/voluptuous_schema.py +1 -0
  340. esphome/vscode.py +5 -4
  341. esphome/wizard.py +1 -1
  342. esphome/writer.py +7 -7
  343. esphome/yaml_util.py +3 -3
  344. esphome/zeroconf.py +1 -1
  345. {esphome-2024.7.3.dist-info → esphome-2024.8.0.dist-info}/METADATA +3 -3
  346. {esphome-2024.7.3.dist-info → esphome-2024.8.0.dist-info}/RECORD +350 -244
  347. {esphome-2024.7.3.dist-info → esphome-2024.8.0.dist-info}/LICENSE +0 -0
  348. {esphome-2024.7.3.dist-info → esphome-2024.8.0.dist-info}/WHEEL +0 -0
  349. {esphome-2024.7.3.dist-info → esphome-2024.8.0.dist-info}/entry_points.txt +0 -0
  350. {esphome-2024.7.3.dist-info → esphome-2024.8.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  #include "util.h"
2
2
  #include "esphome/core/defines.h"
3
-
3
+ #ifdef USE_NETWORK
4
4
  #ifdef USE_WIFI
5
5
  #include "esphome/components/wifi/wifi_component.h"
6
6
  #endif
@@ -63,3 +63,4 @@ std::string get_use_address() {
63
63
 
64
64
  } // namespace network
65
65
  } // namespace esphome
66
+ #endif
@@ -1,5 +1,6 @@
1
1
  #pragma once
2
-
2
+ #include "esphome/core/defines.h"
3
+ #ifdef USE_NETWORK
3
4
  #include <string>
4
5
  #include "ip_address.h"
5
6
 
@@ -16,3 +17,4 @@ IPAddresses get_ip_addresses();
16
17
 
17
18
  } // namespace network
18
19
  } // namespace esphome
20
+ #endif
@@ -1,12 +1,11 @@
1
1
  from string import ascii_letters, digits
2
- import esphome.config_validation as cv
2
+
3
3
  import esphome.codegen as cg
4
4
  from esphome.components import color
5
- from esphome.const import (
6
- CONF_VISIBLE,
7
- )
8
- from . import CONF_NEXTION_ID
9
- from . import Nextion
5
+ import esphome.config_validation as cv
6
+ from esphome.const import CONF_BACKGROUND_COLOR, CONF_FOREGROUND_COLOR, CONF_VISIBLE
7
+
8
+ from . import CONF_NEXTION_ID, Nextion
10
9
 
11
10
  CONF_VARIABLE_NAME = "variable_name"
12
11
  CONF_COMPONENT_NAME = "component_name"
@@ -24,9 +23,7 @@ CONF_WAKE_UP_PAGE = "wake_up_page"
24
23
  CONF_START_UP_PAGE = "start_up_page"
25
24
  CONF_AUTO_WAKE_ON_TOUCH = "auto_wake_on_touch"
26
25
  CONF_WAVE_MAX_LENGTH = "wave_max_length"
27
- CONF_BACKGROUND_COLOR = "background_color"
28
26
  CONF_BACKGROUND_PRESSED_COLOR = "background_pressed_color"
29
- CONF_FOREGROUND_COLOR = "foreground_color"
30
27
  CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color"
31
28
  CONF_FONT_ID = "font_id"
32
29
  CONF_EXIT_REPARSE_ON_START = "exit_reparse_on_start"
@@ -1,24 +1,23 @@
1
+ from esphome import automation
1
2
  import esphome.codegen as cg
3
+ from esphome.components import mqtt, web_server
2
4
  import esphome.config_validation as cv
3
- from esphome import automation
4
- from esphome.components import mqtt
5
- from esphome.components import web_server
6
5
  from esphome.const import (
7
6
  CONF_ABOVE,
8
7
  CONF_BELOW,
8
+ CONF_CYCLE,
9
9
  CONF_DEVICE_CLASS,
10
10
  CONF_ENTITY_CATEGORY,
11
- CONF_ID,
12
11
  CONF_ICON,
12
+ CONF_ID,
13
13
  CONF_MODE,
14
+ CONF_MQTT_ID,
14
15
  CONF_ON_VALUE,
15
16
  CONF_ON_VALUE_RANGE,
17
+ CONF_OPERATION,
16
18
  CONF_TRIGGER_ID,
17
19
  CONF_UNIT_OF_MEASUREMENT,
18
- CONF_MQTT_ID,
19
20
  CONF_VALUE,
20
- CONF_OPERATION,
21
- CONF_CYCLE,
22
21
  CONF_WEB_SERVER_ID,
23
22
  DEVICE_CLASS_APPARENT_POWER,
24
23
  DEVICE_CLASS_AQI,
@@ -72,8 +71,8 @@ from esphome.const import (
72
71
  DEVICE_CLASS_WIND_SPEED,
73
72
  )
74
73
  from esphome.core import CORE, coroutine_with_priority
75
- from esphome.cpp_helpers import setup_entity
76
74
  from esphome.cpp_generator import MockObjClass
75
+ from esphome.cpp_helpers import setup_entity
77
76
 
78
77
  CODEOWNERS = ["@esphome/core"]
79
78
  DEVICE_CLASSES = [
@@ -0,0 +1,167 @@
1
+ import logging
2
+
3
+ from esphome import automation
4
+ import esphome.codegen as cg
5
+ from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent
6
+ from esphome.components.image import (
7
+ CONF_USE_TRANSPARENCY,
8
+ IMAGE_TYPE,
9
+ Image_,
10
+ validate_cross_dependencies,
11
+ )
12
+ import esphome.config_validation as cv
13
+ from esphome.const import (
14
+ CONF_BUFFER_SIZE,
15
+ CONF_FORMAT,
16
+ CONF_ID,
17
+ CONF_ON_ERROR,
18
+ CONF_RESIZE,
19
+ CONF_TRIGGER_ID,
20
+ CONF_TYPE,
21
+ CONF_URL,
22
+ )
23
+
24
+ AUTO_LOAD = ["image"]
25
+ DEPENDENCIES = ["display", "http_request"]
26
+ CODEOWNERS = ["@guillempages"]
27
+ MULTI_CONF = True
28
+
29
+ CONF_ON_DOWNLOAD_FINISHED = "on_download_finished"
30
+ CONF_PLACEHOLDER = "placeholder"
31
+
32
+ _LOGGER = logging.getLogger(__name__)
33
+
34
+ online_image_ns = cg.esphome_ns.namespace("online_image")
35
+
36
+ ImageFormat = online_image_ns.enum("ImageFormat")
37
+
38
+ FORMAT_PNG = "PNG"
39
+
40
+ IMAGE_FORMAT = {FORMAT_PNG: ImageFormat.PNG} # Add new supported formats here
41
+
42
+ OnlineImage = online_image_ns.class_("OnlineImage", cg.PollingComponent, Image_)
43
+
44
+ # Actions
45
+ SetUrlAction = online_image_ns.class_(
46
+ "OnlineImageSetUrlAction", automation.Action, cg.Parented.template(OnlineImage)
47
+ )
48
+ ReleaseImageAction = online_image_ns.class_(
49
+ "OnlineImageReleaseAction", automation.Action, cg.Parented.template(OnlineImage)
50
+ )
51
+
52
+ # Triggers
53
+ DownloadFinishedTrigger = online_image_ns.class_(
54
+ "DownloadFinishedTrigger", automation.Trigger.template()
55
+ )
56
+ DownloadErrorTrigger = online_image_ns.class_(
57
+ "DownloadErrorTrigger", automation.Trigger.template()
58
+ )
59
+
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
+ ),
89
+ }
90
+ ).extend(cv.polling_component_schema("never"))
91
+
92
+ CONFIG_SCHEMA = cv.Schema(
93
+ cv.All(
94
+ ONLINE_IMAGE_SCHEMA,
95
+ validate_cross_dependencies,
96
+ cv.require_framework_version(
97
+ # esp8266 not supported yet; if enabled in the future, minimum version of 2.7.0 is needed
98
+ # esp8266_arduino=cv.Version(2, 7, 0),
99
+ esp32_arduino=cv.Version(0, 0, 0),
100
+ esp_idf=cv.Version(4, 0, 0),
101
+ ),
102
+ )
103
+ )
104
+
105
+ SET_URL_SCHEMA = cv.Schema(
106
+ {
107
+ cv.GenerateID(): cv.use_id(OnlineImage),
108
+ cv.Required(CONF_URL): cv.templatable(cv.url),
109
+ }
110
+ )
111
+
112
+ RELEASE_IMAGE_SCHEMA = automation.maybe_simple_id(
113
+ {
114
+ cv.GenerateID(): cv.use_id(OnlineImage),
115
+ }
116
+ )
117
+
118
+
119
+ @automation.register_action("online_image.set_url", SetUrlAction, SET_URL_SCHEMA)
120
+ @automation.register_action(
121
+ "online_image.release", ReleaseImageAction, RELEASE_IMAGE_SCHEMA
122
+ )
123
+ async def online_image_action_to_code(config, action_id, template_arg, args):
124
+ paren = await cg.get_variable(config[CONF_ID])
125
+ var = cg.new_Pvariable(action_id, template_arg, paren)
126
+
127
+ if CONF_URL in config:
128
+ template_ = await cg.templatable(config[CONF_URL], args, cg.const_char_ptr)
129
+ cg.add(var.set_url(template_))
130
+ return var
131
+
132
+
133
+ async def to_code(config):
134
+ format = config[CONF_FORMAT]
135
+ if format in [FORMAT_PNG]:
136
+ cg.add_define("USE_ONLINE_IMAGE_PNG_SUPPORT")
137
+ cg.add_library("pngle", "1.0.2")
138
+
139
+ url = config[CONF_URL]
140
+ width, height = config.get(CONF_RESIZE, (0, 0))
141
+ transparent = config[CONF_USE_TRANSPARENCY]
142
+
143
+ var = cg.new_Pvariable(
144
+ config[CONF_ID],
145
+ url,
146
+ width,
147
+ height,
148
+ format,
149
+ config[CONF_TYPE],
150
+ config[CONF_BUFFER_SIZE],
151
+ )
152
+ await cg.register_component(var, config)
153
+ await cg.register_parented(var, config[CONF_HTTP_REQUEST_ID])
154
+
155
+ cg.add(var.set_transparency(transparent))
156
+
157
+ if placeholder_id := config.get(CONF_PLACEHOLDER):
158
+ placeholder = await cg.get_variable(placeholder_id)
159
+ cg.add(var.set_placeholder(placeholder))
160
+
161
+ for conf in config.get(CONF_ON_DOWNLOAD_FINISHED, []):
162
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
163
+ await automation.build_automation(trigger, [], conf)
164
+
165
+ for conf in config.get(CONF_ON_ERROR, []):
166
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
167
+ await automation.build_automation(trigger, [], conf)
@@ -0,0 +1,44 @@
1
+ #include "image_decoder.h"
2
+ #include "online_image.h"
3
+
4
+ #include "esphome/core/log.h"
5
+
6
+ namespace esphome {
7
+ namespace online_image {
8
+
9
+ static const char *const TAG = "online_image.decoder";
10
+
11
+ void ImageDecoder::set_size(int width, int height) {
12
+ this->image_->resize_(width, height);
13
+ this->x_scale_ = static_cast<double>(this->image_->buffer_width_) / width;
14
+ this->y_scale_ = static_cast<double>(this->image_->buffer_height_) / height;
15
+ }
16
+
17
+ void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
18
+ auto width = std::min(this->image_->buffer_width_, static_cast<int>(std::ceil((x + w) * this->x_scale_)));
19
+ auto height = std::min(this->image_->buffer_height_, static_cast<int>(std::ceil((y + h) * this->y_scale_)));
20
+ for (int i = x * this->x_scale_; i < width; i++) {
21
+ for (int j = y * this->y_scale_; j < height; j++) {
22
+ this->image_->draw_pixel_(i, j, color);
23
+ }
24
+ }
25
+ }
26
+
27
+ uint8_t *DownloadBuffer::data(size_t offset) {
28
+ if (offset > this->size_) {
29
+ ESP_LOGE(TAG, "Tried to access beyond download buffer bounds!!!");
30
+ return this->buffer_;
31
+ }
32
+ return this->buffer_ + offset;
33
+ }
34
+
35
+ size_t DownloadBuffer::read(size_t len) {
36
+ this->unread_ -= len;
37
+ if (this->unread_ > 0) {
38
+ memmove(this->data(), this->data(len), this->unread_);
39
+ }
40
+ return this->unread_;
41
+ }
42
+
43
+ } // namespace online_image
44
+ } // namespace esphome
@@ -0,0 +1,112 @@
1
+ #pragma once
2
+ #include "esphome/core/defines.h"
3
+ #include "esphome/core/color.h"
4
+
5
+ namespace esphome {
6
+ namespace online_image {
7
+
8
+ class OnlineImage;
9
+
10
+ /**
11
+ * @brief Class to abstract decoding different image formats.
12
+ */
13
+ class ImageDecoder {
14
+ public:
15
+ /**
16
+ * @brief Construct a new Image Decoder object
17
+ *
18
+ * @param image The image to decode the stream into.
19
+ */
20
+ ImageDecoder(OnlineImage *image) : image_(image) {}
21
+ virtual ~ImageDecoder() = default;
22
+
23
+ /**
24
+ * @brief Initialize the decoder.
25
+ *
26
+ * @param download_size The total number of bytes that need to be download for the image.
27
+ */
28
+ virtual void prepare(uint32_t download_size) { this->download_size_ = download_size; }
29
+
30
+ /**
31
+ * @brief Decode a part of the image. It will try reading from the buffer.
32
+ * There is no guarantee that the whole available buffer will be read/decoded;
33
+ * the method will return the amount of bytes actually decoded, so that the
34
+ * unread content can be moved to the beginning.
35
+ *
36
+ * @param buffer The buffer to read from.
37
+ * @param size The maximum amount of bytes that can be read from the buffer.
38
+ * @return int The amount of bytes read. It can be 0 if the buffer does not have enough content to meaningfully
39
+ * decode anything, or negative in case of a decoding error.
40
+ */
41
+ virtual int decode(uint8_t *buffer, size_t size);
42
+
43
+ /**
44
+ * @brief Request the image to be resized once the actual dimensions are known.
45
+ * Called by the callback functions, to be able to access the parent Image class.
46
+ *
47
+ * @param width The image's width.
48
+ * @param height The image's height.
49
+ */
50
+ void set_size(int width, int height);
51
+
52
+ /**
53
+ * @brief Draw a rectangle on the display_buffer using the defined color.
54
+ * Will check the given coordinates for out-of-bounds, and clip the rectangle accordingly.
55
+ * In case of binary displays, the color will be converted to binary as well.
56
+ * Called by the callback functions, to be able to access the parent Image class.
57
+ *
58
+ * @param x The left-most coordinate of the rectangle.
59
+ * @param y The top-most coordinate of the rectangle.
60
+ * @param w The width of the rectangle.
61
+ * @param h The height of the rectangle.
62
+ * @param color The color to draw the rectangle with.
63
+ */
64
+ void draw(int x, int y, int w, int h, const Color &color);
65
+
66
+ bool is_finished() const { return this->decoded_bytes_ == this->download_size_; }
67
+
68
+ protected:
69
+ OnlineImage *image_;
70
+ // Initializing to 1, to ensure it is different than initial "decoded_bytes_".
71
+ // Will be overwritten anyway once the download size is known.
72
+ uint32_t download_size_ = 1;
73
+ uint32_t decoded_bytes_ = 0;
74
+ double x_scale_ = 1.0;
75
+ double y_scale_ = 1.0;
76
+ };
77
+
78
+ class DownloadBuffer {
79
+ public:
80
+ DownloadBuffer(size_t size) : size_(size) {
81
+ this->buffer_ = this->allocator_.allocate(size);
82
+ this->reset();
83
+ }
84
+
85
+ virtual ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); }
86
+
87
+ uint8_t *data(size_t offset = 0);
88
+
89
+ uint8_t *append() { return this->data(this->unread_); }
90
+
91
+ size_t unread() const { return this->unread_; }
92
+ size_t size() const { return this->size_; }
93
+ size_t free_capacity() const { return this->size_ - this->unread_; }
94
+
95
+ size_t read(size_t len);
96
+ size_t write(size_t len) {
97
+ this->unread_ += len;
98
+ return this->unread_;
99
+ }
100
+
101
+ void reset() { this->unread_ = 0; }
102
+
103
+ protected:
104
+ ExternalRAMAllocator<uint8_t> allocator_;
105
+ uint8_t *buffer_;
106
+ size_t size_;
107
+ /** Total number of downloaded bytes not yet read. */
108
+ size_t unread_;
109
+ };
110
+
111
+ } // namespace online_image
112
+ } // namespace esphome
@@ -0,0 +1,283 @@
1
+ #include "online_image.h"
2
+
3
+ #include "esphome/core/log.h"
4
+
5
+ static const char *const TAG = "online_image";
6
+
7
+ #include "image_decoder.h"
8
+
9
+ #ifdef USE_ONLINE_IMAGE_PNG_SUPPORT
10
+ #include "png_image.h"
11
+ #endif
12
+
13
+ namespace esphome {
14
+ namespace online_image {
15
+
16
+ using image::ImageType;
17
+
18
+ inline bool is_color_on(const Color &color) {
19
+ // This produces the most accurate monochrome conversion, but is slightly slower.
20
+ // return (0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b) > 127;
21
+
22
+ // Approximation using fast integer computations; produces acceptable results
23
+ // Equivalent to 0.25 * R + 0.5 * G + 0.25 * B
24
+ return ((color.r >> 2) + (color.g >> 1) + (color.b >> 2)) & 0x80;
25
+ }
26
+
27
+ OnlineImage::OnlineImage(const std::string &url, int width, int height, ImageFormat format, ImageType type,
28
+ uint32_t download_buffer_size)
29
+ : Image(nullptr, 0, 0, type),
30
+ buffer_(nullptr),
31
+ download_buffer_(download_buffer_size),
32
+ format_(format),
33
+ fixed_width_(width),
34
+ fixed_height_(height) {
35
+ this->set_url(url);
36
+ }
37
+
38
+ void OnlineImage::draw(int x, int y, display::Display *display, Color color_on, Color color_off) {
39
+ if (this->data_start_) {
40
+ Image::draw(x, y, display, color_on, color_off);
41
+ } else if (this->placeholder_) {
42
+ this->placeholder_->draw(x, y, display, color_on, color_off);
43
+ }
44
+ }
45
+
46
+ void OnlineImage::release() {
47
+ if (this->buffer_) {
48
+ ESP_LOGD(TAG, "Deallocating old buffer...");
49
+ this->allocator_.deallocate(this->buffer_, this->get_buffer_size_());
50
+ this->data_start_ = nullptr;
51
+ this->buffer_ = nullptr;
52
+ this->width_ = 0;
53
+ this->height_ = 0;
54
+ this->buffer_width_ = 0;
55
+ this->buffer_height_ = 0;
56
+ this->end_connection_();
57
+ }
58
+ }
59
+
60
+ bool OnlineImage::resize_(int width_in, int height_in) {
61
+ int width = this->fixed_width_;
62
+ int height = this->fixed_height_;
63
+ if (this->auto_resize_()) {
64
+ width = width_in;
65
+ height = height_in;
66
+ if (this->width_ != width && this->height_ != height) {
67
+ this->release();
68
+ }
69
+ }
70
+ if (this->buffer_) {
71
+ return false;
72
+ }
73
+ auto new_size = this->get_buffer_size_(width, height);
74
+ ESP_LOGD(TAG, "Allocating new buffer of %d Bytes...", new_size);
75
+ delay_microseconds_safe(2000);
76
+ this->buffer_ = this->allocator_.allocate(new_size);
77
+ if (this->buffer_) {
78
+ this->buffer_width_ = width;
79
+ this->buffer_height_ = height;
80
+ this->width_ = width;
81
+ ESP_LOGD(TAG, "New size: (%d, %d)", width, height);
82
+ } else {
83
+ #if defined(USE_ESP8266)
84
+ // NOLINTNEXTLINE(readability-static-accessed-through-instance)
85
+ int max_block = ESP.getMaxFreeBlockSize();
86
+ #elif defined(USE_ESP32)
87
+ int max_block = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
88
+ #else
89
+ int max_block = -1;
90
+ #endif
91
+ ESP_LOGE(TAG, "allocation failed. Biggest block in heap: %d Bytes", max_block);
92
+ this->end_connection_();
93
+ return false;
94
+ }
95
+ return true;
96
+ }
97
+
98
+ void OnlineImage::update() {
99
+ if (this->decoder_) {
100
+ ESP_LOGW(TAG, "Image already being updated.");
101
+ return;
102
+ } else {
103
+ ESP_LOGI(TAG, "Updating image");
104
+ }
105
+
106
+ this->downloader_ = this->parent_->get(this->url_);
107
+
108
+ if (this->downloader_ == nullptr) {
109
+ ESP_LOGE(TAG, "Download failed.");
110
+ this->end_connection_();
111
+ this->download_error_callback_.call();
112
+ return;
113
+ }
114
+
115
+ int http_code = this->downloader_->status_code;
116
+ if (http_code == HTTP_CODE_NOT_MODIFIED) {
117
+ // Image hasn't changed on server. Skip download.
118
+ this->end_connection_();
119
+ return;
120
+ }
121
+ if (http_code != HTTP_CODE_OK) {
122
+ ESP_LOGE(TAG, "HTTP result: %d", http_code);
123
+ this->end_connection_();
124
+ this->download_error_callback_.call();
125
+ return;
126
+ }
127
+
128
+ ESP_LOGD(TAG, "Starting download");
129
+ size_t total_size = this->downloader_->content_length;
130
+
131
+ #ifdef USE_ONLINE_IMAGE_PNG_SUPPORT
132
+ if (this->format_ == ImageFormat::PNG) {
133
+ this->decoder_ = esphome::make_unique<PngDecoder>(this);
134
+ }
135
+ #endif // ONLINE_IMAGE_PNG_SUPPORT
136
+
137
+ if (!this->decoder_) {
138
+ ESP_LOGE(TAG, "Could not instantiate decoder. Image format unsupported.");
139
+ this->end_connection_();
140
+ this->download_error_callback_.call();
141
+ return;
142
+ }
143
+ this->decoder_->prepare(total_size);
144
+ ESP_LOGI(TAG, "Downloading image");
145
+ }
146
+
147
+ void OnlineImage::loop() {
148
+ if (!this->decoder_) {
149
+ // Not decoding at the moment => nothing to do.
150
+ return;
151
+ }
152
+ if (!this->downloader_ || this->decoder_->is_finished()) {
153
+ ESP_LOGD(TAG, "Image fully downloaded");
154
+ this->data_start_ = buffer_;
155
+ this->width_ = buffer_width_;
156
+ this->height_ = buffer_height_;
157
+ this->end_connection_();
158
+ this->download_finished_callback_.call();
159
+ return;
160
+ }
161
+ if (this->downloader_ == nullptr) {
162
+ ESP_LOGE(TAG, "Downloader not instantiated; cannot download");
163
+ return;
164
+ }
165
+ size_t available = this->download_buffer_.free_capacity();
166
+ if (available) {
167
+ auto len = this->downloader_->read(this->download_buffer_.append(), available);
168
+ if (len > 0) {
169
+ this->download_buffer_.write(len);
170
+ auto fed = this->decoder_->decode(this->download_buffer_.data(), this->download_buffer_.unread());
171
+ if (fed < 0) {
172
+ ESP_LOGE(TAG, "Error when decoding image.");
173
+ this->end_connection_();
174
+ this->download_error_callback_.call();
175
+ return;
176
+ }
177
+ this->download_buffer_.read(fed);
178
+ }
179
+ }
180
+ }
181
+
182
+ void OnlineImage::draw_pixel_(int x, int y, Color color) {
183
+ if (!this->buffer_) {
184
+ ESP_LOGE(TAG, "Buffer not allocated!");
185
+ return;
186
+ }
187
+ if (x < 0 || y < 0 || x >= this->buffer_width_ || y >= this->buffer_height_) {
188
+ ESP_LOGE(TAG, "Tried to paint a pixel (%d,%d) outside the image!", x, y);
189
+ return;
190
+ }
191
+ uint32_t pos = this->get_position_(x, y);
192
+ switch (this->type_) {
193
+ case ImageType::IMAGE_TYPE_BINARY: {
194
+ const uint32_t width_8 = ((this->width_ + 7u) / 8u) * 8u;
195
+ const uint32_t pos = x + y * width_8;
196
+ if ((this->has_transparency() && color.w > 127) || is_color_on(color)) {
197
+ this->buffer_[pos / 8u] |= (0x80 >> (pos % 8u));
198
+ } else {
199
+ this->buffer_[pos / 8u] &= ~(0x80 >> (pos % 8u));
200
+ }
201
+ break;
202
+ }
203
+ case ImageType::IMAGE_TYPE_GRAYSCALE: {
204
+ uint8_t gray = static_cast<uint8_t>(0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b);
205
+ if (this->has_transparency()) {
206
+ if (gray == 1) {
207
+ gray = 0;
208
+ }
209
+ if (color.w < 0x80) {
210
+ gray = 1;
211
+ }
212
+ }
213
+ this->buffer_[pos] = gray;
214
+ break;
215
+ }
216
+ case ImageType::IMAGE_TYPE_RGB565: {
217
+ uint16_t col565 = display::ColorUtil::color_to_565(color);
218
+ if (this->has_transparency()) {
219
+ if (col565 == 0x0020) {
220
+ col565 = 0;
221
+ }
222
+ if (color.w < 0x80) {
223
+ col565 = 0x0020;
224
+ }
225
+ }
226
+ this->buffer_[pos + 0] = static_cast<uint8_t>((col565 >> 8) & 0xFF);
227
+ this->buffer_[pos + 1] = static_cast<uint8_t>(col565 & 0xFF);
228
+ break;
229
+ }
230
+ case ImageType::IMAGE_TYPE_RGBA: {
231
+ this->buffer_[pos + 0] = color.r;
232
+ this->buffer_[pos + 1] = color.g;
233
+ this->buffer_[pos + 2] = color.b;
234
+ this->buffer_[pos + 3] = color.w;
235
+ break;
236
+ }
237
+ case ImageType::IMAGE_TYPE_RGB24:
238
+ default: {
239
+ if (this->has_transparency()) {
240
+ if (color.b == 1 && color.r == 0 && color.g == 0) {
241
+ color.b = 0;
242
+ }
243
+ if (color.w < 0x80) {
244
+ color.r = 0;
245
+ color.g = 0;
246
+ color.b = 1;
247
+ }
248
+ }
249
+ this->buffer_[pos + 0] = color.r;
250
+ this->buffer_[pos + 1] = color.g;
251
+ this->buffer_[pos + 2] = color.b;
252
+ break;
253
+ }
254
+ }
255
+ }
256
+
257
+ void OnlineImage::end_connection_() {
258
+ if (this->downloader_) {
259
+ this->downloader_->end();
260
+ this->downloader_ = nullptr;
261
+ }
262
+ this->decoder_.reset();
263
+ this->download_buffer_.reset();
264
+ }
265
+
266
+ bool OnlineImage::validate_url_(const std::string &url) {
267
+ if ((url.length() < 8) || (url.find("http") != 0) || (url.find("://") == std::string::npos)) {
268
+ ESP_LOGE(TAG, "URL is invalid and/or must be prefixed with 'http://' or 'https://'");
269
+ return false;
270
+ }
271
+ return true;
272
+ }
273
+
274
+ void OnlineImage::add_on_finished_callback(std::function<void()> &&callback) {
275
+ this->download_finished_callback_.add(std::move(callback));
276
+ }
277
+
278
+ void OnlineImage::add_on_error_callback(std::function<void()> &&callback) {
279
+ this->download_error_callback_.add(std::move(callback));
280
+ }
281
+
282
+ } // namespace online_image
283
+ } // namespace esphome