esphome 2024.7.2__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 (353) 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/micro_wake_word/streaming_model.cpp +6 -4
  203. esphome/components/microphone/microphone.h +4 -1
  204. esphome/components/mitsubishi/mitsubishi.cpp +7 -1
  205. esphome/components/modbus_controller/__init__.py +26 -2
  206. esphome/components/modbus_controller/automation.h +19 -0
  207. esphome/components/modbus_controller/const.py +1 -0
  208. esphome/components/modbus_controller/modbus_controller.cpp +8 -0
  209. esphome/components/modbus_controller/modbus_controller.h +3 -0
  210. esphome/components/mqtt/__init__.py +20 -9
  211. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +128 -0
  212. esphome/components/mqtt/mqtt_alarm_control_panel.h +39 -0
  213. esphome/components/mqtt/mqtt_backend.h +3 -1
  214. esphome/components/mqtt/mqtt_backend_esp32.cpp +4 -1
  215. esphome/components/mqtt/mqtt_backend_esp32.h +3 -1
  216. esphome/components/mqtt/mqtt_backend_esp8266.h +3 -1
  217. esphome/components/mqtt/mqtt_backend_libretiny.h +3 -1
  218. esphome/components/mqtt/mqtt_client.cpp +16 -3
  219. esphome/components/mqtt/mqtt_client.h +5 -1
  220. esphome/components/mqtt/mqtt_component.cpp +32 -4
  221. esphome/components/mqtt/mqtt_const.h +2 -0
  222. esphome/components/network/__init__.py +15 -12
  223. esphome/components/network/ip_address.h +3 -0
  224. esphome/components/network/util.cpp +2 -1
  225. esphome/components/network/util.h +3 -1
  226. esphome/components/nextion/base_component.py +5 -8
  227. esphome/components/number/__init__.py +7 -8
  228. esphome/components/online_image/__init__.py +167 -0
  229. esphome/components/online_image/image_decoder.cpp +44 -0
  230. esphome/components/online_image/image_decoder.h +112 -0
  231. esphome/components/online_image/online_image.cpp +283 -0
  232. esphome/components/online_image/online_image.h +195 -0
  233. esphome/components/online_image/png_image.cpp +68 -0
  234. esphome/components/online_image/png_image.h +33 -0
  235. esphome/components/ota/__init__.py +8 -4
  236. esphome/components/pid/pid_climate.h +2 -0
  237. esphome/components/pmwcs3/pmwcs3.cpp +31 -30
  238. esphome/components/remote_base/pronto_protocol.cpp +0 -3
  239. esphome/components/remote_transmitter/remote_transmitter.h +1 -1
  240. esphome/components/rgbct/rgbct_light_output.h +3 -2
  241. esphome/components/rgbw/rgbw_light_output.h +3 -2
  242. esphome/components/rgbww/rgbww_light_output.h +3 -2
  243. esphome/components/rp2040_pio_led_strip/led_strip.cpp +31 -5
  244. esphome/components/rp2040_pio_led_strip/led_strip.h +5 -0
  245. esphome/components/rtttl/rtttl.cpp +108 -21
  246. esphome/components/rtttl/rtttl.h +15 -6
  247. esphome/components/select/__init__.py +7 -7
  248. esphome/components/sensor/__init__.py +29 -10
  249. esphome/components/sensor/filter.cpp +8 -0
  250. esphome/components/sensor/filter.h +9 -0
  251. esphome/components/sml/sml_parser.cpp +48 -22
  252. esphome/components/socket/socket.cpp +11 -14
  253. esphome/components/speaker/__init__.py +14 -5
  254. esphome/components/speaker/automation.h +10 -0
  255. esphome/components/speaker/speaker.h +9 -0
  256. esphome/components/spi/spi.cpp +0 -6
  257. esphome/components/spi/spi.h +2 -19
  258. esphome/components/spi_led_strip/spi_led_strip.h +5 -4
  259. esphome/components/sprinkler/sprinkler.cpp +2 -2
  260. esphome/components/sprinkler/sprinkler.h +1 -1
  261. esphome/components/switch/__init__.py +3 -3
  262. esphome/components/text/__init__.py +5 -5
  263. esphome/components/text_sensor/__init__.py +7 -7
  264. esphome/components/time/__init__.py +8 -8
  265. esphome/components/touchscreen/binary_sensor/__init__.py +24 -10
  266. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp +3 -2
  267. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h +4 -2
  268. esphome/components/uart/uart_component_host.cpp +6 -2
  269. esphome/components/update/__init__.py +33 -15
  270. esphome/components/update/automation.h +23 -0
  271. esphome/components/update/update_entity.h +3 -1
  272. esphome/components/valve/__init__.py +3 -3
  273. esphome/components/voice_assistant/__init__.py +7 -8
  274. esphome/components/wake_on_lan/wake_on_lan.cpp +2 -0
  275. esphome/components/wake_on_lan/wake_on_lan.h +3 -1
  276. esphome/components/watchdog/__init__.py +1 -0
  277. esphome/components/{http_request → watchdog}/watchdog.cpp +0 -2
  278. esphome/components/{http_request → watchdog}/watchdog.h +0 -2
  279. esphome/components/waveshare_epaper/waveshare_epaper.cpp +5 -5
  280. esphome/components/web_server/server_index_v3.h +3615 -3603
  281. esphome/components/web_server/web_server.cpp +0 -209
  282. esphome/components/web_server/web_server.h +1 -1
  283. esphome/components/web_server/web_server_v1.cpp +217 -0
  284. esphome/components/web_server_base/web_server_base.h +1 -0
  285. esphome/components/wifi/__init__.py +15 -14
  286. esphome/components/wifi/wifi_component.cpp +2 -0
  287. esphome/components/wifi/wifi_component.h +7 -1
  288. esphome/components/wifi/wifi_component_esp32_arduino.cpp +5 -2
  289. esphome/components/wifi/wifi_component_esp8266.cpp +2 -0
  290. esphome/components/wifi/wifi_component_esp_idf.cpp +43 -7
  291. esphome/components/wifi/wifi_component_libretiny.cpp +2 -0
  292. esphome/components/wifi/wifi_component_pico_w.cpp +2 -0
  293. esphome/components/wifi/wpa2_eap.py +6 -7
  294. esphome/components/wifi_info/text_sensor.py +3 -3
  295. esphome/components/wifi_info/wifi_info_text_sensor.cpp +2 -0
  296. esphome/components/wifi_info/wifi_info_text_sensor.h +2 -0
  297. esphome/components/wifi_signal/sensor.py +1 -1
  298. esphome/components/wifi_signal/wifi_signal_sensor.cpp +2 -0
  299. esphome/components/wifi_signal/wifi_signal_sensor.h +2 -1
  300. esphome/components/xiaomi_ble/xiaomi_ble.cpp +20 -3
  301. esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
  302. esphome/components/xiaomi_lywsd02mmc/__init__.py +0 -0
  303. esphome/components/xiaomi_lywsd02mmc/sensor.py +77 -0
  304. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp +73 -0
  305. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +37 -0
  306. esphome/config.py +17 -19
  307. esphome/config_validation.py +55 -23
  308. esphome/const.py +25 -9
  309. esphome/core/__init__.py +17 -14
  310. esphome/core/application.h +42 -21
  311. esphome/core/automation.h +5 -3
  312. esphome/core/base_automation.h +3 -2
  313. esphome/core/bytebuffer.cpp +134 -0
  314. esphome/core/bytebuffer.h +96 -0
  315. esphome/core/color.h +24 -16
  316. esphome/core/config.py +3 -3
  317. esphome/core/defines.h +14 -1
  318. esphome/core/entity_base.h +2 -2
  319. esphome/core/entity_helpers.py +1 -2
  320. esphome/core/gpio.h +0 -18
  321. esphome/core/helpers.h +1 -1
  322. esphome/core/optional.h +15 -16
  323. esphome/coroutine.py +1 -1
  324. esphome/cpp_generator.py +1 -1
  325. esphome/cpp_helpers.py +3 -5
  326. esphome/dashboard/core.py +3 -3
  327. esphome/dashboard/dashboard.py +3 -3
  328. esphome/dashboard/entries.py +1 -1
  329. esphome/dashboard/util/file.py +1 -1
  330. esphome/dashboard/web_server.py +3 -3
  331. esphome/external_files.py +5 -3
  332. esphome/final_validate.py +2 -2
  333. esphome/git.py +4 -4
  334. esphome/helpers.py +5 -5
  335. esphome/loader.py +15 -10
  336. esphome/mqtt.py +4 -8
  337. esphome/pins.py +6 -6
  338. esphome/platformio_api.py +5 -5
  339. esphome/storage_json.py +2 -1
  340. esphome/types.py +1 -1
  341. esphome/util.py +2 -3
  342. esphome/voluptuous_schema.py +1 -0
  343. esphome/vscode.py +5 -4
  344. esphome/wizard.py +1 -1
  345. esphome/writer.py +7 -7
  346. esphome/yaml_util.py +3 -3
  347. esphome/zeroconf.py +1 -1
  348. {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/METADATA +3 -3
  349. {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/RECORD +353 -247
  350. {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/LICENSE +0 -0
  351. {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/WHEEL +0 -0
  352. {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/entry_points.txt +0 -0
  353. {esphome-2024.7.2.dist-info → esphome-2024.8.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,407 @@
1
+ #include "esphome/core/defines.h"
2
+ #include "esphome/core/log.h"
3
+ #include "esphome/core/helpers.h"
4
+ #include "esphome/core/hal.h"
5
+ #include "lvgl_hal.h"
6
+ #include "lvgl_esphome.h"
7
+
8
+ namespace esphome {
9
+ namespace lvgl {
10
+ static const char *const TAG = "lvgl";
11
+
12
+ #if LV_USE_LOG
13
+ static void log_cb(const char *buf) {
14
+ esp_log_printf_(ESPHOME_LOG_LEVEL_INFO, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf);
15
+ }
16
+ #endif // LV_USE_LOG
17
+
18
+ static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) {
19
+ // make sure all coordinates are even
20
+ if (area->x1 & 1)
21
+ area->x1--;
22
+ if (!(area->x2 & 1))
23
+ area->x2++;
24
+ if (area->y1 & 1)
25
+ area->y1--;
26
+ if (!(area->y2 & 1))
27
+ area->y2++;
28
+ }
29
+
30
+ lv_event_code_t lv_api_event; // NOLINT
31
+ lv_event_code_t lv_update_event; // NOLINT
32
+ void LvglComponent::dump_config() { ESP_LOGCONFIG(TAG, "LVGL:"); }
33
+ void LvglComponent::set_paused(bool paused, bool show_snow) {
34
+ this->paused_ = paused;
35
+ this->show_snow_ = show_snow;
36
+ this->snow_line_ = 0;
37
+ if (!paused && lv_scr_act() != nullptr) {
38
+ lv_disp_trig_activity(this->disp_); // resets the inactivity time
39
+ lv_obj_invalidate(lv_scr_act());
40
+ }
41
+ }
42
+ void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event) {
43
+ lv_obj_add_event_cb(obj, callback, event, this);
44
+ }
45
+ void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1,
46
+ lv_event_code_t event2) {
47
+ this->add_event_cb(obj, callback, event1);
48
+ this->add_event_cb(obj, callback, event2);
49
+ }
50
+ void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1,
51
+ lv_event_code_t event2, lv_event_code_t event3) {
52
+ this->add_event_cb(obj, callback, event1);
53
+ this->add_event_cb(obj, callback, event2);
54
+ this->add_event_cb(obj, callback, event3);
55
+ }
56
+ void LvglComponent::add_page(LvPageType *page) {
57
+ this->pages_.push_back(page);
58
+ page->setup(this->pages_.size() - 1);
59
+ }
60
+ void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time) {
61
+ if (index >= this->pages_.size())
62
+ return;
63
+ this->current_page_ = index;
64
+ lv_scr_load_anim(this->pages_[this->current_page_]->obj, anim, time, 0, false);
65
+ }
66
+ void LvglComponent::show_next_page(lv_scr_load_anim_t anim, uint32_t time) {
67
+ if (this->pages_.empty() || (this->current_page_ == this->pages_.size() - 1 && !this->page_wrap_))
68
+ return;
69
+ do {
70
+ this->current_page_ = (this->current_page_ + 1) % this->pages_.size();
71
+ } while (this->pages_[this->current_page_]->skip); // skip empty pages()
72
+ this->show_page(this->current_page_, anim, time);
73
+ }
74
+ void LvglComponent::show_prev_page(lv_scr_load_anim_t anim, uint32_t time) {
75
+ if (this->pages_.empty() || (this->current_page_ == 0 && !this->page_wrap_))
76
+ return;
77
+ do {
78
+ this->current_page_ = (this->current_page_ + this->pages_.size() - 1) % this->pages_.size();
79
+ } while (this->pages_[this->current_page_]->skip); // skip empty pages()
80
+ this->show_page(this->current_page_, anim, time);
81
+ }
82
+ void LvglComponent::draw_buffer_(const lv_area_t *area, const uint8_t *ptr) {
83
+ for (auto *display : this->displays_) {
84
+ display->draw_pixels_at(area->x1, area->y1, lv_area_get_width(area), lv_area_get_height(area), ptr,
85
+ display::COLOR_ORDER_RGB, LV_BITNESS, LV_COLOR_16_SWAP);
86
+ }
87
+ }
88
+
89
+ void LvglComponent::flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
90
+ if (!this->paused_) {
91
+ auto now = millis();
92
+ this->draw_buffer_(area, (const uint8_t *) color_p);
93
+ ESP_LOGV(TAG, "flush_cb, area=%d/%d, %d/%d took %dms", area->x1, area->y1, lv_area_get_width(area),
94
+ lv_area_get_height(area), (int) (millis() - now));
95
+ }
96
+ lv_disp_flush_ready(disp_drv);
97
+ }
98
+ IdleTrigger::IdleTrigger(LvglComponent *parent, TemplatableValue<uint32_t> timeout) : timeout_(std::move(timeout)) {
99
+ parent->add_on_idle_callback([this](uint32_t idle_time) {
100
+ if (!this->is_idle_ && idle_time > this->timeout_.value()) {
101
+ this->is_idle_ = true;
102
+ this->trigger();
103
+ } else if (this->is_idle_ && idle_time < this->timeout_.value()) {
104
+ this->is_idle_ = false;
105
+ }
106
+ });
107
+ }
108
+
109
+ #ifdef USE_LVGL_TOUCHSCREEN
110
+ LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time) {
111
+ lv_indev_drv_init(&this->drv_);
112
+ this->drv_.long_press_repeat_time = long_press_repeat_time;
113
+ this->drv_.long_press_time = long_press_time;
114
+ this->drv_.type = LV_INDEV_TYPE_POINTER;
115
+ this->drv_.user_data = this;
116
+ this->drv_.read_cb = [](lv_indev_drv_t *d, lv_indev_data_t *data) {
117
+ auto *l = static_cast<LVTouchListener *>(d->user_data);
118
+ if (l->touch_pressed_) {
119
+ data->point.x = l->touch_point_.x;
120
+ data->point.y = l->touch_point_.y;
121
+ data->state = LV_INDEV_STATE_PRESSED;
122
+ } else {
123
+ data->state = LV_INDEV_STATE_RELEASED;
124
+ }
125
+ };
126
+ }
127
+ void LVTouchListener::update(const touchscreen::TouchPoints_t &tpoints) {
128
+ this->touch_pressed_ = !this->parent_->is_paused() && !tpoints.empty();
129
+ if (this->touch_pressed_)
130
+ this->touch_point_ = tpoints[0];
131
+ }
132
+ #endif // USE_LVGL_TOUCHSCREEN
133
+
134
+ #ifdef USE_LVGL_KEY_LISTENER
135
+ LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt) {
136
+ lv_indev_drv_init(&this->drv_);
137
+ this->drv_.type = type;
138
+ this->drv_.user_data = this;
139
+ this->drv_.long_press_time = lpt;
140
+ this->drv_.long_press_repeat_time = lprt;
141
+ this->drv_.read_cb = [](lv_indev_drv_t *d, lv_indev_data_t *data) {
142
+ auto *l = static_cast<LVEncoderListener *>(d->user_data);
143
+ data->state = l->pressed_ ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
144
+ data->key = l->key_;
145
+ data->enc_diff = (int16_t) (l->count_ - l->last_count_);
146
+ l->last_count_ = l->count_;
147
+ data->continue_reading = false;
148
+ };
149
+ }
150
+ #endif // USE_LVGL_KEY_LISTENER
151
+
152
+ #ifdef USE_LVGL_BUTTONMATRIX
153
+ void LvButtonMatrixType::set_obj(lv_obj_t *lv_obj) {
154
+ LvCompound::set_obj(lv_obj);
155
+ lv_obj_add_event_cb(
156
+ lv_obj,
157
+ [](lv_event_t *event) {
158
+ auto *self = static_cast<LvButtonMatrixType *>(event->user_data);
159
+ if (self->key_callback_.size() == 0)
160
+ return;
161
+ auto key_idx = lv_btnmatrix_get_selected_btn(self->obj);
162
+ if (key_idx == LV_BTNMATRIX_BTN_NONE)
163
+ return;
164
+ if (self->key_map_.count(key_idx) != 0) {
165
+ self->send_key_(self->key_map_[key_idx]);
166
+ return;
167
+ }
168
+ const auto *str = lv_btnmatrix_get_btn_text(self->obj, key_idx);
169
+ auto len = strlen(str);
170
+ while (len--)
171
+ self->send_key_(*str++);
172
+ },
173
+ LV_EVENT_PRESSED, this);
174
+ }
175
+ #endif // USE_LVGL_BUTTONMATRIX
176
+
177
+ #ifdef USE_LVGL_KEYBOARD
178
+ static const char *const KB_SPECIAL_KEYS[] = {
179
+ "abc", "ABC", "1#",
180
+ // maybe add other special keys here
181
+ };
182
+
183
+ void LvKeyboardType::set_obj(lv_obj_t *lv_obj) {
184
+ LvCompound::set_obj(lv_obj);
185
+ lv_obj_add_event_cb(
186
+ lv_obj,
187
+ [](lv_event_t *event) {
188
+ auto *self = static_cast<LvKeyboardType *>(event->user_data);
189
+ if (self->key_callback_.size() == 0)
190
+ return;
191
+
192
+ auto key_idx = lv_btnmatrix_get_selected_btn(self->obj);
193
+ if (key_idx == LV_BTNMATRIX_BTN_NONE)
194
+ return;
195
+ const char *txt = lv_btnmatrix_get_btn_text(self->obj, key_idx);
196
+ if (txt == nullptr)
197
+ return;
198
+ for (const auto *kb_special_key : KB_SPECIAL_KEYS) {
199
+ if (strcmp(txt, kb_special_key) == 0)
200
+ return;
201
+ }
202
+ while (*txt != 0)
203
+ self->send_key_(*txt++);
204
+ },
205
+ LV_EVENT_PRESSED, this);
206
+ }
207
+ #endif // USE_LVGL_KEYBOARD
208
+
209
+ void LvglComponent::write_random_() {
210
+ // length of 2 lines in 32 bit units
211
+ // we write 2 lines for the benefit of displays that won't write one line at a time.
212
+ size_t line_len = this->disp_drv_.hor_res * LV_COLOR_DEPTH / 8 / 4 * 2;
213
+ for (size_t i = 0; i != line_len; i++) {
214
+ ((uint32_t *) (this->draw_buf_.buf1))[i] = random_uint32();
215
+ }
216
+ lv_area_t area;
217
+ area.x1 = 0;
218
+ area.x2 = this->disp_drv_.hor_res - 1;
219
+ if (this->snow_line_ == this->disp_drv_.ver_res / 2) {
220
+ area.y1 = static_cast<lv_coord_t>(random_uint32() % (this->disp_drv_.ver_res / 2) * 2);
221
+ } else {
222
+ area.y1 = this->snow_line_++ * 2;
223
+ }
224
+ // write 2 lines
225
+ area.y2 = area.y1 + 1;
226
+ this->draw_buffer_(&area, (const uint8_t *) this->draw_buf_.buf1);
227
+ }
228
+
229
+ void LvglComponent::setup() {
230
+ ESP_LOGCONFIG(TAG, "LVGL Setup starts");
231
+ #if LV_USE_LOG
232
+ lv_log_register_print_cb(log_cb);
233
+ #endif
234
+ lv_init();
235
+ lv_update_event = static_cast<lv_event_code_t>(lv_event_register_id());
236
+ lv_api_event = static_cast<lv_event_code_t>(lv_event_register_id());
237
+ auto *display = this->displays_[0];
238
+ size_t buffer_pixels = display->get_width() * display->get_height() / this->buffer_frac_;
239
+ auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8;
240
+ auto *buf = lv_custom_mem_alloc(buf_bytes);
241
+ if (buf == nullptr) {
242
+ #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR
243
+ ESP_LOGE(TAG, "Malloc failed to allocate %zu bytes", buf_bytes);
244
+ #endif
245
+ this->mark_failed();
246
+ this->status_set_error("Memory allocation failure");
247
+ return;
248
+ }
249
+ lv_disp_draw_buf_init(&this->draw_buf_, buf, nullptr, buffer_pixels);
250
+ lv_disp_drv_init(&this->disp_drv_);
251
+ this->disp_drv_.draw_buf = &this->draw_buf_;
252
+ this->disp_drv_.user_data = this;
253
+ this->disp_drv_.full_refresh = this->full_refresh_;
254
+ this->disp_drv_.flush_cb = static_flush_cb;
255
+ this->disp_drv_.rounder_cb = rounder_cb;
256
+ switch (display->get_rotation()) {
257
+ case display::DISPLAY_ROTATION_0_DEGREES:
258
+ break;
259
+ case display::DISPLAY_ROTATION_90_DEGREES:
260
+ this->disp_drv_.sw_rotate = true;
261
+ this->disp_drv_.rotated = LV_DISP_ROT_90;
262
+ break;
263
+ case display::DISPLAY_ROTATION_180_DEGREES:
264
+ this->disp_drv_.sw_rotate = true;
265
+ this->disp_drv_.rotated = LV_DISP_ROT_180;
266
+ break;
267
+ case display::DISPLAY_ROTATION_270_DEGREES:
268
+ this->disp_drv_.sw_rotate = true;
269
+ this->disp_drv_.rotated = LV_DISP_ROT_270;
270
+ break;
271
+ }
272
+ display->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);
273
+ this->disp_drv_.hor_res = (lv_coord_t) display->get_width();
274
+ this->disp_drv_.ver_res = (lv_coord_t) display->get_height();
275
+ ESP_LOGV(TAG, "sw_rotate = %d, rotated=%d", this->disp_drv_.sw_rotate, this->disp_drv_.rotated);
276
+ this->disp_ = lv_disp_drv_register(&this->disp_drv_);
277
+ for (const auto &v : this->init_lambdas_)
278
+ v(this);
279
+ this->show_page(0, LV_SCR_LOAD_ANIM_NONE, 0);
280
+ lv_disp_trig_activity(this->disp_);
281
+ ESP_LOGCONFIG(TAG, "LVGL Setup complete");
282
+ }
283
+ void LvglComponent::update() {
284
+ // update indicators
285
+ if (this->paused_) {
286
+ return;
287
+ }
288
+ this->idle_callbacks_.call(lv_disp_get_inactive_time(this->disp_));
289
+ }
290
+ void LvglComponent::loop() {
291
+ if (this->paused_) {
292
+ if (this->show_snow_)
293
+ this->write_random_();
294
+ }
295
+ lv_timer_handler_run_in_period(5);
296
+ }
297
+
298
+ #ifdef USE_LVGL_IMAGE
299
+ lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc) {
300
+ if (img_dsc == nullptr)
301
+ img_dsc = new lv_img_dsc_t(); // NOLINT
302
+ img_dsc->header.always_zero = 0;
303
+ img_dsc->header.reserved = 0;
304
+ img_dsc->header.w = src->get_width();
305
+ img_dsc->header.h = src->get_height();
306
+ img_dsc->data = src->get_data_start();
307
+ img_dsc->data_size = image_type_to_width_stride(img_dsc->header.w * img_dsc->header.h, src->get_type());
308
+ switch (src->get_type()) {
309
+ case image::IMAGE_TYPE_BINARY:
310
+ img_dsc->header.cf = LV_IMG_CF_ALPHA_1BIT;
311
+ break;
312
+
313
+ case image::IMAGE_TYPE_GRAYSCALE:
314
+ img_dsc->header.cf = LV_IMG_CF_ALPHA_8BIT;
315
+ break;
316
+
317
+ case image::IMAGE_TYPE_RGB24:
318
+ img_dsc->header.cf = LV_IMG_CF_RGB888;
319
+ break;
320
+
321
+ case image::IMAGE_TYPE_RGB565:
322
+ #if LV_COLOR_DEPTH == 16
323
+ img_dsc->header.cf = src->has_transparency() ? LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED : LV_IMG_CF_TRUE_COLOR;
324
+ #else
325
+ img_dsc->header.cf = LV_IMG_CF_RGB565;
326
+ #endif
327
+ break;
328
+
329
+ case image::IMAGE_TYPE_RGBA:
330
+ #if LV_COLOR_DEPTH == 32
331
+ img_dsc->header.cf = LV_IMG_CF_TRUE_COLOR;
332
+ #else
333
+ img_dsc->header.cf = LV_IMG_CF_RGBA8888;
334
+ #endif
335
+ break;
336
+ }
337
+ return img_dsc;
338
+ }
339
+ #endif // USE_LVGL_IMAGE
340
+
341
+ #ifdef USE_LVGL_ANIMIMG
342
+ void lv_animimg_stop(lv_obj_t *obj) {
343
+ auto *animg = (lv_animimg_t *) obj;
344
+ int32_t duration = animg->anim.time;
345
+ lv_animimg_set_duration(obj, 0);
346
+ lv_animimg_start(obj);
347
+ lv_animimg_set_duration(obj, duration);
348
+ }
349
+ #endif
350
+ void LvglComponent::static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
351
+ reinterpret_cast<LvglComponent *>(disp_drv->user_data)->flush_cb_(disp_drv, area, color_p);
352
+ }
353
+ } // namespace lvgl
354
+ } // namespace esphome
355
+
356
+ size_t lv_millis(void) { return esphome::millis(); }
357
+
358
+ #if defined(USE_HOST) || defined(USE_RP2040) || defined(USE_ESP8266)
359
+ void *lv_custom_mem_alloc(size_t size) {
360
+ auto *ptr = malloc(size); // NOLINT
361
+ if (ptr == nullptr) {
362
+ #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR
363
+ esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size);
364
+ #endif
365
+ }
366
+ return ptr;
367
+ }
368
+ void lv_custom_mem_free(void *ptr) { return free(ptr); } // NOLINT
369
+ void *lv_custom_mem_realloc(void *ptr, size_t size) { return realloc(ptr, size); } // NOLINT
370
+ #else
371
+ static unsigned cap_bits = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT; // NOLINT
372
+
373
+ void *lv_custom_mem_alloc(size_t size) {
374
+ void *ptr;
375
+ ptr = heap_caps_malloc(size, cap_bits);
376
+ if (ptr == nullptr) {
377
+ cap_bits = MALLOC_CAP_8BIT;
378
+ ptr = heap_caps_malloc(size, cap_bits);
379
+ }
380
+ if (ptr == nullptr) {
381
+ #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR
382
+ esphome::ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size);
383
+ #endif
384
+ return nullptr;
385
+ }
386
+ #ifdef ESPHOME_LOG_HAS_VERBOSE
387
+ esphome::ESP_LOGV(esphome::lvgl::TAG, "allocate %zu - > %p", size, ptr);
388
+ #endif
389
+ return ptr;
390
+ }
391
+
392
+ void lv_custom_mem_free(void *ptr) {
393
+ #ifdef ESPHOME_LOG_HAS_VERBOSE
394
+ esphome::ESP_LOGV(esphome::lvgl::TAG, "free %p", ptr);
395
+ #endif
396
+ if (ptr == nullptr)
397
+ return;
398
+ heap_caps_free(ptr);
399
+ }
400
+
401
+ void *lv_custom_mem_realloc(void *ptr, size_t size) {
402
+ #ifdef ESPHOME_LOG_HAS_VERBOSE
403
+ esphome::ESP_LOGV(esphome::lvgl::TAG, "realloc %p: %zu", ptr, size);
404
+ #endif
405
+ return heap_caps_realloc(ptr, size, cap_bits);
406
+ }
407
+ #endif
@@ -0,0 +1,274 @@
1
+ #pragma once
2
+ #include "esphome/core/defines.h"
3
+
4
+ #ifdef USE_BINARY_SENSOR
5
+ #include "esphome/components/binary_sensor/binary_sensor.h"
6
+ #endif // USE_BINARY_SENSOR
7
+ #ifdef USE_LVGL_ROTARY_ENCODER
8
+ #include "esphome/components/rotary_encoder/rotary_encoder.h"
9
+ #endif // USE_LVGL_ROTARY_ENCODER
10
+
11
+ // required for clang-tidy
12
+ #ifndef LV_CONF_H
13
+ #define LV_CONF_SKIP 1 // NOLINT
14
+ #endif // LV_CONF_H
15
+
16
+ #include "esphome/components/display/display.h"
17
+ #include "esphome/components/display/display_color_utils.h"
18
+ #include "esphome/core/component.h"
19
+ #include "esphome/core/log.h"
20
+ #include <lvgl.h>
21
+ #include <vector>
22
+ #include <map>
23
+ #ifdef USE_LVGL_IMAGE
24
+ #include "esphome/components/image/image.h"
25
+ #endif // USE_LVGL_IMAGE
26
+
27
+ #ifdef USE_LVGL_FONT
28
+ #include "esphome/components/font/font.h"
29
+ #endif // USE_LVGL_FONT
30
+ #ifdef USE_LVGL_TOUCHSCREEN
31
+ #include "esphome/components/touchscreen/touchscreen.h"
32
+ #endif // USE_LVGL_TOUCHSCREEN
33
+
34
+ #if defined(USE_LVGL_BUTTONMATRIX) || defined(USE_LVGL_KEYBOARD)
35
+ #include "esphome/components/key_provider/key_provider.h"
36
+ #endif // USE_LVGL_BUTTONMATRIX
37
+
38
+ namespace esphome {
39
+ namespace lvgl {
40
+
41
+ extern lv_event_code_t lv_api_event; // NOLINT
42
+ extern lv_event_code_t lv_update_event; // NOLINT
43
+ #ifdef USE_LVGL_COLOR
44
+ inline lv_color_t lv_color_from(Color color) { return lv_color_make(color.red, color.green, color.blue); }
45
+ #endif // USE_LVGL_COLOR
46
+ #if LV_COLOR_DEPTH == 16
47
+ static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565;
48
+ #elif LV_COLOR_DEPTH == 32
49
+ static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_888;
50
+ #else // LV_COLOR_DEPTH
51
+ static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_332;
52
+ #endif // LV_COLOR_DEPTH
53
+
54
+ // Parent class for things that wrap an LVGL object
55
+ class LvCompound {
56
+ public:
57
+ virtual void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; }
58
+ lv_obj_t *obj{};
59
+ };
60
+
61
+ class LvPageType {
62
+ public:
63
+ LvPageType(bool skip) : skip(skip) {}
64
+
65
+ void setup(size_t index) {
66
+ this->index = index;
67
+ this->obj = lv_obj_create(nullptr);
68
+ }
69
+ lv_obj_t *obj{};
70
+ size_t index{};
71
+ bool skip;
72
+ };
73
+
74
+ using LvLambdaType = std::function<void(lv_obj_t *)>;
75
+ using set_value_lambda_t = std::function<void(float)>;
76
+ using event_callback_t = void(_lv_event_t *);
77
+ using text_lambda_t = std::function<const char *()>;
78
+
79
+ template<typename... Ts> class ObjUpdateAction : public Action<Ts...> {
80
+ public:
81
+ explicit ObjUpdateAction(std::function<void(Ts...)> &&lamb) : lamb_(std::move(lamb)) {}
82
+
83
+ void play(Ts... x) override { this->lamb_(x...); }
84
+
85
+ protected:
86
+ std::function<void(Ts...)> lamb_;
87
+ };
88
+ #ifdef USE_LVGL_FONT
89
+ class FontEngine {
90
+ public:
91
+ FontEngine(font::Font *esp_font);
92
+ const lv_font_t *get_lv_font();
93
+
94
+ const font::GlyphData *get_glyph_data(uint32_t unicode_letter);
95
+ uint16_t baseline{};
96
+ uint16_t height{};
97
+ uint8_t bpp{};
98
+
99
+ protected:
100
+ font::Font *font_{};
101
+ uint32_t last_letter_{};
102
+ const font::GlyphData *last_data_{};
103
+ lv_font_t lv_font_{};
104
+ };
105
+ #endif // USE_LVGL_FONT
106
+ #ifdef USE_LVGL_IMAGE
107
+ lv_img_dsc_t *lv_img_from(image::Image *src, lv_img_dsc_t *img_dsc = nullptr);
108
+ #endif // USE_LVGL_IMAGE
109
+
110
+ #ifdef USE_LVGL_ANIMIMG
111
+ void lv_animimg_stop(lv_obj_t *obj);
112
+ #endif // USE_LVGL_ANIMIMG
113
+
114
+ class LvglComponent : public PollingComponent {
115
+ constexpr static const char *const TAG = "lvgl";
116
+
117
+ public:
118
+ static void static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p);
119
+
120
+ float get_setup_priority() const override { return setup_priority::PROCESSOR; }
121
+ void setup() override;
122
+ void update() override;
123
+ void loop() override;
124
+ void add_on_idle_callback(std::function<void(uint32_t)> &&callback) {
125
+ this->idle_callbacks_.add(std::move(callback));
126
+ }
127
+ void add_display(display::Display *display) { this->displays_.push_back(display); }
128
+ void add_init_lambda(const std::function<void(LvglComponent *)> &lamb) { this->init_lambdas_.push_back(lamb); }
129
+ void dump_config() override;
130
+ void set_full_refresh(bool full_refresh) { this->full_refresh_ = full_refresh; }
131
+ bool is_idle(uint32_t idle_ms) { return lv_disp_get_inactive_time(this->disp_) > idle_ms; }
132
+ void set_buffer_frac(size_t frac) { this->buffer_frac_ = frac; }
133
+ lv_disp_t *get_disp() { return this->disp_; }
134
+ void set_paused(bool paused, bool show_snow);
135
+ void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event);
136
+ void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2);
137
+ void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2,
138
+ lv_event_code_t event3);
139
+ bool is_paused() const { return this->paused_; }
140
+ void add_page(LvPageType *page);
141
+ void show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time);
142
+ void show_next_page(lv_scr_load_anim_t anim, uint32_t time);
143
+ void show_prev_page(lv_scr_load_anim_t anim, uint32_t time);
144
+ void set_page_wrap(bool wrap) { this->page_wrap_ = wrap; }
145
+
146
+ protected:
147
+ void write_random_();
148
+ void draw_buffer_(const lv_area_t *area, const uint8_t *ptr);
149
+ void flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p);
150
+ std::vector<display::Display *> displays_{};
151
+ lv_disp_draw_buf_t draw_buf_{};
152
+ lv_disp_drv_t disp_drv_{};
153
+ lv_disp_t *disp_{};
154
+ bool paused_{};
155
+ std::vector<LvPageType *> pages_{};
156
+ size_t current_page_{0};
157
+ bool show_snow_{};
158
+ lv_coord_t snow_line_{};
159
+ bool page_wrap_{true};
160
+
161
+ std::vector<std::function<void(LvglComponent *lv_component)>> init_lambdas_;
162
+ CallbackManager<void(uint32_t)> idle_callbacks_{};
163
+ size_t buffer_frac_{1};
164
+ bool full_refresh_{};
165
+ };
166
+
167
+ class IdleTrigger : public Trigger<> {
168
+ public:
169
+ explicit IdleTrigger(LvglComponent *parent, TemplatableValue<uint32_t> timeout);
170
+
171
+ protected:
172
+ TemplatableValue<uint32_t> timeout_;
173
+ bool is_idle_{};
174
+ };
175
+
176
+ template<typename... Ts> class LvglAction : public Action<Ts...>, public Parented<LvglComponent> {
177
+ public:
178
+ explicit LvglAction(std::function<void(LvglComponent *)> &&lamb) : action_(std::move(lamb)) {}
179
+ void play(Ts... x) override { this->action_(this->parent_); }
180
+
181
+ protected:
182
+ std::function<void(LvglComponent *)> action_{};
183
+ };
184
+
185
+ template<typename... Ts> class LvglCondition : public Condition<Ts...>, public Parented<LvglComponent> {
186
+ public:
187
+ LvglCondition(std::function<bool(LvglComponent *)> &&condition_lambda)
188
+ : condition_lambda_(std::move(condition_lambda)) {}
189
+ bool check(Ts... x) override { return this->condition_lambda_(this->parent_); }
190
+
191
+ protected:
192
+ std::function<bool(LvglComponent *)> condition_lambda_{};
193
+ };
194
+
195
+ #ifdef USE_LVGL_TOUCHSCREEN
196
+ class LVTouchListener : public touchscreen::TouchListener, public Parented<LvglComponent> {
197
+ public:
198
+ LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time);
199
+ void update(const touchscreen::TouchPoints_t &tpoints) override;
200
+ void release() override { touch_pressed_ = false; }
201
+ lv_indev_drv_t *get_drv() { return &this->drv_; }
202
+
203
+ protected:
204
+ lv_indev_drv_t drv_{};
205
+ touchscreen::TouchPoint touch_point_{};
206
+ bool touch_pressed_{};
207
+ };
208
+ #endif // USE_LVGL_TOUCHSCREEN
209
+
210
+ #ifdef USE_LVGL_KEY_LISTENER
211
+ class LVEncoderListener : public Parented<LvglComponent> {
212
+ public:
213
+ LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt);
214
+
215
+ void set_left_button(binary_sensor::BinarySensor *left_button) {
216
+ left_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_LEFT, state); });
217
+ }
218
+ void set_right_button(binary_sensor::BinarySensor *right_button) {
219
+ right_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_RIGHT, state); });
220
+ }
221
+
222
+ void set_enter_button(binary_sensor::BinarySensor *enter_button) {
223
+ enter_button->add_on_state_callback([this](bool state) { this->event(LV_KEY_ENTER, state); });
224
+ }
225
+
226
+ #ifdef USE_LVGL_ROTARY_ENCODER
227
+ void set_sensor(rotary_encoder::RotaryEncoderSensor *sensor) {
228
+ sensor->register_listener([this](int32_t count) { this->set_count(count); });
229
+ }
230
+ #endif // USE_LVGL_ROTARY_ENCODER
231
+
232
+ void event(int key, bool pressed) {
233
+ if (!this->parent_->is_paused()) {
234
+ this->pressed_ = pressed;
235
+ this->key_ = key;
236
+ }
237
+ }
238
+
239
+ void set_count(int32_t count) {
240
+ if (!this->parent_->is_paused())
241
+ this->count_ = count;
242
+ }
243
+
244
+ lv_indev_drv_t *get_drv() { return &this->drv_; }
245
+
246
+ protected:
247
+ lv_indev_drv_t drv_{};
248
+ bool pressed_{};
249
+ int32_t count_{};
250
+ int32_t last_count_{};
251
+ int key_{};
252
+ };
253
+ #endif // USE_LVGL_KEY_LISTENER
254
+
255
+ #ifdef USE_LVGL_BUTTONMATRIX
256
+ class LvButtonMatrixType : public key_provider::KeyProvider, public LvCompound {
257
+ public:
258
+ void set_obj(lv_obj_t *lv_obj) override;
259
+ uint16_t get_selected() { return lv_btnmatrix_get_selected_btn(this->obj); }
260
+ void set_key(size_t idx, uint8_t key) { this->key_map_[idx] = key; }
261
+
262
+ protected:
263
+ std::map<size_t, uint8_t> key_map_{};
264
+ };
265
+ #endif // USE_LVGL_BUTTONMATRIX
266
+
267
+ #ifdef USE_LVGL_KEYBOARD
268
+ class LvKeyboardType : public key_provider::KeyProvider, public LvCompound {
269
+ public:
270
+ void set_obj(lv_obj_t *lv_obj) override;
271
+ };
272
+ #endif // USE_LVGL_KEYBOARD
273
+ } // namespace lvgl
274
+ } // namespace esphome
@@ -0,0 +1,21 @@
1
+ //
2
+ // Created by Clyde Stubbs on 20/9/2023.
3
+ //
4
+
5
+ #pragma once
6
+
7
+ #ifdef __cplusplus
8
+ #define EXTERNC extern "C"
9
+ #include <cstddef>
10
+ namespace esphome {
11
+ namespace lvgl {}
12
+ } // namespace esphome
13
+ #else
14
+ #define EXTERNC extern
15
+ #include <stddef.h>
16
+ #endif
17
+
18
+ EXTERNC size_t lv_millis(void);
19
+ EXTERNC void *lv_custom_mem_alloc(size_t size);
20
+ EXTERNC void lv_custom_mem_free(void *ptr);
21
+ EXTERNC void *lv_custom_mem_realloc(void *ptr, size_t size);