esphome 2024.7.3__py3-none-any.whl → 2024.8.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) 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 +79 -51
  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 +9 -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/http_request/__init__.py +12 -1
  100. esphome/components/http_request/http_request_arduino.cpp +2 -2
  101. esphome/components/http_request/http_request_idf.cpp +11 -2
  102. esphome/components/http_request/http_request_idf.h +10 -0
  103. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  104. esphome/components/http_request/update/http_request_update.cpp +2 -2
  105. esphome/components/http_request/update/http_request_update.h +2 -1
  106. esphome/components/hx711/hx711.cpp +10 -1
  107. esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +1 -1
  108. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +11 -2
  109. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +2 -0
  110. esphome/components/ili9xxx/ili9xxx_defines.h +3 -1
  111. esphome/components/ili9xxx/ili9xxx_display.cpp +9 -22
  112. esphome/components/ili9xxx/ili9xxx_display.h +5 -7
  113. esphome/components/ili9xxx/ili9xxx_init.h +4 -4
  114. esphome/components/improv_base/__init__.py +2 -3
  115. esphome/components/improv_serial/__init__.py +4 -10
  116. esphome/components/improv_serial/improv_serial_component.cpp +4 -0
  117. esphome/components/jsn_sr04t/jsn_sr04t.cpp +18 -1
  118. esphome/components/jsn_sr04t/jsn_sr04t.h +7 -1
  119. esphome/components/jsn_sr04t/sensor.py +13 -0
  120. esphome/components/kalman_combinator/sensor.py +1 -1
  121. esphome/components/light/__init__.py +16 -15
  122. esphome/components/light/addressable_light_effect.h +12 -8
  123. esphome/components/light/automation.h +16 -1
  124. esphome/components/light/automation.py +21 -0
  125. esphome/components/light/base_light_effects.h +5 -5
  126. esphome/components/light/types.py +7 -0
  127. esphome/components/lock/__init__.py +3 -3
  128. esphome/components/logger/__init__.py +15 -18
  129. esphome/components/lvgl/__init__.py +346 -0
  130. esphome/components/lvgl/automation.py +226 -0
  131. esphome/components/lvgl/binary_sensor/__init__.py +43 -0
  132. esphome/components/lvgl/defines.py +504 -0
  133. esphome/components/lvgl/encoders.py +77 -0
  134. esphome/components/lvgl/font.cpp +76 -0
  135. esphome/components/lvgl/helpers.py +49 -0
  136. esphome/components/lvgl/light/__init__.py +32 -0
  137. esphome/components/lvgl/light/lvgl_light.h +48 -0
  138. esphome/components/lvgl/lv_validation.py +279 -0
  139. esphome/components/lvgl/lvcode.py +349 -0
  140. esphome/components/lvgl/lvgl_esphome.cpp +407 -0
  141. esphome/components/lvgl/lvgl_esphome.h +274 -0
  142. esphome/components/lvgl/lvgl_hal.h +21 -0
  143. esphome/components/lvgl/number/__init__.py +66 -0
  144. esphome/components/lvgl/number/lvgl_number.h +34 -0
  145. esphome/components/lvgl/schemas.py +426 -0
  146. esphome/components/lvgl/select/__init__.py +55 -0
  147. esphome/components/lvgl/select/lvgl_select.h +62 -0
  148. esphome/components/lvgl/sensor/__init__.py +47 -0
  149. esphome/components/lvgl/styles.py +58 -0
  150. esphome/components/lvgl/switch/__init__.py +56 -0
  151. esphome/components/lvgl/switch/lvgl_switch.h +34 -0
  152. esphome/components/lvgl/text/__init__.py +50 -0
  153. esphome/components/lvgl/text/lvgl_text.h +34 -0
  154. esphome/components/lvgl/text_sensor/__init__.py +42 -0
  155. esphome/components/lvgl/touchscreens.py +45 -0
  156. esphome/components/lvgl/trigger.py +74 -0
  157. esphome/components/lvgl/types.py +191 -0
  158. esphome/components/lvgl/widgets/__init__.py +400 -0
  159. esphome/components/lvgl/widgets/animimg.py +117 -0
  160. esphome/components/lvgl/widgets/arc.py +78 -0
  161. esphome/components/lvgl/widgets/button.py +20 -0
  162. esphome/components/lvgl/widgets/buttonmatrix.py +275 -0
  163. esphome/components/lvgl/widgets/checkbox.py +27 -0
  164. esphome/components/lvgl/widgets/dropdown.py +76 -0
  165. esphome/components/lvgl/widgets/img.py +85 -0
  166. esphome/components/lvgl/widgets/keyboard.py +49 -0
  167. esphome/components/lvgl/widgets/label.py +42 -0
  168. esphome/components/lvgl/widgets/led.py +29 -0
  169. esphome/components/lvgl/widgets/line.py +50 -0
  170. esphome/components/lvgl/widgets/lv_bar.py +55 -0
  171. esphome/components/lvgl/widgets/meter.py +302 -0
  172. esphome/components/lvgl/widgets/msgbox.py +134 -0
  173. esphome/components/lvgl/widgets/obj.py +28 -0
  174. esphome/components/lvgl/widgets/page.py +113 -0
  175. esphome/components/lvgl/widgets/roller.py +77 -0
  176. esphome/components/lvgl/widgets/slider.py +63 -0
  177. esphome/components/lvgl/widgets/spinbox.py +178 -0
  178. esphome/components/lvgl/widgets/spinner.py +43 -0
  179. esphome/components/lvgl/widgets/switch.py +20 -0
  180. esphome/components/lvgl/widgets/tabview.py +114 -0
  181. esphome/components/lvgl/widgets/textarea.py +66 -0
  182. esphome/components/lvgl/widgets/tileview.py +128 -0
  183. esphome/components/m5stack_8angle/__init__.py +33 -0
  184. esphome/components/m5stack_8angle/binary_sensor/__init__.py +30 -0
  185. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.cpp +17 -0
  186. esphome/components/m5stack_8angle/binary_sensor/m5stack_8angle_binary_sensor.h +19 -0
  187. esphome/components/m5stack_8angle/light/__init__.py +31 -0
  188. esphome/components/m5stack_8angle/light/m5stack_8angle_light.cpp +45 -0
  189. esphome/components/m5stack_8angle/light/m5stack_8angle_light.h +37 -0
  190. esphome/components/m5stack_8angle/m5stack_8angle.cpp +74 -0
  191. esphome/components/m5stack_8angle/m5stack_8angle.h +34 -0
  192. esphome/components/m5stack_8angle/sensor/__init__.py +66 -0
  193. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.cpp +24 -0
  194. esphome/components/m5stack_8angle/sensor/m5stack_8angle_sensor.h +27 -0
  195. esphome/components/matrix_keypad/matrix_keypad.cpp +2 -0
  196. esphome/components/max31856/sensor.py +5 -5
  197. esphome/components/media_player/__init__.py +3 -5
  198. esphome/components/media_player/automation.h +31 -27
  199. esphome/components/micro_wake_word/__init__.py +20 -25
  200. esphome/components/modbus_controller/__init__.py +26 -2
  201. esphome/components/modbus_controller/automation.h +19 -0
  202. esphome/components/modbus_controller/const.py +1 -0
  203. esphome/components/modbus_controller/modbus_controller.cpp +8 -0
  204. esphome/components/modbus_controller/modbus_controller.h +3 -0
  205. esphome/components/mqtt/__init__.py +20 -9
  206. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +128 -0
  207. esphome/components/mqtt/mqtt_alarm_control_panel.h +39 -0
  208. esphome/components/mqtt/mqtt_backend.h +3 -1
  209. esphome/components/mqtt/mqtt_backend_esp32.cpp +4 -1
  210. esphome/components/mqtt/mqtt_backend_esp32.h +3 -1
  211. esphome/components/mqtt/mqtt_backend_esp8266.h +3 -1
  212. esphome/components/mqtt/mqtt_backend_libretiny.h +3 -1
  213. esphome/components/mqtt/mqtt_client.cpp +16 -3
  214. esphome/components/mqtt/mqtt_client.h +5 -1
  215. esphome/components/mqtt/mqtt_component.cpp +32 -4
  216. esphome/components/mqtt/mqtt_const.h +2 -0
  217. esphome/components/network/__init__.py +10 -11
  218. esphome/components/network/ip_address.h +3 -0
  219. esphome/components/network/util.cpp +2 -1
  220. esphome/components/network/util.h +3 -1
  221. esphome/components/nextion/base_component.py +5 -8
  222. esphome/components/number/__init__.py +7 -8
  223. esphome/components/online_image/__init__.py +167 -0
  224. esphome/components/online_image/image_decoder.cpp +44 -0
  225. esphome/components/online_image/image_decoder.h +112 -0
  226. esphome/components/online_image/online_image.cpp +283 -0
  227. esphome/components/online_image/online_image.h +195 -0
  228. esphome/components/online_image/png_image.cpp +68 -0
  229. esphome/components/online_image/png_image.h +33 -0
  230. esphome/components/ota/__init__.py +8 -4
  231. esphome/components/pid/pid_climate.h +2 -0
  232. esphome/components/remote_transmitter/remote_transmitter.h +1 -1
  233. esphome/components/rgbct/rgbct_light_output.h +3 -2
  234. esphome/components/rgbw/rgbw_light_output.h +3 -2
  235. esphome/components/rgbww/rgbww_light_output.h +3 -2
  236. esphome/components/select/__init__.py +7 -7
  237. esphome/components/sensor/__init__.py +29 -10
  238. esphome/components/sensor/filter.cpp +8 -0
  239. esphome/components/sensor/filter.h +9 -0
  240. esphome/components/sml/sml_parser.cpp +48 -22
  241. esphome/components/socket/socket.cpp +11 -14
  242. esphome/components/speaker/__init__.py +14 -5
  243. esphome/components/speaker/automation.h +10 -0
  244. esphome/components/speaker/speaker.h +5 -0
  245. esphome/components/spi/spi.cpp +0 -6
  246. esphome/components/spi/spi.h +2 -19
  247. esphome/components/spi_led_strip/spi_led_strip.h +5 -4
  248. esphome/components/sprinkler/sprinkler.cpp +2 -2
  249. esphome/components/sprinkler/sprinkler.h +1 -1
  250. esphome/components/switch/__init__.py +3 -3
  251. esphome/components/text/__init__.py +5 -5
  252. esphome/components/text_sensor/__init__.py +7 -7
  253. esphome/components/time/__init__.py +8 -8
  254. esphome/components/touchscreen/binary_sensor/__init__.py +24 -10
  255. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp +3 -2
  256. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h +4 -2
  257. esphome/components/uart/uart_component_host.cpp +6 -2
  258. esphome/components/update/__init__.py +33 -15
  259. esphome/components/update/automation.h +23 -0
  260. esphome/components/update/update_entity.h +3 -1
  261. esphome/components/valve/__init__.py +3 -3
  262. esphome/components/voice_assistant/__init__.py +7 -8
  263. esphome/components/wake_on_lan/wake_on_lan.cpp +2 -0
  264. esphome/components/wake_on_lan/wake_on_lan.h +3 -1
  265. esphome/components/watchdog/__init__.py +1 -0
  266. esphome/components/{http_request → watchdog}/watchdog.cpp +0 -2
  267. esphome/components/{http_request → watchdog}/watchdog.h +0 -2
  268. esphome/components/web_server/server_index_v3.h +3615 -3603
  269. esphome/components/web_server/web_server.cpp +0 -209
  270. esphome/components/web_server/web_server.h +1 -1
  271. esphome/components/web_server/web_server_v1.cpp +217 -0
  272. esphome/components/web_server_base/web_server_base.h +1 -0
  273. esphome/components/wifi/__init__.py +15 -14
  274. esphome/components/wifi/wifi_component.cpp +2 -0
  275. esphome/components/wifi/wifi_component.h +7 -1
  276. esphome/components/wifi/wifi_component_esp32_arduino.cpp +5 -2
  277. esphome/components/wifi/wifi_component_esp8266.cpp +2 -0
  278. esphome/components/wifi/wifi_component_esp_idf.cpp +43 -7
  279. esphome/components/wifi/wifi_component_libretiny.cpp +2 -0
  280. esphome/components/wifi/wifi_component_pico_w.cpp +2 -0
  281. esphome/components/wifi/wpa2_eap.py +6 -7
  282. esphome/components/wifi_info/text_sensor.py +3 -3
  283. esphome/components/wifi_info/wifi_info_text_sensor.cpp +2 -0
  284. esphome/components/wifi_info/wifi_info_text_sensor.h +2 -0
  285. esphome/components/wifi_signal/sensor.py +1 -1
  286. esphome/components/wifi_signal/wifi_signal_sensor.cpp +2 -0
  287. esphome/components/wifi_signal/wifi_signal_sensor.h +2 -1
  288. esphome/components/xiaomi_ble/xiaomi_ble.cpp +20 -3
  289. esphome/components/xiaomi_ble/xiaomi_ble.h +1 -0
  290. esphome/components/xiaomi_lywsd02mmc/__init__.py +0 -0
  291. esphome/components/xiaomi_lywsd02mmc/sensor.py +77 -0
  292. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.cpp +73 -0
  293. esphome/components/xiaomi_lywsd02mmc/xiaomi_lywsd02mmc.h +37 -0
  294. esphome/config.py +17 -19
  295. esphome/config_validation.py +41 -23
  296. esphome/const.py +25 -9
  297. esphome/core/__init__.py +17 -14
  298. esphome/core/application.h +42 -21
  299. esphome/core/automation.h +5 -3
  300. esphome/core/base_automation.h +3 -2
  301. esphome/core/bytebuffer.cpp +134 -0
  302. esphome/core/bytebuffer.h +96 -0
  303. esphome/core/color.h +24 -16
  304. esphome/core/config.py +3 -3
  305. esphome/core/defines.h +14 -1
  306. esphome/core/entity_base.h +2 -2
  307. esphome/core/entity_helpers.py +1 -2
  308. esphome/core/gpio.h +0 -18
  309. esphome/core/helpers.h +1 -1
  310. esphome/core/optional.h +15 -16
  311. esphome/coroutine.py +1 -1
  312. esphome/cpp_generator.py +1 -1
  313. esphome/cpp_helpers.py +3 -5
  314. esphome/dashboard/core.py +3 -3
  315. esphome/dashboard/dashboard.py +3 -3
  316. esphome/dashboard/entries.py +1 -1
  317. esphome/dashboard/util/file.py +1 -1
  318. esphome/dashboard/web_server.py +3 -3
  319. esphome/external_files.py +5 -3
  320. esphome/final_validate.py +2 -2
  321. esphome/git.py +4 -4
  322. esphome/helpers.py +5 -5
  323. esphome/loader.py +15 -10
  324. esphome/mqtt.py +4 -8
  325. esphome/pins.py +6 -6
  326. esphome/platformio_api.py +5 -5
  327. esphome/storage_json.py +2 -1
  328. esphome/types.py +1 -1
  329. esphome/util.py +2 -3
  330. esphome/voluptuous_schema.py +1 -0
  331. esphome/vscode.py +5 -4
  332. esphome/wizard.py +1 -1
  333. esphome/writer.py +7 -7
  334. esphome/yaml_util.py +3 -3
  335. esphome/zeroconf.py +1 -1
  336. {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/METADATA +3 -3
  337. {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/RECORD +341 -235
  338. {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/LICENSE +0 -0
  339. {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/WHEEL +0 -0
  340. {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/entry_points.txt +0 -0
  341. {esphome-2024.7.3.dist-info → esphome-2024.8.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,504 @@
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 ID, Lambda
10
+ from esphome.cpp_generator import 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
+ class LValidator:
26
+ """
27
+ A validator for a particular type used in LVGL. Usable in configs as a validator, also
28
+ has `process()` to convert a value during code generation
29
+ """
30
+
31
+ def __init__(
32
+ self, validator, rtype, idtype=None, idexpr=None, retmapper=None, requires=None
33
+ ):
34
+ self.validator = validator
35
+ self.rtype = rtype
36
+ self.idtype = idtype
37
+ self.idexpr = idexpr
38
+ self.retmapper = retmapper
39
+ self.requires = requires
40
+
41
+ def __call__(self, value):
42
+ if self.requires:
43
+ value = requires_component(self.requires)(value)
44
+ if isinstance(value, cv.Lambda):
45
+ return cv.returning_lambda(value)
46
+ if self.idtype is not None and isinstance(value, ID):
47
+ return cv.use_id(self.idtype)(value)
48
+ return self.validator(value)
49
+
50
+ async def process(self, value, args=()):
51
+ if value is None:
52
+ return None
53
+ if isinstance(value, Lambda):
54
+ return cg.RawExpression(
55
+ f"{await cg.process_lambda(value, args, return_type=self.rtype)}()"
56
+ )
57
+ if self.idtype is not None and isinstance(value, ID):
58
+ return cg.RawExpression(f"{value}->{self.idexpr}")
59
+ if self.retmapper is not None:
60
+ return self.retmapper(value)
61
+ return cg.safe_exp(value)
62
+
63
+
64
+ class LvConstant(LValidator):
65
+ """
66
+ Allow one of a list of choices, mapped to upper case, and prepend the choice with the prefix.
67
+ It's also permitted to include the prefix in the value
68
+ The property `one_of` has the single case validator, and `several_of` allows a list of constants.
69
+ """
70
+
71
+ def __init__(self, prefix: str, *choices):
72
+ self.prefix = prefix
73
+ self.choices = choices
74
+ prefixed_choices = [prefix + v for v in choices]
75
+ prefixed_validator = cv.one_of(*prefixed_choices, upper=True)
76
+
77
+ @schema_extractor("one_of")
78
+ def validator(value):
79
+ if value == SCHEMA_EXTRACT:
80
+ return self.choices
81
+ if isinstance(value, str) and value.startswith(self.prefix):
82
+ return prefixed_validator(value)
83
+ return self.prefix + cv.one_of(*choices, upper=True)(value)
84
+
85
+ super().__init__(validator, rtype=uint32)
86
+ self.retmapper = self.mapper
87
+ self.one_of = LValidator(validator, uint32, retmapper=self.mapper)
88
+ self.several_of = LValidator(
89
+ cv.ensure_list(self.one_of), uint32, retmapper=self.mapper
90
+ )
91
+
92
+ def mapper(self, value, args=()):
93
+ if not isinstance(value, list):
94
+ value = [value]
95
+ return literal(
96
+ "|".join(
97
+ [
98
+ str(v) if str(v).startswith(self.prefix) else self.prefix + str(v)
99
+ for v in value
100
+ ]
101
+ ).upper()
102
+ )
103
+
104
+ def extend(self, *choices):
105
+ """
106
+ Extend an LVCconstant with additional choices.
107
+ :param choices: The extra choices
108
+ :return: A new LVConstant instance
109
+ """
110
+ return LvConstant(self.prefix, *(self.choices + choices))
111
+
112
+
113
+ # Parts
114
+ CONF_MAIN = "main"
115
+ CONF_SCROLLBAR = "scrollbar"
116
+ CONF_INDICATOR = "indicator"
117
+ CONF_KNOB = "knob"
118
+ CONF_SELECTED = "selected"
119
+ CONF_TICKS = "ticks"
120
+ CONF_CURSOR = "cursor"
121
+ CONF_TEXTAREA_PLACEHOLDER = "textarea_placeholder"
122
+
123
+ # Layout types
124
+
125
+ TYPE_FLEX = "flex"
126
+ TYPE_GRID = "grid"
127
+ TYPE_NONE = "none"
128
+
129
+ LV_FONTS = list(f"montserrat_{s}" for s in range(8, 50, 2)) + [
130
+ "dejavu_16_persian_hebrew",
131
+ "simsun_16_cjk",
132
+ "unscii_8",
133
+ "unscii_16",
134
+ ]
135
+
136
+ LV_EVENT_MAP = {
137
+ "PRESS": "PRESSED",
138
+ "SHORT_CLICK": "SHORT_CLICKED",
139
+ "LONG_PRESS": "LONG_PRESSED",
140
+ "LONG_PRESS_REPEAT": "LONG_PRESSED_REPEAT",
141
+ "CLICK": "CLICKED",
142
+ "RELEASE": "RELEASED",
143
+ "SCROLL_BEGIN": "SCROLL_BEGIN",
144
+ "SCROLL_END": "SCROLL_END",
145
+ "SCROLL": "SCROLL",
146
+ "FOCUS": "FOCUSED",
147
+ "DEFOCUS": "DEFOCUSED",
148
+ "READY": "READY",
149
+ "CANCEL": "CANCEL",
150
+ }
151
+
152
+ LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT_MAP)
153
+
154
+
155
+ LV_ANIM = LvConstant(
156
+ "LV_SCR_LOAD_ANIM_",
157
+ "NONE",
158
+ "OVER_LEFT",
159
+ "OVER_RIGHT",
160
+ "OVER_TOP",
161
+ "OVER_BOTTOM",
162
+ "MOVE_LEFT",
163
+ "MOVE_RIGHT",
164
+ "MOVE_TOP",
165
+ "MOVE_BOTTOM",
166
+ "FADE_IN",
167
+ "FADE_OUT",
168
+ "OUT_LEFT",
169
+ "OUT_RIGHT",
170
+ "OUT_TOP",
171
+ "OUT_BOTTOM",
172
+ )
173
+
174
+ LOG_LEVELS = (
175
+ "TRACE",
176
+ "INFO",
177
+ "WARN",
178
+ "ERROR",
179
+ "USER",
180
+ "NONE",
181
+ )
182
+
183
+ LV_LONG_MODES = LvConstant(
184
+ "LV_LABEL_LONG_",
185
+ "WRAP",
186
+ "DOT",
187
+ "SCROLL",
188
+ "SCROLL_CIRCULAR",
189
+ "CLIP",
190
+ )
191
+
192
+ STATES = (
193
+ "default",
194
+ "checked",
195
+ "focused",
196
+ "focus_key",
197
+ "edited",
198
+ "hovered",
199
+ "pressed",
200
+ "scrolled",
201
+ "disabled",
202
+ "user_1",
203
+ "user_2",
204
+ "user_3",
205
+ "user_4",
206
+ )
207
+
208
+ PARTS = (
209
+ CONF_MAIN,
210
+ CONF_SCROLLBAR,
211
+ CONF_INDICATOR,
212
+ CONF_KNOB,
213
+ CONF_SELECTED,
214
+ CONF_ITEMS,
215
+ CONF_TICKS,
216
+ CONF_CURSOR,
217
+ CONF_TEXTAREA_PLACEHOLDER,
218
+ )
219
+
220
+ KEYBOARD_MODES = LvConstant(
221
+ "LV_KEYBOARD_MODE_",
222
+ "TEXT_LOWER",
223
+ "TEXT_UPPER",
224
+ "SPECIAL",
225
+ "NUMBER",
226
+ )
227
+ ROLLER_MODES = LvConstant("LV_ROLLER_MODE_", "NORMAL", "INFINITE")
228
+ DIRECTIONS = LvConstant("LV_DIR_", "LEFT", "RIGHT", "BOTTOM", "TOP")
229
+ TILE_DIRECTIONS = DIRECTIONS.extend("HOR", "VER", "ALL")
230
+ CHILD_ALIGNMENTS = LvConstant(
231
+ "LV_ALIGN_",
232
+ "TOP_LEFT",
233
+ "TOP_MID",
234
+ "TOP_RIGHT",
235
+ "LEFT_MID",
236
+ "CENTER",
237
+ "RIGHT_MID",
238
+ "BOTTOM_LEFT",
239
+ "BOTTOM_MID",
240
+ "BOTTOM_RIGHT",
241
+ )
242
+
243
+ SIBLING_ALIGNMENTS = LvConstant(
244
+ "LV_ALIGN_",
245
+ "OUT_LEFT_TOP",
246
+ "OUT_TOP_LEFT",
247
+ "OUT_TOP_MID",
248
+ "OUT_TOP_RIGHT",
249
+ "OUT_RIGHT_TOP",
250
+ "OUT_LEFT_MID",
251
+ "OUT_RIGHT_MID",
252
+ "OUT_LEFT_BOTTOM",
253
+ "OUT_BOTTOM_LEFT",
254
+ "OUT_BOTTOM_MID",
255
+ "OUT_BOTTOM_RIGHT",
256
+ "OUT_RIGHT_BOTTOM",
257
+ )
258
+ ALIGN_ALIGNMENTS = CHILD_ALIGNMENTS.extend(*SIBLING_ALIGNMENTS.choices)
259
+
260
+ FLEX_FLOWS = LvConstant(
261
+ "LV_FLEX_FLOW_",
262
+ "ROW",
263
+ "COLUMN",
264
+ "ROW_WRAP",
265
+ "COLUMN_WRAP",
266
+ "ROW_REVERSE",
267
+ "COLUMN_REVERSE",
268
+ "ROW_WRAP_REVERSE",
269
+ "COLUMN_WRAP_REVERSE",
270
+ )
271
+
272
+ OBJ_FLAGS = (
273
+ "hidden",
274
+ "clickable",
275
+ "click_focusable",
276
+ "checkable",
277
+ "scrollable",
278
+ "scroll_elastic",
279
+ "scroll_momentum",
280
+ "scroll_one",
281
+ "scroll_chain_hor",
282
+ "scroll_chain_ver",
283
+ "scroll_chain",
284
+ "scroll_on_focus",
285
+ "scroll_with_arrow",
286
+ "snappable",
287
+ "press_lock",
288
+ "event_bubble",
289
+ "gesture_bubble",
290
+ "adv_hittest",
291
+ "ignore_layout",
292
+ "floating",
293
+ "overflow_visible",
294
+ "layout_1",
295
+ "layout_2",
296
+ "widget_1",
297
+ "widget_2",
298
+ "user_1",
299
+ "user_2",
300
+ "user_3",
301
+ "user_4",
302
+ )
303
+
304
+ ARC_MODES = LvConstant("LV_ARC_MODE_", "NORMAL", "REVERSE", "SYMMETRICAL")
305
+ BAR_MODES = LvConstant("LV_BAR_MODE_", "NORMAL", "SYMMETRICAL", "RANGE")
306
+
307
+ BUTTONMATRIX_CTRLS = LvConstant(
308
+ "LV_BTNMATRIX_CTRL_",
309
+ "HIDDEN",
310
+ "NO_REPEAT",
311
+ "DISABLED",
312
+ "CHECKABLE",
313
+ "CHECKED",
314
+ "CLICK_TRIG",
315
+ "POPOVER",
316
+ "RECOLOR",
317
+ "CUSTOM_1",
318
+ "CUSTOM_2",
319
+ )
320
+
321
+ LV_BASE_ALIGNMENTS = (
322
+ "START",
323
+ "CENTER",
324
+ "END",
325
+ )
326
+ LV_CELL_ALIGNMENTS = LvConstant(
327
+ "LV_GRID_ALIGN_",
328
+ *LV_BASE_ALIGNMENTS,
329
+ )
330
+ LV_GRID_ALIGNMENTS = LV_CELL_ALIGNMENTS.extend(
331
+ "STRETCH",
332
+ "SPACE_EVENLY",
333
+ "SPACE_AROUND",
334
+ "SPACE_BETWEEN",
335
+ )
336
+
337
+ LV_FLEX_ALIGNMENTS = LvConstant(
338
+ "LV_FLEX_ALIGN_",
339
+ *LV_BASE_ALIGNMENTS,
340
+ "SPACE_EVENLY",
341
+ "SPACE_AROUND",
342
+ "SPACE_BETWEEN",
343
+ )
344
+
345
+ LV_MENU_MODES = LvConstant(
346
+ "LV_MENU_HEADER_",
347
+ "TOP_FIXED",
348
+ "TOP_UNFIXED",
349
+ "BOTTOM_FIXED",
350
+ )
351
+
352
+ LV_CHART_TYPES = (
353
+ "NONE",
354
+ "LINE",
355
+ "BAR",
356
+ "SCATTER",
357
+ )
358
+ LV_CHART_AXES = (
359
+ "PRIMARY_Y",
360
+ "SECONDARY_Y",
361
+ "PRIMARY_X",
362
+ "SECONDARY_X",
363
+ )
364
+
365
+ CONF_ACCEPTED_CHARS = "accepted_chars"
366
+ CONF_ADJUSTABLE = "adjustable"
367
+ CONF_ALIGN = "align"
368
+ CONF_ALIGN_TO = "align_to"
369
+ CONF_ANIMATED = "animated"
370
+ CONF_ANIMATION = "animation"
371
+ CONF_ANTIALIAS = "antialias"
372
+ CONF_ARC_LENGTH = "arc_length"
373
+ CONF_AUTO_START = "auto_start"
374
+ CONF_BACKGROUND_STYLE = "background_style"
375
+ CONF_DECIMAL_PLACES = "decimal_places"
376
+ CONF_COLUMN = "column"
377
+ CONF_DIGITS = "digits"
378
+ CONF_DISP_BG_COLOR = "disp_bg_color"
379
+ CONF_DISP_BG_IMAGE = "disp_bg_image"
380
+ CONF_BODY = "body"
381
+ CONF_BUTTONS = "buttons"
382
+ CONF_BYTE_ORDER = "byte_order"
383
+ CONF_CHANGE_RATE = "change_rate"
384
+ CONF_CLOSE_BUTTON = "close_button"
385
+ CONF_COLOR_DEPTH = "color_depth"
386
+ CONF_CONTROL = "control"
387
+ CONF_DEFAULT = "default"
388
+ CONF_DEFAULT_FONT = "default_font"
389
+ CONF_DEFAULT_GROUP = "default_group"
390
+ CONF_DIR = "dir"
391
+ CONF_DISPLAYS = "displays"
392
+ CONF_ENCODERS = "encoders"
393
+ CONF_END_ANGLE = "end_angle"
394
+ CONF_END_VALUE = "end_value"
395
+ CONF_ENTER_BUTTON = "enter_button"
396
+ CONF_ENTRIES = "entries"
397
+ CONF_FLAGS = "flags"
398
+ CONF_FLEX_FLOW = "flex_flow"
399
+ CONF_FLEX_ALIGN_MAIN = "flex_align_main"
400
+ CONF_FLEX_ALIGN_CROSS = "flex_align_cross"
401
+ CONF_FLEX_ALIGN_TRACK = "flex_align_track"
402
+ CONF_FLEX_GROW = "flex_grow"
403
+ CONF_FULL_REFRESH = "full_refresh"
404
+ CONF_GRID_CELL_ROW_POS = "grid_cell_row_pos"
405
+ CONF_GRID_CELL_COLUMN_POS = "grid_cell_column_pos"
406
+ CONF_GRID_CELL_ROW_SPAN = "grid_cell_row_span"
407
+ CONF_GRID_CELL_COLUMN_SPAN = "grid_cell_column_span"
408
+ CONF_GRID_CELL_X_ALIGN = "grid_cell_x_align"
409
+ CONF_GRID_CELL_Y_ALIGN = "grid_cell_y_align"
410
+ CONF_GRID_COLUMN_ALIGN = "grid_column_align"
411
+ CONF_GRID_COLUMNS = "grid_columns"
412
+ CONF_GRID_ROW_ALIGN = "grid_row_align"
413
+ CONF_GRID_ROWS = "grid_rows"
414
+ CONF_HEADER_MODE = "header_mode"
415
+ CONF_HOME = "home"
416
+ CONF_INITIAL_FOCUS = "initial_focus"
417
+ CONF_KEY_CODE = "key_code"
418
+ CONF_LAYOUT = "layout"
419
+ CONF_LEFT_BUTTON = "left_button"
420
+ CONF_LINE_WIDTH = "line_width"
421
+ CONF_LOG_LEVEL = "log_level"
422
+ CONF_LONG_PRESS_TIME = "long_press_time"
423
+ CONF_LONG_PRESS_REPEAT_TIME = "long_press_repeat_time"
424
+ CONF_LVGL_ID = "lvgl_id"
425
+ CONF_LONG_MODE = "long_mode"
426
+ CONF_MSGBOXES = "msgboxes"
427
+ CONF_OBJ = "obj"
428
+ CONF_OFFSET_X = "offset_x"
429
+ CONF_OFFSET_Y = "offset_y"
430
+ CONF_ONE_LINE = "one_line"
431
+ CONF_ON_SELECT = "on_select"
432
+ CONF_ONE_CHECKED = "one_checked"
433
+ CONF_NEXT = "next"
434
+ CONF_PAGE = "page"
435
+ CONF_PAGE_WRAP = "page_wrap"
436
+ CONF_PASSWORD_MODE = "password_mode"
437
+ CONF_PIVOT_X = "pivot_x"
438
+ CONF_PIVOT_Y = "pivot_y"
439
+ CONF_PLACEHOLDER_TEXT = "placeholder_text"
440
+ CONF_POINTS = "points"
441
+ CONF_PREVIOUS = "previous"
442
+ CONF_REPEAT_COUNT = "repeat_count"
443
+ CONF_RECOLOR = "recolor"
444
+ CONF_RIGHT_BUTTON = "right_button"
445
+ CONF_ROLLOVER = "rollover"
446
+ CONF_ROOT_BACK_BTN = "root_back_btn"
447
+ CONF_ROWS = "rows"
448
+ CONF_SCALE_LINES = "scale_lines"
449
+ CONF_SCROLLBAR_MODE = "scrollbar_mode"
450
+ CONF_SELECTED_INDEX = "selected_index"
451
+ CONF_SHOW_SNOW = "show_snow"
452
+ CONF_SPIN_TIME = "spin_time"
453
+ CONF_SRC = "src"
454
+ CONF_START_ANGLE = "start_angle"
455
+ CONF_START_VALUE = "start_value"
456
+ CONF_STATES = "states"
457
+ CONF_STYLE = "style"
458
+ CONF_STYLES = "styles"
459
+ CONF_STYLE_DEFINITIONS = "style_definitions"
460
+ CONF_STYLE_ID = "style_id"
461
+ CONF_SKIP = "skip"
462
+ CONF_SYMBOL = "symbol"
463
+ CONF_TAB_ID = "tab_id"
464
+ CONF_TABS = "tabs"
465
+ CONF_TILE = "tile"
466
+ CONF_TILE_ID = "tile_id"
467
+ CONF_TILES = "tiles"
468
+ CONF_TITLE = "title"
469
+ CONF_TOP_LAYER = "top_layer"
470
+ CONF_TOUCHSCREENS = "touchscreens"
471
+ CONF_TRANSPARENCY_KEY = "transparency_key"
472
+ CONF_THEME = "theme"
473
+ CONF_UPDATE_ON_RELEASE = "update_on_release"
474
+ CONF_VISIBLE_ROW_COUNT = "visible_row_count"
475
+ CONF_WIDGET = "widget"
476
+ CONF_WIDGETS = "widgets"
477
+ CONF_X = "x"
478
+ CONF_Y = "y"
479
+ CONF_ZOOM = "zoom"
480
+
481
+ # Keypad keys
482
+
483
+ LV_KEYS = LvConstant(
484
+ "LV_KEY_",
485
+ "UP",
486
+ "DOWN",
487
+ "RIGHT",
488
+ "LEFT",
489
+ "ESC",
490
+ "DEL",
491
+ "BACKSPACE",
492
+ "ENTER",
493
+ "NEXT",
494
+ "PREV",
495
+ "HOME",
496
+ "END",
497
+ )
498
+
499
+
500
+ DEFAULT_ESPHOME_FONT = "esphome_lv_default_font"
501
+
502
+
503
+ def join_enums(enums, prefix=""):
504
+ 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