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,346 @@
1
+ import logging
2
+
3
+ from esphome.automation import build_automation, register_action, validate_automation
4
+ import esphome.codegen as cg
5
+ from esphome.components.display import Display
6
+ import esphome.config_validation as cv
7
+ from esphome.const import (
8
+ CONF_AUTO_CLEAR_ENABLED,
9
+ CONF_BUFFER_SIZE,
10
+ CONF_ID,
11
+ CONF_LAMBDA,
12
+ CONF_ON_IDLE,
13
+ CONF_PAGES,
14
+ CONF_TIMEOUT,
15
+ CONF_TRIGGER_ID,
16
+ CONF_TYPE,
17
+ )
18
+ from esphome.core import CORE, ID
19
+ from esphome.cpp_generator import MockObj
20
+ from esphome.final_validate import full_config
21
+ from esphome.helpers import write_file_if_changed
22
+
23
+ from . import defines as df, helpers, lv_validation as lvalid
24
+ from .automation import disp_update, update_to_code
25
+ from .defines import CONF_SKIP
26
+ from .encoders import ENCODERS_CONFIG, encoders_to_code, initial_focus_to_code
27
+ from .lv_validation import lv_bool, lv_images_used
28
+ from .lvcode import LvContext, LvglComponent
29
+ from .schemas import (
30
+ DISP_BG_SCHEMA,
31
+ FLEX_OBJ_SCHEMA,
32
+ GRID_CELL_SCHEMA,
33
+ LAYOUT_SCHEMAS,
34
+ STYLE_SCHEMA,
35
+ WIDGET_TYPES,
36
+ any_widget_schema,
37
+ container_schema,
38
+ create_modify_schema,
39
+ grid_alignments,
40
+ obj_schema,
41
+ )
42
+ from .styles import add_top_layer, styles_to_code, theme_to_code
43
+ from .touchscreens import touchscreen_schema, touchscreens_to_code
44
+ from .trigger import generate_triggers
45
+ from .types import (
46
+ FontEngine,
47
+ IdleTrigger,
48
+ ObjUpdateAction,
49
+ lv_font_t,
50
+ lv_group_t,
51
+ lv_style_t,
52
+ lvgl_ns,
53
+ )
54
+ from .widgets import Widget, add_widgets, lv_scr_act, set_obj_properties
55
+ from .widgets.animimg import animimg_spec
56
+ from .widgets.arc import arc_spec
57
+ from .widgets.button import button_spec
58
+ from .widgets.buttonmatrix import buttonmatrix_spec
59
+ from .widgets.checkbox import checkbox_spec
60
+ from .widgets.dropdown import dropdown_spec
61
+ from .widgets.img import img_spec
62
+ from .widgets.keyboard import keyboard_spec
63
+ from .widgets.label import label_spec
64
+ from .widgets.led import led_spec
65
+ from .widgets.line import line_spec
66
+ from .widgets.lv_bar import bar_spec
67
+ from .widgets.meter import meter_spec
68
+ from .widgets.msgbox import MSGBOX_SCHEMA, msgboxes_to_code
69
+ from .widgets.obj import obj_spec
70
+ from .widgets.page import add_pages, page_spec
71
+ from .widgets.roller import roller_spec
72
+ from .widgets.slider import slider_spec
73
+ from .widgets.spinbox import spinbox_spec
74
+ from .widgets.spinner import spinner_spec
75
+ from .widgets.switch import switch_spec
76
+ from .widgets.tabview import tabview_spec
77
+ from .widgets.textarea import textarea_spec
78
+ from .widgets.tileview import tileview_spec
79
+
80
+ DOMAIN = "lvgl"
81
+ DEPENDENCIES = ["display"]
82
+ AUTO_LOAD = ["key_provider"]
83
+ CODEOWNERS = ["@clydebarrow"]
84
+ LOGGER = logging.getLogger(__name__)
85
+
86
+ for w_type in (
87
+ label_spec,
88
+ obj_spec,
89
+ button_spec,
90
+ bar_spec,
91
+ slider_spec,
92
+ arc_spec,
93
+ line_spec,
94
+ spinner_spec,
95
+ led_spec,
96
+ animimg_spec,
97
+ checkbox_spec,
98
+ img_spec,
99
+ switch_spec,
100
+ tabview_spec,
101
+ buttonmatrix_spec,
102
+ meter_spec,
103
+ dropdown_spec,
104
+ roller_spec,
105
+ textarea_spec,
106
+ spinbox_spec,
107
+ keyboard_spec,
108
+ tileview_spec,
109
+ ):
110
+ WIDGET_TYPES[w_type.name] = w_type
111
+
112
+ WIDGET_SCHEMA = any_widget_schema()
113
+
114
+ LAYOUT_SCHEMAS[df.TYPE_GRID] = {
115
+ cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema(GRID_CELL_SCHEMA))
116
+ }
117
+ LAYOUT_SCHEMAS[df.TYPE_FLEX] = {
118
+ cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema(FLEX_OBJ_SCHEMA))
119
+ }
120
+ LAYOUT_SCHEMAS[df.TYPE_NONE] = {
121
+ cv.Optional(df.CONF_WIDGETS): cv.ensure_list(any_widget_schema())
122
+ }
123
+ for w_type in WIDGET_TYPES.values():
124
+ register_action(
125
+ f"lvgl.{w_type.name}.update",
126
+ ObjUpdateAction,
127
+ create_modify_schema(w_type),
128
+ )(update_to_code)
129
+
130
+
131
+ lv_defines = {} # Dict of #defines to provide as build flags
132
+
133
+
134
+ def add_define(macro, value="1"):
135
+ if macro in lv_defines and lv_defines[macro] != value:
136
+ LOGGER.error(
137
+ "Redefinition of %s - was %s now %s", macro, lv_defines[macro], value
138
+ )
139
+ lv_defines[macro] = value
140
+
141
+
142
+ def as_macro(macro, value):
143
+ if value is None:
144
+ return f"#define {macro}"
145
+ return f"#define {macro} {value}"
146
+
147
+
148
+ LV_CONF_FILENAME = "lv_conf.h"
149
+ LV_CONF_H_FORMAT = """\
150
+ #pragma once
151
+ {}
152
+ """
153
+
154
+
155
+ def generate_lv_conf_h():
156
+ definitions = [as_macro(m, v) for m, v in lv_defines.items()]
157
+ definitions.sort()
158
+ return LV_CONF_H_FORMAT.format("\n".join(definitions))
159
+
160
+
161
+ def final_validation(config):
162
+ if pages := config.get(CONF_PAGES):
163
+ if all(p[CONF_SKIP] for p in pages):
164
+ raise cv.Invalid("At least one page must not be skipped")
165
+ global_config = full_config.get()
166
+ for display_id in config[df.CONF_DISPLAYS]:
167
+ path = global_config.get_path_for_id(display_id)[:-1]
168
+ display = global_config.get_config_for_path(path)
169
+ if CONF_LAMBDA in display:
170
+ raise cv.Invalid("Using lambda: in display config not compatible with LVGL")
171
+ if display[CONF_AUTO_CLEAR_ENABLED]:
172
+ raise cv.Invalid(
173
+ "Using auto_clear_enabled: true in display config not compatible with LVGL"
174
+ )
175
+ buffer_frac = config[CONF_BUFFER_SIZE]
176
+ if CORE.is_esp32 and buffer_frac > 0.5 and "psram" not in global_config:
177
+ LOGGER.warning("buffer_size: may need to be reduced without PSRAM")
178
+ for image_id in lv_images_used:
179
+ path = global_config.get_path_for_id(image_id)[:-1]
180
+ image_conf = global_config.get_config_for_path(path)
181
+ if image_conf[CONF_TYPE] in ("RGBA", "RGB24"):
182
+ raise cv.Invalid(
183
+ "Using RGBA or RGB24 in image config not compatible with LVGL", path
184
+ )
185
+
186
+
187
+ async def to_code(config):
188
+ cg.add_library("lvgl/lvgl", "8.4.0")
189
+ CORE.add_define("USE_LVGL")
190
+ # suppress default enabling of extra widgets
191
+ add_define("_LV_KCONFIG_PRESENT")
192
+ # Always enable - lots of things use it.
193
+ add_define("LV_DRAW_COMPLEX", "1")
194
+ add_define("LV_TICK_CUSTOM", "1")
195
+ add_define("LV_TICK_CUSTOM_INCLUDE", '"esphome/components/lvgl/lvgl_hal.h"')
196
+ add_define("LV_TICK_CUSTOM_SYS_TIME_EXPR", "(lv_millis())")
197
+ add_define("LV_MEM_CUSTOM", "1")
198
+ add_define("LV_MEM_CUSTOM_ALLOC", "lv_custom_mem_alloc")
199
+ add_define("LV_MEM_CUSTOM_FREE", "lv_custom_mem_free")
200
+ add_define("LV_MEM_CUSTOM_REALLOC", "lv_custom_mem_realloc")
201
+ add_define("LV_MEM_CUSTOM_INCLUDE", '"esphome/components/lvgl/lvgl_hal.h"')
202
+
203
+ add_define("LV_LOG_LEVEL", f"LV_LOG_LEVEL_{config[df.CONF_LOG_LEVEL]}")
204
+ add_define("LV_COLOR_DEPTH", config[df.CONF_COLOR_DEPTH])
205
+ for font in helpers.lv_fonts_used:
206
+ add_define(f"LV_FONT_{font.upper()}")
207
+
208
+ if config[df.CONF_COLOR_DEPTH] == 16:
209
+ add_define(
210
+ "LV_COLOR_16_SWAP",
211
+ "1" if config[df.CONF_BYTE_ORDER] == "big_endian" else "0",
212
+ )
213
+ add_define(
214
+ "LV_COLOR_CHROMA_KEY",
215
+ await lvalid.lv_color.process(config[df.CONF_TRANSPARENCY_KEY]),
216
+ )
217
+ CORE.add_build_flag("-Isrc")
218
+
219
+ cg.add_global(lvgl_ns.using)
220
+ lv_component = cg.new_Pvariable(config[CONF_ID])
221
+ await cg.register_component(lv_component, config)
222
+ Widget.create(config[CONF_ID], lv_component, obj_spec, config)
223
+ for display in config[df.CONF_DISPLAYS]:
224
+ cg.add(lv_component.add_display(await cg.get_variable(display)))
225
+
226
+ frac = config[CONF_BUFFER_SIZE]
227
+ if frac >= 0.75:
228
+ frac = 1
229
+ elif frac >= 0.375:
230
+ frac = 2
231
+ elif frac > 0.19:
232
+ frac = 4
233
+ else:
234
+ frac = 8
235
+ cg.add(lv_component.set_buffer_frac(int(frac)))
236
+ cg.add(lv_component.set_full_refresh(config[df.CONF_FULL_REFRESH]))
237
+
238
+ for font in helpers.esphome_fonts_used:
239
+ await cg.get_variable(font)
240
+ cg.new_Pvariable(ID(f"{font}_engine", True, type=FontEngine), MockObj(font))
241
+ default_font = config[df.CONF_DEFAULT_FONT]
242
+ if not lvalid.is_lv_font(default_font):
243
+ add_define(
244
+ "LV_FONT_CUSTOM_DECLARE", f"LV_FONT_DECLARE(*{df.DEFAULT_ESPHOME_FONT})"
245
+ )
246
+ globfont_id = ID(
247
+ df.DEFAULT_ESPHOME_FONT,
248
+ True,
249
+ type=lv_font_t.operator("ptr").operator("const"),
250
+ )
251
+ cg.new_variable(
252
+ globfont_id, MockObj(await lvalid.lv_font.process(default_font))
253
+ )
254
+ add_define("LV_FONT_DEFAULT", df.DEFAULT_ESPHOME_FONT)
255
+ else:
256
+ add_define("LV_FONT_DEFAULT", await lvalid.lv_font.process(default_font))
257
+
258
+ async with LvContext(lv_component):
259
+ await touchscreens_to_code(lv_component, config)
260
+ await encoders_to_code(lv_component, config)
261
+ await theme_to_code(config)
262
+ await styles_to_code(config)
263
+ await set_obj_properties(lv_scr_act, config)
264
+ await add_widgets(lv_scr_act, config)
265
+ await add_pages(lv_component, config)
266
+ await add_top_layer(config)
267
+ await msgboxes_to_code(config)
268
+ await disp_update(f"{lv_component}->get_disp()", config)
269
+ Widget.set_completed()
270
+ await generate_triggers(lv_component)
271
+ for conf in config.get(CONF_ON_IDLE, ()):
272
+ templ = await cg.templatable(conf[CONF_TIMEOUT], [], cg.uint32)
273
+ idle_trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], lv_component, templ)
274
+ await build_automation(idle_trigger, [], conf)
275
+ await initial_focus_to_code(config)
276
+
277
+ for comp in helpers.lvgl_components_required:
278
+ CORE.add_define(f"USE_LVGL_{comp.upper()}")
279
+ for use in helpers.lv_uses:
280
+ add_define(f"LV_USE_{use.upper()}")
281
+ lv_conf_h_file = CORE.relative_src_path(LV_CONF_FILENAME)
282
+ write_file_if_changed(lv_conf_h_file, generate_lv_conf_h())
283
+ CORE.add_build_flag("-DLV_CONF_H=1")
284
+ CORE.add_build_flag(f'-DLV_CONF_PATH="{LV_CONF_FILENAME}"')
285
+
286
+
287
+ def display_schema(config):
288
+ value = cv.ensure_list(cv.use_id(Display))(config)
289
+ return value or [cv.use_id(Display)(config)]
290
+
291
+
292
+ FINAL_VALIDATE_SCHEMA = final_validation
293
+
294
+ CONFIG_SCHEMA = (
295
+ cv.polling_component_schema("1s")
296
+ .extend(obj_schema(obj_spec))
297
+ .extend(
298
+ {
299
+ cv.GenerateID(CONF_ID): cv.declare_id(LvglComponent),
300
+ cv.GenerateID(df.CONF_DISPLAYS): display_schema,
301
+ cv.Optional(df.CONF_COLOR_DEPTH, default=16): cv.one_of(16),
302
+ cv.Optional(df.CONF_DEFAULT_FONT, default="montserrat_14"): lvalid.lv_font,
303
+ cv.Optional(df.CONF_FULL_REFRESH, default=False): cv.boolean,
304
+ cv.Optional(CONF_BUFFER_SIZE, default="100%"): cv.percentage,
305
+ cv.Optional(df.CONF_LOG_LEVEL, default="WARN"): cv.one_of(
306
+ *df.LOG_LEVELS, upper=True
307
+ ),
308
+ cv.Optional(df.CONF_BYTE_ORDER, default="big_endian"): cv.one_of(
309
+ "big_endian", "little_endian"
310
+ ),
311
+ cv.Optional(df.CONF_STYLE_DEFINITIONS): cv.ensure_list(
312
+ cv.Schema({cv.Required(CONF_ID): cv.declare_id(lv_style_t)})
313
+ .extend(STYLE_SCHEMA)
314
+ .extend(
315
+ {
316
+ cv.Optional(df.CONF_GRID_CELL_X_ALIGN): grid_alignments,
317
+ cv.Optional(df.CONF_GRID_CELL_Y_ALIGN): grid_alignments,
318
+ }
319
+ )
320
+ ),
321
+ cv.Optional(CONF_ON_IDLE): validate_automation(
322
+ {
323
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(IdleTrigger),
324
+ cv.Required(CONF_TIMEOUT): cv.templatable(
325
+ cv.positive_time_period_milliseconds
326
+ ),
327
+ }
328
+ ),
329
+ cv.Exclusive(df.CONF_WIDGETS, CONF_PAGES): cv.ensure_list(WIDGET_SCHEMA),
330
+ cv.Exclusive(CONF_PAGES, CONF_PAGES): cv.ensure_list(
331
+ container_schema(page_spec)
332
+ ),
333
+ cv.Optional(df.CONF_MSGBOXES): cv.ensure_list(MSGBOX_SCHEMA),
334
+ cv.Optional(df.CONF_PAGE_WRAP, default=True): lv_bool,
335
+ cv.Optional(df.CONF_TOP_LAYER): container_schema(obj_spec),
336
+ cv.Optional(df.CONF_TRANSPARENCY_KEY, default=0x000400): lvalid.lv_color,
337
+ cv.Optional(df.CONF_THEME): cv.Schema(
338
+ {cv.Optional(name): obj_schema(w) for name, w in WIDGET_TYPES.items()}
339
+ ),
340
+ cv.Optional(df.CONF_TOUCHSCREENS, default=None): touchscreen_schema,
341
+ cv.Optional(df.CONF_ENCODERS, default=None): ENCODERS_CONFIG,
342
+ cv.GenerateID(df.CONF_DEFAULT_GROUP): cv.declare_id(lv_group_t),
343
+ }
344
+ )
345
+ .extend(DISP_BG_SCHEMA)
346
+ ).add_extra(cv.has_at_least_one_key(CONF_PAGES, df.CONF_WIDGETS))
@@ -0,0 +1,226 @@
1
+ from collections.abc import Awaitable
2
+ from typing import Callable
3
+
4
+ from esphome import automation
5
+ import esphome.codegen as cg
6
+ import esphome.config_validation as cv
7
+ from esphome.const import CONF_ID, CONF_TIMEOUT
8
+ from esphome.cpp_types import nullptr
9
+
10
+ from .defines import (
11
+ CONF_DISP_BG_COLOR,
12
+ CONF_DISP_BG_IMAGE,
13
+ CONF_LVGL_ID,
14
+ CONF_SHOW_SNOW,
15
+ literal,
16
+ )
17
+ from .lv_validation import lv_bool, lv_color, lv_image
18
+ from .lvcode import (
19
+ LVGL_COMP_ARG,
20
+ UPDATE_EVENT,
21
+ LambdaContext,
22
+ LocalVariable,
23
+ LvConditional,
24
+ LvglComponent,
25
+ ReturnStatement,
26
+ add_line_marks,
27
+ lv,
28
+ lv_add,
29
+ lv_obj,
30
+ lvgl_comp,
31
+ )
32
+ from .schemas import DISP_BG_SCHEMA, LIST_ACTION_SCHEMA, LVGL_SCHEMA
33
+ from .types import (
34
+ LV_STATE,
35
+ LvglAction,
36
+ LvglCondition,
37
+ ObjUpdateAction,
38
+ lv_disp_t,
39
+ lv_obj_t,
40
+ )
41
+ from .widgets import Widget, get_widgets, lv_scr_act, set_obj_properties
42
+
43
+
44
+ async def action_to_code(
45
+ widgets: list[Widget],
46
+ action: Callable[[Widget], Awaitable[None]],
47
+ action_id,
48
+ template_arg,
49
+ args,
50
+ ):
51
+ async with LambdaContext(parameters=args, where=action_id) as context:
52
+ for widget in widgets:
53
+ with LvConditional(widget.obj != nullptr):
54
+ await action(widget)
55
+ var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
56
+ return var
57
+
58
+
59
+ async def update_to_code(config, action_id, template_arg, args):
60
+ async def do_update(widget: Widget):
61
+ await set_obj_properties(widget, config)
62
+ await widget.type.to_code(widget, config)
63
+ if (
64
+ widget.type.w_type.value_property is not None
65
+ and widget.type.w_type.value_property in config
66
+ ):
67
+ lv.event_send(widget.obj, UPDATE_EVENT, nullptr)
68
+
69
+ widgets = await get_widgets(config[CONF_ID])
70
+ return await action_to_code(widgets, do_update, action_id, template_arg, args)
71
+
72
+
73
+ @automation.register_condition(
74
+ "lvgl.is_paused",
75
+ LvglCondition,
76
+ LVGL_SCHEMA,
77
+ )
78
+ async def lvgl_is_paused(config, condition_id, template_arg, args):
79
+ lvgl = config[CONF_LVGL_ID]
80
+ async with LambdaContext(LVGL_COMP_ARG, return_type=cg.bool_) as context:
81
+ lv_add(ReturnStatement(lvgl_comp.is_paused()))
82
+ var = cg.new_Pvariable(condition_id, template_arg, await context.get_lambda())
83
+ await cg.register_parented(var, lvgl)
84
+ return var
85
+
86
+
87
+ @automation.register_condition(
88
+ "lvgl.is_idle",
89
+ LvglCondition,
90
+ LVGL_SCHEMA.extend(
91
+ {
92
+ cv.Required(CONF_TIMEOUT): cv.templatable(
93
+ cv.positive_time_period_milliseconds
94
+ )
95
+ }
96
+ ),
97
+ )
98
+ async def lvgl_is_idle(config, condition_id, template_arg, args):
99
+ lvgl = config[CONF_LVGL_ID]
100
+ timeout = await cg.templatable(config[CONF_TIMEOUT], [], cg.uint32)
101
+ async with LambdaContext(LVGL_COMP_ARG, return_type=cg.bool_) as context:
102
+ lv_add(ReturnStatement(lvgl_comp.is_idle(timeout)))
103
+ var = cg.new_Pvariable(condition_id, template_arg, await context.get_lambda())
104
+ await cg.register_parented(var, lvgl)
105
+ return var
106
+
107
+
108
+ async def disp_update(disp, config: dict):
109
+ if CONF_DISP_BG_COLOR not in config and CONF_DISP_BG_IMAGE not in config:
110
+ return
111
+ with LocalVariable("lv_disp_tmp", lv_disp_t, literal(disp)) as disp_temp:
112
+ if (bg_color := config.get(CONF_DISP_BG_COLOR)) is not None:
113
+ lv.disp_set_bg_color(disp_temp, await lv_color.process(bg_color))
114
+ if bg_image := config.get(CONF_DISP_BG_IMAGE):
115
+ lv.disp_set_bg_image(disp_temp, await lv_image.process(bg_image))
116
+
117
+
118
+ @automation.register_action(
119
+ "lvgl.widget.redraw",
120
+ ObjUpdateAction,
121
+ cv.Schema(
122
+ {
123
+ cv.Optional(CONF_ID): cv.use_id(lv_obj_t),
124
+ cv.GenerateID(CONF_LVGL_ID): cv.use_id(LvglComponent),
125
+ }
126
+ ),
127
+ )
128
+ async def obj_invalidate_to_code(config, action_id, template_arg, args):
129
+ widgets = await get_widgets(config) or [lv_scr_act]
130
+
131
+ async def do_invalidate(widget: Widget):
132
+ lv_obj.invalidate(widget.obj)
133
+
134
+ return await action_to_code(widgets, do_invalidate, action_id, template_arg, args)
135
+
136
+
137
+ @automation.register_action(
138
+ "lvgl.update",
139
+ LvglAction,
140
+ DISP_BG_SCHEMA.extend(
141
+ {
142
+ cv.GenerateID(): cv.use_id(LvglComponent),
143
+ }
144
+ ).add_extra(cv.has_at_least_one_key(CONF_DISP_BG_COLOR, CONF_DISP_BG_IMAGE)),
145
+ )
146
+ async def lvgl_update_to_code(config, action_id, template_arg, args):
147
+ widgets = await get_widgets(config)
148
+ w = widgets[0]
149
+ disp = f"{w.obj}->get_disp()"
150
+ async with LambdaContext(parameters=args, where=action_id) as context:
151
+ await disp_update(disp, config)
152
+ var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
153
+ await cg.register_parented(var, w.var)
154
+ return var
155
+
156
+
157
+ @automation.register_action(
158
+ "lvgl.pause",
159
+ LvglAction,
160
+ {
161
+ cv.GenerateID(): cv.use_id(LvglComponent),
162
+ cv.Optional(CONF_SHOW_SNOW, default=False): lv_bool,
163
+ },
164
+ )
165
+ async def pause_action_to_code(config, action_id, template_arg, args):
166
+ async with LambdaContext(LVGL_COMP_ARG) as context:
167
+ add_line_marks(where=action_id)
168
+ lv_add(lvgl_comp.set_paused(True, config[CONF_SHOW_SNOW]))
169
+ var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
170
+ await cg.register_parented(var, config[CONF_ID])
171
+ return var
172
+
173
+
174
+ @automation.register_action(
175
+ "lvgl.resume",
176
+ LvglAction,
177
+ {
178
+ cv.GenerateID(): cv.use_id(LvglComponent),
179
+ },
180
+ )
181
+ async def resume_action_to_code(config, action_id, template_arg, args):
182
+ async with LambdaContext(LVGL_COMP_ARG, where=action_id) as context:
183
+ lv_add(lvgl_comp.set_paused(False, False))
184
+ var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
185
+ await cg.register_parented(var, config[CONF_ID])
186
+ return var
187
+
188
+
189
+ @automation.register_action("lvgl.widget.disable", ObjUpdateAction, LIST_ACTION_SCHEMA)
190
+ async def obj_disable_to_code(config, action_id, template_arg, args):
191
+ async def do_disable(widget: Widget):
192
+ widget.add_state(LV_STATE.DISABLED)
193
+
194
+ return await action_to_code(
195
+ await get_widgets(config), do_disable, action_id, template_arg, args
196
+ )
197
+
198
+
199
+ @automation.register_action("lvgl.widget.enable", ObjUpdateAction, LIST_ACTION_SCHEMA)
200
+ async def obj_enable_to_code(config, action_id, template_arg, args):
201
+ async def do_enable(widget: Widget):
202
+ widget.clear_state(LV_STATE.DISABLED)
203
+
204
+ return await action_to_code(
205
+ await get_widgets(config), do_enable, action_id, template_arg, args
206
+ )
207
+
208
+
209
+ @automation.register_action("lvgl.widget.hide", ObjUpdateAction, LIST_ACTION_SCHEMA)
210
+ async def obj_hide_to_code(config, action_id, template_arg, args):
211
+ async def do_hide(widget: Widget):
212
+ widget.add_flag("LV_OBJ_FLAG_HIDDEN")
213
+
214
+ return await action_to_code(
215
+ await get_widgets(config), do_hide, action_id, template_arg, args
216
+ )
217
+
218
+
219
+ @automation.register_action("lvgl.widget.show", ObjUpdateAction, LIST_ACTION_SCHEMA)
220
+ async def obj_show_to_code(config, action_id, template_arg, args):
221
+ async def do_show(widget: Widget):
222
+ widget.clear_flag("LV_OBJ_FLAG_HIDDEN")
223
+
224
+ return await action_to_code(
225
+ await get_widgets(config), do_show, action_id, template_arg, args
226
+ )
@@ -0,0 +1,43 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components.binary_sensor import (
3
+ BinarySensor,
4
+ binary_sensor_schema,
5
+ new_binary_sensor,
6
+ )
7
+ import esphome.config_validation as cv
8
+
9
+ from ..defines import CONF_LVGL_ID, CONF_WIDGET
10
+ from ..lvcode import EVENT_ARG, LambdaContext, LvContext
11
+ from ..schemas import LVGL_SCHEMA
12
+ from ..types import LV_EVENT, lv_pseudo_button_t
13
+ from ..widgets import Widget, get_widgets
14
+
15
+ CONFIG_SCHEMA = (
16
+ binary_sensor_schema(BinarySensor)
17
+ .extend(LVGL_SCHEMA)
18
+ .extend(
19
+ {
20
+ cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t),
21
+ }
22
+ )
23
+ )
24
+
25
+
26
+ async def to_code(config):
27
+ sensor = await new_binary_sensor(config)
28
+ paren = await cg.get_variable(config[CONF_LVGL_ID])
29
+ widget = await get_widgets(config, CONF_WIDGET)
30
+ widget = widget[0]
31
+ assert isinstance(widget, Widget)
32
+ async with LambdaContext(EVENT_ARG) as pressed_ctx:
33
+ pressed_ctx.add(sensor.publish_state(widget.is_pressed()))
34
+ async with LvContext(paren) as ctx:
35
+ ctx.add(sensor.publish_initial_state(widget.is_pressed()))
36
+ ctx.add(
37
+ paren.add_event_cb(
38
+ widget.obj,
39
+ await pressed_ctx.get_lambda(),
40
+ LV_EVENT.PRESSING,
41
+ LV_EVENT.RELEASED,
42
+ )
43
+ )