esphome 2025.3.3__py3-none-any.whl → 2025.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (713) hide show
  1. esphome/__main__.py +34 -10
  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/am2315c.cpp +4 -4
  27. esphome/components/am2315c/sensor.py +1 -1
  28. esphome/components/am2320/sensor.py +1 -1
  29. esphome/components/am43/cover/__init__.py +1 -1
  30. esphome/components/am43/sensor/__init__.py +3 -3
  31. esphome/components/analog_threshold/binary_sensor.py +2 -5
  32. esphome/components/anova/climate.py +1 -1
  33. esphome/components/apds9306/sensor.py +1 -1
  34. esphome/components/apds9960/__init__.py +1 -1
  35. esphome/components/apds9960/binary_sensor.py +2 -1
  36. esphome/components/apds9960/sensor.py +3 -2
  37. esphome/components/api/api_frame_helper.cpp +25 -1
  38. esphome/components/as3935/__init__.py +3 -3
  39. esphome/components/as3935/binary_sensor.py +2 -1
  40. esphome/components/as3935/sensor.py +4 -3
  41. esphome/components/as3935_i2c/__init__.py +1 -1
  42. esphome/components/as3935_spi/__init__.py +1 -1
  43. esphome/components/as5600/__init__.py +2 -2
  44. esphome/components/as5600/sensor/__init__.py +10 -9
  45. esphome/components/as7341/sensor.py +1 -2
  46. esphome/components/at581x/__init__.py +4 -8
  47. esphome/components/at581x/switch/__init__.py +2 -4
  48. esphome/components/atc_mithermometer/sensor.py +3 -3
  49. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +7 -3
  50. esphome/components/b_parasite/sensor.py +2 -2
  51. esphome/components/ballu/climate.py +1 -1
  52. esphome/components/bang_bang/climate.py +2 -2
  53. esphome/components/bedjet/__init__.py +2 -6
  54. esphome/components/bedjet/climate/__init__.py +3 -6
  55. esphome/components/bedjet/fan/__init__.py +4 -9
  56. esphome/components/bedjet/sensor/__init__.py +3 -6
  57. esphome/components/beken_spi_led_strip/light.py +2 -2
  58. esphome/components/bh1750/sensor.py +2 -6
  59. esphome/components/binary/fan/__init__.py +2 -1
  60. esphome/components/binary/light/__init__.py +3 -2
  61. esphome/components/binary_sensor_map/sensor.py +5 -6
  62. esphome/components/bl0939/sensor.py +1 -1
  63. esphome/components/bl0940/sensor.py +3 -3
  64. esphome/components/ble_client/__init__.py +3 -2
  65. esphome/components/ble_client/sensor/__init__.py +1 -1
  66. esphome/components/ble_client/text_sensor/__init__.py +1 -1
  67. esphome/components/bluetooth_proxy/__init__.py +35 -23
  68. esphome/components/bme280_base/__init__.py +1 -1
  69. esphome/components/bme280_i2c/sensor.py +3 -2
  70. esphome/components/bme280_spi/sensor.py +3 -2
  71. esphome/components/bme680/sensor.py +4 -4
  72. esphome/components/bme680_bsec/__init__.py +1 -1
  73. esphome/components/bme680_bsec/sensor.py +3 -6
  74. esphome/components/bme680_bsec/text_sensor.py +3 -2
  75. esphome/components/bmi160/sensor.py +6 -6
  76. esphome/components/bmp085/sensor.py +1 -1
  77. esphome/components/bmp280_base/__init__.py +1 -1
  78. esphome/components/bmp280_i2c/sensor.py +3 -2
  79. esphome/components/bmp280_spi/sensor.py +3 -2
  80. esphome/components/bmp3xx_base/__init__.py +1 -1
  81. esphome/components/bmp3xx_i2c/sensor.py +2 -1
  82. esphome/components/bmp3xx_spi/sensor.py +2 -1
  83. esphome/components/bmp581/sensor.py +2 -1
  84. esphome/components/bp1658cj/__init__.py +2 -6
  85. esphome/components/bp1658cj/output.py +2 -1
  86. esphome/components/bp5758d/__init__.py +2 -6
  87. esphome/components/bp5758d/output.py +3 -2
  88. esphome/components/canbus/__init__.py +13 -2
  89. esphome/components/canbus/canbus.cpp +7 -1
  90. esphome/components/cap1188/__init__.py +2 -2
  91. esphome/components/cap1188/binary_sensor.py +3 -2
  92. esphome/components/captive_portal/__init__.py +3 -3
  93. esphome/components/ccs811/sensor.py +10 -10
  94. esphome/components/cd74hc4067/__init__.py +2 -5
  95. esphome/components/cd74hc4067/sensor.py +6 -5
  96. esphome/components/climate_ir/__init__.py +2 -2
  97. esphome/components/climate_ir_lg/climate.py +1 -1
  98. esphome/components/color/__init__.py +1 -2
  99. esphome/components/color_temperature/light.py +2 -2
  100. esphome/components/combination/sensor.py +1 -1
  101. esphome/components/coolix/climate.py +1 -1
  102. esphome/components/copy/binary_sensor/__init__.py +1 -1
  103. esphome/components/copy/button/__init__.py +1 -1
  104. esphome/components/copy/cover/__init__.py +1 -1
  105. esphome/components/copy/fan/__init__.py +2 -7
  106. esphome/components/copy/lock/__init__.py +2 -7
  107. esphome/components/copy/number/__init__.py +1 -1
  108. esphome/components/copy/select/__init__.py +2 -7
  109. esphome/components/copy/sensor/__init__.py +2 -2
  110. esphome/components/copy/switch/__init__.py +1 -1
  111. esphome/components/copy/text/__init__.py +2 -7
  112. esphome/components/copy/text_sensor/__init__.py +2 -6
  113. esphome/components/cs5460a/sensor.py +7 -7
  114. esphome/components/cse7761/sensor.py +2 -2
  115. esphome/components/cse7766/sensor.py +1 -1
  116. esphome/components/cst226/touchscreen/__init__.py +3 -4
  117. esphome/components/ct_clamp/sensor.py +1 -1
  118. esphome/components/current_based/cover.py +3 -4
  119. esphome/components/cwww/light.py +3 -3
  120. esphome/components/dac7678/__init__.py +1 -1
  121. esphome/components/dac7678/output.py +2 -1
  122. esphome/components/daikin/climate.py +1 -1
  123. esphome/components/daikin_arc/climate.py +1 -1
  124. esphome/components/daikin_brc/climate.py +1 -1
  125. esphome/components/dallas_temp/sensor.py +1 -1
  126. esphome/components/daly_bms/__init__.py +2 -2
  127. esphome/components/daly_bms/binary_sensor.py +3 -2
  128. esphome/components/daly_bms/sensor.py +14 -13
  129. esphome/components/daly_bms/text_sensor.py +3 -2
  130. esphome/components/dashboard_import/__init__.py +5 -5
  131. esphome/components/debug/sensor.py +7 -6
  132. esphome/components/debug/text_sensor.py +1 -1
  133. esphome/components/deep_sleep/__init__.py +12 -13
  134. esphome/components/delonghi/climate.py +1 -1
  135. esphome/components/demo/__init__.py +1 -1
  136. esphome/components/dfplayer/__init__.py +3 -3
  137. esphome/components/dfrobot_sen0395/__init__.py +3 -3
  138. esphome/components/dfrobot_sen0395/binary_sensor.py +2 -1
  139. esphome/components/dfrobot_sen0395/switch/__init__.py +2 -3
  140. esphome/components/dht/sensor.py +4 -5
  141. esphome/components/dht12/sensor.py +3 -3
  142. esphome/components/dps310/sensor.py +3 -3
  143. esphome/components/ds1307/time.py +2 -3
  144. esphome/components/dsmr/__init__.py +3 -7
  145. esphome/components/dsmr/sensor.py +5 -4
  146. esphome/components/dsmr/text_sensor.py +3 -2
  147. esphome/components/duty_cycle/sensor.py +3 -8
  148. esphome/components/duty_time/sensor.py +7 -7
  149. esphome/components/e131/__init__.py +3 -3
  150. esphome/components/ee895/sensor.py +5 -5
  151. esphome/components/ektf2232/touchscreen/__init__.py +2 -3
  152. esphome/components/emc2101/__init__.py +1 -1
  153. esphome/components/emc2101/output/__init__.py +3 -2
  154. esphome/components/emc2101/sensor/__init__.py +4 -3
  155. esphome/components/emmeti/climate.py +1 -1
  156. esphome/components/endstop/cover.py +3 -3
  157. esphome/components/ens160_base/__init__.py +1 -1
  158. esphome/components/ens160_i2c/sensor.py +2 -1
  159. esphome/components/ens160_spi/sensor.py +2 -1
  160. esphome/components/ens210/sensor.py +1 -1
  161. esphome/components/esp32/__init__.py +10 -0
  162. esphome/components/esp32_ble_tracker/__init__.py +135 -51
  163. esphome/components/esp32_camera/__init__.py +7 -8
  164. esphome/components/esp32_camera_web_server/__init__.py +2 -2
  165. esphome/components/esp32_can/canbus.py +21 -0
  166. esphome/components/esp32_can/esp32_can.cpp +1 -1
  167. esphome/components/esp32_can/esp32_can.h +4 -0
  168. esphome/components/esp32_dac/output.py +2 -2
  169. esphome/components/esp32_hall/sensor.py +2 -6
  170. esphome/components/esp32_touch/__init__.py +7 -7
  171. esphome/components/esp32_touch/binary_sensor.py +4 -7
  172. esphome/components/esp8266_pwm/output.py +3 -8
  173. esphome/components/ethernet/__init__.py +1 -0
  174. esphome/components/ethernet/ethernet_component.cpp +1 -1
  175. esphome/components/ethernet_info/ethernet_info_text_sensor.h +1 -0
  176. esphome/components/exposure_notifications/__init__.py +2 -2
  177. esphome/components/external_components/__init__.py +1 -1
  178. esphome/components/ezo/sensor.py +2 -2
  179. esphome/components/ezo_pmp/__init__.py +4 -4
  180. esphome/components/ezo_pmp/binary_sensor.py +4 -4
  181. esphome/components/ezo_pmp/sensor.py +4 -5
  182. esphome/components/ezo_pmp/text_sensor.py +2 -6
  183. esphome/components/factory_reset/button/__init__.py +2 -1
  184. esphome/components/factory_reset/switch/__init__.py +3 -2
  185. esphome/components/fastled_base/__init__.py +3 -3
  186. esphome/components/fastled_clockless/light.py +2 -2
  187. esphome/components/fastled_spi/light.py +2 -2
  188. esphome/components/feedback/cover.py +3 -3
  189. esphome/components/fingerprint_grow/__init__.py +5 -6
  190. esphome/components/fingerprint_grow/binary_sensor.py +2 -1
  191. esphome/components/fingerprint_grow/sensor.py +2 -1
  192. esphome/components/fs3000/sensor.py +2 -6
  193. esphome/components/ft5x06/touchscreen/__init__.py +2 -2
  194. esphome/components/ft63x6/touchscreen.py +2 -3
  195. esphome/components/fujitsu_general/climate.py +1 -1
  196. esphome/components/gcja5/sensor.py +4 -4
  197. esphome/components/gdk101/__init__.py +1 -1
  198. esphome/components/gdk101/binary_sensor.py +2 -1
  199. esphome/components/gdk101/sensor.py +5 -4
  200. esphome/components/globals/__init__.py +1 -2
  201. esphome/components/gp2y1010au0f/sensor.py +3 -3
  202. esphome/components/gp8403/__init__.py +1 -2
  203. esphome/components/gp8403/output/__init__.py +3 -4
  204. esphome/components/gpio/binary_sensor/__init__.py +3 -2
  205. esphome/components/gpio/one_wire/__init__.py +3 -2
  206. esphome/components/gpio/output/__init__.py +3 -2
  207. esphome/components/gpio/switch/__init__.py +3 -2
  208. esphome/components/gps/__init__.py +4 -5
  209. esphome/components/gps/time/__init__.py +3 -2
  210. esphome/components/graph/__init__.py +12 -12
  211. esphome/components/grove_tb6612fng/__init__.py +5 -6
  212. esphome/components/growatt_solar/sensor.py +1 -1
  213. esphome/components/gt911/binary_sensor/__init__.py +2 -2
  214. esphome/components/haier/binary_sensor/__init__.py +4 -10
  215. esphome/components/haier/button/__init__.py +3 -6
  216. esphome/components/haier/sensor/__init__.py +4 -6
  217. esphome/components/haier/switch/__init__.py +4 -7
  218. esphome/components/haier/text_sensor/__init__.py +4 -9
  219. esphome/components/havells_solar/sensor.py +1 -1
  220. esphome/components/hbridge/fan/__init__.py +6 -6
  221. esphome/components/hbridge/light/__init__.py +2 -1
  222. esphome/components/hdc1080/sensor.py +1 -1
  223. esphome/components/he60r/cover.py +2 -6
  224. esphome/components/heatpumpir/climate.py +1 -1
  225. esphome/components/hitachi_ac344/climate.py +1 -1
  226. esphome/components/hitachi_ac424/climate.py +1 -1
  227. esphome/components/hlw8012/sensor.py +6 -6
  228. esphome/components/hm3301/sensor.py +3 -3
  229. esphome/components/hmc5883l/sensor.py +4 -4
  230. esphome/components/homeassistant/time/__init__.py +2 -1
  231. esphome/components/honeywell_hih_i2c/sensor.py +3 -3
  232. esphome/components/honeywellabp/sensor.py +1 -2
  233. esphome/components/honeywellabp2_i2c/sensor.py +1 -2
  234. esphome/components/host/time/__init__.py +2 -2
  235. esphome/components/hrxl_maxsonar_wr/sensor.py +1 -1
  236. esphome/components/hte501/sensor.py +3 -3
  237. esphome/components/http_request/ota/__init__.py +5 -9
  238. esphome/components/http_request/update/__init__.py +3 -7
  239. esphome/components/htu21d/sensor.py +6 -6
  240. esphome/components/htu31d/sensor.py +1 -1
  241. esphome/components/hx711/sensor.py +3 -8
  242. esphome/components/hydreon_rgxx/binary_sensor.py +3 -7
  243. esphome/components/hydreon_rgxx/sensor.py +4 -4
  244. esphome/components/hyt271/sensor.py +1 -1
  245. esphome/components/i2c_device/__init__.py +1 -1
  246. esphome/components/i2s_audio/media_player/__init__.py +6 -8
  247. esphome/components/iaqcore/sensor.py +2 -2
  248. esphome/components/ina219/sensor.py +2 -2
  249. esphome/components/ina226/sensor.py +4 -4
  250. esphome/components/ina260/sensor.py +4 -4
  251. esphome/components/ina2xx_base/__init__.py +2 -2
  252. esphome/components/ina2xx_i2c/sensor.py +1 -1
  253. esphome/components/ina2xx_spi/sensor.py +1 -1
  254. esphome/components/ina3221/sensor.py +3 -3
  255. esphome/components/inkbird_ibsth1_mini/sensor.py +2 -2
  256. esphome/components/inkplate6/display.py +2 -2
  257. esphome/components/integration/sensor.py +4 -4
  258. esphome/components/internal_temperature/sensor.py +5 -7
  259. esphome/components/interval/__init__.py +1 -1
  260. esphome/components/jsn_sr04t/sensor.py +3 -3
  261. esphome/components/kamstrup_kmp/sensor.py +1 -1
  262. esphome/components/key_collector/__init__.py +2 -2
  263. esphome/components/kmeteriso/sensor.py +2 -2
  264. esphome/components/kuntze/sensor.py +5 -5
  265. esphome/components/lcd_base/__init__.py +2 -2
  266. esphome/components/lcd_gpio/display.py +4 -4
  267. esphome/components/lcd_menu/__init__.py +3 -7
  268. esphome/components/lcd_pcf8574/display.py +1 -1
  269. esphome/components/ld2410/__init__.py +4 -4
  270. esphome/components/ld2410/binary_sensor.py +5 -4
  271. esphome/components/ld2410/button/__init__.py +3 -2
  272. esphome/components/ld2410/number/__init__.py +5 -4
  273. esphome/components/ld2410/select/__init__.py +4 -3
  274. esphome/components/ld2410/sensor.py +6 -5
  275. esphome/components/ld2410/switch/__init__.py +2 -1
  276. esphome/components/ld2410/text_sensor.py +3 -2
  277. esphome/components/ld2420/__init__.py +1 -1
  278. esphome/components/ld2420/binary_sensor/__init__.py +4 -3
  279. esphome/components/ld2420/button/__init__.py +3 -2
  280. esphome/components/ld2420/number/__init__.py +3 -2
  281. esphome/components/ld2420/select/__init__.py +1 -0
  282. esphome/components/ld2420/sensor/__init__.py +3 -2
  283. esphome/components/ld2420/text_sensor/__init__.py +2 -6
  284. esphome/components/ld2450/__init__.py +2 -5
  285. esphome/components/ledc/output.py +3 -3
  286. esphome/components/libretiny/text_sensor.py +1 -1
  287. esphome/components/libretiny_pwm/output.py +3 -7
  288. esphome/components/lightwaverf/__init__.py +6 -8
  289. esphome/components/lilygo_t5_47/touchscreen/__init__.py +2 -3
  290. esphome/components/ltr390/sensor.py +1 -1
  291. esphome/components/ltr501/sensor.py +2 -2
  292. esphome/components/ltr_als_ps/sensor.py +2 -2
  293. esphome/components/lvgl/__init__.py +9 -12
  294. esphome/components/lvgl/automation.py +15 -3
  295. esphome/components/lvgl/defines.py +5 -2
  296. esphome/components/lvgl/encoders.py +3 -2
  297. esphome/components/lvgl/lv_validation.py +17 -9
  298. esphome/components/lvgl/lvcode.py +11 -9
  299. esphome/components/lvgl/lvgl_esphome.h +21 -0
  300. esphome/components/lvgl/number/__init__.py +23 -20
  301. esphome/components/lvgl/number/lvgl_number.h +27 -14
  302. esphome/components/lvgl/schemas.py +70 -19
  303. esphome/components/lvgl/select/__init__.py +11 -13
  304. esphome/components/lvgl/select/lvgl_select.h +25 -18
  305. esphome/components/lvgl/styles.py +42 -11
  306. esphome/components/lvgl/trigger.py +10 -1
  307. esphome/components/lvgl/widgets/__init__.py +1 -2
  308. esphome/components/lvgl/widgets/buttonmatrix.py +2 -2
  309. esphome/components/lvgl/widgets/canvas.py +407 -0
  310. esphome/components/lvgl/widgets/line.py +22 -32
  311. esphome/components/lvgl/widgets/meter.py +3 -1
  312. esphome/components/m5stack_8angle/__init__.py +1 -2
  313. esphome/components/m5stack_8angle/binary_sensor/__init__.py +2 -3
  314. esphome/components/m5stack_8angle/light/__init__.py +2 -4
  315. esphome/components/m5stack_8angle/sensor/__init__.py +2 -4
  316. esphome/components/matrix_keypad/binary_sensor/__init__.py +4 -3
  317. esphome/components/max31855/sensor.py +1 -1
  318. esphome/components/max31865/sensor.py +1 -1
  319. esphome/components/max44009/sensor.py +1 -1
  320. esphome/components/max6675/sensor.py +1 -1
  321. esphome/components/max6956/__init__.py +5 -5
  322. esphome/components/max6956/output/__init__.py +4 -3
  323. esphome/components/max7219/display.py +1 -1
  324. esphome/components/max7219digit/display.py +1 -1
  325. esphome/components/max9611/sensor.py +10 -10
  326. esphome/components/mcp23008/__init__.py +1 -1
  327. esphome/components/mcp23016/__init__.py +4 -4
  328. esphome/components/mcp23017/__init__.py +1 -1
  329. esphome/components/mcp23s08/__init__.py +1 -1
  330. esphome/components/mcp23s17/__init__.py +1 -1
  331. esphome/components/mcp23xxx_base/__init__.py +4 -4
  332. esphome/components/mcp2515/canbus.py +2 -2
  333. esphome/components/mcp3008/__init__.py +1 -1
  334. esphome/components/mcp3008/sensor/__init__.py +4 -4
  335. esphome/components/mcp3204/__init__.py +1 -1
  336. esphome/components/mcp3204/sensor/__init__.py +3 -2
  337. esphome/components/mcp4461/__init__.py +42 -0
  338. esphome/components/mcp4461/mcp4461.cpp +618 -0
  339. esphome/components/mcp4461/mcp4461.h +171 -0
  340. esphome/components/mcp4461/output/__init__.py +60 -0
  341. esphome/components/mcp4461/output/mcp4461_output.cpp +73 -0
  342. esphome/components/mcp4461/output/mcp4461_output.h +49 -0
  343. esphome/components/mcp4725/output.py +2 -2
  344. esphome/components/mcp4728/__init__.py +1 -1
  345. esphome/components/mcp4728/output/__init__.py +4 -3
  346. esphome/components/mcp47a1/output.py +2 -2
  347. esphome/components/mcp9808/sensor.py +1 -1
  348. esphome/components/mhz19/sensor.py +4 -4
  349. esphome/components/micronova/__init__.py +3 -5
  350. esphome/components/micronova/button/__init__.py +5 -5
  351. esphome/components/micronova/number/__init__.py +6 -10
  352. esphome/components/micronova/sensor/__init__.py +6 -6
  353. esphome/components/micronova/switch/__init__.py +6 -8
  354. esphome/components/micronova/text_sensor/__init__.py +5 -5
  355. esphome/components/microphone/__init__.py +2 -4
  356. esphome/components/midea/climate.py +6 -10
  357. esphome/components/midea_ir/climate.py +1 -1
  358. esphome/components/mitsubishi/climate.py +1 -1
  359. esphome/components/mlx90614/sensor.py +1 -1
  360. esphome/components/mmc5603/sensor.py +4 -4
  361. esphome/components/mmc5983/sensor.py +1 -1
  362. esphome/components/modbus/__init__.py +5 -9
  363. esphome/components/modbus_controller/__init__.py +1 -1
  364. esphome/components/monochromatic/light.py +2 -2
  365. esphome/components/mopeka_ble/__init__.py +1 -1
  366. esphome/components/mopeka_pro_check/sensor.py +12 -12
  367. esphome/components/mopeka_std_check/sensor.py +8 -8
  368. esphome/components/mpl3115a2/sensor.py +1 -1
  369. esphome/components/mpr121/__init__.py +3 -3
  370. esphome/components/mpr121/binary_sensor/__init__.py +5 -4
  371. esphome/components/mpu6050/sensor.py +4 -4
  372. esphome/components/mpu6886/sensor.py +4 -4
  373. esphome/components/mqtt_subscribe/sensor/__init__.py +3 -5
  374. esphome/components/mqtt_subscribe/text_sensor/__init__.py +1 -1
  375. esphome/components/ms5611/sensor.py +2 -2
  376. esphome/components/ms8607/sensor.py +1 -1
  377. esphome/components/my9231/__init__.py +1 -1
  378. esphome/components/my9231/output.py +2 -1
  379. esphome/components/nau7802/nau7802.cpp +0 -4
  380. esphome/components/nau7802/nau7802.h +0 -2
  381. esphome/components/neopixelbus/_methods.py +11 -9
  382. esphome/components/neopixelbus/light.py +11 -18
  383. esphome/components/nextion/binary_sensor/__init__.py +6 -14
  384. esphome/components/nextion/sensor/__init__.py +7 -10
  385. esphome/components/nextion/switch/__init__.py +3 -5
  386. esphome/components/nextion/text_sensor/__init__.py +3 -7
  387. esphome/components/noblex/climate.py +1 -1
  388. esphome/components/ntc/sensor.py +1 -1
  389. esphome/components/opentherm/__init__.py +6 -6
  390. esphome/components/opentherm/input.py +2 -1
  391. esphome/components/opentherm/number/__init__.py +5 -4
  392. esphome/components/opentherm/output/__init__.py +3 -2
  393. esphome/components/opentherm/schema.py +7 -7
  394. esphome/components/opentherm/switch/__init__.py +3 -2
  395. esphome/components/opentherm/validate.py +1 -1
  396. esphome/components/output/__init__.py +2 -3
  397. esphome/components/output/button/__init__.py +3 -2
  398. esphome/components/output/lock/__init__.py +2 -1
  399. esphome/components/output/switch/__init__.py +2 -1
  400. esphome/components/partition/light.py +4 -4
  401. esphome/components/pca6416a/__init__.py +4 -4
  402. esphome/components/pca9554/__init__.py +4 -4
  403. esphome/components/pca9685/__init__.py +2 -2
  404. esphome/components/pca9685/output.py +2 -1
  405. esphome/components/pcf85063/time.py +2 -3
  406. esphome/components/pcf8563/time.py +2 -2
  407. esphome/components/pcf8574/__init__.py +4 -4
  408. esphome/components/pid/climate.py +2 -2
  409. esphome/components/pid/sensor/__init__.py +4 -8
  410. esphome/components/pipsolar/__init__.py +1 -1
  411. esphome/components/pipsolar/binary_sensor/__init__.py +2 -2
  412. esphome/components/pipsolar/output/__init__.py +4 -3
  413. esphome/components/pipsolar/sensor/__init__.py +5 -4
  414. esphome/components/pipsolar/switch/__init__.py +2 -1
  415. esphome/components/pipsolar/text_sensor/__init__.py +2 -1
  416. esphome/components/pm1006/sensor.py +2 -2
  417. esphome/components/pmsa003i/sensor.py +4 -4
  418. esphome/components/pmsx003/sensor.py +10 -11
  419. esphome/components/pmwcs3/sensor.py +5 -5
  420. esphome/components/pn532/__init__.py +3 -3
  421. esphome/components/pn532_i2c/__init__.py +1 -1
  422. esphome/components/pn532_spi/__init__.py +1 -1
  423. esphome/components/pn7150/__init__.py +2 -2
  424. esphome/components/pn7150_i2c/__init__.py +1 -1
  425. esphome/components/pn7160/__init__.py +2 -2
  426. esphome/components/pn7160_i2c/__init__.py +1 -1
  427. esphome/components/pn7160_spi/__init__.py +1 -1
  428. esphome/components/power_supply/__init__.py +1 -1
  429. esphome/components/prometheus/__init__.py +3 -8
  430. esphome/components/psram/__init__.py +75 -11
  431. esphome/components/psram/psram.cpp +18 -7
  432. esphome/components/pulse_counter/sensor.py +4 -4
  433. esphome/components/pulse_meter/sensor.py +3 -3
  434. esphome/components/pulse_width/sensor.py +3 -8
  435. esphome/components/pvvx_mithermometer/display/__init__.py +1 -1
  436. esphome/components/pvvx_mithermometer/sensor.py +3 -3
  437. esphome/components/pylontech/__init__.py +1 -0
  438. esphome/components/pylontech/sensor/__init__.py +8 -13
  439. esphome/components/pylontech/text_sensor/__init__.py +2 -7
  440. esphome/components/pzem004t/sensor.py +3 -3
  441. esphome/components/pzemac/sensor.py +9 -9
  442. esphome/components/pzemdc/sensor.py +6 -6
  443. esphome/components/qmc5883l/sensor.py +5 -5
  444. esphome/components/qmp6988/sensor.py +3 -3
  445. esphome/components/qr_code/__init__.py +1 -1
  446. esphome/components/qspi_dbi/display.py +1 -1
  447. esphome/components/qspi_dbi/qspi_dbi.cpp +1 -1
  448. esphome/components/qspi_dbi/qspi_dbi.h +1 -1
  449. esphome/components/qwiic_pir/binary_sensor.py +2 -5
  450. esphome/components/radon_eye_ble/__init__.py +1 -1
  451. esphome/components/radon_eye_rd200/sensor.py +3 -4
  452. esphome/components/rc522/__init__.py +3 -3
  453. esphome/components/rc522_i2c/__init__.py +1 -1
  454. esphome/components/rc522_spi/__init__.py +1 -1
  455. esphome/components/rdm6300/__init__.py +2 -2
  456. esphome/components/rdm6300/binary_sensor.py +2 -1
  457. esphome/components/resistance/sensor.py +2 -2
  458. esphome/components/restart/button/__init__.py +1 -1
  459. esphome/components/restart/switch/__init__.py +2 -5
  460. esphome/components/rf_bridge/__init__.py +3 -3
  461. esphome/components/rgb/light.py +2 -2
  462. esphome/components/rgbct/light.py +3 -3
  463. esphome/components/rgbw/light.py +2 -2
  464. esphome/components/rgbww/light.py +4 -4
  465. esphome/components/rotary_encoder/sensor.py +8 -8
  466. esphome/components/rp2040_pio/__init__.py +0 -1
  467. esphome/components/rp2040_pio_led_strip/light.py +2 -4
  468. esphome/components/rp2040_pwm/output.py +3 -7
  469. esphome/components/rtttl/__init__.py +6 -6
  470. esphome/components/ruuvi_ble/__init__.py +1 -1
  471. esphome/components/ruuvitag/sensor.py +15 -15
  472. esphome/components/safe_mode/__init__.py +2 -3
  473. esphome/components/safe_mode/button/__init__.py +3 -2
  474. esphome/components/safe_mode/switch/__init__.py +4 -7
  475. esphome/components/scd30/sensor.py +5 -6
  476. esphome/components/scd4x/sensor.py +6 -8
  477. esphome/components/script/__init__.py +2 -2
  478. esphome/components/sdl/display.py +3 -3
  479. esphome/components/sdl/touchscreen/__init__.py +2 -2
  480. esphome/components/sdm_meter/sensor.py +3 -3
  481. esphome/components/sdp3x/sensor.py +1 -2
  482. esphome/components/sds011/sensor.py +4 -4
  483. esphome/components/seeed_mr24hpc1/__init__.py +1 -1
  484. esphome/components/seeed_mr24hpc1/binary_sensor.py +2 -5
  485. esphome/components/seeed_mr24hpc1/button/__init__.py +1 -0
  486. esphome/components/seeed_mr24hpc1/number/__init__.py +2 -4
  487. esphome/components/seeed_mr24hpc1/select/__init__.py +2 -3
  488. esphome/components/seeed_mr24hpc1/sensor.py +1 -0
  489. esphome/components/seeed_mr24hpc1/switch/__init__.py +2 -4
  490. esphome/components/seeed_mr24hpc1/text_sensor.py +1 -0
  491. esphome/components/seeed_mr60bha2/binary_sensor.py +2 -4
  492. esphome/components/seeed_mr60bha2/sensor.py +1 -1
  493. esphome/components/seeed_mr60fda2/button/__init__.py +1 -1
  494. esphome/components/seeed_mr60fda2/select/__init__.py +0 -1
  495. esphome/components/selec_meter/sensor.py +1 -1
  496. esphome/components/sen0321/sensor.py +2 -2
  497. esphome/components/sen21231/sensor.py +1 -1
  498. esphome/components/senseair/sensor.py +3 -3
  499. esphome/components/sensirion_common/__init__.py +0 -2
  500. esphome/components/servo/__init__.py +3 -3
  501. esphome/components/sfa30/sensor.py +4 -5
  502. esphome/components/sgp4x/sensor.py +2 -2
  503. esphome/components/shelly_dimmer/light.py +16 -16
  504. esphome/components/sht3xd/sensor.py +1 -1
  505. esphome/components/sht4x/sensor.py +6 -6
  506. esphome/components/shtcx/sensor.py +1 -1
  507. esphome/components/shutdown/button/__init__.py +2 -6
  508. esphome/components/shutdown/switch/__init__.py +2 -5
  509. esphome/components/sigma_delta_output/output.py +2 -7
  510. esphome/components/sim800l/__init__.py +3 -7
  511. esphome/components/sim800l/binary_sensor.py +3 -5
  512. esphome/components/sim800l/sensor.py +2 -1
  513. esphome/components/slow_pwm/output.py +4 -5
  514. esphome/components/sm10bit_base/__init__.py +2 -6
  515. esphome/components/sm16716/__init__.py +1 -1
  516. esphome/components/sm16716/output.py +2 -1
  517. esphome/components/sm2135/__init__.py +2 -6
  518. esphome/components/sm2135/output.py +2 -1
  519. esphome/components/sm2235/__init__.py +1 -1
  520. esphome/components/sm2235/output.py +2 -1
  521. esphome/components/sm2335/__init__.py +1 -1
  522. esphome/components/sm2335/output.py +2 -1
  523. esphome/components/sm300d2/sensor.py +13 -13
  524. esphome/components/sml/__init__.py +1 -1
  525. esphome/components/sml/sensor/__init__.py +1 -1
  526. esphome/components/sml/sml.cpp +8 -6
  527. esphome/components/sml/sml.h +1 -1
  528. esphome/components/sml/sml_parser.cpp +16 -18
  529. esphome/components/sml/sml_parser.h +42 -12
  530. esphome/components/sml/text_sensor/__init__.py +1 -1
  531. esphome/components/smt100/sensor.py +5 -6
  532. esphome/components/sn74hc165/__init__.py +5 -5
  533. esphome/components/sn74hc595/__init__.py +5 -5
  534. esphome/components/socket/__init__.py +1 -1
  535. esphome/components/sonoff_d1/light.py +2 -6
  536. esphome/components/speaker/media_player/audio_pipeline.cpp +3 -2
  537. esphome/components/speed/fan/__init__.py +2 -2
  538. esphome/components/spi/__init__.py +45 -36
  539. esphome/components/spi/spi.h +1 -0
  540. esphome/components/spi/spi_esp_idf.cpp +13 -5
  541. esphome/components/sprinkler/__init__.py +4 -5
  542. esphome/components/sps30/sensor.py +8 -8
  543. esphome/components/ssd1306_i2c/display.py +2 -2
  544. esphome/components/ssd1322_base/__init__.py +2 -2
  545. esphome/components/ssd1325_base/__init__.py +2 -2
  546. esphome/components/ssd1327_base/__init__.py +2 -2
  547. esphome/components/ssd1327_i2c/display.py +1 -1
  548. esphome/components/ssd1331_base/__init__.py +2 -2
  549. esphome/components/ssd1351_base/__init__.py +2 -2
  550. esphome/components/st7567_base/__init__.py +4 -4
  551. esphome/components/st7567_i2c/display.py +1 -1
  552. esphome/components/st7920/display.py +2 -2
  553. esphome/components/statsd/__init__.py +3 -3
  554. esphome/components/status/binary_sensor.py +2 -5
  555. esphome/components/status_led/__init__.py +1 -1
  556. esphome/components/status_led/light/__init__.py +2 -1
  557. esphome/components/stepper/__init__.py +2 -2
  558. esphome/components/sts3x/sensor.py +1 -1
  559. esphome/components/substitutions/__init__.py +2 -2
  560. esphome/components/sun/__init__.py +4 -4
  561. esphome/components/sun/sensor/__init__.py +4 -7
  562. esphome/components/sun/text_sensor/__init__.py +5 -4
  563. esphome/components/sun_gtil2/__init__.py +1 -1
  564. esphome/components/sun_gtil2/sensor.py +7 -6
  565. esphome/components/sun_gtil2/text_sensor.py +3 -2
  566. esphome/components/sx1509/__init__.py +5 -5
  567. esphome/components/sx1509/binary_sensor/__init__.py +3 -3
  568. esphome/components/sx1509/output/__init__.py +4 -3
  569. esphome/components/t6615/sensor.py +1 -1
  570. esphome/components/tca9548a/__init__.py +1 -1
  571. esphome/components/tcl112/climate.py +1 -1
  572. esphome/components/tcs34725/sensor.py +4 -4
  573. esphome/components/tee501/sensor.py +1 -1
  574. esphome/components/teleinfo/__init__.py +1 -1
  575. esphome/components/teleinfo/sensor/__init__.py +1 -7
  576. esphome/components/teleinfo/text_sensor/__init__.py +1 -1
  577. esphome/components/tem3200/sensor.py +1 -2
  578. esphome/components/template/alarm_control_panel/__init__.py +3 -10
  579. esphome/components/template/cover/__init__.py +4 -3
  580. esphome/components/template/datetime/__init__.py +8 -9
  581. esphome/components/template/event/__init__.py +2 -5
  582. esphome/components/template/fan/__init__.py +2 -6
  583. esphome/components/template/lock/__init__.py +3 -2
  584. esphome/components/template/number/__init__.py +3 -2
  585. esphome/components/template/output/__init__.py +4 -3
  586. esphome/components/template/select/__init__.py +3 -2
  587. esphome/components/template/sensor/__init__.py +4 -7
  588. esphome/components/template/switch/__init__.py +3 -2
  589. esphome/components/template/text/__init__.py +4 -3
  590. esphome/components/template/text_sensor/__init__.py +3 -2
  591. esphome/components/template/valve/__init__.py +3 -2
  592. esphome/components/time/real_time_clock.cpp +0 -4
  593. esphome/components/time/real_time_clock.h +4 -3
  594. esphome/components/time_based/cover.py +3 -3
  595. esphome/components/tlc59208f/__init__.py +1 -1
  596. esphome/components/tlc59208f/output.py +2 -1
  597. esphome/components/tlc5947/__init__.py +1 -1
  598. esphome/components/tlc5947/output/__init__.py +2 -1
  599. esphome/components/tlc5971/__init__.py +2 -8
  600. esphome/components/tlc5971/output/__init__.py +2 -1
  601. esphome/components/tm1621/display.py +3 -3
  602. esphome/components/tm1637/binary_sensor.py +1 -1
  603. esphome/components/tm1637/display.py +3 -3
  604. esphome/components/tm1651/__init__.py +4 -4
  605. esphome/components/tmp102/sensor.py +1 -1
  606. esphome/components/tmp1075/sensor.py +2 -2
  607. esphome/components/tmp117/sensor.py +1 -1
  608. esphome/components/tof10120/sensor.py +2 -2
  609. esphome/components/tormatic/cover.py +2 -6
  610. esphome/components/toshiba/climate.py +1 -1
  611. esphome/components/total_daily_energy/sensor.py +4 -4
  612. esphome/components/tsl2561/sensor.py +1 -1
  613. esphome/components/tsl2591/sensor.py +9 -9
  614. esphome/components/tt21100/binary_sensor/__init__.py +2 -2
  615. esphome/components/tt21100/touchscreen/__init__.py +2 -3
  616. esphome/components/ttp229_bsf/__init__.py +2 -2
  617. esphome/components/ttp229_bsf/binary_sensor.py +3 -2
  618. esphome/components/ttp229_lsf/__init__.py +1 -1
  619. esphome/components/ttp229_lsf/binary_sensor.py +3 -2
  620. esphome/components/tuya/__init__.py +3 -5
  621. esphome/components/tuya/binary_sensor/__init__.py +2 -2
  622. esphome/components/tuya/climate/__init__.py +6 -5
  623. esphome/components/tuya/cover/__init__.py +5 -4
  624. esphome/components/tuya/fan/__init__.py +3 -2
  625. esphome/components/tuya/light/__init__.py +9 -8
  626. esphome/components/tuya/number/__init__.py +6 -5
  627. esphome/components/tuya/select/__init__.py +4 -3
  628. esphome/components/tuya/sensor/__init__.py +3 -2
  629. esphome/components/tuya/switch/__init__.py +3 -2
  630. esphome/components/tuya/text_sensor/__init__.py +3 -2
  631. esphome/components/tx20/sensor.py +6 -6
  632. esphome/components/uart/__init__.py +20 -19
  633. esphome/components/uart/button/__init__.py +2 -1
  634. esphome/components/uart/switch/__init__.py +2 -1
  635. esphome/components/ufire_ise/sensor.py +2 -2
  636. esphome/components/uln2003/stepper.py +2 -2
  637. esphome/components/ultrasonic/sensor.py +4 -4
  638. esphome/components/uponor_smatrix/__init__.py +2 -6
  639. esphome/components/uponor_smatrix/climate/__init__.py +3 -3
  640. esphome/components/vbus/__init__.py +1 -1
  641. esphome/components/vbus/binary_sensor/__init__.py +7 -6
  642. esphome/components/vbus/sensor/__init__.py +7 -6
  643. esphome/components/veml3235/sensor.py +1 -1
  644. esphome/components/veml7700/sensor.py +1 -1
  645. esphome/components/version/text_sensor.py +2 -6
  646. esphome/components/vl53l0x/sensor.py +6 -6
  647. esphome/components/web_server_base/__init__.py +2 -2
  648. esphome/components/web_server_idf/__init__.py +1 -1
  649. esphome/components/weikai/__init__.py +1 -1
  650. esphome/components/whirlpool/climate.py +1 -1
  651. esphome/components/whynter/climate.py +1 -1
  652. esphome/components/wireguard/binary_sensor.py +1 -1
  653. esphome/components/wireguard/sensor.py +2 -5
  654. esphome/components/wireguard/text_sensor.py +2 -5
  655. esphome/components/wk2132_i2c/__init__.py +1 -1
  656. esphome/components/wk2132_spi/__init__.py +1 -2
  657. esphome/components/wk2168_i2c/__init__.py +3 -8
  658. esphome/components/wk2168_spi/__init__.py +3 -8
  659. esphome/components/wk2204_i2c/__init__.py +1 -1
  660. esphome/components/wk2204_spi/__init__.py +1 -1
  661. esphome/components/wk2212_i2c/__init__.py +3 -8
  662. esphome/components/wk2212_spi/__init__.py +3 -8
  663. esphome/components/wl_134/text_sensor.py +2 -4
  664. esphome/components/wled/__init__.py +2 -2
  665. esphome/components/x9c/output.py +4 -4
  666. esphome/components/xgzp68xx/sensor.py +5 -5
  667. esphome/components/xiaomi_ble/__init__.py +1 -1
  668. esphome/components/xiaomi_cgd1/sensor.py +3 -3
  669. esphome/components/xiaomi_cgdk2/sensor.py +3 -3
  670. esphome/components/xiaomi_cgg1/sensor.py +2 -2
  671. esphome/components/xiaomi_cgpr1/binary_sensor.py +6 -6
  672. esphome/components/xiaomi_gcls002/sensor.py +7 -7
  673. esphome/components/xiaomi_hhccjcy01/sensor.py +9 -9
  674. esphome/components/xiaomi_hhccjcy10/sensor.py +9 -9
  675. esphome/components/xiaomi_hhccpot002/sensor.py +7 -7
  676. esphome/components/xiaomi_jqjcy01ym/sensor.py +6 -6
  677. esphome/components/xiaomi_lywsd02/sensor.py +4 -4
  678. esphome/components/xiaomi_lywsd02mmc/sensor.py +5 -5
  679. esphome/components/xiaomi_lywsd03mmc/sensor.py +6 -6
  680. esphome/components/xiaomi_lywsdcgq/sensor.py +5 -5
  681. esphome/components/xiaomi_mhoc303/sensor.py +4 -4
  682. esphome/components/xiaomi_mhoc401/sensor.py +6 -6
  683. esphome/components/xiaomi_miscale/sensor.py +6 -6
  684. esphome/components/xiaomi_mjyd02yla/binary_sensor.py +8 -8
  685. esphome/components/xiaomi_mue4094rt/binary_sensor.py +2 -7
  686. esphome/components/xiaomi_rtcgq02lm/__init__.py +2 -3
  687. esphome/components/xiaomi_rtcgq02lm/binary_sensor.py +3 -3
  688. esphome/components/xiaomi_rtcgq02lm/sensor.py +3 -3
  689. esphome/components/xiaomi_wx08zm/binary_sensor.py +2 -3
  690. esphome/components/xl9535/__init__.py +2 -2
  691. esphome/components/yashima/climate.py +1 -1
  692. esphome/components/zhlt01/climate.py +1 -1
  693. esphome/components/zio_ultrasonic/sensor.py +2 -5
  694. esphome/components/zyaura/sensor.py +7 -7
  695. esphome/config_validation.py +0 -42
  696. esphome/const.py +3 -1
  697. esphome/core/__init__.py +0 -1
  698. esphome/core/component.cpp +3 -1
  699. esphome/core/component.h +15 -2
  700. esphome/core/config.py +4 -0
  701. esphome/core/defines.h +21 -0
  702. esphome/core/helpers.cpp +6 -7
  703. esphome/core/scheduler.cpp +34 -67
  704. esphome/core/scheduler.h +7 -17
  705. esphome/dashboard/status/mqtt.py +0 -2
  706. esphome/vscode.py +27 -8
  707. esphome/yaml_util.py +75 -39
  708. {esphome-2025.3.3.dist-info → esphome-2025.4.0.dist-info}/METADATA +45 -44
  709. {esphome-2025.3.3.dist-info → esphome-2025.4.0.dist-info}/RECORD +713 -706
  710. {esphome-2025.3.3.dist-info → esphome-2025.4.0.dist-info}/WHEEL +1 -1
  711. {esphome-2025.3.3.dist-info → esphome-2025.4.0.dist-info}/entry_points.txt +0 -0
  712. {esphome-2025.3.3.dist-info → esphome-2025.4.0.dist-info/licenses}/LICENSE +0 -0
  713. {esphome-2025.3.3.dist-info → esphome-2025.4.0.dist-info}/top_level.txt +0 -0
@@ -254,11 +254,27 @@ def pixels_or_percent_validator(value):
254
254
  pixels_or_percent = LValidator(pixels_or_percent_validator, uint32, retmapper=literal)
255
255
 
256
256
 
257
- def zoom(value):
257
+ def pixels_validator(value):
258
+ if isinstance(value, str) and value.lower().endswith("px"):
259
+ value = value[:-2]
260
+ return cv.positive_int(value)
261
+
262
+
263
+ pixels = LValidator(pixels_validator, uint32, retmapper=literal)
264
+
265
+
266
+ def zoom_validator(value):
258
267
  value = cv.float_range(0.1, 10.0)(value)
268
+ return value
269
+
270
+
271
+ def zoom_retmapper(value):
259
272
  return int(value * 256)
260
273
 
261
274
 
275
+ zoom = LValidator(zoom_validator, uint32, retmapper=zoom_retmapper)
276
+
277
+
262
278
  def angle(value):
263
279
  """
264
280
  Validation for an angle in degrees, converted to an integer representing 0.1deg units
@@ -286,14 +302,6 @@ def size_validator(value):
286
302
  size = LValidator(size_validator, uint32, retmapper=literal)
287
303
 
288
304
 
289
- def pixels_validator(value):
290
- if isinstance(value, str) and value.lower().endswith("px"):
291
- return cv.int_(value[:-2])
292
- return cv.int_(value)
293
-
294
-
295
- pixels = LValidator(pixels_validator, uint32, retmapper=literal)
296
-
297
305
  radius_consts = LvConstant("LV_RADIUS_", "CIRCLE")
298
306
 
299
307
 
@@ -173,7 +173,8 @@ class LambdaContext(CodeContext):
173
173
 
174
174
  class LvContext(LambdaContext):
175
175
  """
176
- Code generation into the LVGL initialisation code (called in `setup()`)
176
+ Code generation into the LVGL initialisation code, called before setup() and loop()
177
+ Basically just does cg.add, so now fairly redundant.
177
178
  """
178
179
 
179
180
  added_lambda_count = 0
@@ -206,11 +207,16 @@ class LocalVariable(MockObj):
206
207
 
207
208
  def __enter__(self):
208
209
  CodeContext.start_block()
209
- CodeContext.append(
210
- VariableDeclarationExpression(self.base.type, self.modifier, self.base.id)
211
- )
212
210
  if self.rhs is not None:
213
- CodeContext.append(AssignmentExpression(None, "", self.base, self.rhs))
211
+ CodeContext.append(
212
+ AssignmentExpression(self.base.type, self.modifier, self.base, self.rhs)
213
+ )
214
+ else:
215
+ CodeContext.append(
216
+ VariableDeclarationExpression(
217
+ self.base.type, self.modifier, self.base.id
218
+ )
219
+ )
214
220
  return MockObj(self.base)
215
221
 
216
222
  def __exit__(self, *args):
@@ -285,10 +291,6 @@ class LvExpr(MockLv):
285
291
  pass
286
292
 
287
293
 
288
- def static_cast(type, value):
289
- return literal(f"static_cast<{type}>({value})")
290
-
291
-
292
294
  # Top level mock for generic lv_ calls to be recorded
293
295
  lv = MockLv("lv_")
294
296
  # Just generate an expression
@@ -63,6 +63,13 @@ inline void lv_disp_set_bg_image(lv_disp_t *disp, esphome::image::Image *image)
63
63
  inline void lv_obj_set_style_bg_img_src(lv_obj_t *obj, esphome::image::Image *image, lv_style_selector_t selector) {
64
64
  lv_obj_set_style_bg_img_src(obj, image->get_lv_img_dsc(), selector);
65
65
  }
66
+ #ifdef USE_LVGL_CANVAS
67
+ inline void lv_canvas_draw_img(lv_obj_t *canvas, lv_coord_t x, lv_coord_t y, image::Image *image,
68
+ lv_draw_img_dsc_t *dsc) {
69
+ lv_canvas_draw_img(canvas, x, y, image->get_lv_img_dsc(), dsc);
70
+ }
71
+ #endif
72
+
66
73
  #ifdef USE_LVGL_METER
67
74
  inline lv_meter_indicator_t *lv_meter_add_needle_img(lv_obj_t *obj, lv_meter_scale_t *scale, esphome::image::Image *src,
68
75
  lv_coord_t pivot_x, lv_coord_t pivot_y) {
@@ -90,6 +97,7 @@ inline void lv_animimg_set_src(lv_obj_t *img, std::vector<image::Image *> images
90
97
  // Parent class for things that wrap an LVGL object
91
98
  class LvCompound {
92
99
  public:
100
+ virtual ~LvCompound() = default;
93
101
  virtual void set_obj(lv_obj_t *lv_obj) { this->obj = lv_obj; }
94
102
  lv_obj_t *obj{};
95
103
  };
@@ -330,6 +338,19 @@ class LVEncoderListener : public Parented<LvglComponent> {
330
338
  };
331
339
  #endif // USE_LVGL_KEY_LISTENER
332
340
 
341
+ #ifdef USE_LVGL_LINE
342
+ class LvLineType : public LvCompound {
343
+ public:
344
+ std::vector<lv_point_t> get_points() { return this->points_; }
345
+ void set_points(std::vector<lv_point_t> points) {
346
+ this->points_ = std::move(points);
347
+ lv_line_set_points(this->obj, this->points_.data(), this->points_.size());
348
+ }
349
+
350
+ protected:
351
+ std::vector<lv_point_t> points_{};
352
+ };
353
+ #endif
333
354
  #if defined(USE_LVGL_DROPDOWN) || defined(LV_USE_ROLLER)
334
355
  class LvSelectable : public LvCompound {
335
356
  public:
@@ -1,6 +1,7 @@
1
1
  import esphome.codegen as cg
2
2
  from esphome.components import number
3
3
  import esphome.config_validation as cv
4
+ from esphome.const import CONF_RESTORE_VALUE
4
5
  from esphome.cpp_generator import MockObj
5
6
 
6
7
  from ..defines import CONF_ANIMATED, CONF_UPDATE_ON_RELEASE, CONF_WIDGET
@@ -10,21 +11,21 @@ from ..lvcode import (
10
11
  EVENT_ARG,
11
12
  UPDATE_EVENT,
12
13
  LambdaContext,
13
- LvContext,
14
+ ReturnStatement,
14
15
  lv,
15
- lv_add,
16
16
  lvgl_static,
17
17
  )
18
18
  from ..types import LV_EVENT, LvNumber, lvgl_ns
19
19
  from ..widgets import get_widgets, wait_for_widgets
20
20
 
21
- LVGLNumber = lvgl_ns.class_("LVGLNumber", number.Number)
21
+ LVGLNumber = lvgl_ns.class_("LVGLNumber", number.Number, cg.Component)
22
22
 
23
23
  CONFIG_SCHEMA = number.number_schema(LVGLNumber).extend(
24
24
  {
25
25
  cv.Required(CONF_WIDGET): cv.use_id(LvNumber),
26
26
  cv.Optional(CONF_ANIMATED, default=True): animated,
27
27
  cv.Optional(CONF_UPDATE_ON_RELEASE, default=False): cv.boolean,
28
+ cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean,
28
29
  }
29
30
  )
30
31
 
@@ -32,32 +33,34 @@ CONFIG_SCHEMA = number.number_schema(LVGLNumber).extend(
32
33
  async def to_code(config):
33
34
  widget = await get_widgets(config, CONF_WIDGET)
34
35
  widget = widget[0]
35
- var = await number.new_number(
36
- config,
37
- max_value=widget.get_max(),
38
- min_value=widget.get_min(),
39
- step=widget.get_step(),
40
- )
41
-
42
36
  await wait_for_widgets()
37
+ async with LambdaContext([], return_type=cg.float_) as value:
38
+ value.add(ReturnStatement(widget.get_value()))
43
39
  async with LambdaContext([(cg.float_, "v")]) as control:
44
40
  await widget.set_property(
45
41
  "value", MockObj("v") * MockObj(widget.get_scale()), config[CONF_ANIMATED]
46
42
  )
47
43
  lv.event_send(widget.obj, API_EVENT, cg.nullptr)
48
- control.add(var.publish_state(widget.get_value()))
49
- async with LambdaContext(EVENT_ARG) as event:
50
- event.add(var.publish_state(widget.get_value()))
51
44
  event_code = (
52
45
  LV_EVENT.VALUE_CHANGED
53
46
  if not config[CONF_UPDATE_ON_RELEASE]
54
47
  else LV_EVENT.RELEASED
55
48
  )
56
- async with LvContext():
57
- lv_add(var.set_control_lambda(await control.get_lambda()))
58
- lv_add(
59
- lvgl_static.add_event_cb(
60
- widget.obj, await event.get_lambda(), UPDATE_EVENT, event_code
61
- )
49
+ var = await number.new_number(
50
+ config,
51
+ await control.get_lambda(),
52
+ await value.get_lambda(),
53
+ event_code,
54
+ config[CONF_RESTORE_VALUE],
55
+ max_value=widget.get_max(),
56
+ min_value=widget.get_min(),
57
+ step=widget.get_step(),
58
+ )
59
+ async with LambdaContext(EVENT_ARG) as event:
60
+ event.add(var.on_value())
61
+ await cg.register_component(var, config)
62
+ cg.add(
63
+ lvgl_static.add_event_cb(
64
+ widget.obj, await event.get_lambda(), UPDATE_EVENT, event_code
62
65
  )
63
- lv_add(var.publish_state(widget.get_value()))
66
+ )
@@ -3,33 +3,46 @@
3
3
  #include <utility>
4
4
 
5
5
  #include "esphome/components/number/number.h"
6
- #include "esphome/core/automation.h"
7
6
  #include "esphome/core/component.h"
8
7
  #include "esphome/core/preferences.h"
9
8
 
10
9
  namespace esphome {
11
10
  namespace lvgl {
12
11
 
13
- class LVGLNumber : public number::Number {
12
+ class LVGLNumber : public number::Number, public Component {
14
13
  public:
15
- void set_control_lambda(std::function<void(float)> control_lambda) {
16
- this->control_lambda_ = std::move(control_lambda);
17
- if (this->initial_state_.has_value()) {
18
- this->control_lambda_(this->initial_state_.value());
19
- this->initial_state_.reset();
14
+ LVGLNumber(std::function<void(float)> control_lambda, std::function<float()> value_lambda, lv_event_code_t event,
15
+ bool restore)
16
+ : control_lambda_(std::move(control_lambda)),
17
+ value_lambda_(std::move(value_lambda)),
18
+ event_(event),
19
+ restore_(restore) {}
20
+
21
+ void setup() override {
22
+ float value = this->value_lambda_();
23
+ if (this->restore_) {
24
+ this->pref_ = global_preferences->make_preference<float>(this->get_object_id_hash());
25
+ if (this->pref_.load(&value)) {
26
+ this->control_lambda_(value);
27
+ }
20
28
  }
29
+ this->publish_state(value);
21
30
  }
22
31
 
32
+ void on_value() { this->publish_state(this->value_lambda_()); }
33
+
23
34
  protected:
24
35
  void control(float value) override {
25
- if (this->control_lambda_ != nullptr) {
26
- this->control_lambda_(value);
27
- } else {
28
- this->initial_state_ = value;
29
- }
36
+ this->control_lambda_(value);
37
+ this->publish_state(value);
38
+ if (this->restore_)
39
+ this->pref_.save(&value);
30
40
  }
31
- std::function<void(float)> control_lambda_{};
32
- optional<float> initial_state_{};
41
+ std::function<void(float)> control_lambda_;
42
+ std::function<float()> value_lambda_;
43
+ lv_event_code_t event_;
44
+ bool restore_;
45
+ ESPPreferenceObject pref_{};
33
46
  };
34
47
 
35
48
  } // namespace lvgl
@@ -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
@@ -79,12 +81,39 @@ ENCODER_SCHEMA = cv.Schema(
79
81
  cv.declare_id(LVEncoderListener), requires_component("binary_sensor")
80
82
  ),
81
83
  cv.Optional(CONF_GROUP): cv.declare_id(lv_group_t),
82
- cv.Optional(df.CONF_INITIAL_FOCUS): cv.use_id(lv_obj_t),
84
+ cv.Optional(df.CONF_INITIAL_FOCUS): cv.All(
85
+ LIST_ACTION_SCHEMA, cv.Length(min=1, max=1)
86
+ ),
83
87
  cv.Optional(df.CONF_LONG_PRESS_TIME, default="400ms"): PRESS_TIME,
84
88
  cv.Optional(df.CONF_LONG_PRESS_REPEAT_TIME, default="100ms"): PRESS_TIME,
85
89
  }
86
90
  )
87
91
 
92
+ POINT_SCHEMA = cv.Schema(
93
+ {
94
+ cv.Required(CONF_X): cv.templatable(cv.int_),
95
+ cv.Required(CONF_Y): cv.templatable(cv.int_),
96
+ }
97
+ )
98
+
99
+
100
+ def point_schema(value):
101
+ """
102
+ A shorthand for a point in the form of x,y
103
+ :param value: The value to check
104
+ :return: The value as a tuple of x,y
105
+ """
106
+ if isinstance(value, dict):
107
+ return POINT_SCHEMA(value)
108
+ try:
109
+ x, y = map(int, value.split(","))
110
+ return {CONF_X: x, CONF_Y: y}
111
+ except ValueError:
112
+ pass
113
+ # not raising this in the catch block because pylint doesn't like it
114
+ raise cv.Invalid("Invalid point format, should be <x_int>, <y_int>")
115
+
116
+
88
117
  # All LVGL styles and their validators
89
118
  STYLE_PROPS = {
90
119
  "align": df.CHILD_ALIGNMENTS.one_of,
@@ -103,6 +132,7 @@ STYLE_PROPS = {
103
132
  "bg_image_recolor": lvalid.lv_color,
104
133
  "bg_image_recolor_opa": lvalid.opacity,
105
134
  "bg_image_src": lvalid.lv_image,
135
+ "bg_image_tiled": lvalid.lv_bool,
106
136
  "bg_main_stop": lvalid.stop_value,
107
137
  "bg_opa": lvalid.opacity,
108
138
  "border_color": lvalid.lv_color,
@@ -117,9 +147,9 @@ STYLE_PROPS = {
117
147
  "height": lvalid.size,
118
148
  "image_recolor": lvalid.lv_color,
119
149
  "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,
150
+ "line_width": lvalid.lv_positive_int,
151
+ "line_dash_width": lvalid.lv_positive_int,
152
+ "line_dash_gap": lvalid.lv_positive_int,
123
153
  "line_rounded": lvalid.lv_bool,
124
154
  "line_color": lvalid.lv_color,
125
155
  "opa": lvalid.opacity,
@@ -147,8 +177,8 @@ STYLE_PROPS = {
147
177
  "LV_TEXT_DECOR_", "NONE", "UNDERLINE", "STRIKETHROUGH"
148
178
  ).several_of,
149
179
  "text_font": lv_font,
150
- "text_letter_space": cv.positive_int,
151
- "text_line_space": cv.positive_int,
180
+ "text_letter_space": lvalid.lv_positive_int,
181
+ "text_line_space": lvalid.lv_positive_int,
152
182
  "text_opa": lvalid.opacity,
153
183
  "transform_angle": lvalid.lv_angle,
154
184
  "transform_height": lvalid.pixels_or_percent,
@@ -172,10 +202,15 @@ STYLE_REMAP = {
172
202
  "bg_image_recolor": "bg_img_recolor",
173
203
  "bg_image_recolor_opa": "bg_img_recolor_opa",
174
204
  "bg_image_src": "bg_img_src",
205
+ "bg_image_tiled": "bg_img_tiled",
175
206
  "image_recolor": "img_recolor",
176
207
  "image_recolor_opa": "img_recolor_opa",
177
208
  }
178
209
 
210
+ cell_alignments = df.LV_CELL_ALIGNMENTS.one_of
211
+ grid_alignments = df.LV_GRID_ALIGNMENTS.one_of
212
+ flex_alignments = df.LV_FLEX_ALIGNMENTS.one_of
213
+
179
214
  # Complete object style schema
180
215
  STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend(
181
216
  {
@@ -186,6 +221,16 @@ STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).ex
186
221
  }
187
222
  )
188
223
 
224
+ # Also allow widget specific properties for use in style definitions
225
+ FULL_STYLE_SCHEMA = STYLE_SCHEMA.extend(
226
+ {
227
+ cv.Optional(df.CONF_GRID_CELL_X_ALIGN): grid_alignments,
228
+ cv.Optional(df.CONF_GRID_CELL_Y_ALIGN): grid_alignments,
229
+ cv.Optional(df.CONF_PAD_ROW): lvalid.pixels,
230
+ cv.Optional(df.CONF_PAD_COLUMN): lvalid.pixels,
231
+ }
232
+ )
233
+
189
234
  # Object states. Top level properties apply to MAIN
190
235
  STATE_SCHEMA = cv.Schema(
191
236
  {cv.Optional(state): STYLE_SCHEMA for state in df.STATES}
@@ -216,14 +261,24 @@ def automation_schema(typ: LvType):
216
261
  events = events + (CONF_ON_VALUE,)
217
262
  args = typ.get_arg_type() if isinstance(typ, LvType) else []
218
263
  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
- }
264
+ return cv.Schema(
265
+ {
266
+ cv.Optional(event): validate_automation(
267
+ {
268
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
269
+ Trigger.template(*args)
270
+ ),
271
+ }
272
+ )
273
+ for event in events
274
+ }
275
+ ).extend(
276
+ {
277
+ cv.Optional(CONF_ON_BOOT): validate_automation(
278
+ {cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StartupTrigger)}
279
+ )
280
+ }
281
+ )
227
282
 
228
283
 
229
284
  def base_update_schema(widget_type, parts):
@@ -307,10 +362,6 @@ grid_spec = cv.Any(
307
362
  lvalid.size, df.LvConstant("LV_GRID_", "CONTENT").one_of, grid_free_space
308
363
  )
309
364
 
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
365
  LAYOUT_SCHEMA = {
315
366
  cv.Optional(df.CONF_LAYOUT): cv.typed_schema(
316
367
  {
@@ -1,18 +1,19 @@
1
+ import esphome.codegen as cg
1
2
  from esphome.components import select
2
3
  import esphome.config_validation as cv
3
- from esphome.const import CONF_OPTIONS
4
+ from esphome.const import CONF_ID, CONF_OPTIONS, CONF_RESTORE_VALUE
4
5
 
5
6
  from ..defines import CONF_ANIMATED, CONF_WIDGET, literal
6
- from ..lvcode import LvContext
7
7
  from ..types import LvSelect, lvgl_ns
8
- from ..widgets import get_widgets, wait_for_widgets
8
+ from ..widgets import get_widgets
9
9
 
10
- LVGLSelect = lvgl_ns.class_("LVGLSelect", select.Select)
10
+ LVGLSelect = lvgl_ns.class_("LVGLSelect", select.Select, cg.Component)
11
11
 
12
12
  CONFIG_SCHEMA = select.select_schema(LVGLSelect).extend(
13
13
  {
14
14
  cv.Required(CONF_WIDGET): cv.use_id(LvSelect),
15
15
  cv.Optional(CONF_ANIMATED, default=False): cv.boolean,
16
+ cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean,
16
17
  }
17
18
  )
18
19
 
@@ -21,12 +22,9 @@ async def to_code(config):
21
22
  widget = await get_widgets(config, CONF_WIDGET)
22
23
  widget = widget[0]
23
24
  options = widget.config.get(CONF_OPTIONS, [])
24
- selector = await select.new_select(config, options=options)
25
- await wait_for_widgets()
26
- async with LvContext() as ctx:
27
- ctx.add(
28
- selector.set_widget(
29
- widget.var,
30
- literal("LV_ANIM_ON" if config[CONF_ANIMATED] else "LV_ANIM_OFF"),
31
- )
32
- )
25
+ animated = literal("LV_ANIM_ON" if config[CONF_ANIMATED] else "LV_ANIM_OFF")
26
+ selector = cg.new_Pvariable(
27
+ config[CONF_ID], widget.var, animated, config[CONF_RESTORE_VALUE]
28
+ )
29
+ await select.register_select(selector, config, options=options)
30
+ await cg.register_component(selector, config)
@@ -11,12 +11,20 @@
11
11
  namespace esphome {
12
12
  namespace lvgl {
13
13
 
14
- class LVGLSelect : public select::Select {
14
+ class LVGLSelect : public select::Select, public Component {
15
15
  public:
16
- void set_widget(LvSelectable *widget, lv_anim_enable_t anim = LV_ANIM_OFF) {
17
- this->widget_ = widget;
18
- this->anim_ = anim;
16
+ LVGLSelect(LvSelectable *widget, lv_anim_enable_t anim, bool restore)
17
+ : widget_(widget), anim_(anim), restore_(restore) {}
18
+
19
+ void setup() override {
19
20
  this->set_options_();
21
+ if (this->restore_) {
22
+ size_t index;
23
+ this->pref_ = global_preferences->make_preference<size_t>(this->get_object_id_hash());
24
+ if (this->pref_.load(&index))
25
+ this->widget_->set_selected_index(index, LV_ANIM_OFF);
26
+ }
27
+ this->publish();
20
28
  lv_obj_add_event_cb(
21
29
  this->widget_->obj,
22
30
  [](lv_event_t *e) {
@@ -24,11 +32,6 @@ class LVGLSelect : public select::Select {
24
32
  it->set_options_();
25
33
  },
26
34
  LV_EVENT_REFRESH, this);
27
- if (this->initial_state_.has_value()) {
28
- this->control(this->initial_state_.value());
29
- this->initial_state_.reset();
30
- }
31
- this->publish();
32
35
  auto lamb = [](lv_event_t *e) {
33
36
  auto *self = static_cast<LVGLSelect *>(e->user_data);
34
37
  self->publish();
@@ -37,21 +40,25 @@ class LVGLSelect : public select::Select {
37
40
  lv_obj_add_event_cb(this->widget_->obj, lamb, lv_update_event, this);
38
41
  }
39
42
 
40
- void publish() { this->publish_state(this->widget_->get_selected_text()); }
43
+ void publish() {
44
+ this->publish_state(this->widget_->get_selected_text());
45
+ if (this->restore_) {
46
+ auto index = this->widget_->get_selected_index();
47
+ this->pref_.save(&index);
48
+ }
49
+ }
41
50
 
42
51
  protected:
43
52
  void control(const std::string &value) override {
44
- if (this->widget_ != nullptr) {
45
- this->widget_->set_selected_text(value, this->anim_);
46
- } else {
47
- this->initial_state_ = value;
48
- }
53
+ this->widget_->set_selected_text(value, this->anim_);
54
+ this->publish();
49
55
  }
50
56
  void set_options_() { this->traits.set_options(this->widget_->get_options()); }
51
57
 
52
- LvSelectable *widget_{};
53
- optional<std::string> initial_state_{};
54
- lv_anim_enable_t anim_{LV_ANIM_OFF};
58
+ LvSelectable *widget_;
59
+ lv_anim_enable_t anim_;
60
+ bool restore_;
61
+ ESPPreferenceObject pref_{};
55
62
  };
56
63
 
57
64
  } // namespace lvgl
@@ -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,