esphome 2025.3.3__py3-none-any.whl → 2025.4.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.

Potentially problematic release.


This version of esphome might be problematic. Click here for more details.

Files changed (695) hide show
  1. esphome/__main__.py +29 -7
  2. esphome/components/a01nyub/sensor.py +2 -2
  3. esphome/components/a02yyuw/sensor.py +2 -2
  4. esphome/components/a4988/stepper.py +1 -2
  5. esphome/components/absolute_humidity/sensor.py +3 -3
  6. esphome/components/ac_dimmer/output.py +3 -3
  7. esphome/components/adalight/__init__.py +2 -2
  8. esphome/components/adc128s102/__init__.py +1 -1
  9. esphome/components/adc128s102/sensor/__init__.py +3 -3
  10. esphome/components/addressable_light/display.py +5 -5
  11. esphome/components/ade7880/sensor.py +2 -2
  12. esphome/components/ade7953_base/__init__.py +10 -10
  13. esphome/components/ade7953_i2c/sensor.py +1 -2
  14. esphome/components/ade7953_spi/sensor.py +1 -2
  15. esphome/components/ads1115/__init__.py +1 -1
  16. esphome/components/ads1115/sensor/__init__.py +4 -3
  17. esphome/components/ads1118/__init__.py +1 -1
  18. esphome/components/ads1118/sensor/__init__.py +5 -4
  19. esphome/components/ags10/sensor.py +9 -9
  20. esphome/components/aht10/sensor.py +2 -2
  21. esphome/components/airthings_ble/__init__.py +1 -1
  22. esphome/components/airthings_wave_base/__init__.py +2 -3
  23. esphome/components/airthings_wave_mini/sensor.py +2 -5
  24. esphome/components/airthings_wave_plus/sensor.py +8 -9
  25. esphome/components/alpha3/sensor.py +5 -5
  26. esphome/components/am2315c/sensor.py +1 -1
  27. esphome/components/am2320/sensor.py +1 -1
  28. esphome/components/am43/cover/__init__.py +1 -1
  29. esphome/components/am43/sensor/__init__.py +3 -3
  30. esphome/components/analog_threshold/binary_sensor.py +2 -5
  31. esphome/components/anova/climate.py +1 -1
  32. esphome/components/apds9306/sensor.py +1 -1
  33. esphome/components/apds9960/__init__.py +1 -1
  34. esphome/components/apds9960/binary_sensor.py +2 -1
  35. esphome/components/apds9960/sensor.py +3 -2
  36. esphome/components/api/api_frame_helper.cpp +21 -1
  37. esphome/components/as3935/__init__.py +3 -3
  38. esphome/components/as3935/binary_sensor.py +2 -1
  39. esphome/components/as3935/sensor.py +4 -3
  40. esphome/components/as3935_i2c/__init__.py +1 -1
  41. esphome/components/as3935_spi/__init__.py +1 -1
  42. esphome/components/as5600/__init__.py +2 -2
  43. esphome/components/as5600/sensor/__init__.py +10 -9
  44. esphome/components/as7341/sensor.py +1 -2
  45. esphome/components/at581x/__init__.py +4 -8
  46. esphome/components/at581x/switch/__init__.py +2 -4
  47. esphome/components/atc_mithermometer/sensor.py +3 -3
  48. esphome/components/b_parasite/sensor.py +2 -2
  49. esphome/components/ballu/climate.py +1 -1
  50. esphome/components/bang_bang/climate.py +2 -2
  51. esphome/components/bedjet/__init__.py +2 -6
  52. esphome/components/bedjet/climate/__init__.py +3 -6
  53. esphome/components/bedjet/fan/__init__.py +4 -9
  54. esphome/components/bedjet/sensor/__init__.py +3 -6
  55. esphome/components/beken_spi_led_strip/light.py +2 -2
  56. esphome/components/bh1750/sensor.py +2 -6
  57. esphome/components/binary/fan/__init__.py +2 -1
  58. esphome/components/binary/light/__init__.py +3 -2
  59. esphome/components/binary_sensor_map/sensor.py +5 -6
  60. esphome/components/bl0939/sensor.py +1 -1
  61. esphome/components/bl0940/sensor.py +3 -3
  62. esphome/components/ble_client/__init__.py +3 -2
  63. esphome/components/ble_client/sensor/__init__.py +1 -1
  64. esphome/components/ble_client/text_sensor/__init__.py +1 -1
  65. esphome/components/bluetooth_proxy/__init__.py +35 -23
  66. esphome/components/bme280_base/__init__.py +1 -1
  67. esphome/components/bme280_i2c/sensor.py +3 -2
  68. esphome/components/bme280_spi/sensor.py +3 -2
  69. esphome/components/bme680/sensor.py +4 -4
  70. esphome/components/bme680_bsec/__init__.py +1 -1
  71. esphome/components/bme680_bsec/sensor.py +3 -6
  72. esphome/components/bme680_bsec/text_sensor.py +3 -2
  73. esphome/components/bmi160/sensor.py +6 -6
  74. esphome/components/bmp085/sensor.py +1 -1
  75. esphome/components/bmp280_base/__init__.py +1 -1
  76. esphome/components/bmp280_i2c/sensor.py +3 -2
  77. esphome/components/bmp280_spi/sensor.py +3 -2
  78. esphome/components/bmp3xx_base/__init__.py +1 -1
  79. esphome/components/bmp3xx_i2c/sensor.py +2 -1
  80. esphome/components/bmp3xx_spi/sensor.py +2 -1
  81. esphome/components/bmp581/sensor.py +2 -1
  82. esphome/components/bp1658cj/__init__.py +2 -6
  83. esphome/components/bp1658cj/output.py +2 -1
  84. esphome/components/bp5758d/__init__.py +2 -6
  85. esphome/components/bp5758d/output.py +3 -2
  86. esphome/components/canbus/__init__.py +13 -2
  87. esphome/components/canbus/canbus.cpp +7 -1
  88. esphome/components/cap1188/__init__.py +2 -2
  89. esphome/components/cap1188/binary_sensor.py +3 -2
  90. esphome/components/captive_portal/__init__.py +3 -3
  91. esphome/components/ccs811/sensor.py +10 -10
  92. esphome/components/cd74hc4067/__init__.py +2 -5
  93. esphome/components/cd74hc4067/sensor.py +6 -5
  94. esphome/components/climate_ir/__init__.py +2 -2
  95. esphome/components/climate_ir_lg/climate.py +1 -1
  96. esphome/components/color/__init__.py +1 -2
  97. esphome/components/color_temperature/light.py +2 -2
  98. esphome/components/combination/sensor.py +1 -1
  99. esphome/components/coolix/climate.py +1 -1
  100. esphome/components/copy/binary_sensor/__init__.py +1 -1
  101. esphome/components/copy/button/__init__.py +1 -1
  102. esphome/components/copy/cover/__init__.py +1 -1
  103. esphome/components/copy/fan/__init__.py +2 -7
  104. esphome/components/copy/lock/__init__.py +2 -7
  105. esphome/components/copy/number/__init__.py +1 -1
  106. esphome/components/copy/select/__init__.py +2 -7
  107. esphome/components/copy/sensor/__init__.py +2 -2
  108. esphome/components/copy/switch/__init__.py +1 -1
  109. esphome/components/copy/text/__init__.py +2 -7
  110. esphome/components/copy/text_sensor/__init__.py +2 -6
  111. esphome/components/cs5460a/sensor.py +7 -7
  112. esphome/components/cse7761/sensor.py +2 -2
  113. esphome/components/cse7766/sensor.py +1 -1
  114. esphome/components/cst226/touchscreen/__init__.py +3 -4
  115. esphome/components/ct_clamp/sensor.py +1 -1
  116. esphome/components/current_based/cover.py +3 -4
  117. esphome/components/cwww/light.py +3 -3
  118. esphome/components/dac7678/__init__.py +1 -1
  119. esphome/components/dac7678/output.py +2 -1
  120. esphome/components/daikin/climate.py +1 -1
  121. esphome/components/daikin_arc/climate.py +1 -1
  122. esphome/components/daikin_brc/climate.py +1 -1
  123. esphome/components/dallas_temp/sensor.py +1 -1
  124. esphome/components/daly_bms/__init__.py +2 -2
  125. esphome/components/daly_bms/binary_sensor.py +3 -2
  126. esphome/components/daly_bms/sensor.py +14 -13
  127. esphome/components/daly_bms/text_sensor.py +3 -2
  128. esphome/components/dashboard_import/__init__.py +5 -5
  129. esphome/components/debug/sensor.py +7 -6
  130. esphome/components/debug/text_sensor.py +1 -1
  131. esphome/components/deep_sleep/__init__.py +12 -13
  132. esphome/components/delonghi/climate.py +1 -1
  133. esphome/components/demo/__init__.py +1 -1
  134. esphome/components/dfplayer/__init__.py +3 -3
  135. esphome/components/dfrobot_sen0395/__init__.py +3 -3
  136. esphome/components/dfrobot_sen0395/binary_sensor.py +2 -1
  137. esphome/components/dfrobot_sen0395/switch/__init__.py +2 -3
  138. esphome/components/dht/sensor.py +4 -5
  139. esphome/components/dht12/sensor.py +3 -3
  140. esphome/components/dps310/sensor.py +3 -3
  141. esphome/components/ds1307/time.py +2 -3
  142. esphome/components/dsmr/__init__.py +3 -7
  143. esphome/components/dsmr/sensor.py +5 -4
  144. esphome/components/dsmr/text_sensor.py +3 -2
  145. esphome/components/duty_cycle/sensor.py +3 -8
  146. esphome/components/duty_time/sensor.py +7 -7
  147. esphome/components/e131/__init__.py +3 -3
  148. esphome/components/ee895/sensor.py +5 -5
  149. esphome/components/ektf2232/touchscreen/__init__.py +2 -3
  150. esphome/components/emc2101/__init__.py +1 -1
  151. esphome/components/emc2101/output/__init__.py +3 -2
  152. esphome/components/emc2101/sensor/__init__.py +4 -3
  153. esphome/components/emmeti/climate.py +1 -1
  154. esphome/components/endstop/cover.py +3 -3
  155. esphome/components/ens160_base/__init__.py +1 -1
  156. esphome/components/ens160_i2c/sensor.py +2 -1
  157. esphome/components/ens160_spi/sensor.py +2 -1
  158. esphome/components/ens210/sensor.py +1 -1
  159. esphome/components/esp32/__init__.py +10 -0
  160. esphome/components/esp32_ble_tracker/__init__.py +135 -51
  161. esphome/components/esp32_camera/__init__.py +7 -8
  162. esphome/components/esp32_camera_web_server/__init__.py +2 -2
  163. esphome/components/esp32_can/canbus.py +21 -0
  164. esphome/components/esp32_can/esp32_can.cpp +1 -1
  165. esphome/components/esp32_can/esp32_can.h +4 -0
  166. esphome/components/esp32_dac/output.py +2 -2
  167. esphome/components/esp32_hall/sensor.py +2 -6
  168. esphome/components/esp32_touch/__init__.py +7 -7
  169. esphome/components/esp32_touch/binary_sensor.py +4 -7
  170. esphome/components/esp8266_pwm/output.py +3 -8
  171. esphome/components/ethernet/__init__.py +1 -0
  172. esphome/components/ethernet/ethernet_component.cpp +1 -1
  173. esphome/components/ethernet_info/ethernet_info_text_sensor.h +1 -0
  174. esphome/components/exposure_notifications/__init__.py +2 -2
  175. esphome/components/external_components/__init__.py +1 -1
  176. esphome/components/ezo/sensor.py +2 -2
  177. esphome/components/ezo_pmp/__init__.py +4 -4
  178. esphome/components/ezo_pmp/binary_sensor.py +4 -4
  179. esphome/components/ezo_pmp/sensor.py +4 -5
  180. esphome/components/ezo_pmp/text_sensor.py +2 -6
  181. esphome/components/factory_reset/button/__init__.py +2 -1
  182. esphome/components/factory_reset/switch/__init__.py +3 -2
  183. esphome/components/fastled_base/__init__.py +3 -3
  184. esphome/components/fastled_clockless/light.py +2 -2
  185. esphome/components/fastled_spi/light.py +2 -2
  186. esphome/components/feedback/cover.py +3 -3
  187. esphome/components/fingerprint_grow/__init__.py +5 -6
  188. esphome/components/fingerprint_grow/binary_sensor.py +2 -1
  189. esphome/components/fingerprint_grow/sensor.py +2 -1
  190. esphome/components/fs3000/sensor.py +2 -6
  191. esphome/components/ft5x06/touchscreen/__init__.py +2 -2
  192. esphome/components/ft63x6/touchscreen.py +2 -3
  193. esphome/components/fujitsu_general/climate.py +1 -1
  194. esphome/components/gcja5/sensor.py +4 -4
  195. esphome/components/gdk101/__init__.py +1 -1
  196. esphome/components/gdk101/binary_sensor.py +2 -1
  197. esphome/components/gdk101/sensor.py +5 -4
  198. esphome/components/globals/__init__.py +1 -2
  199. esphome/components/gp2y1010au0f/sensor.py +3 -3
  200. esphome/components/gp8403/__init__.py +1 -2
  201. esphome/components/gp8403/output/__init__.py +3 -4
  202. esphome/components/gpio/binary_sensor/__init__.py +3 -2
  203. esphome/components/gpio/one_wire/__init__.py +3 -2
  204. esphome/components/gpio/output/__init__.py +3 -2
  205. esphome/components/gpio/switch/__init__.py +3 -2
  206. esphome/components/gps/__init__.py +4 -5
  207. esphome/components/gps/time/__init__.py +3 -2
  208. esphome/components/graph/__init__.py +12 -12
  209. esphome/components/grove_tb6612fng/__init__.py +5 -6
  210. esphome/components/growatt_solar/sensor.py +1 -1
  211. esphome/components/gt911/binary_sensor/__init__.py +2 -2
  212. esphome/components/haier/binary_sensor/__init__.py +4 -10
  213. esphome/components/haier/button/__init__.py +3 -6
  214. esphome/components/haier/sensor/__init__.py +4 -6
  215. esphome/components/haier/switch/__init__.py +4 -7
  216. esphome/components/haier/text_sensor/__init__.py +4 -9
  217. esphome/components/havells_solar/sensor.py +1 -1
  218. esphome/components/hbridge/fan/__init__.py +6 -6
  219. esphome/components/hbridge/light/__init__.py +2 -1
  220. esphome/components/hdc1080/sensor.py +1 -1
  221. esphome/components/he60r/cover.py +2 -6
  222. esphome/components/heatpumpir/climate.py +1 -1
  223. esphome/components/hitachi_ac344/climate.py +1 -1
  224. esphome/components/hitachi_ac424/climate.py +1 -1
  225. esphome/components/hlw8012/sensor.py +6 -6
  226. esphome/components/hm3301/sensor.py +3 -3
  227. esphome/components/hmc5883l/sensor.py +4 -4
  228. esphome/components/homeassistant/time/__init__.py +2 -1
  229. esphome/components/honeywell_hih_i2c/sensor.py +3 -3
  230. esphome/components/honeywellabp/sensor.py +1 -2
  231. esphome/components/honeywellabp2_i2c/sensor.py +1 -2
  232. esphome/components/host/time/__init__.py +2 -2
  233. esphome/components/hrxl_maxsonar_wr/sensor.py +1 -1
  234. esphome/components/hte501/sensor.py +3 -3
  235. esphome/components/http_request/ota/__init__.py +5 -9
  236. esphome/components/http_request/update/__init__.py +3 -7
  237. esphome/components/htu21d/sensor.py +6 -6
  238. esphome/components/htu31d/sensor.py +1 -1
  239. esphome/components/hx711/sensor.py +3 -8
  240. esphome/components/hydreon_rgxx/binary_sensor.py +3 -7
  241. esphome/components/hydreon_rgxx/sensor.py +4 -4
  242. esphome/components/hyt271/sensor.py +1 -1
  243. esphome/components/i2c_device/__init__.py +1 -1
  244. esphome/components/i2s_audio/media_player/__init__.py +6 -8
  245. esphome/components/iaqcore/sensor.py +2 -2
  246. esphome/components/ina219/sensor.py +2 -2
  247. esphome/components/ina226/sensor.py +4 -4
  248. esphome/components/ina260/sensor.py +4 -4
  249. esphome/components/ina2xx_base/__init__.py +2 -2
  250. esphome/components/ina2xx_i2c/sensor.py +1 -1
  251. esphome/components/ina2xx_spi/sensor.py +1 -1
  252. esphome/components/ina3221/sensor.py +3 -3
  253. esphome/components/inkbird_ibsth1_mini/sensor.py +2 -2
  254. esphome/components/inkplate6/display.py +2 -2
  255. esphome/components/integration/sensor.py +4 -4
  256. esphome/components/internal_temperature/sensor.py +5 -7
  257. esphome/components/interval/__init__.py +1 -1
  258. esphome/components/jsn_sr04t/sensor.py +3 -3
  259. esphome/components/kamstrup_kmp/sensor.py +1 -1
  260. esphome/components/key_collector/__init__.py +2 -2
  261. esphome/components/kmeteriso/sensor.py +2 -2
  262. esphome/components/kuntze/sensor.py +5 -5
  263. esphome/components/lcd_base/__init__.py +2 -2
  264. esphome/components/lcd_gpio/display.py +4 -4
  265. esphome/components/lcd_menu/__init__.py +3 -7
  266. esphome/components/lcd_pcf8574/display.py +1 -1
  267. esphome/components/ld2410/__init__.py +4 -4
  268. esphome/components/ld2410/binary_sensor.py +5 -4
  269. esphome/components/ld2410/button/__init__.py +3 -2
  270. esphome/components/ld2410/number/__init__.py +5 -4
  271. esphome/components/ld2410/select/__init__.py +4 -3
  272. esphome/components/ld2410/sensor.py +6 -5
  273. esphome/components/ld2410/switch/__init__.py +2 -1
  274. esphome/components/ld2410/text_sensor.py +3 -2
  275. esphome/components/ld2420/__init__.py +1 -1
  276. esphome/components/ld2420/binary_sensor/__init__.py +4 -3
  277. esphome/components/ld2420/button/__init__.py +3 -2
  278. esphome/components/ld2420/number/__init__.py +3 -2
  279. esphome/components/ld2420/select/__init__.py +1 -0
  280. esphome/components/ld2420/sensor/__init__.py +3 -2
  281. esphome/components/ld2420/text_sensor/__init__.py +2 -6
  282. esphome/components/ld2450/__init__.py +2 -5
  283. esphome/components/ledc/output.py +3 -3
  284. esphome/components/libretiny/text_sensor.py +1 -1
  285. esphome/components/libretiny_pwm/output.py +3 -7
  286. esphome/components/lightwaverf/__init__.py +6 -8
  287. esphome/components/lilygo_t5_47/touchscreen/__init__.py +2 -3
  288. esphome/components/ltr390/sensor.py +1 -1
  289. esphome/components/ltr501/sensor.py +2 -2
  290. esphome/components/ltr_als_ps/sensor.py +2 -2
  291. esphome/components/lvgl/__init__.py +9 -12
  292. esphome/components/lvgl/automation.py +1 -1
  293. esphome/components/lvgl/defines.py +5 -2
  294. esphome/components/lvgl/lv_validation.py +17 -9
  295. esphome/components/lvgl/lvcode.py +9 -8
  296. esphome/components/lvgl/lvgl_esphome.h +19 -0
  297. esphome/components/lvgl/schemas.py +67 -18
  298. esphome/components/lvgl/styles.py +42 -11
  299. esphome/components/lvgl/trigger.py +10 -1
  300. esphome/components/lvgl/widgets/__init__.py +1 -2
  301. esphome/components/lvgl/widgets/canvas.py +403 -0
  302. esphome/components/lvgl/widgets/line.py +22 -32
  303. esphome/components/m5stack_8angle/__init__.py +1 -2
  304. esphome/components/m5stack_8angle/binary_sensor/__init__.py +2 -3
  305. esphome/components/m5stack_8angle/light/__init__.py +2 -4
  306. esphome/components/m5stack_8angle/sensor/__init__.py +2 -4
  307. esphome/components/matrix_keypad/binary_sensor/__init__.py +4 -3
  308. esphome/components/max31855/sensor.py +1 -1
  309. esphome/components/max31865/sensor.py +1 -1
  310. esphome/components/max44009/sensor.py +1 -1
  311. esphome/components/max6675/sensor.py +1 -1
  312. esphome/components/max6956/__init__.py +5 -5
  313. esphome/components/max6956/output/__init__.py +4 -3
  314. esphome/components/max7219/display.py +1 -1
  315. esphome/components/max7219digit/display.py +1 -1
  316. esphome/components/max9611/sensor.py +10 -10
  317. esphome/components/mcp23008/__init__.py +1 -1
  318. esphome/components/mcp23016/__init__.py +4 -4
  319. esphome/components/mcp23017/__init__.py +1 -1
  320. esphome/components/mcp23s08/__init__.py +1 -1
  321. esphome/components/mcp23s17/__init__.py +1 -1
  322. esphome/components/mcp23xxx_base/__init__.py +4 -4
  323. esphome/components/mcp2515/canbus.py +2 -2
  324. esphome/components/mcp3008/__init__.py +1 -1
  325. esphome/components/mcp3008/sensor/__init__.py +4 -4
  326. esphome/components/mcp3204/__init__.py +1 -1
  327. esphome/components/mcp3204/sensor/__init__.py +3 -2
  328. esphome/components/mcp4461/__init__.py +42 -0
  329. esphome/components/mcp4461/mcp4461.cpp +618 -0
  330. esphome/components/mcp4461/mcp4461.h +171 -0
  331. esphome/components/mcp4461/output/__init__.py +60 -0
  332. esphome/components/mcp4461/output/mcp4461_output.cpp +73 -0
  333. esphome/components/mcp4461/output/mcp4461_output.h +49 -0
  334. esphome/components/mcp4725/output.py +2 -2
  335. esphome/components/mcp4728/__init__.py +1 -1
  336. esphome/components/mcp4728/output/__init__.py +4 -3
  337. esphome/components/mcp47a1/output.py +2 -2
  338. esphome/components/mcp9808/sensor.py +1 -1
  339. esphome/components/mhz19/sensor.py +4 -4
  340. esphome/components/micronova/__init__.py +3 -5
  341. esphome/components/micronova/button/__init__.py +5 -5
  342. esphome/components/micronova/number/__init__.py +6 -10
  343. esphome/components/micronova/sensor/__init__.py +6 -6
  344. esphome/components/micronova/switch/__init__.py +6 -8
  345. esphome/components/micronova/text_sensor/__init__.py +5 -5
  346. esphome/components/microphone/__init__.py +2 -4
  347. esphome/components/midea/climate.py +6 -10
  348. esphome/components/midea_ir/climate.py +1 -1
  349. esphome/components/mitsubishi/climate.py +1 -1
  350. esphome/components/mlx90614/sensor.py +1 -1
  351. esphome/components/mmc5603/sensor.py +4 -4
  352. esphome/components/mmc5983/sensor.py +1 -1
  353. esphome/components/modbus/__init__.py +5 -9
  354. esphome/components/modbus_controller/__init__.py +1 -1
  355. esphome/components/monochromatic/light.py +2 -2
  356. esphome/components/mopeka_ble/__init__.py +1 -1
  357. esphome/components/mopeka_pro_check/sensor.py +12 -12
  358. esphome/components/mopeka_std_check/sensor.py +8 -8
  359. esphome/components/mpl3115a2/sensor.py +1 -1
  360. esphome/components/mpr121/__init__.py +3 -3
  361. esphome/components/mpr121/binary_sensor/__init__.py +5 -4
  362. esphome/components/mpu6050/sensor.py +4 -4
  363. esphome/components/mpu6886/sensor.py +4 -4
  364. esphome/components/mqtt_subscribe/sensor/__init__.py +3 -5
  365. esphome/components/mqtt_subscribe/text_sensor/__init__.py +1 -1
  366. esphome/components/ms5611/sensor.py +2 -2
  367. esphome/components/ms8607/sensor.py +1 -1
  368. esphome/components/my9231/__init__.py +1 -1
  369. esphome/components/my9231/output.py +2 -1
  370. esphome/components/nau7802/nau7802.cpp +0 -4
  371. esphome/components/nau7802/nau7802.h +0 -2
  372. esphome/components/neopixelbus/_methods.py +11 -9
  373. esphome/components/neopixelbus/light.py +11 -18
  374. esphome/components/nextion/binary_sensor/__init__.py +6 -14
  375. esphome/components/nextion/sensor/__init__.py +7 -10
  376. esphome/components/nextion/switch/__init__.py +3 -5
  377. esphome/components/nextion/text_sensor/__init__.py +3 -7
  378. esphome/components/noblex/climate.py +1 -1
  379. esphome/components/ntc/sensor.py +1 -1
  380. esphome/components/opentherm/__init__.py +6 -6
  381. esphome/components/opentherm/input.py +2 -1
  382. esphome/components/opentherm/number/__init__.py +5 -4
  383. esphome/components/opentherm/output/__init__.py +3 -2
  384. esphome/components/opentherm/schema.py +7 -7
  385. esphome/components/opentherm/switch/__init__.py +3 -2
  386. esphome/components/opentherm/validate.py +1 -1
  387. esphome/components/output/__init__.py +2 -3
  388. esphome/components/output/button/__init__.py +3 -2
  389. esphome/components/output/lock/__init__.py +2 -1
  390. esphome/components/output/switch/__init__.py +2 -1
  391. esphome/components/partition/light.py +4 -4
  392. esphome/components/pca6416a/__init__.py +4 -4
  393. esphome/components/pca9554/__init__.py +4 -4
  394. esphome/components/pca9685/__init__.py +2 -2
  395. esphome/components/pca9685/output.py +2 -1
  396. esphome/components/pcf85063/time.py +2 -3
  397. esphome/components/pcf8563/time.py +2 -2
  398. esphome/components/pcf8574/__init__.py +4 -4
  399. esphome/components/pid/climate.py +2 -2
  400. esphome/components/pid/sensor/__init__.py +4 -8
  401. esphome/components/pipsolar/__init__.py +1 -1
  402. esphome/components/pipsolar/binary_sensor/__init__.py +2 -2
  403. esphome/components/pipsolar/output/__init__.py +4 -3
  404. esphome/components/pipsolar/sensor/__init__.py +5 -4
  405. esphome/components/pipsolar/switch/__init__.py +2 -1
  406. esphome/components/pipsolar/text_sensor/__init__.py +2 -1
  407. esphome/components/pm1006/sensor.py +2 -2
  408. esphome/components/pmsa003i/sensor.py +4 -4
  409. esphome/components/pmsx003/sensor.py +10 -11
  410. esphome/components/pmwcs3/sensor.py +5 -5
  411. esphome/components/pn532/__init__.py +3 -3
  412. esphome/components/pn532_i2c/__init__.py +1 -1
  413. esphome/components/pn532_spi/__init__.py +1 -1
  414. esphome/components/pn7150/__init__.py +2 -2
  415. esphome/components/pn7150_i2c/__init__.py +1 -1
  416. esphome/components/pn7160/__init__.py +2 -2
  417. esphome/components/pn7160_i2c/__init__.py +1 -1
  418. esphome/components/pn7160_spi/__init__.py +1 -1
  419. esphome/components/power_supply/__init__.py +1 -1
  420. esphome/components/prometheus/__init__.py +3 -8
  421. esphome/components/psram/__init__.py +75 -11
  422. esphome/components/psram/psram.cpp +18 -7
  423. esphome/components/pulse_counter/sensor.py +4 -4
  424. esphome/components/pulse_meter/sensor.py +3 -3
  425. esphome/components/pulse_width/sensor.py +3 -8
  426. esphome/components/pvvx_mithermometer/display/__init__.py +1 -1
  427. esphome/components/pvvx_mithermometer/sensor.py +3 -3
  428. esphome/components/pylontech/__init__.py +1 -0
  429. esphome/components/pylontech/sensor/__init__.py +8 -13
  430. esphome/components/pylontech/text_sensor/__init__.py +2 -7
  431. esphome/components/pzem004t/sensor.py +3 -3
  432. esphome/components/pzemac/sensor.py +9 -9
  433. esphome/components/pzemdc/sensor.py +6 -6
  434. esphome/components/qmc5883l/sensor.py +5 -5
  435. esphome/components/qmp6988/sensor.py +3 -3
  436. esphome/components/qr_code/__init__.py +1 -1
  437. esphome/components/qspi_dbi/display.py +1 -1
  438. esphome/components/qspi_dbi/qspi_dbi.cpp +1 -1
  439. esphome/components/qspi_dbi/qspi_dbi.h +1 -1
  440. esphome/components/qwiic_pir/binary_sensor.py +2 -5
  441. esphome/components/radon_eye_ble/__init__.py +1 -1
  442. esphome/components/radon_eye_rd200/sensor.py +3 -4
  443. esphome/components/rc522/__init__.py +3 -3
  444. esphome/components/rc522_i2c/__init__.py +1 -1
  445. esphome/components/rc522_spi/__init__.py +1 -1
  446. esphome/components/rdm6300/__init__.py +2 -2
  447. esphome/components/rdm6300/binary_sensor.py +2 -1
  448. esphome/components/resistance/sensor.py +2 -2
  449. esphome/components/restart/button/__init__.py +1 -1
  450. esphome/components/restart/switch/__init__.py +2 -5
  451. esphome/components/rf_bridge/__init__.py +3 -3
  452. esphome/components/rgb/light.py +2 -2
  453. esphome/components/rgbct/light.py +3 -3
  454. esphome/components/rgbw/light.py +2 -2
  455. esphome/components/rgbww/light.py +4 -4
  456. esphome/components/rotary_encoder/sensor.py +8 -8
  457. esphome/components/rp2040_pio/__init__.py +0 -1
  458. esphome/components/rp2040_pio_led_strip/light.py +2 -4
  459. esphome/components/rp2040_pwm/output.py +3 -7
  460. esphome/components/rtttl/__init__.py +6 -6
  461. esphome/components/ruuvi_ble/__init__.py +1 -1
  462. esphome/components/ruuvitag/sensor.py +15 -15
  463. esphome/components/safe_mode/__init__.py +2 -3
  464. esphome/components/safe_mode/button/__init__.py +3 -2
  465. esphome/components/safe_mode/switch/__init__.py +4 -7
  466. esphome/components/scd30/sensor.py +5 -6
  467. esphome/components/scd4x/sensor.py +6 -8
  468. esphome/components/script/__init__.py +2 -2
  469. esphome/components/sdl/display.py +3 -3
  470. esphome/components/sdl/touchscreen/__init__.py +2 -2
  471. esphome/components/sdm_meter/sensor.py +3 -3
  472. esphome/components/sdp3x/sensor.py +1 -2
  473. esphome/components/sds011/sensor.py +4 -4
  474. esphome/components/seeed_mr24hpc1/__init__.py +1 -1
  475. esphome/components/seeed_mr24hpc1/binary_sensor.py +2 -5
  476. esphome/components/seeed_mr24hpc1/button/__init__.py +1 -0
  477. esphome/components/seeed_mr24hpc1/number/__init__.py +2 -4
  478. esphome/components/seeed_mr24hpc1/select/__init__.py +2 -3
  479. esphome/components/seeed_mr24hpc1/sensor.py +1 -0
  480. esphome/components/seeed_mr24hpc1/switch/__init__.py +2 -4
  481. esphome/components/seeed_mr24hpc1/text_sensor.py +1 -0
  482. esphome/components/seeed_mr60bha2/binary_sensor.py +2 -4
  483. esphome/components/seeed_mr60bha2/sensor.py +1 -1
  484. esphome/components/seeed_mr60fda2/button/__init__.py +1 -1
  485. esphome/components/seeed_mr60fda2/select/__init__.py +0 -1
  486. esphome/components/selec_meter/sensor.py +1 -1
  487. esphome/components/sen0321/sensor.py +2 -2
  488. esphome/components/sen21231/sensor.py +1 -1
  489. esphome/components/senseair/sensor.py +3 -3
  490. esphome/components/sensirion_common/__init__.py +0 -2
  491. esphome/components/servo/__init__.py +3 -3
  492. esphome/components/sfa30/sensor.py +4 -5
  493. esphome/components/sgp4x/sensor.py +2 -2
  494. esphome/components/shelly_dimmer/light.py +16 -16
  495. esphome/components/sht3xd/sensor.py +1 -1
  496. esphome/components/sht4x/sensor.py +6 -6
  497. esphome/components/shtcx/sensor.py +1 -1
  498. esphome/components/shutdown/button/__init__.py +2 -6
  499. esphome/components/shutdown/switch/__init__.py +2 -5
  500. esphome/components/sigma_delta_output/output.py +2 -7
  501. esphome/components/sim800l/__init__.py +3 -7
  502. esphome/components/sim800l/binary_sensor.py +3 -5
  503. esphome/components/sim800l/sensor.py +2 -1
  504. esphome/components/slow_pwm/output.py +4 -5
  505. esphome/components/sm10bit_base/__init__.py +2 -6
  506. esphome/components/sm16716/__init__.py +1 -1
  507. esphome/components/sm16716/output.py +2 -1
  508. esphome/components/sm2135/__init__.py +2 -6
  509. esphome/components/sm2135/output.py +2 -1
  510. esphome/components/sm2235/__init__.py +1 -1
  511. esphome/components/sm2235/output.py +2 -1
  512. esphome/components/sm2335/__init__.py +1 -1
  513. esphome/components/sm2335/output.py +2 -1
  514. esphome/components/sm300d2/sensor.py +13 -13
  515. esphome/components/sml/__init__.py +1 -1
  516. esphome/components/sml/sensor/__init__.py +1 -1
  517. esphome/components/sml/text_sensor/__init__.py +1 -1
  518. esphome/components/smt100/sensor.py +5 -6
  519. esphome/components/sn74hc165/__init__.py +5 -5
  520. esphome/components/sn74hc595/__init__.py +5 -5
  521. esphome/components/socket/__init__.py +1 -1
  522. esphome/components/sonoff_d1/light.py +2 -6
  523. esphome/components/speed/fan/__init__.py +2 -2
  524. esphome/components/spi/__init__.py +45 -36
  525. esphome/components/spi/spi.h +1 -0
  526. esphome/components/spi/spi_esp_idf.cpp +13 -5
  527. esphome/components/sprinkler/__init__.py +4 -5
  528. esphome/components/sps30/sensor.py +8 -8
  529. esphome/components/ssd1306_i2c/display.py +2 -2
  530. esphome/components/ssd1322_base/__init__.py +2 -2
  531. esphome/components/ssd1325_base/__init__.py +2 -2
  532. esphome/components/ssd1327_base/__init__.py +2 -2
  533. esphome/components/ssd1327_i2c/display.py +1 -1
  534. esphome/components/ssd1331_base/__init__.py +2 -2
  535. esphome/components/ssd1351_base/__init__.py +2 -2
  536. esphome/components/st7567_base/__init__.py +4 -4
  537. esphome/components/st7567_i2c/display.py +1 -1
  538. esphome/components/st7920/display.py +2 -2
  539. esphome/components/statsd/__init__.py +3 -3
  540. esphome/components/status/binary_sensor.py +2 -5
  541. esphome/components/status_led/__init__.py +1 -1
  542. esphome/components/status_led/light/__init__.py +2 -1
  543. esphome/components/stepper/__init__.py +2 -2
  544. esphome/components/sts3x/sensor.py +1 -1
  545. esphome/components/substitutions/__init__.py +2 -2
  546. esphome/components/sun/__init__.py +4 -4
  547. esphome/components/sun/sensor/__init__.py +4 -7
  548. esphome/components/sun/text_sensor/__init__.py +5 -4
  549. esphome/components/sun_gtil2/__init__.py +1 -1
  550. esphome/components/sun_gtil2/sensor.py +7 -6
  551. esphome/components/sun_gtil2/text_sensor.py +3 -2
  552. esphome/components/sx1509/__init__.py +5 -5
  553. esphome/components/sx1509/binary_sensor/__init__.py +3 -3
  554. esphome/components/sx1509/output/__init__.py +4 -3
  555. esphome/components/t6615/sensor.py +1 -1
  556. esphome/components/tca9548a/__init__.py +1 -1
  557. esphome/components/tcl112/climate.py +1 -1
  558. esphome/components/tcs34725/sensor.py +4 -4
  559. esphome/components/tee501/sensor.py +1 -1
  560. esphome/components/teleinfo/__init__.py +1 -1
  561. esphome/components/teleinfo/sensor/__init__.py +1 -7
  562. esphome/components/teleinfo/text_sensor/__init__.py +1 -1
  563. esphome/components/tem3200/sensor.py +1 -2
  564. esphome/components/template/alarm_control_panel/__init__.py +3 -10
  565. esphome/components/template/cover/__init__.py +4 -3
  566. esphome/components/template/datetime/__init__.py +8 -9
  567. esphome/components/template/event/__init__.py +2 -5
  568. esphome/components/template/fan/__init__.py +2 -6
  569. esphome/components/template/lock/__init__.py +3 -2
  570. esphome/components/template/number/__init__.py +3 -2
  571. esphome/components/template/output/__init__.py +4 -3
  572. esphome/components/template/select/__init__.py +3 -2
  573. esphome/components/template/sensor/__init__.py +4 -7
  574. esphome/components/template/switch/__init__.py +3 -2
  575. esphome/components/template/text/__init__.py +4 -3
  576. esphome/components/template/text_sensor/__init__.py +3 -2
  577. esphome/components/template/valve/__init__.py +3 -2
  578. esphome/components/time/real_time_clock.cpp +0 -4
  579. esphome/components/time/real_time_clock.h +4 -3
  580. esphome/components/time_based/cover.py +3 -3
  581. esphome/components/tlc59208f/__init__.py +1 -1
  582. esphome/components/tlc59208f/output.py +2 -1
  583. esphome/components/tlc5947/__init__.py +1 -1
  584. esphome/components/tlc5947/output/__init__.py +2 -1
  585. esphome/components/tlc5971/__init__.py +2 -8
  586. esphome/components/tlc5971/output/__init__.py +2 -1
  587. esphome/components/tm1621/display.py +3 -3
  588. esphome/components/tm1637/binary_sensor.py +1 -1
  589. esphome/components/tm1637/display.py +3 -3
  590. esphome/components/tm1651/__init__.py +4 -4
  591. esphome/components/tmp102/sensor.py +1 -1
  592. esphome/components/tmp1075/sensor.py +2 -2
  593. esphome/components/tmp117/sensor.py +1 -1
  594. esphome/components/tof10120/sensor.py +2 -2
  595. esphome/components/tormatic/cover.py +2 -6
  596. esphome/components/toshiba/climate.py +1 -1
  597. esphome/components/total_daily_energy/sensor.py +4 -4
  598. esphome/components/tsl2561/sensor.py +1 -1
  599. esphome/components/tsl2591/sensor.py +9 -9
  600. esphome/components/tt21100/binary_sensor/__init__.py +2 -2
  601. esphome/components/tt21100/touchscreen/__init__.py +2 -3
  602. esphome/components/ttp229_bsf/__init__.py +2 -2
  603. esphome/components/ttp229_bsf/binary_sensor.py +3 -2
  604. esphome/components/ttp229_lsf/__init__.py +1 -1
  605. esphome/components/ttp229_lsf/binary_sensor.py +3 -2
  606. esphome/components/tuya/__init__.py +3 -5
  607. esphome/components/tuya/binary_sensor/__init__.py +2 -2
  608. esphome/components/tuya/climate/__init__.py +6 -5
  609. esphome/components/tuya/cover/__init__.py +5 -4
  610. esphome/components/tuya/fan/__init__.py +3 -2
  611. esphome/components/tuya/light/__init__.py +9 -8
  612. esphome/components/tuya/number/__init__.py +6 -5
  613. esphome/components/tuya/select/__init__.py +4 -3
  614. esphome/components/tuya/sensor/__init__.py +3 -2
  615. esphome/components/tuya/switch/__init__.py +3 -2
  616. esphome/components/tuya/text_sensor/__init__.py +3 -2
  617. esphome/components/tx20/sensor.py +6 -6
  618. esphome/components/uart/__init__.py +20 -19
  619. esphome/components/uart/button/__init__.py +2 -1
  620. esphome/components/uart/switch/__init__.py +2 -1
  621. esphome/components/ufire_ise/sensor.py +2 -2
  622. esphome/components/uln2003/stepper.py +2 -2
  623. esphome/components/ultrasonic/sensor.py +4 -4
  624. esphome/components/uponor_smatrix/__init__.py +2 -6
  625. esphome/components/uponor_smatrix/climate/__init__.py +3 -3
  626. esphome/components/vbus/__init__.py +1 -1
  627. esphome/components/vbus/binary_sensor/__init__.py +7 -6
  628. esphome/components/vbus/sensor/__init__.py +7 -6
  629. esphome/components/veml3235/sensor.py +1 -1
  630. esphome/components/veml7700/sensor.py +1 -1
  631. esphome/components/version/text_sensor.py +2 -6
  632. esphome/components/vl53l0x/sensor.py +6 -6
  633. esphome/components/web_server_base/__init__.py +2 -2
  634. esphome/components/web_server_idf/__init__.py +1 -1
  635. esphome/components/weikai/__init__.py +1 -1
  636. esphome/components/whirlpool/climate.py +1 -1
  637. esphome/components/whynter/climate.py +1 -1
  638. esphome/components/wireguard/binary_sensor.py +1 -1
  639. esphome/components/wireguard/sensor.py +2 -5
  640. esphome/components/wireguard/text_sensor.py +2 -5
  641. esphome/components/wk2132_i2c/__init__.py +1 -1
  642. esphome/components/wk2132_spi/__init__.py +1 -2
  643. esphome/components/wk2168_i2c/__init__.py +3 -8
  644. esphome/components/wk2168_spi/__init__.py +3 -8
  645. esphome/components/wk2204_i2c/__init__.py +1 -1
  646. esphome/components/wk2204_spi/__init__.py +1 -1
  647. esphome/components/wk2212_i2c/__init__.py +3 -8
  648. esphome/components/wk2212_spi/__init__.py +3 -8
  649. esphome/components/wl_134/text_sensor.py +2 -4
  650. esphome/components/wled/__init__.py +2 -2
  651. esphome/components/x9c/output.py +4 -4
  652. esphome/components/xgzp68xx/sensor.py +5 -5
  653. esphome/components/xiaomi_ble/__init__.py +1 -1
  654. esphome/components/xiaomi_cgd1/sensor.py +3 -3
  655. esphome/components/xiaomi_cgdk2/sensor.py +3 -3
  656. esphome/components/xiaomi_cgg1/sensor.py +2 -2
  657. esphome/components/xiaomi_cgpr1/binary_sensor.py +6 -6
  658. esphome/components/xiaomi_gcls002/sensor.py +7 -7
  659. esphome/components/xiaomi_hhccjcy01/sensor.py +9 -9
  660. esphome/components/xiaomi_hhccjcy10/sensor.py +9 -9
  661. esphome/components/xiaomi_hhccpot002/sensor.py +7 -7
  662. esphome/components/xiaomi_jqjcy01ym/sensor.py +6 -6
  663. esphome/components/xiaomi_lywsd02/sensor.py +4 -4
  664. esphome/components/xiaomi_lywsd02mmc/sensor.py +5 -5
  665. esphome/components/xiaomi_lywsd03mmc/sensor.py +6 -6
  666. esphome/components/xiaomi_lywsdcgq/sensor.py +5 -5
  667. esphome/components/xiaomi_mhoc303/sensor.py +4 -4
  668. esphome/components/xiaomi_mhoc401/sensor.py +6 -6
  669. esphome/components/xiaomi_miscale/sensor.py +6 -6
  670. esphome/components/xiaomi_mjyd02yla/binary_sensor.py +8 -8
  671. esphome/components/xiaomi_mue4094rt/binary_sensor.py +2 -7
  672. esphome/components/xiaomi_rtcgq02lm/__init__.py +2 -3
  673. esphome/components/xiaomi_rtcgq02lm/binary_sensor.py +3 -3
  674. esphome/components/xiaomi_rtcgq02lm/sensor.py +3 -3
  675. esphome/components/xiaomi_wx08zm/binary_sensor.py +2 -3
  676. esphome/components/xl9535/__init__.py +2 -2
  677. esphome/components/yashima/climate.py +1 -1
  678. esphome/components/zhlt01/climate.py +1 -1
  679. esphome/components/zio_ultrasonic/sensor.py +2 -5
  680. esphome/components/zyaura/sensor.py +7 -7
  681. esphome/const.py +3 -1
  682. esphome/core/component.cpp +3 -1
  683. esphome/core/component.h +15 -2
  684. esphome/core/config.py +4 -0
  685. esphome/core/defines.h +21 -0
  686. esphome/core/helpers.cpp +6 -7
  687. esphome/core/scheduler.cpp +34 -67
  688. esphome/core/scheduler.h +7 -17
  689. esphome/dashboard/status/mqtt.py +0 -2
  690. {esphome-2025.3.3.dist-info → esphome-2025.4.0b1.dist-info}/METADATA +45 -44
  691. {esphome-2025.3.3.dist-info → esphome-2025.4.0b1.dist-info}/RECORD +695 -688
  692. {esphome-2025.3.3.dist-info → esphome-2025.4.0b1.dist-info}/WHEEL +1 -1
  693. {esphome-2025.3.3.dist-info → esphome-2025.4.0b1.dist-info}/entry_points.txt +0 -0
  694. {esphome-2025.3.3.dist-info → esphome-2025.4.0b1.dist-info/licenses}/LICENSE +0 -0
  695. {esphome-2025.3.3.dist-info → esphome-2025.4.0b1.dist-info}/top_level.txt +0 -0
@@ -6,6 +6,7 @@ from esphome.const import (
6
6
  CONF_FORMAT,
7
7
  CONF_GROUP,
8
8
  CONF_ID,
9
+ CONF_ON_BOOT,
9
10
  CONF_ON_VALUE,
10
11
  CONF_STATE,
11
12
  CONF_TEXT,
@@ -14,10 +15,11 @@ from esphome.const import (
14
15
  CONF_TYPE,
15
16
  )
16
17
  from esphome.core import TimePeriod
18
+ from esphome.core.config import StartupTrigger
17
19
  from esphome.schema_extractors import SCHEMA_EXTRACT
18
20
 
19
21
  from . import defines as df, lv_validation as lvalid
20
- from .defines import CONF_TIME_FORMAT, LV_GRAD_DIR
22
+ from .defines import CONF_TIME_FORMAT, CONF_X, CONF_Y, LV_GRAD_DIR
21
23
  from .helpers import add_lv_use, requires_component, validate_printf
22
24
  from .lv_validation import lv_color, lv_font, lv_gradient, lv_image, opacity
23
25
  from .lvcode import LvglComponent, lv_event_t_ptr
@@ -85,6 +87,31 @@ ENCODER_SCHEMA = cv.Schema(
85
87
  }
86
88
  )
87
89
 
90
+ POINT_SCHEMA = cv.Schema(
91
+ {
92
+ cv.Required(CONF_X): cv.templatable(cv.int_),
93
+ cv.Required(CONF_Y): cv.templatable(cv.int_),
94
+ }
95
+ )
96
+
97
+
98
+ def point_schema(value):
99
+ """
100
+ A shorthand for a point in the form of x,y
101
+ :param value: The value to check
102
+ :return: The value as a tuple of x,y
103
+ """
104
+ if isinstance(value, dict):
105
+ return POINT_SCHEMA(value)
106
+ try:
107
+ x, y = map(int, value.split(","))
108
+ return {CONF_X: x, CONF_Y: y}
109
+ except ValueError:
110
+ pass
111
+ # not raising this in the catch block because pylint doesn't like it
112
+ raise cv.Invalid("Invalid point format, should be <x_int>, <y_int>")
113
+
114
+
88
115
  # All LVGL styles and their validators
89
116
  STYLE_PROPS = {
90
117
  "align": df.CHILD_ALIGNMENTS.one_of,
@@ -103,6 +130,7 @@ STYLE_PROPS = {
103
130
  "bg_image_recolor": lvalid.lv_color,
104
131
  "bg_image_recolor_opa": lvalid.opacity,
105
132
  "bg_image_src": lvalid.lv_image,
133
+ "bg_image_tiled": lvalid.lv_bool,
106
134
  "bg_main_stop": lvalid.stop_value,
107
135
  "bg_opa": lvalid.opacity,
108
136
  "border_color": lvalid.lv_color,
@@ -117,9 +145,9 @@ STYLE_PROPS = {
117
145
  "height": lvalid.size,
118
146
  "image_recolor": lvalid.lv_color,
119
147
  "image_recolor_opa": lvalid.opacity,
120
- "line_width": cv.positive_int,
121
- "line_dash_width": cv.positive_int,
122
- "line_dash_gap": cv.positive_int,
148
+ "line_width": lvalid.lv_positive_int,
149
+ "line_dash_width": lvalid.lv_positive_int,
150
+ "line_dash_gap": lvalid.lv_positive_int,
123
151
  "line_rounded": lvalid.lv_bool,
124
152
  "line_color": lvalid.lv_color,
125
153
  "opa": lvalid.opacity,
@@ -147,8 +175,8 @@ STYLE_PROPS = {
147
175
  "LV_TEXT_DECOR_", "NONE", "UNDERLINE", "STRIKETHROUGH"
148
176
  ).several_of,
149
177
  "text_font": lv_font,
150
- "text_letter_space": cv.positive_int,
151
- "text_line_space": cv.positive_int,
178
+ "text_letter_space": lvalid.lv_positive_int,
179
+ "text_line_space": lvalid.lv_positive_int,
152
180
  "text_opa": lvalid.opacity,
153
181
  "transform_angle": lvalid.lv_angle,
154
182
  "transform_height": lvalid.pixels_or_percent,
@@ -172,10 +200,15 @@ STYLE_REMAP = {
172
200
  "bg_image_recolor": "bg_img_recolor",
173
201
  "bg_image_recolor_opa": "bg_img_recolor_opa",
174
202
  "bg_image_src": "bg_img_src",
203
+ "bg_image_tiled": "bg_img_tiled",
175
204
  "image_recolor": "img_recolor",
176
205
  "image_recolor_opa": "img_recolor_opa",
177
206
  }
178
207
 
208
+ cell_alignments = df.LV_CELL_ALIGNMENTS.one_of
209
+ grid_alignments = df.LV_GRID_ALIGNMENTS.one_of
210
+ flex_alignments = df.LV_FLEX_ALIGNMENTS.one_of
211
+
179
212
  # Complete object style schema
180
213
  STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend(
181
214
  {
@@ -186,6 +219,16 @@ STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).ex
186
219
  }
187
220
  )
188
221
 
222
+ # Also allow widget specific properties for use in style definitions
223
+ FULL_STYLE_SCHEMA = STYLE_SCHEMA.extend(
224
+ {
225
+ cv.Optional(df.CONF_GRID_CELL_X_ALIGN): grid_alignments,
226
+ cv.Optional(df.CONF_GRID_CELL_Y_ALIGN): grid_alignments,
227
+ cv.Optional(df.CONF_PAD_ROW): lvalid.pixels,
228
+ cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels,
229
+ }
230
+ )
231
+
189
232
  # Object states. Top level properties apply to MAIN
190
233
  STATE_SCHEMA = cv.Schema(
191
234
  {cv.Optional(state): STYLE_SCHEMA for state in df.STATES}
@@ -216,14 +259,24 @@ def automation_schema(typ: LvType):
216
259
  events = events + (CONF_ON_VALUE,)
217
260
  args = typ.get_arg_type() if isinstance(typ, LvType) else []
218
261
  args.append(lv_event_t_ptr)
219
- return {
220
- cv.Optional(event): validate_automation(
221
- {
222
- cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger.template(*args)),
223
- }
224
- )
225
- for event in events
226
- }
262
+ return cv.Schema(
263
+ {
264
+ cv.Optional(event): validate_automation(
265
+ {
266
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
267
+ Trigger.template(*args)
268
+ ),
269
+ }
270
+ )
271
+ for event in events
272
+ }
273
+ ).extend(
274
+ {
275
+ cv.Optional(CONF_ON_BOOT): validate_automation(
276
+ {cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StartupTrigger)}
277
+ )
278
+ }
279
+ )
227
280
 
228
281
 
229
282
  def base_update_schema(widget_type, parts):
@@ -307,10 +360,6 @@ grid_spec = cv.Any(
307
360
  lvalid.size, df.LvConstant("LV_GRID_", "CONTENT").one_of, grid_free_space
308
361
  )
309
362
 
310
- cell_alignments = df.LV_CELL_ALIGNMENTS.one_of
311
- grid_alignments = df.LV_GRID_ALIGNMENTS.one_of
312
- flex_alignments = df.LV_FLEX_ALIGNMENTS.one_of
313
-
314
363
  LAYOUT_SCHEMA = {
315
364
  cv.Optional(df.CONF_LAYOUT): cv.typed_schema(
316
365
  {
@@ -1,4 +1,6 @@
1
+ from esphome import automation
1
2
  import esphome.codegen as cg
3
+ import esphome.config_validation as cv
2
4
  from esphome.const import CONF_ID
3
5
  from esphome.core import ID
4
6
  from esphome.cpp_generator import MockObj
@@ -12,25 +14,54 @@ from .defines import (
12
14
  )
13
15
  from .helpers import add_lv_use
14
16
  from .lvcode import LambdaContext, LocalVariable, lv, lv_assign, lv_variable
15
- from .schemas import ALL_STYLES, STYLE_REMAP
16
- from .types import lv_lambda_t, lv_obj_t, lv_obj_t_ptr
17
- from .widgets import Widget, add_widgets, set_obj_properties, theme_widget_map
17
+ from .schemas import ALL_STYLES, FULL_STYLE_SCHEMA, STYLE_REMAP
18
+ from .types import ObjUpdateAction, lv_lambda_t, lv_obj_t, lv_obj_t_ptr, lv_style_t
19
+ from .widgets import (
20
+ Widget,
21
+ add_widgets,
22
+ set_obj_properties,
23
+ theme_widget_map,
24
+ wait_for_widgets,
25
+ )
18
26
  from .widgets.obj import obj_spec
19
27
 
20
28
 
29
+ async def style_set(svar, style):
30
+ for prop, validator in ALL_STYLES.items():
31
+ if (value := style.get(prop)) is not None:
32
+ if isinstance(validator, LValidator):
33
+ value = await validator.process(value)
34
+ if isinstance(value, list):
35
+ value = "|".join(value)
36
+ remapped_prop = STYLE_REMAP.get(prop, prop)
37
+ lv.call(f"style_set_{remapped_prop}", svar, literal(value))
38
+
39
+
21
40
  async def styles_to_code(config):
22
41
  """Convert styles to C__ code."""
23
42
  for style in config.get(CONF_STYLE_DEFINITIONS, ()):
24
43
  svar = cg.new_Pvariable(style[CONF_ID])
25
44
  lv.style_init(svar)
26
- for prop, validator in ALL_STYLES.items():
27
- if (value := style.get(prop)) is not None:
28
- if isinstance(validator, LValidator):
29
- value = await validator.process(value)
30
- if isinstance(value, list):
31
- value = "|".join(value)
32
- remapped_prop = STYLE_REMAP.get(prop, prop)
33
- lv.call(f"style_set_{remapped_prop}", svar, literal(value))
45
+ await style_set(svar, style)
46
+
47
+
48
+ @automation.register_action(
49
+ "lvgl.style.update",
50
+ ObjUpdateAction,
51
+ FULL_STYLE_SCHEMA.extend(
52
+ {
53
+ cv.Required(CONF_ID): cv.use_id(lv_style_t),
54
+ }
55
+ ),
56
+ )
57
+ async def style_update_to_code(config, action_id, template_arg, args):
58
+ await wait_for_widgets()
59
+ style = await cg.get_variable(config[CONF_ID])
60
+ async with LambdaContext(parameters=args, where=action_id) as context:
61
+ await style_set(style, config)
62
+
63
+ var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
64
+ return var
34
65
 
35
66
 
36
67
  async def theme_to_code(config):
@@ -1,6 +1,6 @@
1
1
  from esphome import automation
2
2
  import esphome.codegen as cg
3
- from esphome.const import CONF_ID, CONF_ON_VALUE, CONF_TRIGGER_ID
3
+ from esphome.const import CONF_ID, CONF_ON_BOOT, CONF_ON_VALUE, CONF_TRIGGER_ID
4
4
 
5
5
  from .defines import (
6
6
  CONF_ALIGN,
@@ -28,6 +28,13 @@ from .types import LV_EVENT
28
28
  from .widgets import LvScrActType, get_scr_act, widget_map
29
29
 
30
30
 
31
+ async def add_on_boot_triggers(triggers):
32
+ for conf in triggers:
33
+ trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], 390)
34
+ await cg.register_component(trigger, conf)
35
+ await automation.build_automation(trigger, [], conf)
36
+
37
+
31
38
  async def generate_triggers():
32
39
  """
33
40
  Generate LVGL triggers for all defined widgets
@@ -75,6 +82,8 @@ async def generate_triggers():
75
82
  UPDATE_EVENT,
76
83
  )
77
84
 
85
+ await add_on_boot_triggers(w.config.get(CONF_ON_BOOT, ()))
86
+
78
87
  # Generate align to directives while we're here
79
88
  if align_to := w.config.get(CONF_ALIGN_TO):
80
89
  target = widget_map[align_to[CONF_ID]].obj
@@ -3,13 +3,12 @@ from typing import Any, Union
3
3
 
4
4
  from esphome import codegen as cg, config_validation as cv
5
5
  from esphome.config_validation import Invalid
6
- from esphome.const import CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE
6
+ from esphome.const import CONF_DEFAULT, CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE
7
7
  from esphome.core import ID, TimePeriod
8
8
  from esphome.coroutine import FakeAwaitable
9
9
  from esphome.cpp_generator import CallExpression, MockObj
10
10
 
11
11
  from ..defines import (
12
- CONF_DEFAULT,
13
12
  CONF_FLEX_ALIGN_CROSS,
14
13
  CONF_FLEX_ALIGN_MAIN,
15
14
  CONF_FLEX_ALIGN_TRACK,
@@ -0,0 +1,403 @@
1
+ from esphome import automation, codegen as cg, config_validation as cv
2
+ from esphome.components.display_menu_base import CONF_LABEL
3
+ from esphome.const import CONF_COLOR, CONF_HEIGHT, CONF_ID, CONF_TEXT, CONF_WIDTH
4
+ from esphome.cpp_generator import Literal, MockObj
5
+
6
+ from ..automation import action_to_code
7
+ from ..defines import (
8
+ CONF_END_ANGLE,
9
+ CONF_MAIN,
10
+ CONF_OPA,
11
+ CONF_PIVOT_X,
12
+ CONF_PIVOT_Y,
13
+ CONF_POINTS,
14
+ CONF_SRC,
15
+ CONF_START_ANGLE,
16
+ CONF_X,
17
+ CONF_Y,
18
+ literal,
19
+ )
20
+ from ..lv_validation import (
21
+ lv_angle,
22
+ lv_bool,
23
+ lv_color,
24
+ lv_image,
25
+ lv_text,
26
+ opacity,
27
+ pixels,
28
+ size,
29
+ )
30
+ from ..lvcode import LocalVariable, lv, lv_assign
31
+ from ..schemas import STYLE_PROPS, STYLE_REMAP, TEXT_SCHEMA, point_schema
32
+ from ..types import LvType, ObjUpdateAction, WidgetType
33
+ from . import Widget, get_widgets
34
+ from .line import lv_point_t, process_coord
35
+
36
+ CONF_CANVAS = "canvas"
37
+ CONF_BUFFER_ID = "buffer_id"
38
+ CONF_MAX_WIDTH = "max_width"
39
+ CONF_TRANSPARENT = "transparent"
40
+ CONF_RADIUS = "radius"
41
+
42
+ lv_canvas_t = LvType("lv_canvas_t")
43
+
44
+
45
+ class CanvasType(WidgetType):
46
+ def __init__(self):
47
+ super().__init__(
48
+ CONF_CANVAS,
49
+ lv_canvas_t,
50
+ (CONF_MAIN,),
51
+ cv.Schema(
52
+ {
53
+ cv.Required(CONF_WIDTH): size,
54
+ cv.Required(CONF_HEIGHT): size,
55
+ cv.Optional(CONF_TRANSPARENT, default=False): cv.boolean,
56
+ }
57
+ ),
58
+ )
59
+
60
+ def get_uses(self):
61
+ return "img", CONF_LABEL
62
+
63
+ async def to_code(self, w: Widget, config):
64
+ width = config[CONF_WIDTH]
65
+ height = config[CONF_HEIGHT]
66
+ use_alpha = "_ALPHA" if config[CONF_TRANSPARENT] else ""
67
+ lv.canvas_set_buffer(
68
+ w.obj,
69
+ lv.custom_mem_alloc(
70
+ literal(f"LV_CANVAS_BUF_SIZE_TRUE_COLOR{use_alpha}({width}, {height})")
71
+ ),
72
+ width,
73
+ height,
74
+ literal(f"LV_IMG_CF_TRUE_COLOR{use_alpha}"),
75
+ )
76
+
77
+
78
+ canvas_spec = CanvasType()
79
+
80
+
81
+ @automation.register_action(
82
+ "lvgl.canvas.fill",
83
+ ObjUpdateAction,
84
+ cv.Schema(
85
+ {
86
+ cv.GenerateID(CONF_ID): cv.use_id(lv_canvas_t),
87
+ cv.Required(CONF_COLOR): lv_color,
88
+ cv.Optional(CONF_OPA, default="COVER"): opacity,
89
+ },
90
+ ),
91
+ )
92
+ async def canvas_fill(config, action_id, template_arg, args):
93
+ widget = await get_widgets(config)
94
+ color = await lv_color.process(config[CONF_COLOR])
95
+ opa = await opacity.process(config[CONF_OPA])
96
+
97
+ async def do_fill(w: Widget):
98
+ lv.canvas_fill_bg(w.obj, color, opa)
99
+
100
+ return await action_to_code(widget, do_fill, action_id, template_arg, args)
101
+
102
+
103
+ @automation.register_action(
104
+ "lvgl.canvas.set_pixels",
105
+ ObjUpdateAction,
106
+ cv.Schema(
107
+ {
108
+ cv.GenerateID(CONF_ID): cv.use_id(lv_canvas_t),
109
+ cv.Required(CONF_COLOR): lv_color,
110
+ cv.Optional(CONF_OPA): opacity,
111
+ cv.Required(CONF_POINTS): cv.ensure_list(point_schema),
112
+ },
113
+ ),
114
+ )
115
+ async def canvas_set_pixel(config, action_id, template_arg, args):
116
+ widget = await get_widgets(config)
117
+ color = await lv_color.process(config[CONF_COLOR])
118
+ opa = await opacity.process(config.get(CONF_OPA))
119
+ points = [
120
+ (
121
+ await pixels.process(p[CONF_X]),
122
+ await pixels.process(p[CONF_Y]),
123
+ )
124
+ for p in config[CONF_POINTS]
125
+ ]
126
+
127
+ async def do_set_pixels(w: Widget):
128
+ if isinstance(color, MockObj):
129
+ for point in points:
130
+ x, y = point
131
+ lv.canvas_set_px_color(w.obj, x, y, color)
132
+ else:
133
+ with LocalVariable("color", "lv_color_t", color, modifier="") as color_var:
134
+ for point in points:
135
+ x, y = point
136
+ lv.canvas_set_px_color(w.obj, x, y, color_var)
137
+ if opa:
138
+ if isinstance(opa, Literal):
139
+ for point in points:
140
+ x, y = point
141
+ lv.canvas_set_px_opa(w.obj, x, y, opa)
142
+ else:
143
+ with LocalVariable("opa", "lv_opa_t", opa, modifier="") as opa_var:
144
+ for point in points:
145
+ x, y = point
146
+ lv.canvas_set_px_opa(w.obj, x, y, opa_var)
147
+
148
+ return await action_to_code(widget, do_set_pixels, action_id, template_arg, args)
149
+
150
+
151
+ DRAW_SCHEMA = cv.Schema(
152
+ {
153
+ cv.GenerateID(CONF_ID): cv.use_id(lv_canvas_t),
154
+ cv.Required(CONF_X): pixels,
155
+ cv.Required(CONF_Y): pixels,
156
+ }
157
+ )
158
+ DRAW_OPA_SCHEMA = DRAW_SCHEMA.extend(
159
+ {
160
+ cv.Optional(CONF_OPA): opacity,
161
+ }
162
+ )
163
+
164
+
165
+ async def draw_to_code(config, dsc_type, props, do_draw, action_id, template_arg, args):
166
+ widget = await get_widgets(config)
167
+ x = await pixels.process(config.get(CONF_X))
168
+ y = await pixels.process(config.get(CONF_Y))
169
+
170
+ async def action_func(w: Widget):
171
+ with LocalVariable("dsc", f"lv_draw_{dsc_type}_dsc_t", modifier="") as dsc:
172
+ dsc_addr = literal(f"&{dsc}")
173
+ lv.call(f"draw_{dsc_type}_dsc_init", dsc_addr)
174
+ if CONF_OPA in config:
175
+ opa = await opacity.process(config[CONF_OPA])
176
+ lv_assign(dsc.opa, opa)
177
+ for prop, validator in props.items():
178
+ if prop in config:
179
+ value = await validator.process(config[prop])
180
+ mapped_prop = STYLE_REMAP.get(prop, prop)
181
+ lv_assign(getattr(dsc, mapped_prop), value)
182
+ await do_draw(w, x, y, dsc_addr)
183
+
184
+ return await action_to_code(widget, action_func, action_id, template_arg, args)
185
+
186
+
187
+ RECT_PROPS = {
188
+ p: STYLE_PROPS[p]
189
+ for p in (
190
+ "radius",
191
+ "bg_opa",
192
+ "bg_color",
193
+ "bg_grad",
194
+ "border_color",
195
+ "border_width",
196
+ "border_opa",
197
+ "outline_color",
198
+ "outline_width",
199
+ "outline_pad",
200
+ "outline_opa",
201
+ "shadow_color",
202
+ "shadow_width",
203
+ "shadow_ofs_x",
204
+ "shadow_ofs_y",
205
+ "shadow_spread",
206
+ "shadow_opa",
207
+ )
208
+ }
209
+
210
+
211
+ @automation.register_action(
212
+ "lvgl.canvas.draw_rectangle",
213
+ ObjUpdateAction,
214
+ DRAW_SCHEMA.extend(
215
+ {
216
+ cv.Required(CONF_WIDTH): cv.templatable(cv.int_),
217
+ cv.Required(CONF_HEIGHT): cv.templatable(cv.int_),
218
+ },
219
+ ).extend({cv.Optional(prop): STYLE_PROPS[prop] for prop in RECT_PROPS}),
220
+ )
221
+ async def canvas_draw_rect(config, action_id, template_arg, args):
222
+ width = await pixels.process(config[CONF_WIDTH])
223
+ height = await pixels.process(config[CONF_HEIGHT])
224
+
225
+ async def do_draw_rect(w: Widget, x, y, dsc_addr):
226
+ lv.canvas_draw_rect(w.obj, x, y, width, height, dsc_addr)
227
+
228
+ return await draw_to_code(
229
+ config, "rect", RECT_PROPS, do_draw_rect, action_id, template_arg, args
230
+ )
231
+
232
+
233
+ TEXT_PROPS = {
234
+ p: STYLE_PROPS[f"text_{p}"]
235
+ for p in (
236
+ "font",
237
+ "color",
238
+ # "sel_color",
239
+ # "sel_bg_color",
240
+ "line_space",
241
+ "letter_space",
242
+ "align",
243
+ "decor",
244
+ )
245
+ }
246
+
247
+
248
+ @automation.register_action(
249
+ "lvgl.canvas.draw_text",
250
+ ObjUpdateAction,
251
+ TEXT_SCHEMA.extend(DRAW_OPA_SCHEMA)
252
+ .extend(
253
+ {
254
+ cv.Required(CONF_MAX_WIDTH): cv.templatable(cv.int_),
255
+ },
256
+ )
257
+ .extend({cv.Optional(prop): STYLE_PROPS[f"text_{prop}"] for prop in TEXT_PROPS}),
258
+ )
259
+ async def canvas_draw_text(config, action_id, template_arg, args):
260
+ text = await lv_text.process(config[CONF_TEXT])
261
+ max_width = await pixels.process(config[CONF_MAX_WIDTH])
262
+
263
+ async def do_draw_text(w: Widget, x, y, dsc_addr):
264
+ lv.canvas_draw_text(w.obj, x, y, max_width, dsc_addr, text)
265
+
266
+ return await draw_to_code(
267
+ config, "label", TEXT_PROPS, do_draw_text, action_id, template_arg, args
268
+ )
269
+
270
+
271
+ IMG_PROPS = {
272
+ "angle": STYLE_PROPS["transform_angle"],
273
+ "zoom": STYLE_PROPS["transform_zoom"],
274
+ "recolor": STYLE_PROPS["image_recolor"],
275
+ "recolor_opa": STYLE_PROPS["image_recolor_opa"],
276
+ "opa": STYLE_PROPS["opa"],
277
+ }
278
+
279
+
280
+ @automation.register_action(
281
+ "lvgl.canvas.draw_image",
282
+ ObjUpdateAction,
283
+ DRAW_OPA_SCHEMA.extend(
284
+ {
285
+ cv.Required(CONF_SRC): lv_image,
286
+ cv.Optional(CONF_PIVOT_X, default=0): pixels,
287
+ cv.Optional(CONF_PIVOT_Y, default=0): pixels,
288
+ },
289
+ ).extend({cv.Optional(prop): validator for prop, validator in IMG_PROPS.items()}),
290
+ )
291
+ async def canvas_draw_image(config, action_id, template_arg, args):
292
+ src = await lv_image.process(config[CONF_SRC])
293
+ pivot_x = await pixels.process(config[CONF_PIVOT_X])
294
+ pivot_y = await pixels.process(config[CONF_PIVOT_Y])
295
+
296
+ async def do_draw_image(w: Widget, x, y, dsc_addr):
297
+ dsc = MockObj(f"(*{dsc_addr})")
298
+ if pivot_x or pivot_y:
299
+ # pylint :disable=no-member
300
+ lv_assign(dsc.pivot, literal(f"{{{pivot_x}, {pivot_y}}}"))
301
+ lv.canvas_draw_img(w.obj, x, y, src, dsc_addr)
302
+
303
+ return await draw_to_code(
304
+ config, "img", IMG_PROPS, do_draw_image, action_id, template_arg, args
305
+ )
306
+
307
+
308
+ LINE_PROPS = {
309
+ "width": STYLE_PROPS["line_width"],
310
+ "color": STYLE_PROPS["line_color"],
311
+ "dash-width": STYLE_PROPS["line_dash_width"],
312
+ "dash-gap": STYLE_PROPS["line_dash_gap"],
313
+ "round_start": lv_bool,
314
+ "round_end": lv_bool,
315
+ }
316
+
317
+
318
+ @automation.register_action(
319
+ "lvgl.canvas.draw_line",
320
+ ObjUpdateAction,
321
+ cv.Schema(
322
+ {
323
+ cv.GenerateID(CONF_ID): cv.use_id(lv_canvas_t),
324
+ cv.Optional(CONF_OPA): opacity,
325
+ cv.Required(CONF_POINTS): cv.ensure_list(point_schema),
326
+ },
327
+ ).extend({cv.Optional(prop): validator for prop, validator in LINE_PROPS.items()}),
328
+ )
329
+ async def canvas_draw_line(config, action_id, template_arg, args):
330
+ points = [
331
+ [await process_coord(p[CONF_X]), await process_coord(p[CONF_Y])]
332
+ for p in config[CONF_POINTS]
333
+ ]
334
+
335
+ async def do_draw_line(w: Widget, x, y, dsc_addr):
336
+ with LocalVariable(
337
+ "points", cg.std_vector.template(lv_point_t), points, modifier=""
338
+ ) as points_var:
339
+ lv.canvas_draw_line(w.obj, points_var.data(), points_var.size(), dsc_addr)
340
+
341
+ return await draw_to_code(
342
+ config, "line", LINE_PROPS, do_draw_line, action_id, template_arg, args
343
+ )
344
+
345
+
346
+ @automation.register_action(
347
+ "lvgl.canvas.draw_polygon",
348
+ ObjUpdateAction,
349
+ cv.Schema(
350
+ {
351
+ cv.GenerateID(CONF_ID): cv.use_id(lv_canvas_t),
352
+ cv.Required(CONF_POINTS): cv.ensure_list(point_schema),
353
+ },
354
+ ).extend({cv.Optional(prop): STYLE_PROPS[prop] for prop in RECT_PROPS}),
355
+ )
356
+ async def canvas_draw_polygon(config, action_id, template_arg, args):
357
+ points = [
358
+ [await process_coord(p[CONF_X]), await process_coord(p[CONF_Y])]
359
+ for p in config[CONF_POINTS]
360
+ ]
361
+
362
+ async def do_draw_polygon(w: Widget, x, y, dsc_addr):
363
+ with LocalVariable(
364
+ "points", cg.std_vector.template(lv_point_t), points, modifier=""
365
+ ) as points_var:
366
+ lv.canvas_draw_polygon(
367
+ w.obj, points_var.data(), points_var.size(), dsc_addr
368
+ )
369
+
370
+ return await draw_to_code(
371
+ config, "rect", RECT_PROPS, do_draw_polygon, action_id, template_arg, args
372
+ )
373
+
374
+
375
+ ARC_PROPS = {
376
+ "width": STYLE_PROPS["arc_width"],
377
+ "color": STYLE_PROPS["arc_color"],
378
+ "rounded": STYLE_PROPS["arc_rounded"],
379
+ }
380
+
381
+
382
+ @automation.register_action(
383
+ "lvgl.canvas.draw_arc",
384
+ ObjUpdateAction,
385
+ DRAW_OPA_SCHEMA.extend(
386
+ {
387
+ cv.Required(CONF_RADIUS): pixels,
388
+ cv.Required(CONF_START_ANGLE): lv_angle,
389
+ cv.Required(CONF_END_ANGLE): lv_angle,
390
+ }
391
+ ).extend({cv.Optional(prop): validator for prop, validator in ARC_PROPS.items()}),
392
+ )
393
+ async def canvas_draw_arc(config, action_id, template_arg, args):
394
+ radius = await size.process(config[CONF_RADIUS])
395
+ start_angle = await lv_angle.process(config[CONF_START_ANGLE])
396
+ end_angle = await lv_angle.process(config[CONF_END_ANGLE])
397
+
398
+ async def do_draw_arc(w: Widget, x, y, dsc_addr):
399
+ lv.canvas_draw_arc(w.obj, x, y, radius, start_angle, end_angle, dsc_addr)
400
+
401
+ return await draw_to_code(
402
+ config, "arc", ARC_PROPS, do_draw_arc, action_id, template_arg, args
403
+ )