esphome 2024.10.3__py3-none-any.whl → 2024.11.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 (228) hide show
  1. esphome/__main__.py +22 -4
  2. esphome/automation.py +29 -2
  3. esphome/components/animation/__init__.py +5 -8
  4. esphome/components/animation/animation.cpp +1 -1
  5. esphome/components/audio/__init__.py +9 -0
  6. esphome/components/audio/audio.h +21 -0
  7. esphome/components/axs15231/__init__.py +6 -0
  8. esphome/components/axs15231/touchscreen/__init__.py +36 -0
  9. esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +64 -0
  10. esphome/components/axs15231/touchscreen/axs15231_touchscreen.h +27 -0
  11. esphome/components/bme68x_bsec2/__init__.py +1 -1
  12. esphome/components/bytebuffer/__init__.py +5 -0
  13. esphome/components/bytebuffer/bytebuffer.h +421 -0
  14. esphome/components/climate/__init__.py +14 -13
  15. esphome/components/datetime/__init__.py +3 -3
  16. esphome/components/debug/debug_esp32.cpp +16 -8
  17. esphome/components/dfplayer/dfplayer.cpp +132 -6
  18. esphome/components/dfplayer/dfplayer.h +19 -53
  19. esphome/components/display/display.cpp +142 -0
  20. esphome/components/display/display.h +7 -0
  21. esphome/components/es8311/__init__.py +0 -0
  22. esphome/components/es8311/audio_dac.py +70 -0
  23. esphome/components/es8311/es8311.cpp +227 -0
  24. esphome/components/es8311/es8311.h +135 -0
  25. esphome/components/es8311/es8311_const.h +195 -0
  26. esphome/components/esp32/boards.py +199 -1
  27. esphome/components/esp32/gpio.py +3 -1
  28. esphome/components/esp32_ble/const_esp32c6.h +7 -0
  29. esphome/components/esp32_ble_client/ble_client_base.h +1 -1
  30. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -1
  31. esphome/components/esp32_rmt_led_strip/led_strip.cpp +2 -2
  32. esphome/components/esp32_rmt_led_strip/led_strip.h +2 -0
  33. esphome/components/esp32_rmt_led_strip/light.py +3 -1
  34. esphome/components/esp8266/gpio.py +7 -5
  35. esphome/components/ethernet/__init__.py +55 -1
  36. esphome/components/ethernet/ethernet_component.cpp +14 -1
  37. esphome/components/ethernet/ethernet_component.h +7 -1
  38. esphome/components/font/__init__.py +213 -108
  39. esphome/components/gp8403/output/__init__.py +1 -1
  40. esphome/components/host/gpio.py +6 -4
  41. esphome/components/http_request/__init__.py +12 -0
  42. esphome/components/http_request/http_request.h +65 -3
  43. esphome/components/http_request/http_request_arduino.cpp +2 -3
  44. esphome/components/http_request/http_request_idf.cpp +6 -14
  45. esphome/components/http_request/ota/ota_http_request.cpp +1 -1
  46. esphome/components/http_request/update/http_request_update.cpp +1 -1
  47. esphome/components/i2c_device/__init__.py +26 -0
  48. esphome/components/i2c_device/i2c_device.cpp +17 -0
  49. esphome/components/i2c_device/i2c_device.h +18 -0
  50. esphome/components/i2s_audio/__init__.py +1 -3
  51. esphome/components/i2s_audio/speaker/__init__.py +12 -4
  52. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +432 -197
  53. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +91 -32
  54. esphome/components/ili9xxx/display.py +5 -1
  55. esphome/components/image/__init__.py +5 -8
  56. esphome/components/image/image.cpp +14 -14
  57. esphome/components/image/image.h +20 -24
  58. esphome/components/internal_temperature/internal_temperature.cpp +51 -2
  59. esphome/components/internal_temperature/internal_temperature.h +1 -0
  60. esphome/components/libretiny/gpio.py +4 -2
  61. esphome/components/light/__init__.py +32 -1
  62. esphome/components/light/automation.py +39 -32
  63. esphome/components/light/effects.py +36 -36
  64. esphome/components/light/light_state.cpp +6 -16
  65. esphome/components/light/light_state.h +34 -0
  66. esphome/components/light/types.py +3 -1
  67. esphome/components/logger/logger_esp32.cpp +15 -0
  68. esphome/components/lvgl/__init__.py +202 -95
  69. esphome/components/lvgl/automation.py +42 -40
  70. esphome/components/lvgl/binary_sensor/__init__.py +8 -15
  71. esphome/components/lvgl/defines.py +14 -8
  72. esphome/components/lvgl/encoders.py +11 -8
  73. esphome/components/lvgl/keypads.py +77 -0
  74. esphome/components/lvgl/light/__init__.py +6 -8
  75. esphome/components/lvgl/lv_validation.py +2 -4
  76. esphome/components/lvgl/lvcode.py +3 -9
  77. esphome/components/lvgl/lvgl_esphome.cpp +210 -89
  78. esphome/components/lvgl/lvgl_esphome.h +113 -30
  79. esphome/components/lvgl/lvgl_proxy.h +17 -0
  80. esphome/components/lvgl/number/__init__.py +10 -15
  81. esphome/components/lvgl/schemas.py +4 -2
  82. esphome/components/lvgl/select/__init__.py +12 -37
  83. esphome/components/lvgl/select/lvgl_select.h +27 -33
  84. esphome/components/lvgl/sensor/__init__.py +8 -14
  85. esphome/components/lvgl/styles.py +3 -4
  86. esphome/components/lvgl/switch/__init__.py +8 -13
  87. esphome/components/lvgl/text/__init__.py +5 -6
  88. esphome/components/lvgl/text_sensor/__init__.py +15 -15
  89. esphome/components/lvgl/touchscreens.py +2 -3
  90. esphome/components/lvgl/trigger.py +7 -9
  91. esphome/components/lvgl/types.py +9 -3
  92. esphome/components/lvgl/widgets/__init__.py +32 -21
  93. esphome/components/lvgl/widgets/dropdown.py +22 -10
  94. esphome/components/lvgl/widgets/msgbox.py +6 -5
  95. esphome/components/lvgl/widgets/obj.py +4 -2
  96. esphome/components/lvgl/widgets/page.py +3 -2
  97. esphome/components/lvgl/widgets/qrcode.py +54 -0
  98. esphome/components/lvgl/widgets/roller.py +21 -14
  99. esphome/components/lvgl/widgets/tileview.py +2 -1
  100. esphome/components/max17043/__init__.py +1 -0
  101. esphome/components/max17043/automation.h +20 -0
  102. esphome/components/max17043/max17043.cpp +98 -0
  103. esphome/components/max17043/max17043.h +29 -0
  104. esphome/components/max17043/sensor.py +77 -0
  105. esphome/components/media_player/__init__.py +11 -0
  106. esphome/components/media_player/automation.h +10 -0
  107. esphome/components/media_player/media_player.cpp +4 -0
  108. esphome/components/midea/air_conditioner.cpp +17 -1
  109. esphome/components/mlx90393/sensor.py +1 -1
  110. esphome/components/modbus_controller/__init__.py +31 -1
  111. esphome/components/modbus_controller/automation.h +16 -0
  112. esphome/components/modbus_controller/const.py +2 -0
  113. esphome/components/modbus_controller/modbus_controller.cpp +14 -2
  114. esphome/components/modbus_controller/modbus_controller.h +9 -0
  115. esphome/components/mopeka_pro_check/mopeka_pro_check.cpp +40 -21
  116. esphome/components/mopeka_pro_check/mopeka_pro_check.h +9 -2
  117. esphome/components/mopeka_pro_check/sensor.py +41 -0
  118. esphome/components/mqtt/__init__.py +36 -0
  119. esphome/components/mqtt/mqtt_client.cpp +27 -3
  120. esphome/components/mqtt/mqtt_client.h +27 -2
  121. esphome/components/mqtt/mqtt_climate.cpp +4 -2
  122. esphome/components/mqtt/mqtt_component.cpp +6 -0
  123. esphome/components/mqtt/mqtt_component.h +4 -0
  124. esphome/components/mqtt/mqtt_const.h +6 -0
  125. esphome/components/online_image/online_image.cpp +2 -8
  126. esphome/components/online_image/online_image.h +2 -6
  127. esphome/components/opentherm/__init__.py +35 -9
  128. esphome/components/opentherm/binary_sensor/__init__.py +33 -0
  129. esphome/components/opentherm/const.py +11 -0
  130. esphome/components/opentherm/generate.py +142 -0
  131. esphome/components/opentherm/hub.cpp +130 -24
  132. esphome/components/opentherm/hub.h +62 -9
  133. esphome/components/opentherm/input.h +18 -0
  134. esphome/components/opentherm/input.py +51 -0
  135. esphome/components/opentherm/number/__init__.py +74 -0
  136. esphome/components/opentherm/number/number.cpp +40 -0
  137. esphome/components/opentherm/number/number.h +31 -0
  138. esphome/components/opentherm/opentherm.cpp +30 -0
  139. esphome/components/opentherm/opentherm.h +34 -2
  140. esphome/components/opentherm/opentherm_macros.h +151 -0
  141. esphome/components/opentherm/output/__init__.py +47 -0
  142. esphome/components/opentherm/output/output.cpp +18 -0
  143. esphome/components/opentherm/output/output.h +33 -0
  144. esphome/components/opentherm/schema.py +814 -0
  145. esphome/components/opentherm/sensor/__init__.py +51 -0
  146. esphome/components/opentherm/switch/__init__.py +43 -0
  147. esphome/components/opentherm/switch/switch.cpp +28 -0
  148. esphome/components/opentherm/switch/switch.h +20 -0
  149. esphome/components/opentherm/validate.py +31 -0
  150. esphome/components/pcd8544/display.py +8 -4
  151. esphome/components/prometheus/prometheus_handler.cpp +176 -14
  152. esphome/components/prometheus/prometheus_handler.h +25 -7
  153. esphome/components/qspi_amoled/display.py +1 -141
  154. esphome/components/qspi_dbi/display.py +185 -0
  155. esphome/components/qspi_dbi/models.py +64 -0
  156. esphome/components/{qspi_amoled/qspi_amoled.cpp → qspi_dbi/qspi_dbi.cpp} +95 -46
  157. esphome/components/{qspi_amoled/qspi_amoled.h → qspi_dbi/qspi_dbi.h} +26 -15
  158. esphome/components/rp2040/__init__.py +6 -3
  159. esphome/components/rp2040/gpio.py +5 -3
  160. esphome/components/rtttl/rtttl.cpp +4 -1
  161. esphome/components/rtttl/rtttl.h +1 -0
  162. esphome/components/sdl/sdl_esphome.cpp +22 -5
  163. esphome/components/sdl/sdl_esphome.h +1 -0
  164. esphome/components/sensor/__init__.py +18 -8
  165. esphome/components/sensor/filter.cpp +19 -18
  166. esphome/components/sensor/filter.h +9 -10
  167. esphome/components/sgp4x/sgp4x.cpp +40 -74
  168. esphome/components/sgp4x/sgp4x.h +5 -3
  169. esphome/components/speaker/__init__.py +51 -5
  170. esphome/components/speaker/automation.h +25 -0
  171. esphome/components/speaker/speaker.h +72 -1
  172. esphome/components/spi/__init__.py +15 -14
  173. esphome/components/spi_device/__init__.py +4 -15
  174. esphome/components/ssd1306_spi/display.py +6 -2
  175. esphome/components/ssd1322_spi/display.py +6 -2
  176. esphome/components/ssd1325_spi/display.py +6 -2
  177. esphome/components/ssd1327_spi/display.py +6 -2
  178. esphome/components/ssd1331_spi/display.py +6 -2
  179. esphome/components/ssd1351_spi/display.py +6 -2
  180. esphome/components/st7567_spi/display.py +6 -2
  181. esphome/components/st7701s/display.py +5 -1
  182. esphome/components/st7735/display.py +10 -5
  183. esphome/components/st7789v/display.py +12 -7
  184. esphome/components/statsd/statsd.cpp +2 -0
  185. esphome/components/statsd/statsd.h +2 -0
  186. esphome/components/sun/sun.h +3 -0
  187. esphome/components/tc74/__init__.py +1 -0
  188. esphome/components/tc74/sensor.py +32 -0
  189. esphome/components/tc74/tc74.cpp +68 -0
  190. esphome/components/tc74/tc74.h +28 -0
  191. esphome/components/touchscreen/__init__.py +41 -50
  192. esphome/components/touchscreen/touchscreen.h +4 -8
  193. esphome/components/udp/udp_component.cpp +6 -3
  194. esphome/components/udp/udp_component.h +4 -2
  195. esphome/components/waveshare_epaper/display.py +6 -2
  196. esphome/components/web_server/web_server.cpp +22 -0
  197. esphome/components/web_server/web_server.h +3 -0
  198. esphome/components/weikai/weikai.h +2 -2
  199. esphome/components/wifi/wifi_component.cpp +2 -2
  200. esphome/components/wifi/wifi_component_esp32_arduino.cpp +4 -4
  201. esphome/components/wifi/wifi_component_esp8266.cpp +4 -4
  202. esphome/components/wifi/wifi_component_esp_idf.cpp +2 -2
  203. esphome/components/xpt2046/touchscreen/__init__.py +7 -32
  204. esphome/config_validation.py +3 -1
  205. esphome/const.py +8 -1
  206. esphome/core/defines.h +8 -2
  207. esphome/core/helpers.cpp +32 -17
  208. esphome/core/helpers.h +32 -16
  209. esphome/core/ring_buffer.cpp +2 -2
  210. esphome/core/ring_buffer.h +2 -2
  211. esphome/dashboard/core.py +25 -0
  212. esphome/dashboard/status/mdns.py +3 -4
  213. esphome/dashboard/web_server.py +54 -19
  214. esphome/espota2.py +36 -35
  215. esphome/helpers.py +68 -16
  216. esphome/mqtt.py +9 -2
  217. esphome/storage_json.py +4 -0
  218. esphome/writer.py +7 -18
  219. esphome/zeroconf.py +8 -6
  220. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/METADATA +7 -5
  221. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/RECORD +226 -180
  222. esphome/core/bytebuffer.cpp +0 -167
  223. esphome/core/bytebuffer.h +0 -144
  224. /esphome/components/{qspi_amoled → qspi_dbi}/__init__.py +0 -0
  225. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/LICENSE +0 -0
  226. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/WHEEL +0 -0
  227. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/entry_points.txt +0 -0
  228. {esphome-2024.10.3.dist-info → esphome-2024.11.0b1.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,10 @@
1
- from collections.abc import Awaitable
2
- from typing import Callable
1
+ from typing import Any, Callable
3
2
 
4
3
  from esphome import automation
5
4
  import esphome.codegen as cg
6
5
  import esphome.config_validation as cv
7
6
  from esphome.const import CONF_ACTION, CONF_GROUP, CONF_ID, CONF_TIMEOUT
8
- from esphome.cpp_generator import RawExpression, get_variable
7
+ from esphome.cpp_generator import get_variable
9
8
  from esphome.cpp_types import nullptr
10
9
 
11
10
  from .defines import (
@@ -23,8 +22,6 @@ from .lvcode import (
23
22
  UPDATE_EVENT,
24
23
  LambdaContext,
25
24
  LocalVariable,
26
- LvConditional,
27
- LvglComponent,
28
25
  ReturnStatement,
29
26
  add_line_marks,
30
27
  lv,
@@ -47,8 +44,8 @@ from .types import (
47
44
  )
48
45
  from .widgets import (
49
46
  Widget,
47
+ get_scr_act,
50
48
  get_widgets,
51
- lv_scr_act,
52
49
  set_obj_properties,
53
50
  wait_for_widgets,
54
51
  )
@@ -59,15 +56,13 @@ focused_widgets = set()
59
56
 
60
57
  async def action_to_code(
61
58
  widgets: list[Widget],
62
- action: Callable[[Widget], Awaitable[None]],
59
+ action: Callable[[Widget], Any],
63
60
  action_id,
64
61
  template_arg,
65
62
  args,
66
63
  ):
67
64
  await wait_for_widgets()
68
65
  async with LambdaContext(parameters=args, where=action_id) as context:
69
- with LvConditional(lv_expr.is_pre_initialise()):
70
- context.add(RawExpression("return"))
71
66
  for widget in widgets:
72
67
  await action(widget)
73
68
  var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
@@ -126,7 +121,7 @@ async def lvgl_is_idle(config, condition_id, template_arg, args):
126
121
  async def disp_update(disp, config: dict):
127
122
  if CONF_DISP_BG_COLOR not in config and CONF_DISP_BG_IMAGE not in config:
128
123
  return
129
- with LocalVariable("lv_disp_tmp", lv_disp_t, literal(disp)) as disp_temp:
124
+ with LocalVariable("lv_disp_tmp", lv_disp_t, disp) as disp_temp:
130
125
  if (bg_color := config.get(CONF_DISP_BG_COLOR)) is not None:
131
126
  lv.disp_set_bg_color(disp_temp, await lv_color.process(bg_color))
132
127
  if bg_image := config.get(CONF_DISP_BG_IMAGE):
@@ -136,15 +131,22 @@ async def disp_update(disp, config: dict):
136
131
  @automation.register_action(
137
132
  "lvgl.widget.redraw",
138
133
  ObjUpdateAction,
139
- cv.Schema(
140
- {
141
- cv.Optional(CONF_ID): cv.use_id(lv_obj_t),
142
- cv.GenerateID(CONF_LVGL_ID): cv.use_id(LvglComponent),
143
- }
134
+ cv.Any(
135
+ cv.maybe_simple_value(
136
+ {
137
+ cv.Required(CONF_ID): cv.use_id(lv_obj_t),
138
+ },
139
+ key=CONF_ID,
140
+ ),
141
+ LVGL_SCHEMA,
144
142
  ),
145
143
  )
146
144
  async def obj_invalidate_to_code(config, action_id, template_arg, args):
147
- widgets = await get_widgets(config) or [lv_scr_act]
145
+ if CONF_LVGL_ID in config:
146
+ lv_comp = await cg.get_variable(config[CONF_LVGL_ID])
147
+ widgets = [get_scr_act(lv_comp)]
148
+ else:
149
+ widgets = await get_widgets(config)
148
150
 
149
151
  async def do_invalidate(widget: Widget):
150
152
  lv_obj.invalidate(widget.obj)
@@ -155,16 +157,14 @@ async def obj_invalidate_to_code(config, action_id, template_arg, args):
155
157
  @automation.register_action(
156
158
  "lvgl.update",
157
159
  LvglAction,
158
- DISP_BG_SCHEMA.extend(
159
- {
160
- cv.GenerateID(): cv.use_id(LvglComponent),
161
- }
162
- ).add_extra(cv.has_at_least_one_key(CONF_DISP_BG_COLOR, CONF_DISP_BG_IMAGE)),
160
+ DISP_BG_SCHEMA.extend(LVGL_SCHEMA).add_extra(
161
+ cv.has_at_least_one_key(CONF_DISP_BG_COLOR, CONF_DISP_BG_IMAGE)
162
+ ),
163
163
  )
164
164
  async def lvgl_update_to_code(config, action_id, template_arg, args):
165
- widgets = await get_widgets(config)
165
+ widgets = await get_widgets(config, CONF_LVGL_ID)
166
166
  w = widgets[0]
167
- disp = f"{w.obj}->get_disp()"
167
+ disp = literal(f"{w.obj}->get_disp()")
168
168
  async with LambdaContext(LVGL_COMP_ARG, where=action_id) as context:
169
169
  await disp_update(disp, config)
170
170
  var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
@@ -175,32 +175,33 @@ async def lvgl_update_to_code(config, action_id, template_arg, args):
175
175
  @automation.register_action(
176
176
  "lvgl.pause",
177
177
  LvglAction,
178
- {
179
- cv.GenerateID(): cv.use_id(LvglComponent),
180
- cv.Optional(CONF_SHOW_SNOW, default=False): lv_bool,
181
- },
178
+ LVGL_SCHEMA.extend(
179
+ {
180
+ cv.Optional(CONF_SHOW_SNOW, default=False): lv_bool,
181
+ }
182
+ ),
182
183
  )
183
184
  async def pause_action_to_code(config, action_id, template_arg, args):
185
+ lv_comp = await cg.get_variable(config[CONF_LVGL_ID])
184
186
  async with LambdaContext(LVGL_COMP_ARG) as context:
185
187
  add_line_marks(where=action_id)
186
188
  lv_add(lvgl_comp.set_paused(True, config[CONF_SHOW_SNOW]))
187
189
  var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
188
- await cg.register_parented(var, config[CONF_ID])
190
+ await cg.register_parented(var, lv_comp)
189
191
  return var
190
192
 
191
193
 
192
194
  @automation.register_action(
193
195
  "lvgl.resume",
194
196
  LvglAction,
195
- {
196
- cv.GenerateID(): cv.use_id(LvglComponent),
197
- },
197
+ LVGL_SCHEMA,
198
198
  )
199
199
  async def resume_action_to_code(config, action_id, template_arg, args):
200
+ lv_comp = await cg.get_variable(config[CONF_LVGL_ID])
200
201
  async with LambdaContext(LVGL_COMP_ARG, where=action_id) as context:
201
202
  lv_add(lvgl_comp.set_paused(False, False))
202
203
  var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda())
203
- await cg.register_parented(var, config[CONF_ID])
204
+ await cg.register_parented(var, lv_comp)
204
205
  return var
205
206
 
206
207
 
@@ -259,14 +260,15 @@ def focused_id(value):
259
260
  ObjUpdateAction,
260
261
  cv.Any(
261
262
  cv.maybe_simple_value(
262
- {
263
- cv.Optional(CONF_GROUP): cv.use_id(lv_group_t),
264
- cv.Required(CONF_ACTION): cv.one_of(
265
- "MARK", "RESTORE", "NEXT", "PREVIOUS", upper=True
266
- ),
267
- cv.GenerateID(CONF_LVGL_ID): cv.use_id(LvglComponent),
268
- cv.Optional(CONF_FREEZE, default=False): cv.boolean,
269
- },
263
+ LVGL_SCHEMA.extend(
264
+ {
265
+ cv.Optional(CONF_GROUP): cv.use_id(lv_group_t),
266
+ cv.Required(CONF_ACTION): cv.one_of(
267
+ "MARK", "RESTORE", "NEXT", "PREVIOUS", upper=True
268
+ ),
269
+ cv.Optional(CONF_FREEZE, default=False): cv.boolean,
270
+ }
271
+ ),
270
272
  key=CONF_ACTION,
271
273
  ),
272
274
  cv.maybe_simple_value(
@@ -1,4 +1,3 @@
1
- import esphome.codegen as cg
2
1
  from esphome.components.binary_sensor import (
3
2
  BinarySensor,
4
3
  binary_sensor_schema,
@@ -6,36 +5,30 @@ from esphome.components.binary_sensor import (
6
5
  )
7
6
  import esphome.config_validation as cv
8
7
 
9
- from ..defines import CONF_LVGL_ID, CONF_WIDGET
10
- from ..lvcode import EVENT_ARG, LambdaContext, LvContext
11
- from ..schemas import LVGL_SCHEMA
8
+ from ..defines import CONF_WIDGET
9
+ from ..lvcode import EVENT_ARG, LambdaContext, LvContext, lvgl_static
12
10
  from ..types import LV_EVENT, lv_pseudo_button_t
13
11
  from ..widgets import Widget, get_widgets, wait_for_widgets
14
12
 
15
- CONFIG_SCHEMA = (
16
- binary_sensor_schema(BinarySensor)
17
- .extend(LVGL_SCHEMA)
18
- .extend(
19
- {
20
- cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t),
21
- }
22
- )
13
+ CONFIG_SCHEMA = binary_sensor_schema(BinarySensor).extend(
14
+ {
15
+ cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t),
16
+ }
23
17
  )
24
18
 
25
19
 
26
20
  async def to_code(config):
27
21
  sensor = await new_binary_sensor(config)
28
- paren = await cg.get_variable(config[CONF_LVGL_ID])
29
22
  widget = await get_widgets(config, CONF_WIDGET)
30
23
  widget = widget[0]
31
24
  assert isinstance(widget, Widget)
32
25
  await wait_for_widgets()
33
26
  async with LambdaContext(EVENT_ARG) as pressed_ctx:
34
27
  pressed_ctx.add(sensor.publish_state(widget.is_pressed()))
35
- async with LvContext(paren) as ctx:
28
+ async with LvContext() as ctx:
36
29
  ctx.add(sensor.publish_initial_state(widget.is_pressed()))
37
30
  ctx.add(
38
- paren.add_event_cb(
31
+ lvgl_static.add_event_cb(
39
32
  widget.obj,
40
33
  await pressed_ctx.get_lambda(),
41
34
  LV_EVENT.PRESSING,
@@ -189,14 +189,14 @@ LV_ANIM = LvConstant(
189
189
  LV_GRAD_DIR = LvConstant("LV_GRAD_DIR_", "NONE", "HOR", "VER")
190
190
  LV_DITHER = LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF")
191
191
 
192
- LOG_LEVELS = (
193
- "TRACE",
194
- "INFO",
195
- "WARN",
196
- "ERROR",
197
- "USER",
198
- "NONE",
199
- )
192
+ LV_LOG_LEVELS = {
193
+ "VERBOSE": "TRACE",
194
+ "DEBUG": "TRACE",
195
+ "INFO": "INFO",
196
+ "WARN": "WARN",
197
+ "ERROR": "ERROR",
198
+ "NONE": "NONE",
199
+ }
200
200
 
201
201
  LV_LONG_MODES = LvConstant(
202
202
  "LV_LABEL_LONG_",
@@ -408,6 +408,7 @@ CONF_DEFAULT_FONT = "default_font"
408
408
  CONF_DEFAULT_GROUP = "default_group"
409
409
  CONF_DIR = "dir"
410
410
  CONF_DISPLAYS = "displays"
411
+ CONF_DRAW_ROUNDING = "draw_rounding"
411
412
  CONF_EDITING = "editing"
412
413
  CONF_ENCODERS = "encoders"
413
414
  CONF_END_ANGLE = "end_angle"
@@ -437,6 +438,7 @@ CONF_HEADER_MODE = "header_mode"
437
438
  CONF_HOME = "home"
438
439
  CONF_INITIAL_FOCUS = "initial_focus"
439
440
  CONF_KEY_CODE = "key_code"
441
+ CONF_KEYPADS = "keypads"
440
442
  CONF_LAYOUT = "layout"
441
443
  CONF_LEFT_BUTTON = "left_button"
442
444
  CONF_LINE_WIDTH = "line_width"
@@ -451,6 +453,8 @@ CONF_OFFSET_X = "offset_x"
451
453
  CONF_OFFSET_Y = "offset_y"
452
454
  CONF_ONE_CHECKED = "one_checked"
453
455
  CONF_ONE_LINE = "one_line"
456
+ CONF_ON_PAUSE = "on_pause"
457
+ CONF_ON_RESUME = "on_resume"
454
458
  CONF_ON_SELECT = "on_select"
455
459
  CONF_OPA = "opa"
456
460
  CONF_NEXT = "next"
@@ -466,6 +470,7 @@ CONF_POINTS = "points"
466
470
  CONF_PREVIOUS = "previous"
467
471
  CONF_REPEAT_COUNT = "repeat_count"
468
472
  CONF_RECOLOR = "recolor"
473
+ CONF_RESUME_ON_INPUT = "resume_on_input"
469
474
  CONF_RIGHT_BUTTON = "right_button"
470
475
  CONF_ROLLOVER = "rollover"
471
476
  CONF_ROOT_BACK_BTN = "root_back_btn"
@@ -473,6 +478,7 @@ CONF_ROWS = "rows"
473
478
  CONF_SCALE_LINES = "scale_lines"
474
479
  CONF_SCROLLBAR_MODE = "scrollbar_mode"
475
480
  CONF_SELECTED_INDEX = "selected_index"
481
+ CONF_SELECTED_TEXT = "selected_text"
476
482
  CONF_SHOW_SNOW = "show_snow"
477
483
  CONF_SPIN_TIME = "spin_time"
478
484
  CONF_SRC = "src"
@@ -17,7 +17,7 @@ from .defines import (
17
17
  from .helpers import lvgl_components_required, requires_component
18
18
  from .lvcode import lv, lv_add, lv_assign, lv_expr, lv_Pvariable
19
19
  from .schemas import ENCODER_SCHEMA
20
- from .types import lv_group_t, lv_indev_type_t
20
+ from .types import lv_group_t, lv_indev_type_t, lv_key_t
21
21
 
22
22
  ENCODERS_CONFIG = cv.ensure_list(
23
23
  ENCODER_SCHEMA.extend(
@@ -39,10 +39,13 @@ ENCODERS_CONFIG = cv.ensure_list(
39
39
  )
40
40
 
41
41
 
42
- async def encoders_to_code(var, config):
43
- default_group = lv_Pvariable(lv_group_t, config[CONF_DEFAULT_GROUP])
44
- lv_assign(default_group, lv_expr.group_create())
45
- lv.group_set_default(default_group)
42
+ def get_default_group(config):
43
+ default_group = cg.Pvariable(config[CONF_DEFAULT_GROUP], lv_expr.group_create())
44
+ cg.add(lv.group_set_default(default_group))
45
+ return default_group
46
+
47
+
48
+ async def encoders_to_code(var, config, default_group):
46
49
  for enc_conf in config[CONF_ENCODERS]:
47
50
  lvgl_components_required.add("KEY_LISTENER")
48
51
  lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds
@@ -54,14 +57,14 @@ async def encoders_to_code(var, config):
54
57
  if sensor_config := enc_conf.get(CONF_SENSOR):
55
58
  if isinstance(sensor_config, dict):
56
59
  b_sensor = await cg.get_variable(sensor_config[CONF_LEFT_BUTTON])
57
- cg.add(listener.set_left_button(b_sensor))
60
+ cg.add(listener.add_button(b_sensor, lv_key_t.LV_KEY_LEFT))
58
61
  b_sensor = await cg.get_variable(sensor_config[CONF_RIGHT_BUTTON])
59
- cg.add(listener.set_right_button(b_sensor))
62
+ cg.add(listener.add_button(b_sensor, lv_key_t.LV_KEY_RIGHT))
60
63
  else:
61
64
  sensor_config = await cg.get_variable(sensor_config)
62
65
  lv_add(listener.set_sensor(sensor_config))
63
66
  b_sensor = await cg.get_variable(enc_conf[CONF_ENTER_BUTTON])
64
- cg.add(listener.set_enter_button(b_sensor))
67
+ cg.add(listener.add_button(b_sensor, lv_key_t.LV_KEY_ENTER))
65
68
  if group := enc_conf.get(CONF_GROUP):
66
69
  group = lv_Pvariable(lv_group_t, group)
67
70
  lv_assign(group, lv_expr.group_create())
@@ -0,0 +1,77 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components.binary_sensor import BinarySensor
3
+ import esphome.config_validation as cv
4
+ from esphome.const import CONF_GROUP, CONF_ID
5
+
6
+ from .defines import (
7
+ CONF_ENCODERS,
8
+ CONF_INITIAL_FOCUS,
9
+ CONF_KEYPADS,
10
+ CONF_LONG_PRESS_REPEAT_TIME,
11
+ CONF_LONG_PRESS_TIME,
12
+ literal,
13
+ )
14
+ from .helpers import lvgl_components_required
15
+ from .lvcode import lv, lv_assign, lv_expr, lv_Pvariable
16
+ from .schemas import ENCODER_SCHEMA
17
+ from .types import lv_group_t, lv_indev_type_t
18
+
19
+ KEYPAD_KEYS = (
20
+ "up",
21
+ "down",
22
+ "right",
23
+ "left",
24
+ "esc",
25
+ "del",
26
+ "backspace",
27
+ "enter",
28
+ "next",
29
+ "prev",
30
+ "home",
31
+ "end",
32
+ "0",
33
+ "1",
34
+ "2",
35
+ "3",
36
+ "4",
37
+ "5",
38
+ "6",
39
+ "7",
40
+ "8",
41
+ "9",
42
+ "#",
43
+ "*",
44
+ )
45
+
46
+ KEYPADS_CONFIG = cv.ensure_list(
47
+ ENCODER_SCHEMA.extend(
48
+ {cv.Optional(key): cv.use_id(BinarySensor) for key in KEYPAD_KEYS}
49
+ )
50
+ )
51
+
52
+
53
+ async def keypads_to_code(var, config, default_group):
54
+ for enc_conf in config[CONF_KEYPADS]:
55
+ lvgl_components_required.add("KEY_LISTENER")
56
+ lpt = enc_conf[CONF_LONG_PRESS_TIME].total_milliseconds
57
+ lprt = enc_conf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds
58
+ listener = cg.new_Pvariable(
59
+ enc_conf[CONF_ID], lv_indev_type_t.LV_INDEV_TYPE_KEYPAD, lpt, lprt
60
+ )
61
+ await cg.register_parented(listener, var)
62
+ for key in [x for x in enc_conf if x in KEYPAD_KEYS]:
63
+ b_sensor = await cg.get_variable(enc_conf[key])
64
+ cg.add(listener.add_button(b_sensor, literal(f"LV_KEY_{key.upper()}")))
65
+ if group := enc_conf.get(CONF_GROUP):
66
+ group = lv_Pvariable(lv_group_t, group)
67
+ lv_assign(group, lv_expr.group_create())
68
+ else:
69
+ group = default_group
70
+ lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group)
71
+
72
+
73
+ async def initial_focus_to_code(config):
74
+ for enc_conf in config[CONF_ENCODERS]:
75
+ if default_focus := enc_conf.get(CONF_INITIAL_FOCUS):
76
+ obj = await cg.get_variable(default_focus)
77
+ lv.group_focus_obj(obj)
@@ -2,11 +2,10 @@ import esphome.codegen as cg
2
2
  from esphome.components import light
3
3
  from esphome.components.light import LightOutput
4
4
  import esphome.config_validation as cv
5
- from esphome.const import CONF_GAMMA_CORRECT, CONF_LED, CONF_OUTPUT_ID
5
+ from esphome.const import CONF_GAMMA_CORRECT, CONF_OUTPUT_ID
6
6
 
7
- from ..defines import CONF_LVGL_ID
7
+ from ..defines import CONF_WIDGET
8
8
  from ..lvcode import LvContext
9
- from ..schemas import LVGL_SCHEMA
10
9
  from ..types import LvType, lvgl_ns
11
10
  from ..widgets import get_widgets, wait_for_widgets
12
11
 
@@ -15,19 +14,18 @@ LVLight = lvgl_ns.class_("LVLight", LightOutput)
15
14
  CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend(
16
15
  {
17
16
  cv.Optional(CONF_GAMMA_CORRECT, default=0.0): cv.positive_float,
18
- cv.Required(CONF_LED): cv.use_id(lv_led_t),
17
+ cv.Required(CONF_WIDGET): cv.use_id(lv_led_t),
19
18
  cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(LVLight),
20
19
  }
21
- ).extend(LVGL_SCHEMA)
20
+ )
22
21
 
23
22
 
24
23
  async def to_code(config):
25
24
  var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
26
25
  await light.register_light(var, config)
27
26
 
28
- paren = await cg.get_variable(config[CONF_LVGL_ID])
29
- widget = await get_widgets(config, CONF_LED)
27
+ widget = await get_widgets(config, CONF_WIDGET)
30
28
  widget = widget[0]
31
29
  await wait_for_widgets()
32
- async with LvContext(paren) as ctx:
30
+ async with LvContext() as ctx:
33
31
  ctx.add(var.set_obj(widget.obj))
@@ -277,10 +277,8 @@ def size_validator(value):
277
277
  return ["SIZE_CONTENT", "number of pixels", "percentage"]
278
278
  if isinstance(value, str) and value.lower().endswith("px"):
279
279
  value = cv.int_(value[:-2])
280
- if isinstance(value, str) and not value.endswith("%"):
281
- if value.upper() == "SIZE_CONTENT":
282
- return "LV_SIZE_CONTENT"
283
- raise cv.Invalid("must be 'size_content', a percentage or an integer (pixels)")
280
+ if isinstance(value, str) and value.upper() == "SIZE_CONTENT":
281
+ return "LV_SIZE_CONTENT"
284
282
  return pixels_or_percent_validator(value)
285
283
 
286
284
 
@@ -178,22 +178,15 @@ class LvContext(LambdaContext):
178
178
 
179
179
  added_lambda_count = 0
180
180
 
181
- def __init__(self, lv_component, args=None):
181
+ def __init__(self, args=None):
182
182
  self.args = args or LVGL_COMP_ARG
183
183
  super().__init__(parameters=self.args)
184
- self.lv_component = lv_component
185
-
186
- async def add_init_lambda(self):
187
- if self.code_list:
188
- cg.add(self.lv_component.add_init_lambda(await self.get_lambda()))
189
- LvContext.added_lambda_count += 1
190
184
 
191
185
  async def __aexit__(self, exc_type, exc_val, exc_tb):
192
186
  await super().__aexit__(exc_type, exc_val, exc_tb)
193
- await self.add_init_lambda()
194
187
 
195
188
  def add(self, expression: Union[Expression, Statement]):
196
- self.code_list.append(self.indented_statement(expression))
189
+ cg.add(expression)
197
190
  return expression
198
191
 
199
192
  def __call__(self, *args):
@@ -304,6 +297,7 @@ lv_expr = LvExpr("lv_")
304
297
  lv_obj = MockLv("lv_obj_")
305
298
  # Operations on the LVGL component
306
299
  lvgl_comp = MockObj(LVGL_COMP, "->")
300
+ lvgl_static = MockObj("LvglComponent", "::")
307
301
 
308
302
 
309
303
  # equivalent to cg.add() for the current code context