esphome 2024.8.2__py3-none-any.whl → 2024.9.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 (204) hide show
  1. esphome/__main__.py +6 -2
  2. esphome/components/api/api_connection.cpp +53 -0
  3. esphome/components/api/api_connection.h +4 -0
  4. esphome/components/api/api_pb2.cpp +280 -0
  5. esphome/components/api/api_pb2.h +91 -0
  6. esphome/components/api/api_pb2_service.cpp +85 -0
  7. esphome/components/api/api_pb2_service.h +28 -0
  8. esphome/components/async_tcp/__init__.py +3 -3
  9. esphome/components/atm90e26/sensor.py +10 -10
  10. esphome/components/atm90e32/sensor.py +1 -1
  11. esphome/components/bl0906/__init__.py +1 -0
  12. esphome/components/bl0906/bl0906.cpp +238 -0
  13. esphome/components/bl0906/bl0906.h +96 -0
  14. esphome/components/bl0906/const.py +4 -0
  15. esphome/components/bl0906/constants.h +122 -0
  16. esphome/components/bl0906/sensor.py +184 -0
  17. esphome/components/bl0942/__init__.py +1 -1
  18. esphome/components/bl0942/bl0942.cpp +127 -34
  19. esphome/components/bl0942/bl0942.h +87 -3
  20. esphome/components/bl0942/sensor.py +46 -8
  21. esphome/components/ble_client/__init__.py +1 -3
  22. esphome/components/ble_presence/binary_sensor.py +2 -2
  23. esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +5 -0
  24. esphome/components/bmp280/sensor.py +2 -93
  25. esphome/components/bmp280_base/__init__.py +88 -0
  26. esphome/components/{bmp280/bmp280.cpp → bmp280_base/bmp280_base.cpp} +11 -4
  27. esphome/components/{bmp280/bmp280.h → bmp280_base/bmp280_base.h} +9 -5
  28. esphome/components/bmp280_i2c/__init__.py +0 -0
  29. esphome/components/bmp280_i2c/bmp280_i2c.cpp +27 -0
  30. esphome/components/bmp280_i2c/bmp280_i2c.h +22 -0
  31. esphome/components/bmp280_i2c/sensor.py +22 -0
  32. esphome/components/bmp280_spi/__init__.py +0 -0
  33. esphome/components/bmp280_spi/bmp280_spi.cpp +65 -0
  34. esphome/components/bmp280_spi/bmp280_spi.h +20 -0
  35. esphome/components/bmp280_spi/sensor.py +22 -0
  36. esphome/components/captive_portal/captive_portal.cpp +2 -0
  37. esphome/components/captive_portal/captive_portal.h +3 -1
  38. esphome/components/ch422g/__init__.py +67 -0
  39. esphome/components/ch422g/ch422g.cpp +122 -0
  40. esphome/components/ch422g/ch422g.h +70 -0
  41. esphome/components/debug/debug_esp32.cpp +3 -1
  42. esphome/components/display/__init__.py +5 -4
  43. esphome/components/dsmr/dsmr.cpp +6 -0
  44. esphome/components/dsmr/dsmr.h +6 -0
  45. esphome/components/dsmr/text_sensor.py +7 -2
  46. esphome/components/e131/e131.cpp +2 -0
  47. esphome/components/e131/e131.h +3 -1
  48. esphome/components/e131/e131_addressable_light_effect.cpp +2 -0
  49. esphome/components/e131/e131_addressable_light_effect.h +2 -1
  50. esphome/components/e131/e131_packet.cpp +2 -0
  51. esphome/components/esp32_ble/ble_uuid.cpp +7 -0
  52. esphome/components/esp32_ble/ble_uuid.h +1 -0
  53. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +11 -9
  54. esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +3 -3
  55. esphome/components/esp32_camera/__init__.py +4 -0
  56. esphome/components/esp32_camera/esp32_camera.cpp +9 -1
  57. esphome/components/esp32_camera/esp32_camera.h +3 -0
  58. esphome/components/esp32_can/canbus.py +18 -7
  59. esphome/components/esp32_can/esp32_can.cpp +8 -0
  60. esphome/components/esp32_can/esp32_can.h +4 -0
  61. esphome/components/esp32_rmt_led_strip/led_strip.cpp +14 -2
  62. esphome/components/esp32_rmt_led_strip/led_strip.h +3 -2
  63. esphome/components/esp32_rmt_led_strip/light.py +21 -4
  64. esphome/components/esphome/ota/ota_esphome.cpp +2 -1
  65. esphome/components/esphome/ota/ota_esphome.h +2 -0
  66. esphome/components/font/__init__.py +11 -22
  67. esphome/components/font/font.cpp +3 -2
  68. esphome/components/font/font.h +12 -3
  69. esphome/components/gree/climate.py +2 -1
  70. esphome/components/gree/gree.cpp +54 -3
  71. esphome/components/gree/gree.h +10 -2
  72. esphome/components/gt911/touchscreen/__init__.py +6 -4
  73. esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +17 -0
  74. esphome/components/gt911/touchscreen/gt911_touchscreen.h +2 -0
  75. esphome/components/hmac_md5/__init__.py +2 -0
  76. esphome/components/hmac_md5/hmac_md5.cpp +56 -0
  77. esphome/components/hmac_md5/hmac_md5.h +48 -0
  78. esphome/components/homeassistant/__init__.py +13 -0
  79. esphome/components/homeassistant/switch/__init__.py +15 -2
  80. esphome/components/homeassistant/switch/homeassistant_switch.cpp +2 -2
  81. esphome/components/i2s_audio/__init__.py +88 -9
  82. esphome/components/i2s_audio/i2s_audio.h +20 -2
  83. esphome/components/i2s_audio/media_player/__init__.py +8 -4
  84. esphome/components/i2s_audio/media_player/i2s_audio_media_player.h +1 -1
  85. esphome/components/i2s_audio/microphone/__init__.py +19 -51
  86. esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +18 -15
  87. esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +0 -12
  88. esphome/components/i2s_audio/speaker/__init__.py +39 -27
  89. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +49 -37
  90. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +3 -4
  91. esphome/components/ili9xxx/display.py +16 -17
  92. esphome/components/ili9xxx/ili9xxx_display.cpp +1 -1
  93. esphome/components/ili9xxx/ili9xxx_display.h +18 -18
  94. esphome/components/ili9xxx/ili9xxx_init.h +0 -3
  95. esphome/components/improv_serial/improv_serial_component.cpp +2 -1
  96. esphome/components/improv_serial/improv_serial_component.h +2 -1
  97. esphome/components/ledc/ledc_output.cpp +11 -7
  98. esphome/components/libretiny/__init__.py +8 -13
  99. esphome/components/ltr501/__init__.py +1 -0
  100. esphome/components/ltr501/ltr501.cpp +542 -0
  101. esphome/components/ltr501/ltr501.h +184 -0
  102. esphome/components/ltr501/ltr_definitions_501.h +260 -0
  103. esphome/components/ltr501/sensor.py +274 -0
  104. esphome/components/ltr_als_ps/sensor.py +2 -2
  105. esphome/components/lvgl/__init__.py +19 -16
  106. esphome/components/lvgl/automation.py +90 -9
  107. esphome/components/lvgl/defines.py +29 -2
  108. esphome/components/lvgl/gradient.py +61 -0
  109. esphome/components/lvgl/lv_validation.py +45 -27
  110. esphome/components/lvgl/lvcode.py +8 -3
  111. esphome/components/lvgl/lvgl_esphome.cpp +54 -0
  112. esphome/components/lvgl/lvgl_esphome.h +9 -3
  113. esphome/components/lvgl/number/__init__.py +1 -0
  114. esphome/components/lvgl/number/lvgl_number.h +3 -1
  115. esphome/components/lvgl/schemas.py +16 -11
  116. esphome/components/lvgl/select/__init__.py +1 -0
  117. esphome/components/lvgl/select/lvgl_select.h +3 -1
  118. esphome/components/lvgl/switch/__init__.py +2 -1
  119. esphome/components/lvgl/switch/lvgl_switch.h +3 -1
  120. esphome/components/lvgl/text/__init__.py +1 -0
  121. esphome/components/lvgl/text/lvgl_text.h +3 -1
  122. esphome/components/lvgl/trigger.py +3 -2
  123. esphome/components/lvgl/types.py +2 -1
  124. esphome/components/lvgl/widgets/__init__.py +23 -8
  125. esphome/components/lvgl/widgets/arc.py +5 -1
  126. esphome/components/lvgl/widgets/buttonmatrix.py +5 -1
  127. esphome/components/lvgl/widgets/checkbox.py +8 -3
  128. esphome/components/lvgl/widgets/meter.py +8 -1
  129. esphome/components/lvgl/widgets/msgbox.py +26 -15
  130. esphome/components/lvgl/widgets/page.py +51 -7
  131. esphome/components/lvgl/widgets/tileview.py +2 -8
  132. esphome/components/max31856/max31856.cpp +12 -1
  133. esphome/components/max31856/max31856.h +5 -2
  134. esphome/components/max31856/sensor.py +20 -0
  135. esphome/components/mcp9600/sensor.py +2 -2
  136. esphome/components/mdns/__init__.py +6 -6
  137. esphome/components/media_player/media_player.h +16 -0
  138. esphome/components/micro_wake_word/__init__.py +2 -25
  139. esphome/components/microphone/microphone.h +1 -1
  140. esphome/components/mics_4514/mics_4514.cpp +26 -36
  141. esphome/components/modbus_controller/__init__.py +6 -0
  142. esphome/components/modbus_controller/const.py +2 -0
  143. esphome/components/modbus_controller/modbus_controller.cpp +30 -27
  144. esphome/components/modbus_controller/modbus_controller.h +22 -4
  145. esphome/components/network/__init__.py +11 -8
  146. esphome/components/pipsolar/pipsolar.cpp +3 -0
  147. esphome/components/pipsolar/pipsolar.h +1 -0
  148. esphome/components/pipsolar/switch/__init__.py +2 -0
  149. esphome/components/prometheus/prometheus_handler.cpp +2 -0
  150. esphome/components/prometheus/prometheus_handler.h +3 -1
  151. esphome/components/rp2040/__init__.py +7 -8
  152. esphome/components/rpi_dpi_rgb/display.py +20 -17
  153. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +36 -6
  154. esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.h +4 -0
  155. esphome/components/socket/socket.cpp +2 -0
  156. esphome/components/socket/socket.h +2 -0
  157. esphome/components/speaker/speaker.h +1 -1
  158. esphome/components/st7701s/display.py +35 -37
  159. esphome/components/st7701s/st7701s.cpp +11 -6
  160. esphome/components/st7701s/st7701s.h +1 -0
  161. esphome/components/statsd/__init__.py +65 -0
  162. esphome/components/statsd/statsd.cpp +156 -0
  163. esphome/components/statsd/statsd.h +86 -0
  164. esphome/components/tuya/__init__.py +1 -0
  165. esphome/components/tuya/number/__init__.py +39 -2
  166. esphome/components/tuya/number/tuya_number.cpp +58 -2
  167. esphome/components/tuya/number/tuya_number.h +12 -3
  168. esphome/components/udp/__init__.py +158 -0
  169. esphome/components/udp/binary_sensor.py +27 -0
  170. esphome/components/udp/sensor.py +27 -0
  171. esphome/components/udp/udp_component.cpp +616 -0
  172. esphome/components/udp/udp_component.h +158 -0
  173. esphome/components/uponor_smatrix/uponor_smatrix.cpp +4 -6
  174. esphome/components/uponor_smatrix/uponor_smatrix.h +0 -1
  175. esphome/components/veml7700/sensor.py +2 -2
  176. esphome/components/voice_assistant/__init__.py +6 -0
  177. esphome/components/voice_assistant/voice_assistant.cpp +24 -2
  178. esphome/components/voice_assistant/voice_assistant.h +20 -0
  179. esphome/components/web_server/__init__.py +11 -11
  180. esphome/components/web_server/list_entities.cpp +2 -0
  181. esphome/components/web_server/list_entities.h +3 -1
  182. esphome/components/web_server/web_server.cpp +2 -1
  183. esphome/components/web_server/web_server.h +2 -0
  184. esphome/components/web_server_base/web_server_base.cpp +2 -0
  185. esphome/components/web_server_base/web_server_base.h +3 -1
  186. esphome/components/wifi/wifi_component_libretiny.cpp +15 -1
  187. esphome/components/wireguard/__init__.py +9 -6
  188. esphome/components/wireguard/wireguard.cpp +2 -1
  189. esphome/components/wireguard/wireguard.h +3 -1
  190. esphome/config_validation.py +8 -0
  191. esphome/const.py +8 -1
  192. esphome/core/bytebuffer.cpp +117 -84
  193. esphome/core/bytebuffer.h +69 -21
  194. esphome/core/config.py +0 -3
  195. esphome/core/defines.h +2 -0
  196. esphome/core/ring_buffer.cpp +13 -2
  197. esphome/core/ring_buffer.h +56 -0
  198. esphome/external_files.py +5 -3
  199. {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/METADATA +1 -1
  200. {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/RECORD +204 -169
  201. {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/LICENSE +0 -0
  202. {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/WHEEL +0 -0
  203. {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/entry_points.txt +0 -0
  204. {esphome-2024.8.2.dist-info → esphome-2024.9.0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,8 @@
1
+ from esphome.config_validation import Optional
1
2
  from esphome.const import CONF_TEXT
2
3
 
3
- from ..defines import CONF_INDICATOR, CONF_MAIN
4
- from ..lv_validation import lv_text
4
+ from ..defines import CONF_INDICATOR, CONF_MAIN, CONF_PAD_COLUMN
5
+ from ..lv_validation import lv_text, pixels
5
6
  from ..lvcode import lv
6
7
  from ..schemas import TEXT_SCHEMA
7
8
  from ..types import LvBoolean
@@ -16,7 +17,11 @@ class CheckboxType(WidgetType):
16
17
  CONF_CHECKBOX,
17
18
  LvBoolean("lv_checkbox_t"),
18
19
  (CONF_MAIN, CONF_INDICATOR),
19
- TEXT_SCHEMA,
20
+ TEXT_SCHEMA.extend(
21
+ {
22
+ Optional(CONF_PAD_COLUMN): pixels,
23
+ }
24
+ ),
20
25
  )
21
26
 
22
27
  async def to_code(self, w: Widget, config):
@@ -5,6 +5,7 @@ from esphome.const import (
5
5
  CONF_COLOR,
6
6
  CONF_COUNT,
7
7
  CONF_ID,
8
+ CONF_ITEMS,
8
9
  CONF_LENGTH,
9
10
  CONF_LOCAL,
10
11
  CONF_RANGE_FROM,
@@ -17,6 +18,7 @@ from esphome.const import (
17
18
  from ..automation import action_to_code
18
19
  from ..defines import (
19
20
  CONF_END_VALUE,
21
+ CONF_INDICATOR,
20
22
  CONF_MAIN,
21
23
  CONF_PIVOT_X,
22
24
  CONF_PIVOT_Y,
@@ -165,7 +167,12 @@ METER_SCHEMA = {cv.Optional(CONF_SCALES): cv.ensure_list(SCALE_SCHEMA)}
165
167
 
166
168
  class MeterType(WidgetType):
167
169
  def __init__(self):
168
- super().__init__(CONF_METER, lv_meter_t, (CONF_MAIN,), METER_SCHEMA)
170
+ super().__init__(
171
+ CONF_METER,
172
+ lv_meter_t,
173
+ (CONF_MAIN, CONF_INDICATOR, CONF_TICKS, CONF_ITEMS),
174
+ METER_SCHEMA,
175
+ )
169
176
 
170
177
  async def to_code(self, w: Widget, config):
171
178
  """For a meter object, create and set parameters"""
@@ -1,11 +1,12 @@
1
1
  from esphome import config_validation as cv
2
- from esphome.const import CONF_BUTTON, CONF_ID, CONF_TEXT
2
+ from esphome.const import CONF_BUTTON, CONF_ID, CONF_ITEMS, CONF_TEXT
3
3
  from esphome.core import ID
4
4
  from esphome.cpp_generator import new_Pvariable, static_const_array
5
5
  from esphome.cpp_types import nullptr
6
6
 
7
7
  from ..defines import (
8
8
  CONF_BODY,
9
+ CONF_BUTTON_STYLE,
9
10
  CONF_BUTTONS,
10
11
  CONF_CLOSE_BUTTON,
11
12
  CONF_MSGBOXES,
@@ -25,7 +26,7 @@ from ..lvcode import (
25
26
  lv_obj,
26
27
  lv_Pvariable,
27
28
  )
28
- from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema
29
+ from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema, part_schema
29
30
  from ..styles import TOP_LAYER
30
31
  from ..types import LV_EVENT, char_ptr, lv_obj_t
31
32
  from . import Widget, set_obj_properties
@@ -48,9 +49,10 @@ MSGBOX_SCHEMA = container_schema(
48
49
  {
49
50
  cv.GenerateID(CONF_ID): cv.declare_id(lv_obj_t),
50
51
  cv.Required(CONF_TITLE): STYLED_TEXT_SCHEMA,
51
- cv.Optional(CONF_BODY): STYLED_TEXT_SCHEMA,
52
+ cv.Optional(CONF_BODY, default=""): STYLED_TEXT_SCHEMA,
52
53
  cv.Optional(CONF_BUTTONS): cv.ensure_list(BUTTONMATRIX_BUTTON_SCHEMA),
53
- cv.Optional(CONF_CLOSE_BUTTON): lv_bool,
54
+ cv.Optional(CONF_BUTTON_STYLE): part_schema(buttonmatrix_spec),
55
+ cv.Optional(CONF_CLOSE_BUTTON, default=True): lv_bool,
54
56
  cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr),
55
57
  }
56
58
  ),
@@ -74,7 +76,8 @@ async def msgbox_to_code(conf):
74
76
  )
75
77
  lvgl_components_required.add("BUTTONMATRIX")
76
78
  messagebox_id = conf[CONF_ID]
77
- outer = lv_Pvariable(lv_obj_t, messagebox_id.id)
79
+ outer_id = f"{messagebox_id.id}_outer"
80
+ outer = lv_Pvariable(lv_obj_t, messagebox_id.id + "_outer")
78
81
  buttonmatrix = new_Pvariable(
79
82
  ID(
80
83
  f"{messagebox_id.id}_buttonmatrix_",
@@ -82,8 +85,11 @@ async def msgbox_to_code(conf):
82
85
  type=lv_buttonmatrix_t,
83
86
  )
84
87
  )
85
- msgbox = lv_Pvariable(lv_obj_t, f"{messagebox_id.id}_msgbox")
86
- outer_widget = Widget.create(messagebox_id, outer, obj_spec, conf)
88
+ msgbox = lv_Pvariable(lv_obj_t, messagebox_id.id)
89
+ outer_widget = Widget.create(outer_id, outer, obj_spec, conf)
90
+ outer_widget.move_to_foreground = True
91
+ msgbox_widget = Widget.create(messagebox_id, msgbox, obj_spec, conf)
92
+ msgbox_widget.outer = outer_widget
87
93
  buttonmatrix_widget = Widget.create(
88
94
  str(buttonmatrix), buttonmatrix, buttonmatrix_spec, conf
89
95
  )
@@ -92,10 +98,8 @@ async def msgbox_to_code(conf):
92
98
  )
93
99
  text_id = conf[CONF_BUTTON_TEXT_LIST_ID]
94
100
  text_list = static_const_array(text_id, text_list)
95
- if (text := conf.get(CONF_BODY)) is not None:
96
- text = await lv_text.process(text.get(CONF_TEXT))
97
- if (title := conf.get(CONF_TITLE)) is not None:
98
- title = await lv_text.process(title.get(CONF_TEXT))
101
+ text = await lv_text.process(conf[CONF_BODY].get(CONF_TEXT, ""))
102
+ title = await lv_text.process(conf[CONF_TITLE].get(CONF_TEXT, ""))
99
103
  close_button = conf[CONF_CLOSE_BUTTON]
100
104
  lv_assign(outer, lv_expr.obj_create(TOP_LAYER))
101
105
  lv_obj.set_width(outer, lv_pct(100))
@@ -111,20 +115,27 @@ async def msgbox_to_code(conf):
111
115
  )
112
116
  lv_obj.set_style_align(msgbox, literal("LV_ALIGN_CENTER"), 0)
113
117
  lv_add(buttonmatrix.set_obj(lv_expr.msgbox_get_btns(msgbox)))
114
- await set_obj_properties(outer_widget, conf)
118
+ if button_style := conf.get(CONF_BUTTON_STYLE):
119
+ button_style = {CONF_ITEMS: button_style}
120
+ await set_obj_properties(buttonmatrix_widget, button_style)
121
+ await set_obj_properties(msgbox_widget, conf)
122
+ async with LambdaContext(EVENT_ARG, where=messagebox_id) as close_action:
123
+ outer_widget.add_flag("LV_OBJ_FLAG_HIDDEN")
115
124
  if close_button:
116
- async with LambdaContext(EVENT_ARG, where=messagebox_id) as context:
117
- outer_widget.add_flag("LV_OBJ_FLAG_HIDDEN")
118
125
  with LocalVariable(
119
126
  "close_btn_", lv_obj_t, lv_expr.msgbox_get_close_btn(msgbox)
120
127
  ) as close_btn:
121
128
  lv_obj.remove_event_cb(close_btn, nullptr)
122
129
  lv_obj.add_event_cb(
123
130
  close_btn,
124
- await context.get_lambda(),
131
+ await close_action.get_lambda(),
125
132
  LV_EVENT.CLICKED,
126
133
  nullptr,
127
134
  )
135
+ else:
136
+ lv_obj.add_event_cb(
137
+ outer, await close_action.get_lambda(), LV_EVENT.CLICKED, nullptr
138
+ )
128
139
 
129
140
  if len(ctrl_list) != 0 or len(width_list) != 0:
130
141
  set_btn_data(buttonmatrix.obj, ctrl_list, width_list)
@@ -1,6 +1,7 @@
1
1
  from esphome import automation, codegen as cg
2
+ from esphome.automation import Trigger
2
3
  import esphome.config_validation as cv
3
- from esphome.const import CONF_ID, CONF_PAGES, CONF_TIME
4
+ from esphome.const import CONF_ID, CONF_PAGES, CONF_TIME, CONF_TRIGGER_ID
4
5
 
5
6
  from ..defines import (
6
7
  CONF_ANIMATION,
@@ -9,12 +10,39 @@ from ..defines import (
9
10
  CONF_PAGE_WRAP,
10
11
  CONF_SKIP,
11
12
  LV_ANIM,
13
+ literal,
12
14
  )
13
15
  from ..lv_validation import lv_bool, lv_milliseconds
14
- from ..lvcode import LVGL_COMP_ARG, LambdaContext, add_line_marks, lv_add, lvgl_comp
16
+ from ..lvcode import (
17
+ EVENT_ARG,
18
+ LVGL_COMP_ARG,
19
+ LambdaContext,
20
+ add_line_marks,
21
+ lv_add,
22
+ lvgl_comp,
23
+ )
15
24
  from ..schemas import LVGL_SCHEMA
16
25
  from ..types import LvglAction, lv_page_t
17
- from . import Widget, WidgetType, add_widgets, set_obj_properties
26
+ from . import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties
27
+
28
+ CONF_ON_LOAD = "on_load"
29
+ CONF_ON_UNLOAD = "on_unload"
30
+
31
+ PAGE_SCHEMA = cv.Schema(
32
+ {
33
+ cv.Optional(CONF_SKIP, default=False): lv_bool,
34
+ cv.Optional(CONF_ON_LOAD): automation.validate_automation(
35
+ {
36
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger.template()),
37
+ }
38
+ ),
39
+ cv.Optional(CONF_ON_UNLOAD): automation.validate_automation(
40
+ {
41
+ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger.template()),
42
+ }
43
+ ),
44
+ }
45
+ )
18
46
 
19
47
 
20
48
  class PageType(WidgetType):
@@ -23,9 +51,8 @@ class PageType(WidgetType):
23
51
  CONF_PAGE,
24
52
  lv_page_t,
25
53
  (),
26
- {
27
- cv.Optional(CONF_SKIP, default=False): lv_bool,
28
- },
54
+ PAGE_SCHEMA,
55
+ modify_schema={},
29
56
  )
30
57
 
31
58
  async def to_code(self, w: Widget, config: dict):
@@ -39,7 +66,6 @@ SHOW_SCHEMA = LVGL_SCHEMA.extend(
39
66
  }
40
67
  )
41
68
 
42
-
43
69
  page_spec = PageType()
44
70
 
45
71
 
@@ -111,3 +137,21 @@ async def add_pages(lv_component, config):
111
137
  await set_obj_properties(page, config)
112
138
  await set_obj_properties(page, pconf)
113
139
  await add_widgets(page, pconf)
140
+
141
+
142
+ async def generate_page_triggers(lv_component, config):
143
+ for pconf in config.get(CONF_PAGES, ()):
144
+ page = (await get_widgets(pconf))[0]
145
+ for ev in (CONF_ON_LOAD, CONF_ON_UNLOAD):
146
+ for loaded in pconf.get(ev, ()):
147
+ trigger = cg.new_Pvariable(loaded[CONF_TRIGGER_ID])
148
+ await automation.build_automation(trigger, [], loaded)
149
+ async with LambdaContext(EVENT_ARG, where=id) as context:
150
+ lv_add(trigger.trigger())
151
+ lv_add(
152
+ lv_component.add_event_cb(
153
+ page.obj,
154
+ await context.get_lambda(),
155
+ literal(f"LV_EVENT_SCREEN_{ev[3:].upper()}_START"),
156
+ )
157
+ )
@@ -1,7 +1,7 @@
1
1
  from esphome import automation
2
2
  import esphome.codegen as cg
3
3
  import esphome.config_validation as cv
4
- from esphome.const import CONF_ID, CONF_ON_VALUE, CONF_ROW, CONF_TRIGGER_ID
4
+ from esphome.const import CONF_ID, CONF_ROW
5
5
 
6
6
  from ..automation import action_to_code
7
7
  from ..defines import (
@@ -29,6 +29,7 @@ lv_tileview_t = LvType(
29
29
  "lv_tileview_t",
30
30
  largs=[(lv_obj_t_ptr, "tile")],
31
31
  lvalue=lambda w: w.get_property("tile_act"),
32
+ has_on_value=True,
32
33
  )
33
34
 
34
35
  tile_spec = WidgetType("lv_tileview_tile_t", lv_tile_t, (CONF_MAIN,), {})
@@ -46,13 +47,6 @@ TILEVIEW_SCHEMA = cv.Schema(
46
47
  },
47
48
  )
48
49
  ),
49
- cv.Optional(CONF_ON_VALUE): automation.validate_automation(
50
- {
51
- cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
52
- automation.Trigger.template(lv_obj_t_ptr)
53
- )
54
- }
55
- ),
56
50
  }
57
51
  )
58
52
 
@@ -32,6 +32,12 @@ void MAX31856Sensor::dump_config() {
32
32
  LOG_PIN(" CS Pin: ", this->cs_);
33
33
  ESP_LOGCONFIG(TAG, " Mains Filter: %s",
34
34
  (filter_ == FILTER_60HZ ? "60 Hz" : (filter_ == FILTER_50HZ ? "50 Hz" : "Unknown!")));
35
+ if (this->thermocouple_type_ < 0 || this->thermocouple_type_ > 7) {
36
+ ESP_LOGCONFIG(TAG, " Thermocouple Type: Unknown");
37
+ } else {
38
+ ESP_LOGCONFIG(TAG, " Thermocouple Type: %c", "BEJKNRST"[this->thermocouple_type_]);
39
+ }
40
+
35
41
  LOG_UPDATE_INTERVAL(this);
36
42
  }
37
43
 
@@ -129,7 +135,12 @@ void MAX31856Sensor::clear_fault_() {
129
135
  }
130
136
 
131
137
  void MAX31856Sensor::set_thermocouple_type_() {
132
- MAX31856ThermocoupleType type = MAX31856_TCTYPE_K;
138
+ MAX31856ThermocoupleType type;
139
+ if (this->thermocouple_type_ < 0 || this->thermocouple_type_ > 7) {
140
+ type = MAX31856_TCTYPE_K;
141
+ } else {
142
+ type = this->thermocouple_type_;
143
+ }
133
144
  ESP_LOGCONFIG(TAG, "set_thermocouple_type_: 0x%02X", type);
134
145
  uint8_t t = this->read_register_(MAX31856_CR1_REG);
135
146
  t &= 0xF0; // mask off bottom 4 bits
@@ -50,7 +50,6 @@ enum MAX31856Registers {
50
50
 
51
51
  /**
52
52
  * Multiple types of thermocouples supported by the chip.
53
- * Currently only K type implemented here.
54
53
  */
55
54
  enum MAX31856ThermocoupleType {
56
55
  MAX31856_TCTYPE_B = 0b0000, // 0x00
@@ -78,11 +77,15 @@ class MAX31856Sensor : public sensor::Sensor,
78
77
  void setup() override;
79
78
  void dump_config() override;
80
79
  float get_setup_priority() const override;
81
- void set_filter(MAX31856ConfigFilter filter) { filter_ = filter; }
80
+ void set_filter(MAX31856ConfigFilter filter) { this->filter_ = filter; }
81
+ void set_thermocouple_type(MAX31856ThermocoupleType thermocouple_type) {
82
+ this->thermocouple_type_ = thermocouple_type;
83
+ }
82
84
  void update() override;
83
85
 
84
86
  protected:
85
87
  MAX31856ConfigFilter filter_;
88
+ MAX31856ThermocoupleType thermocouple_type_;
86
89
 
87
90
  uint8_t read_register_(uint8_t reg);
88
91
  uint32_t read_register24_(uint8_t reg);
@@ -3,6 +3,7 @@ from esphome.components import sensor, spi
3
3
  import esphome.config_validation as cv
4
4
  from esphome.const import (
5
5
  CONF_MAINS_FILTER,
6
+ CONF_THERMOCOUPLE_TYPE,
6
7
  DEVICE_CLASS_TEMPERATURE,
7
8
  STATE_CLASS_MEASUREMENT,
8
9
  UNIT_CELSIUS,
@@ -18,6 +19,17 @@ FILTER = {
18
19
  50: MAX31865ConfigFilter.FILTER_50HZ,
19
20
  60: MAX31865ConfigFilter.FILTER_60HZ,
20
21
  }
22
+ MAX31856ThermocoupleType = max31856_ns.enum("MAX31856ThermocoupleType")
23
+ THERMOCOUPLE_TYPE = {
24
+ "B": MAX31856ThermocoupleType.MAX31856_TCTYPE_B,
25
+ "E": MAX31856ThermocoupleType.MAX31856_TCTYPE_E,
26
+ "J": MAX31856ThermocoupleType.MAX31856_TCTYPE_J,
27
+ "K": MAX31856ThermocoupleType.MAX31856_TCTYPE_K,
28
+ "N": MAX31856ThermocoupleType.MAX31856_TCTYPE_N,
29
+ "R": MAX31856ThermocoupleType.MAX31856_TCTYPE_R,
30
+ "S": MAX31856ThermocoupleType.MAX31856_TCTYPE_S,
31
+ "T": MAX31856ThermocoupleType.MAX31856_TCTYPE_T,
32
+ }
21
33
 
22
34
  CONFIG_SCHEMA = (
23
35
  sensor.sensor_schema(
@@ -34,6 +46,13 @@ CONFIG_SCHEMA = (
34
46
  ),
35
47
  }
36
48
  )
49
+ .extend(
50
+ {
51
+ cv.Optional(CONF_THERMOCOUPLE_TYPE, default="K"): cv.enum(
52
+ THERMOCOUPLE_TYPE, upper=True, space=""
53
+ ),
54
+ }
55
+ )
37
56
  .extend(cv.polling_component_schema("60s"))
38
57
  .extend(spi.spi_device_schema())
39
58
  )
@@ -44,3 +63,4 @@ async def to_code(config):
44
63
  await cg.register_component(var, config)
45
64
  await spi.register_spi_device(var, config)
46
65
  cg.add(var.set_filter(config[CONF_MAINS_FILTER]))
66
+ cg.add(var.set_thermocouple_type(config[CONF_THERMOCOUPLE_TYPE]))
@@ -1,14 +1,14 @@
1
1
  import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
2
  from esphome.components import i2c, sensor
3
+ import esphome.config_validation as cv
4
4
  from esphome.const import (
5
5
  CONF_ID,
6
+ CONF_THERMOCOUPLE_TYPE,
6
7
  DEVICE_CLASS_TEMPERATURE,
7
8
  STATE_CLASS_MEASUREMENT,
8
9
  UNIT_CELSIUS,
9
10
  )
10
11
 
11
- CONF_THERMOCOUPLE_TYPE = "thermocouple_type"
12
12
  CONF_HOT_JUNCTION = "hot_junction"
13
13
  CONF_COLD_JUNCTION = "cold_junction"
14
14
 
@@ -1,17 +1,17 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components.esp32 import add_idf_component
3
+ import esphome.config_validation as cv
1
4
  from esphome.const import (
5
+ CONF_DISABLED,
2
6
  CONF_ID,
3
7
  CONF_PORT,
4
8
  CONF_PROTOCOL,
5
- CONF_SERVICES,
6
9
  CONF_SERVICE,
10
+ CONF_SERVICES,
7
11
  KEY_CORE,
8
12
  KEY_FRAMEWORK_VERSION,
9
- CONF_DISABLED,
10
13
  )
11
- import esphome.codegen as cg
12
- import esphome.config_validation as cv
13
14
  from esphome.core import CORE, coroutine_with_priority
14
- from esphome.components.esp32 import add_idf_component
15
15
 
16
16
  CODEOWNERS = ["@esphome/core"]
17
17
  DEPENDENCIES = ["network"]
@@ -91,7 +91,7 @@ async def to_code(config):
91
91
  add_idf_component(
92
92
  name="mdns",
93
93
  repo="https://github.com/espressif/esp-protocols.git",
94
- ref="mdns-v1.2.5",
94
+ ref="mdns-v1.3.2",
95
95
  path="components/mdns",
96
96
  )
97
97
 
@@ -27,6 +27,19 @@ enum MediaPlayerCommand : uint8_t {
27
27
  };
28
28
  const char *media_player_command_to_string(MediaPlayerCommand command);
29
29
 
30
+ enum class MediaPlayerFormatPurpose : uint8_t {
31
+ PURPOSE_DEFAULT = 0,
32
+ PURPOSE_ANNOUNCEMENT = 1,
33
+ };
34
+
35
+ struct MediaPlayerSupportedFormat {
36
+ std::string format;
37
+ uint32_t sample_rate;
38
+ uint32_t num_channels;
39
+ MediaPlayerFormatPurpose purpose;
40
+ uint32_t sample_bytes;
41
+ };
42
+
30
43
  class MediaPlayer;
31
44
 
32
45
  class MediaPlayerTraits {
@@ -37,8 +50,11 @@ class MediaPlayerTraits {
37
50
 
38
51
  bool get_supports_pause() const { return this->supports_pause_; }
39
52
 
53
+ std::vector<MediaPlayerSupportedFormat> &get_supported_formats() { return this->supported_formats_; }
54
+
40
55
  protected:
41
56
  bool supports_pause_{false};
57
+ std::vector<MediaPlayerSupportedFormat> supported_formats_{};
42
58
  };
43
59
 
44
60
  class MediaPlayerCall {
@@ -4,8 +4,6 @@ import logging
4
4
  from pathlib import Path
5
5
  from urllib.parse import urljoin
6
6
 
7
- import requests
8
-
9
7
  from esphome import automation, external_files, git
10
8
  from esphome.automation import register_action, register_condition
11
9
  import esphome.codegen as cg
@@ -26,7 +24,6 @@ from esphome.const import (
26
24
  CONF_USERNAME,
27
25
  TYPE_GIT,
28
26
  TYPE_LOCAL,
29
- __version__,
30
27
  )
31
28
  from esphome.core import CORE, HexInt
32
29
 
@@ -179,26 +176,6 @@ def _convert_manifest_v1_to_v2(v1_manifest):
179
176
  return v2_manifest
180
177
 
181
178
 
182
- def _download_file(url: str, path: Path) -> bytes:
183
- if not external_files.has_remote_file_changed(url, path):
184
- _LOGGER.debug("Remote file has not changed, skipping download")
185
- return path.read_bytes()
186
-
187
- try:
188
- req = requests.get(
189
- url,
190
- timeout=external_files.NETWORK_TIMEOUT,
191
- headers={"User-agent": f"ESPHome/{__version__} (https://esphome.io)"},
192
- )
193
- req.raise_for_status()
194
- except requests.exceptions.RequestException as e:
195
- raise cv.Invalid(f"Could not download file from {url}: {e}") from e
196
-
197
- path.parent.mkdir(parents=True, exist_ok=True)
198
- path.write_bytes(req.content)
199
- return req.content
200
-
201
-
202
179
  def _validate_manifest_version(manifest_data):
203
180
  if manifest_version := manifest_data.get(KEY_VERSION):
204
181
  if manifest_version == 1:
@@ -223,7 +200,7 @@ def _process_http_source(config):
223
200
 
224
201
  json_path = path / "manifest.json"
225
202
 
226
- json_contents = _download_file(url, json_path)
203
+ json_contents = external_files.download_content(url, json_path)
227
204
 
228
205
  manifest_data = json.loads(json_contents)
229
206
  if not isinstance(manifest_data, dict):
@@ -234,7 +211,7 @@ def _process_http_source(config):
234
211
 
235
212
  model_path = path / model
236
213
 
237
- _download_file(str(model_url), model_path)
214
+ external_files.download_content(str(model_url), model_path)
238
215
 
239
216
  return config
240
217
 
@@ -1,6 +1,6 @@
1
1
  #pragma once
2
2
 
3
- #include <stddef.h>
3
+ #include <cstddef>
4
4
  #include <cstdint>
5
5
  #include <functional>
6
6
  #include <vector>
@@ -70,72 +70,62 @@ void MICS4514Component::update() {
70
70
 
71
71
  if (this->carbon_monoxide_sensor_ != nullptr) {
72
72
  float co = 0.0f;
73
- if (red_f <= 0.425f) {
74
- co = (0.425f - red_f) / 0.000405f;
75
- if (co < 1.0f)
76
- co = 0.0f;
77
- if (co > 1000.0f)
78
- co = 1000.0f;
73
+ if (red_f > 3.4f) {
74
+ co = 0.0;
75
+ } else if (red_f < 0.01) {
76
+ co = 1000.0;
77
+ } else {
78
+ co = 4.2 / pow(red_f, 1.2);
79
79
  }
80
80
  this->carbon_monoxide_sensor_->publish_state(co);
81
81
  }
82
82
 
83
83
  if (this->nitrogen_dioxide_sensor_ != nullptr) {
84
84
  float nitrogendioxide = 0.0f;
85
- if (ox_f >= 1.1f) {
86
- nitrogendioxide = (ox_f - 0.045f) / 6.13f;
87
- if (nitrogendioxide < 0.1f)
88
- nitrogendioxide = 0.0f;
89
- if (nitrogendioxide > 10.0f)
90
- nitrogendioxide = 10.0f;
85
+ if (ox_f < 0.3f) {
86
+ nitrogendioxide = 0.0;
87
+ } else {
88
+ nitrogendioxide = 0.164 * pow(ox_f, 0.975);
91
89
  }
92
90
  this->nitrogen_dioxide_sensor_->publish_state(nitrogendioxide);
93
91
  }
94
92
 
95
93
  if (this->methane_sensor_ != nullptr) {
96
94
  float methane = 0.0f;
97
- if (red_f <= 0.786f) {
98
- methane = (0.786f - red_f) / 0.000023f;
99
- if (methane < 1000.0f)
100
- methane = 0.0f;
101
- if (methane > 25000.0f)
102
- methane = 25000.0f;
95
+ if (red_f > 0.9f || red_f < 0.5) { // outside the range->unlikely
96
+ methane = 0.0;
97
+ } else {
98
+ methane = 630 / pow(red_f, 4.4);
103
99
  }
104
100
  this->methane_sensor_->publish_state(methane);
105
101
  }
106
102
 
107
103
  if (this->ethanol_sensor_ != nullptr) {
108
104
  float ethanol = 0.0f;
109
- if (red_f <= 0.306f) {
110
- ethanol = (0.306f - red_f) / 0.00057f;
111
- if (ethanol < 10.0f)
112
- ethanol = 0.0f;
113
- if (ethanol > 500.0f)
114
- ethanol = 500.0f;
105
+ if (red_f > 1.0f || red_f < 0.02) { // outside the range->unlikely
106
+ ethanol = 0.0;
107
+ } else {
108
+ ethanol = 1.52 / pow(red_f, 1.55);
115
109
  }
116
110
  this->ethanol_sensor_->publish_state(ethanol);
117
111
  }
118
112
 
119
113
  if (this->hydrogen_sensor_ != nullptr) {
120
114
  float hydrogen = 0.0f;
121
- if (red_f <= 0.279f) {
122
- hydrogen = (0.279f - red_f) / 0.00026f;
123
- if (hydrogen < 1.0f)
124
- hydrogen = 0.0f;
125
- if (hydrogen > 1000.0f)
126
- hydrogen = 1000.0f;
115
+ if (red_f > 0.9f || red_f < 0.02) { // outside the range->unlikely
116
+ hydrogen = 0.0;
117
+ } else {
118
+ hydrogen = 0.85 / pow(red_f, 1.75);
127
119
  }
128
120
  this->hydrogen_sensor_->publish_state(hydrogen);
129
121
  }
130
122
 
131
123
  if (this->ammonia_sensor_ != nullptr) {
132
124
  float ammonia = 0.0f;
133
- if (red_f <= 0.8f) {
134
- ammonia = (0.8f - red_f) / 0.0015f;
135
- if (ammonia < 1.0f)
136
- ammonia = 0.0f;
137
- if (ammonia > 500.0f)
138
- ammonia = 500.0f;
125
+ if (red_f > 0.98f || red_f < 0.2532) { // outside the ammonia range->unlikely
126
+ ammonia = 0.0;
127
+ } else {
128
+ ammonia = 0.9 / pow(red_f, 4.6);
139
129
  }
140
130
  this->ammonia_sensor_->publish_state(ammonia);
141
131
  }
@@ -13,6 +13,7 @@ from esphome.const import (
13
13
  )
14
14
  from esphome.cpp_helpers import logging
15
15
  from .const import (
16
+ CONF_ALLOW_DUPLICATE_COMMANDS,
16
17
  CONF_BITMASK,
17
18
  CONF_BYTE_OFFSET,
18
19
  CONF_COMMAND_THROTTLE,
@@ -20,6 +21,7 @@ from .const import (
20
21
  CONF_CUSTOM_COMMAND,
21
22
  CONF_FORCE_NEW_RANGE,
22
23
  CONF_MODBUS_CONTROLLER_ID,
24
+ CONF_MAX_CMD_RETRIES,
23
25
  CONF_ON_COMMAND_SENT,
24
26
  CONF_REGISTER_COUNT,
25
27
  CONF_REGISTER_TYPE,
@@ -126,9 +128,11 @@ CONFIG_SCHEMA = cv.All(
126
128
  cv.Schema(
127
129
  {
128
130
  cv.GenerateID(): cv.declare_id(ModbusController),
131
+ cv.Optional(CONF_ALLOW_DUPLICATE_COMMANDS, default=False): cv.boolean,
129
132
  cv.Optional(
130
133
  CONF_COMMAND_THROTTLE, default="0ms"
131
134
  ): cv.positive_time_period_milliseconds,
135
+ cv.Optional(CONF_MAX_CMD_RETRIES, default=4): cv.positive_int,
132
136
  cv.Optional(CONF_OFFLINE_SKIP_UPDATES, default=0): cv.positive_int,
133
137
  cv.Optional(
134
138
  CONF_SERVER_REGISTERS,
@@ -253,7 +257,9 @@ async def add_modbus_base_properties(
253
257
 
254
258
  async def to_code(config):
255
259
  var = cg.new_Pvariable(config[CONF_ID])
260
+ cg.add(var.set_allow_duplicate_commands(config[CONF_ALLOW_DUPLICATE_COMMANDS]))
256
261
  cg.add(var.set_command_throttle(config[CONF_COMMAND_THROTTLE]))
262
+ cg.add(var.set_max_cmd_retries(config[CONF_MAX_CMD_RETRIES]))
257
263
  cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES]))
258
264
  if CONF_SERVER_REGISTERS in config:
259
265
  for server_register in config[CONF_SERVER_REGISTERS]:
@@ -1,9 +1,11 @@
1
+ CONF_ALLOW_DUPLICATE_COMMANDS = "allow_duplicate_commands"
1
2
  CONF_BITMASK = "bitmask"
2
3
  CONF_BYTE_OFFSET = "byte_offset"
3
4
  CONF_COMMAND_THROTTLE = "command_throttle"
4
5
  CONF_OFFLINE_SKIP_UPDATES = "offline_skip_updates"
5
6
  CONF_CUSTOM_COMMAND = "custom_command"
6
7
  CONF_FORCE_NEW_RANGE = "force_new_range"
8
+ CONF_MAX_CMD_RETRIES = "max_cmd_retries"
7
9
  CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id"
8
10
  CONF_MODBUS_FUNCTIONCODE = "modbus_functioncode"
9
11
  CONF_ON_COMMAND_SENT = "on_command_sent"