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.
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
+ )