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,508 @@
1
+ """
2
+ This is the base of the import tree for LVGL. It contains constant definitions used elsewhere.
3
+ Constants already defined in esphome.const are not duplicated here and must be imported where used.
4
+
5
+ """
6
+
7
+ from esphome import codegen as cg, config_validation as cv
8
+ from esphome.const import CONF_ITEMS
9
+ from esphome.core import Lambda
10
+ from esphome.cpp_generator import LambdaExpression, MockObj
11
+ from esphome.cpp_types import uint32
12
+ from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
13
+
14
+ from .helpers import requires_component
15
+
16
+ lvgl_ns = cg.esphome_ns.namespace("lvgl")
17
+
18
+
19
+ def literal(arg):
20
+ if isinstance(arg, str):
21
+ return MockObj(arg)
22
+ return arg
23
+
24
+
25
+ def call_lambda(lamb: LambdaExpression):
26
+ expr = lamb.content.strip()
27
+ if expr.startswith("return") and expr.endswith(";"):
28
+ return expr[7:][:-1]
29
+ return f"{lamb}()"
30
+
31
+
32
+ class LValidator:
33
+ """
34
+ A validator for a particular type used in LVGL. Usable in configs as a validator, also
35
+ has `process()` to convert a value during code generation
36
+ """
37
+
38
+ def __init__(self, validator, rtype, retmapper=None, requires=None):
39
+ self.validator = validator
40
+ self.rtype = rtype
41
+ self.retmapper = retmapper
42
+ self.requires = requires
43
+
44
+ def __call__(self, value):
45
+ if self.requires:
46
+ value = requires_component(self.requires)(value)
47
+ if isinstance(value, cv.Lambda):
48
+ return cv.returning_lambda(value)
49
+ return self.validator(value)
50
+
51
+ async def process(self, value, args=()):
52
+ if value is None:
53
+ return None
54
+ if isinstance(value, Lambda):
55
+ return cg.RawExpression(
56
+ call_lambda(
57
+ await cg.process_lambda(value, args, return_type=self.rtype)
58
+ )
59
+ )
60
+ if self.retmapper is not None:
61
+ return self.retmapper(value)
62
+ return cg.safe_exp(value)
63
+
64
+
65
+ class LvConstant(LValidator):
66
+ """
67
+ Allow one of a list of choices, mapped to upper case, and prepend the choice with the prefix.
68
+ It's also permitted to include the prefix in the value
69
+ The property `one_of` has the single case validator, and `several_of` allows a list of constants.
70
+ """
71
+
72
+ def __init__(self, prefix: str, *choices):
73
+ self.prefix = prefix
74
+ self.choices = choices
75
+ prefixed_choices = [prefix + v for v in choices]
76
+ prefixed_validator = cv.one_of(*prefixed_choices, upper=True)
77
+
78
+ @schema_extractor("one_of")
79
+ def validator(value):
80
+ if value == SCHEMA_EXTRACT:
81
+ return self.choices
82
+ if isinstance(value, str) and value.startswith(self.prefix):
83
+ return prefixed_validator(value)
84
+ return self.prefix + cv.one_of(*choices, upper=True)(value)
85
+
86
+ super().__init__(validator, rtype=uint32)
87
+ self.retmapper = self.mapper
88
+ self.one_of = LValidator(validator, uint32, retmapper=self.mapper)
89
+ self.several_of = LValidator(
90
+ cv.ensure_list(self.one_of), uint32, retmapper=self.mapper
91
+ )
92
+
93
+ def mapper(self, value):
94
+ if not isinstance(value, list):
95
+ value = [value]
96
+ return literal(
97
+ "|".join(
98
+ [
99
+ str(v) if str(v).startswith(self.prefix) else self.prefix + str(v)
100
+ for v in value
101
+ ]
102
+ ).upper()
103
+ )
104
+
105
+ def extend(self, *choices):
106
+ """
107
+ Extend an LVconstant with additional choices.
108
+ :param choices: The extra choices
109
+ :return: A new LVConstant instance
110
+ """
111
+ return LvConstant(self.prefix, *(self.choices + choices))
112
+
113
+
114
+ # Parts
115
+ CONF_MAIN = "main"
116
+ CONF_SCROLLBAR = "scrollbar"
117
+ CONF_INDICATOR = "indicator"
118
+ CONF_KNOB = "knob"
119
+ CONF_SELECTED = "selected"
120
+ CONF_TICKS = "ticks"
121
+ CONF_CURSOR = "cursor"
122
+ CONF_TEXTAREA_PLACEHOLDER = "textarea_placeholder"
123
+
124
+ # Layout types
125
+
126
+ TYPE_FLEX = "flex"
127
+ TYPE_GRID = "grid"
128
+ TYPE_NONE = "none"
129
+
130
+ LV_FONTS = list(f"montserrat_{s}" for s in range(8, 50, 2)) + [
131
+ "dejavu_16_persian_hebrew",
132
+ "simsun_16_cjk",
133
+ "unscii_8",
134
+ "unscii_16",
135
+ ]
136
+
137
+ LV_EVENT_MAP = {
138
+ "PRESS": "PRESSED",
139
+ "SHORT_CLICK": "SHORT_CLICKED",
140
+ "LONG_PRESS": "LONG_PRESSED",
141
+ "LONG_PRESS_REPEAT": "LONG_PRESSED_REPEAT",
142
+ "CLICK": "CLICKED",
143
+ "RELEASE": "RELEASED",
144
+ "SCROLL_BEGIN": "SCROLL_BEGIN",
145
+ "SCROLL_END": "SCROLL_END",
146
+ "SCROLL": "SCROLL",
147
+ "FOCUS": "FOCUSED",
148
+ "DEFOCUS": "DEFOCUSED",
149
+ "READY": "READY",
150
+ "CANCEL": "CANCEL",
151
+ }
152
+
153
+ LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT_MAP)
154
+
155
+
156
+ LV_ANIM = LvConstant(
157
+ "LV_SCR_LOAD_ANIM_",
158
+ "NONE",
159
+ "OVER_LEFT",
160
+ "OVER_RIGHT",
161
+ "OVER_TOP",
162
+ "OVER_BOTTOM",
163
+ "MOVE_LEFT",
164
+ "MOVE_RIGHT",
165
+ "MOVE_TOP",
166
+ "MOVE_BOTTOM",
167
+ "FADE_IN",
168
+ "FADE_OUT",
169
+ "OUT_LEFT",
170
+ "OUT_RIGHT",
171
+ "OUT_TOP",
172
+ "OUT_BOTTOM",
173
+ )
174
+
175
+ LOG_LEVELS = (
176
+ "TRACE",
177
+ "INFO",
178
+ "WARN",
179
+ "ERROR",
180
+ "USER",
181
+ "NONE",
182
+ )
183
+
184
+ LV_LONG_MODES = LvConstant(
185
+ "LV_LABEL_LONG_",
186
+ "WRAP",
187
+ "DOT",
188
+ "SCROLL",
189
+ "SCROLL_CIRCULAR",
190
+ "CLIP",
191
+ )
192
+
193
+ STATES = (
194
+ "default",
195
+ "checked",
196
+ "focused",
197
+ "focus_key",
198
+ "edited",
199
+ "hovered",
200
+ "pressed",
201
+ "scrolled",
202
+ "disabled",
203
+ "user_1",
204
+ "user_2",
205
+ "user_3",
206
+ "user_4",
207
+ )
208
+
209
+ PARTS = (
210
+ CONF_MAIN,
211
+ CONF_SCROLLBAR,
212
+ CONF_INDICATOR,
213
+ CONF_KNOB,
214
+ CONF_SELECTED,
215
+ CONF_ITEMS,
216
+ CONF_TICKS,
217
+ CONF_CURSOR,
218
+ CONF_TEXTAREA_PLACEHOLDER,
219
+ )
220
+
221
+ KEYBOARD_MODES = LvConstant(
222
+ "LV_KEYBOARD_MODE_",
223
+ "TEXT_LOWER",
224
+ "TEXT_UPPER",
225
+ "SPECIAL",
226
+ "NUMBER",
227
+ )
228
+ ROLLER_MODES = LvConstant("LV_ROLLER_MODE_", "NORMAL", "INFINITE")
229
+ DIRECTIONS = LvConstant("LV_DIR_", "LEFT", "RIGHT", "BOTTOM", "TOP")
230
+ TILE_DIRECTIONS = DIRECTIONS.extend("HOR", "VER", "ALL")
231
+ CHILD_ALIGNMENTS = LvConstant(
232
+ "LV_ALIGN_",
233
+ "TOP_LEFT",
234
+ "TOP_MID",
235
+ "TOP_RIGHT",
236
+ "LEFT_MID",
237
+ "CENTER",
238
+ "RIGHT_MID",
239
+ "BOTTOM_LEFT",
240
+ "BOTTOM_MID",
241
+ "BOTTOM_RIGHT",
242
+ )
243
+
244
+ SIBLING_ALIGNMENTS = LvConstant(
245
+ "LV_ALIGN_",
246
+ "OUT_LEFT_TOP",
247
+ "OUT_TOP_LEFT",
248
+ "OUT_TOP_MID",
249
+ "OUT_TOP_RIGHT",
250
+ "OUT_RIGHT_TOP",
251
+ "OUT_LEFT_MID",
252
+ "OUT_RIGHT_MID",
253
+ "OUT_LEFT_BOTTOM",
254
+ "OUT_BOTTOM_LEFT",
255
+ "OUT_BOTTOM_MID",
256
+ "OUT_BOTTOM_RIGHT",
257
+ "OUT_RIGHT_BOTTOM",
258
+ )
259
+ ALIGN_ALIGNMENTS = CHILD_ALIGNMENTS.extend(*SIBLING_ALIGNMENTS.choices)
260
+
261
+ FLEX_FLOWS = LvConstant(
262
+ "LV_FLEX_FLOW_",
263
+ "ROW",
264
+ "COLUMN",
265
+ "ROW_WRAP",
266
+ "COLUMN_WRAP",
267
+ "ROW_REVERSE",
268
+ "COLUMN_REVERSE",
269
+ "ROW_WRAP_REVERSE",
270
+ "COLUMN_WRAP_REVERSE",
271
+ )
272
+
273
+ OBJ_FLAGS = (
274
+ "hidden",
275
+ "clickable",
276
+ "click_focusable",
277
+ "checkable",
278
+ "scrollable",
279
+ "scroll_elastic",
280
+ "scroll_momentum",
281
+ "scroll_one",
282
+ "scroll_chain_hor",
283
+ "scroll_chain_ver",
284
+ "scroll_chain",
285
+ "scroll_on_focus",
286
+ "scroll_with_arrow",
287
+ "snappable",
288
+ "press_lock",
289
+ "event_bubble",
290
+ "gesture_bubble",
291
+ "adv_hittest",
292
+ "ignore_layout",
293
+ "floating",
294
+ "overflow_visible",
295
+ "layout_1",
296
+ "layout_2",
297
+ "widget_1",
298
+ "widget_2",
299
+ "user_1",
300
+ "user_2",
301
+ "user_3",
302
+ "user_4",
303
+ )
304
+
305
+ ARC_MODES = LvConstant("LV_ARC_MODE_", "NORMAL", "REVERSE", "SYMMETRICAL")
306
+ BAR_MODES = LvConstant("LV_BAR_MODE_", "NORMAL", "SYMMETRICAL", "RANGE")
307
+
308
+ BUTTONMATRIX_CTRLS = LvConstant(
309
+ "LV_BTNMATRIX_CTRL_",
310
+ "HIDDEN",
311
+ "NO_REPEAT",
312
+ "DISABLED",
313
+ "CHECKABLE",
314
+ "CHECKED",
315
+ "CLICK_TRIG",
316
+ "POPOVER",
317
+ "RECOLOR",
318
+ "CUSTOM_1",
319
+ "CUSTOM_2",
320
+ )
321
+
322
+ LV_BASE_ALIGNMENTS = (
323
+ "START",
324
+ "CENTER",
325
+ "END",
326
+ )
327
+ LV_CELL_ALIGNMENTS = LvConstant(
328
+ "LV_GRID_ALIGN_",
329
+ *LV_BASE_ALIGNMENTS,
330
+ )
331
+ LV_GRID_ALIGNMENTS = LV_CELL_ALIGNMENTS.extend(
332
+ "STRETCH",
333
+ "SPACE_EVENLY",
334
+ "SPACE_AROUND",
335
+ "SPACE_BETWEEN",
336
+ )
337
+
338
+ LV_FLEX_ALIGNMENTS = LvConstant(
339
+ "LV_FLEX_ALIGN_",
340
+ *LV_BASE_ALIGNMENTS,
341
+ "SPACE_EVENLY",
342
+ "SPACE_AROUND",
343
+ "SPACE_BETWEEN",
344
+ )
345
+
346
+ LV_MENU_MODES = LvConstant(
347
+ "LV_MENU_HEADER_",
348
+ "TOP_FIXED",
349
+ "TOP_UNFIXED",
350
+ "BOTTOM_FIXED",
351
+ )
352
+
353
+ LV_CHART_TYPES = (
354
+ "NONE",
355
+ "LINE",
356
+ "BAR",
357
+ "SCATTER",
358
+ )
359
+ LV_CHART_AXES = (
360
+ "PRIMARY_Y",
361
+ "SECONDARY_Y",
362
+ "PRIMARY_X",
363
+ "SECONDARY_X",
364
+ )
365
+
366
+ CONF_ACCEPTED_CHARS = "accepted_chars"
367
+ CONF_ADJUSTABLE = "adjustable"
368
+ CONF_ALIGN = "align"
369
+ CONF_ALIGN_TO = "align_to"
370
+ CONF_ANIMATED = "animated"
371
+ CONF_ANIMATION = "animation"
372
+ CONF_ANTIALIAS = "antialias"
373
+ CONF_ARC_LENGTH = "arc_length"
374
+ CONF_AUTO_START = "auto_start"
375
+ CONF_BACKGROUND_STYLE = "background_style"
376
+ CONF_DECIMAL_PLACES = "decimal_places"
377
+ CONF_COLUMN = "column"
378
+ CONF_DIGITS = "digits"
379
+ CONF_DISP_BG_COLOR = "disp_bg_color"
380
+ CONF_DISP_BG_IMAGE = "disp_bg_image"
381
+ CONF_BODY = "body"
382
+ CONF_BUTTONS = "buttons"
383
+ CONF_BYTE_ORDER = "byte_order"
384
+ CONF_CHANGE_RATE = "change_rate"
385
+ CONF_CLOSE_BUTTON = "close_button"
386
+ CONF_COLOR_DEPTH = "color_depth"
387
+ CONF_CONTROL = "control"
388
+ CONF_DEFAULT = "default"
389
+ CONF_DEFAULT_FONT = "default_font"
390
+ CONF_DEFAULT_GROUP = "default_group"
391
+ CONF_DIR = "dir"
392
+ CONF_DISPLAYS = "displays"
393
+ CONF_ENCODERS = "encoders"
394
+ CONF_END_ANGLE = "end_angle"
395
+ CONF_END_VALUE = "end_value"
396
+ CONF_ENTER_BUTTON = "enter_button"
397
+ CONF_ENTRIES = "entries"
398
+ CONF_FLAGS = "flags"
399
+ CONF_FLEX_FLOW = "flex_flow"
400
+ CONF_FLEX_ALIGN_MAIN = "flex_align_main"
401
+ CONF_FLEX_ALIGN_CROSS = "flex_align_cross"
402
+ CONF_FLEX_ALIGN_TRACK = "flex_align_track"
403
+ CONF_FLEX_GROW = "flex_grow"
404
+ CONF_FULL_REFRESH = "full_refresh"
405
+ CONF_GRID_CELL_ROW_POS = "grid_cell_row_pos"
406
+ CONF_GRID_CELL_COLUMN_POS = "grid_cell_column_pos"
407
+ CONF_GRID_CELL_ROW_SPAN = "grid_cell_row_span"
408
+ CONF_GRID_CELL_COLUMN_SPAN = "grid_cell_column_span"
409
+ CONF_GRID_CELL_X_ALIGN = "grid_cell_x_align"
410
+ CONF_GRID_CELL_Y_ALIGN = "grid_cell_y_align"
411
+ CONF_GRID_COLUMN_ALIGN = "grid_column_align"
412
+ CONF_GRID_COLUMNS = "grid_columns"
413
+ CONF_GRID_ROW_ALIGN = "grid_row_align"
414
+ CONF_GRID_ROWS = "grid_rows"
415
+ CONF_HEADER_MODE = "header_mode"
416
+ CONF_HOME = "home"
417
+ CONF_INITIAL_FOCUS = "initial_focus"
418
+ CONF_KEY_CODE = "key_code"
419
+ CONF_LAYOUT = "layout"
420
+ CONF_LEFT_BUTTON = "left_button"
421
+ CONF_LINE_WIDTH = "line_width"
422
+ CONF_LOG_LEVEL = "log_level"
423
+ CONF_LONG_PRESS_TIME = "long_press_time"
424
+ CONF_LONG_PRESS_REPEAT_TIME = "long_press_repeat_time"
425
+ CONF_LVGL_ID = "lvgl_id"
426
+ CONF_LONG_MODE = "long_mode"
427
+ CONF_MSGBOXES = "msgboxes"
428
+ CONF_OBJ = "obj"
429
+ CONF_OFFSET_X = "offset_x"
430
+ CONF_OFFSET_Y = "offset_y"
431
+ CONF_ONE_LINE = "one_line"
432
+ CONF_ON_SELECT = "on_select"
433
+ CONF_ONE_CHECKED = "one_checked"
434
+ CONF_NEXT = "next"
435
+ CONF_PAD_ROW = "pad_row"
436
+ CONF_PAD_COLUMN = "pad_column"
437
+ CONF_PAGE = "page"
438
+ CONF_PAGE_WRAP = "page_wrap"
439
+ CONF_PASSWORD_MODE = "password_mode"
440
+ CONF_PIVOT_X = "pivot_x"
441
+ CONF_PIVOT_Y = "pivot_y"
442
+ CONF_PLACEHOLDER_TEXT = "placeholder_text"
443
+ CONF_POINTS = "points"
444
+ CONF_PREVIOUS = "previous"
445
+ CONF_REPEAT_COUNT = "repeat_count"
446
+ CONF_RECOLOR = "recolor"
447
+ CONF_RIGHT_BUTTON = "right_button"
448
+ CONF_ROLLOVER = "rollover"
449
+ CONF_ROOT_BACK_BTN = "root_back_btn"
450
+ CONF_ROWS = "rows"
451
+ CONF_SCALE_LINES = "scale_lines"
452
+ CONF_SCROLLBAR_MODE = "scrollbar_mode"
453
+ CONF_SELECTED_INDEX = "selected_index"
454
+ CONF_SHOW_SNOW = "show_snow"
455
+ CONF_SPIN_TIME = "spin_time"
456
+ CONF_SRC = "src"
457
+ CONF_START_ANGLE = "start_angle"
458
+ CONF_START_VALUE = "start_value"
459
+ CONF_STATES = "states"
460
+ CONF_STYLE = "style"
461
+ CONF_STYLES = "styles"
462
+ CONF_STYLE_DEFINITIONS = "style_definitions"
463
+ CONF_STYLE_ID = "style_id"
464
+ CONF_SKIP = "skip"
465
+ CONF_SYMBOL = "symbol"
466
+ CONF_TAB_ID = "tab_id"
467
+ CONF_TABS = "tabs"
468
+ CONF_TIME_FORMAT = "time_format"
469
+ CONF_TILE = "tile"
470
+ CONF_TILE_ID = "tile_id"
471
+ CONF_TILES = "tiles"
472
+ CONF_TITLE = "title"
473
+ CONF_TOP_LAYER = "top_layer"
474
+ CONF_TOUCHSCREENS = "touchscreens"
475
+ CONF_TRANSPARENCY_KEY = "transparency_key"
476
+ CONF_THEME = "theme"
477
+ CONF_UPDATE_ON_RELEASE = "update_on_release"
478
+ CONF_VISIBLE_ROW_COUNT = "visible_row_count"
479
+ CONF_WIDGET = "widget"
480
+ CONF_WIDGETS = "widgets"
481
+ CONF_X = "x"
482
+ CONF_Y = "y"
483
+ CONF_ZOOM = "zoom"
484
+
485
+ # Keypad keys
486
+
487
+ LV_KEYS = LvConstant(
488
+ "LV_KEY_",
489
+ "UP",
490
+ "DOWN",
491
+ "RIGHT",
492
+ "LEFT",
493
+ "ESC",
494
+ "DEL",
495
+ "BACKSPACE",
496
+ "ENTER",
497
+ "NEXT",
498
+ "PREV",
499
+ "HOME",
500
+ "END",
501
+ )
502
+
503
+
504
+ DEFAULT_ESPHOME_FONT = "esphome_lv_default_font"
505
+
506
+
507
+ def join_enums(enums, prefix=""):
508
+ return literal("|".join(f"(int){prefix}{e.upper()}" for e in enums))
@@ -0,0 +1,77 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components.binary_sensor import BinarySensor
3
+ from esphome.components.rotary_encoder.sensor import RotaryEncoderSensor
4
+ import esphome.config_validation as cv
5
+ from esphome.const import CONF_GROUP, CONF_ID, CONF_SENSOR
6
+
7
+ from .defines import (
8
+ CONF_DEFAULT_GROUP,
9
+ CONF_ENCODERS,
10
+ CONF_ENTER_BUTTON,
11
+ CONF_INITIAL_FOCUS,
12
+ CONF_LEFT_BUTTON,
13
+ CONF_LONG_PRESS_REPEAT_TIME,
14
+ CONF_LONG_PRESS_TIME,
15
+ CONF_RIGHT_BUTTON,
16
+ )
17
+ from .helpers import lvgl_components_required, requires_component
18
+ from .lvcode import lv, lv_add, lv_assign, lv_expr, lv_Pvariable
19
+ from .schemas import ENCODER_SCHEMA
20
+ from .types import lv_group_t, lv_indev_type_t
21
+
22
+ ENCODERS_CONFIG = cv.ensure_list(
23
+ ENCODER_SCHEMA.extend(
24
+ {
25
+ cv.Required(CONF_ENTER_BUTTON): cv.use_id(BinarySensor),
26
+ cv.Required(CONF_SENSOR): cv.Any(
27
+ cv.All(
28
+ cv.use_id(RotaryEncoderSensor), requires_component("rotary_encoder")
29
+ ),
30
+ cv.Schema(
31
+ {
32
+ cv.Required(CONF_LEFT_BUTTON): cv.use_id(BinarySensor),
33
+ cv.Required(CONF_RIGHT_BUTTON): cv.use_id(BinarySensor),
34
+ }
35
+ ),
36
+ ),
37
+ }
38
+ )
39
+ )
40
+
41
+
42
+ async def encoders_to_code(var, config):
43
+ default_group = lv_Pvariable(lv_group_t, config[CONF_DEFAULT_GROUP])
44
+ lv_assign(default_group, lv_expr.group_create())
45
+ lv.group_set_default(default_group)
46
+ for enc_conf in config[CONF_ENCODERS]:
47
+ lvgl_components_required.add("KEY_LISTENER")
48
+ lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds
49
+ lprt = enc_conf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds
50
+ listener = cg.new_Pvariable(
51
+ enc_conf[CONF_ID], lv_indev_type_t.LV_INDEV_TYPE_ENCODER, lpt, lprt
52
+ )
53
+ await cg.register_parented(listener, var)
54
+ if sensor_config := enc_conf.get(CONF_SENSOR):
55
+ if isinstance(sensor_config, dict):
56
+ b_sensor = await cg.get_variable(sensor_config[CONF_LEFT_BUTTON])
57
+ cg.add(listener.set_left_button(b_sensor))
58
+ b_sensor = await cg.get_variable(sensor_config[CONF_RIGHT_BUTTON])
59
+ cg.add(listener.set_right_button(b_sensor))
60
+ else:
61
+ sensor_config = await cg.get_variable(sensor_config)
62
+ lv_add(listener.set_sensor(sensor_config))
63
+ b_sensor = await cg.get_variable(enc_conf[CONF_ENTER_BUTTON])
64
+ cg.add(listener.set_enter_button(b_sensor))
65
+ if group := enc_conf.get(CONF_GROUP):
66
+ group = lv_Pvariable(lv_group_t, group)
67
+ lv_assign(group, lv_expr.group_create())
68
+ else:
69
+ group = default_group
70
+ lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group)
71
+
72
+
73
+ async def initial_focus_to_code(config):
74
+ for enc_conf in config[CONF_ENCODERS]:
75
+ if default_focus := enc_conf.get(CONF_INITIAL_FOCUS):
76
+ obj = await cg.get_variable(default_focus)
77
+ lv.group_focus_obj(obj)
@@ -0,0 +1,76 @@
1
+ #include "lvgl_esphome.h"
2
+
3
+ #ifdef USE_LVGL_FONT
4
+ namespace esphome {
5
+ namespace lvgl {
6
+
7
+ static const uint8_t *get_glyph_bitmap(const lv_font_t *font, uint32_t unicode_letter) {
8
+ auto *fe = (FontEngine *) font->dsc;
9
+ const auto *gd = fe->get_glyph_data(unicode_letter);
10
+ if (gd == nullptr)
11
+ return nullptr;
12
+ // esph_log_d(TAG, "Returning bitmap @ %X", (uint32_t)gd->data);
13
+
14
+ return gd->data;
15
+ }
16
+
17
+ static bool get_glyph_dsc_cb(const lv_font_t *font, lv_font_glyph_dsc_t *dsc, uint32_t unicode_letter, uint32_t next) {
18
+ auto *fe = (FontEngine *) font->dsc;
19
+ const auto *gd = fe->get_glyph_data(unicode_letter);
20
+ if (gd == nullptr)
21
+ return false;
22
+ dsc->adv_w = gd->offset_x + gd->width;
23
+ dsc->ofs_x = gd->offset_x;
24
+ dsc->ofs_y = fe->height - gd->height - gd->offset_y - fe->baseline;
25
+ dsc->box_w = gd->width;
26
+ dsc->box_h = gd->height;
27
+ dsc->is_placeholder = 0;
28
+ dsc->bpp = fe->bpp;
29
+ return true;
30
+ }
31
+
32
+ FontEngine::FontEngine(font::Font *esp_font) : font_(esp_font) {
33
+ this->bpp = esp_font->get_bpp();
34
+ this->lv_font_.dsc = this;
35
+ this->lv_font_.line_height = this->height = esp_font->get_height();
36
+ this->lv_font_.base_line = this->baseline = this->lv_font_.line_height - esp_font->get_baseline();
37
+ this->lv_font_.get_glyph_dsc = get_glyph_dsc_cb;
38
+ this->lv_font_.get_glyph_bitmap = get_glyph_bitmap;
39
+ this->lv_font_.subpx = LV_FONT_SUBPX_NONE;
40
+ this->lv_font_.underline_position = -1;
41
+ this->lv_font_.underline_thickness = 1;
42
+ }
43
+
44
+ const lv_font_t *FontEngine::get_lv_font() { return &this->lv_font_; }
45
+
46
+ const font::GlyphData *FontEngine::get_glyph_data(uint32_t unicode_letter) {
47
+ if (unicode_letter == last_letter_)
48
+ return this->last_data_;
49
+ uint8_t unicode[5];
50
+ memset(unicode, 0, sizeof unicode);
51
+ if (unicode_letter > 0xFFFF) {
52
+ unicode[0] = 0xF0 + ((unicode_letter >> 18) & 0x7);
53
+ unicode[1] = 0x80 + ((unicode_letter >> 12) & 0x3F);
54
+ unicode[2] = 0x80 + ((unicode_letter >> 6) & 0x3F);
55
+ unicode[3] = 0x80 + (unicode_letter & 0x3F);
56
+ } else if (unicode_letter > 0x7FF) {
57
+ unicode[0] = 0xE0 + ((unicode_letter >> 12) & 0xF);
58
+ unicode[1] = 0x80 + ((unicode_letter >> 6) & 0x3F);
59
+ unicode[2] = 0x80 + (unicode_letter & 0x3F);
60
+ } else if (unicode_letter > 0x7F) {
61
+ unicode[0] = 0xC0 + ((unicode_letter >> 6) & 0x1F);
62
+ unicode[1] = 0x80 + (unicode_letter & 0x3F);
63
+ } else {
64
+ unicode[0] = unicode_letter;
65
+ }
66
+ int match_length;
67
+ int glyph_n = this->font_->match_next_glyph(unicode, &match_length);
68
+ if (glyph_n < 0)
69
+ return nullptr;
70
+ this->last_data_ = this->font_->get_glyphs()[glyph_n].get_glyph_data();
71
+ this->last_letter_ = unicode_letter;
72
+ return this->last_data_;
73
+ }
74
+ } // namespace lvgl
75
+ } // namespace esphome
76
+ #endif // USES_LVGL_FONT
@@ -0,0 +1,49 @@
1
+ import re
2
+
3
+ from esphome import config_validation as cv
4
+ from esphome.const import CONF_ARGS, CONF_FORMAT
5
+
6
+ lv_uses = {
7
+ "USER_DATA",
8
+ "LOG",
9
+ "STYLE",
10
+ "FONT_PLACEHOLDER",
11
+ "THEME_DEFAULT",
12
+ }
13
+
14
+
15
+ def add_lv_use(*names):
16
+ for name in names:
17
+ lv_uses.add(name)
18
+
19
+
20
+ lv_fonts_used = set()
21
+ esphome_fonts_used = set()
22
+ lvgl_components_required = set()
23
+
24
+
25
+ def validate_printf(value):
26
+ cfmt = r"""
27
+ ( # start of capture group 1
28
+ % # literal "%"
29
+ (?:[-+0 #]{0,5}) # optional flags
30
+ (?:\d+|\*)? # width
31
+ (?:\.(?:\d+|\*))? # precision
32
+ (?:h|l|ll|w|I|I32|I64)? # size
33
+ [cCdiouxXeEfgGaAnpsSZ] # type
34
+ )
35
+ """ # noqa
36
+ matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.X)
37
+ if len(matches) != len(value[CONF_ARGS]):
38
+ raise cv.Invalid(
39
+ f"Found {len(matches)} printf-patterns ({', '.join(matches)}), but {len(value[CONF_ARGS])} args were given!"
40
+ )
41
+ return value
42
+
43
+
44
+ def requires_component(comp):
45
+ def validator(value):
46
+ lvgl_components_required.add(comp)
47
+ return cv.requires_component(comp)(value)
48
+
49
+ return validator