esphome 2025.2.2__py3-none-any.whl → 2025.3.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 (148) hide show
  1. esphome/__main__.py +9 -1
  2. esphome/components/api/api_connection.cpp +426 -70
  3. esphome/components/api/api_connection.h +117 -25
  4. esphome/components/api/api_pb2.cpp +33 -0
  5. esphome/components/api/api_pb2.h +4 -0
  6. esphome/components/api/api_server.cpp +2 -2
  7. esphome/components/api/list_entities.cpp +76 -22
  8. esphome/components/api/list_entities.h +1 -0
  9. esphome/components/api/subscribe_state.h +2 -0
  10. esphome/components/audio/__init__.py +1 -1
  11. esphome/components/audio/audio_decoder.cpp +43 -11
  12. esphome/components/audio/audio_reader.cpp +2 -2
  13. esphome/components/audio/audio_resampler.cpp +4 -2
  14. esphome/components/audio/audio_transfer_buffer.cpp +19 -9
  15. esphome/components/audio/audio_transfer_buffer.h +7 -2
  16. esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -0
  17. esphome/components/bmp085/bmp085.cpp +1 -1
  18. esphome/components/chsc6x/__init__.py +2 -0
  19. esphome/components/chsc6x/chsc6x_touchscreen.cpp +47 -0
  20. esphome/components/chsc6x/chsc6x_touchscreen.h +34 -0
  21. esphome/components/chsc6x/touchscreen.py +33 -0
  22. esphome/components/climate/__init__.py +0 -1
  23. esphome/components/cst816/binary_sensor/__init__.py +2 -25
  24. esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +3 -14
  25. esphome/components/cst816/touchscreen/cst816_touchscreen.h +0 -4
  26. esphome/components/esp32_ble_beacon/__init__.py +3 -1
  27. esphome/components/esp8266/gpio.py +1 -2
  28. esphome/components/font/__init__.py +198 -215
  29. esphome/components/font/font.cpp +4 -4
  30. esphome/components/font/font.h +1 -0
  31. esphome/components/graph/graph.cpp +4 -0
  32. esphome/components/graph/graph.h +4 -0
  33. esphome/components/haier/climate.py +11 -10
  34. esphome/components/hbridge/switch/hbridge_switch.cpp +2 -2
  35. esphome/components/heatpumpir/climate.py +2 -1
  36. esphome/components/heatpumpir/heatpumpir.cpp +1 -0
  37. esphome/components/heatpumpir/heatpumpir.h +1 -0
  38. esphome/components/i2c/__init__.py +6 -6
  39. esphome/components/i2c/i2c_bus_esp_idf.cpp +6 -2
  40. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  41. esphome/components/ili9xxx/display.py +1 -0
  42. esphome/components/ili9xxx/ili9xxx_display.h +5 -0
  43. esphome/components/ili9xxx/ili9xxx_init.h +59 -0
  44. esphome/components/ld2450/__init__.py +51 -0
  45. esphome/components/ld2450/binary_sensor.py +47 -0
  46. esphome/components/ld2450/button/__init__.py +45 -0
  47. esphome/components/ld2450/button/reset_button.cpp +9 -0
  48. esphome/components/ld2450/button/reset_button.h +18 -0
  49. esphome/components/ld2450/button/restart_button.cpp +9 -0
  50. esphome/components/ld2450/button/restart_button.h +18 -0
  51. esphome/components/ld2450/ld2450.cpp +876 -0
  52. esphome/components/ld2450/ld2450.h +234 -0
  53. esphome/components/ld2450/number/__init__.py +121 -0
  54. esphome/components/ld2450/number/presence_timeout_number.cpp +12 -0
  55. esphome/components/ld2450/number/presence_timeout_number.h +18 -0
  56. esphome/components/ld2450/number/zone_coordinate_number.cpp +14 -0
  57. esphome/components/ld2450/number/zone_coordinate_number.h +19 -0
  58. esphome/components/ld2450/select/__init__.py +56 -0
  59. esphome/components/ld2450/select/baud_rate_select.cpp +12 -0
  60. esphome/components/ld2450/select/baud_rate_select.h +18 -0
  61. esphome/components/ld2450/select/zone_type_select.cpp +12 -0
  62. esphome/components/ld2450/select/zone_type_select.h +18 -0
  63. esphome/components/ld2450/sensor.py +156 -0
  64. esphome/components/ld2450/switch/__init__.py +45 -0
  65. esphome/components/ld2450/switch/bluetooth_switch.cpp +12 -0
  66. esphome/components/ld2450/switch/bluetooth_switch.h +18 -0
  67. esphome/components/ld2450/switch/multi_target_switch.cpp +12 -0
  68. esphome/components/ld2450/switch/multi_target_switch.h +18 -0
  69. esphome/components/ld2450/text_sensor.py +62 -0
  70. esphome/components/lvgl/defines.py +0 -2
  71. esphome/components/lvgl/font.cpp +1 -1
  72. esphome/components/lvgl/lvgl_esphome.cpp +27 -19
  73. esphome/components/lvgl/widgets/img.py +1 -3
  74. esphome/components/mcp2515/mcp2515.cpp +1 -0
  75. esphome/components/mdns/__init__.py +1 -1
  76. esphome/components/mixer/speaker/mixer_speaker.cpp +6 -1
  77. esphome/components/mixer/speaker/mixer_speaker.h +2 -0
  78. esphome/components/mlx90393/sensor.py +53 -33
  79. esphome/components/mlx90393/sensor_mlx90393.cpp +4 -0
  80. esphome/components/mlx90393/sensor_mlx90393.h +8 -3
  81. esphome/components/mqtt/__init__.py +2 -2
  82. esphome/components/msa3xx/__init__.py +189 -0
  83. esphome/components/msa3xx/binary_sensor.py +40 -0
  84. esphome/components/msa3xx/msa3xx.cpp +417 -0
  85. esphome/components/msa3xx/msa3xx.h +311 -0
  86. esphome/components/msa3xx/sensor.py +42 -0
  87. esphome/components/msa3xx/text_sensor.py +38 -0
  88. esphome/components/nfc/binary_sensor/__init__.py +4 -4
  89. esphome/components/opentherm/binary_sensor/__init__.py +4 -4
  90. esphome/components/opentherm/generate.py +6 -6
  91. esphome/components/opentherm/sensor/__init__.py +5 -6
  92. esphome/components/packages/__init__.py +35 -11
  93. esphome/components/pn532/binary_sensor.py +4 -4
  94. esphome/components/rc522/binary_sensor.py +4 -4
  95. esphome/components/resampler/speaker/resampler_speaker.h +2 -0
  96. esphome/components/socket/bsd_sockets_impl.cpp +1 -0
  97. esphome/components/socket/lwip_sockets_impl.cpp +1 -0
  98. esphome/components/socket/socket.h +3 -1
  99. esphome/components/speaker/speaker.h +2 -2
  100. esphome/components/ssd1306_base/__init__.py +7 -7
  101. esphome/components/thermostat/climate.py +1 -1
  102. esphome/components/tmp1075/tmp1075.cpp +7 -11
  103. esphome/components/tmp1075/tmp1075.h +1 -2
  104. esphome/components/tormatic/__init__.py +1 -0
  105. esphome/components/tormatic/cover.py +47 -0
  106. esphome/components/tormatic/tormatic_cover.cpp +355 -0
  107. esphome/components/tormatic/tormatic_cover.h +60 -0
  108. esphome/components/tormatic/tormatic_protocol.h +211 -0
  109. esphome/components/touchscreen/binary_sensor/__init__.py +3 -0
  110. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp +7 -1
  111. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h +3 -1
  112. esphome/components/touchscreen/touchscreen.cpp +3 -4
  113. esphome/components/udp/udp_component.h +4 -1
  114. esphome/components/web_server/list_entities.cpp +70 -66
  115. esphome/components/web_server/list_entities.h +43 -22
  116. esphome/components/web_server/web_server.cpp +345 -68
  117. esphome/components/web_server/web_server.h +138 -6
  118. esphome/components/web_server_base/__init__.py +1 -1
  119. esphome/components/web_server_idf/__init__.py +2 -0
  120. esphome/components/web_server_idf/web_server_idf.cpp +177 -30
  121. esphome/components/web_server_idf/web_server_idf.h +53 -4
  122. esphome/config_validation.py +23 -125
  123. esphome/const.py +5 -1
  124. esphome/core/config.py +15 -6
  125. esphome/core/defines.h +1 -1
  126. esphome/core/helpers.h +24 -3
  127. esphome/core/time.cpp +1 -0
  128. esphome/cpp_generator.py +3 -3
  129. esphome/dashboard/core.py +30 -21
  130. esphome/dashboard/dns.py +7 -1
  131. esphome/dashboard/entries.py +83 -16
  132. esphome/dashboard/settings.py +0 -4
  133. esphome/dashboard/status/mdns.py +43 -14
  134. esphome/dashboard/status/mqtt.py +22 -9
  135. esphome/dashboard/status/ping.py +54 -10
  136. esphome/dashboard/web_server.py +56 -24
  137. esphome/storage_json.py +4 -0
  138. esphome/wizard.py +13 -17
  139. esphome/writer.py +1 -3
  140. esphome/yaml_util.py +36 -33
  141. esphome/zeroconf.py +9 -21
  142. {esphome-2025.2.2.dist-info → esphome-2025.3.0.dist-info}/METADATA +7 -7
  143. {esphome-2025.2.2.dist-info → esphome-2025.3.0.dist-info}/RECORD +147 -107
  144. esphome/components/cst816/binary_sensor/cst816_button.h +0 -27
  145. {esphome-2025.2.2.dist-info → esphome-2025.3.0.dist-info}/LICENSE +0 -0
  146. {esphome-2025.2.2.dist-info → esphome-2025.3.0.dist-info}/WHEEL +0 -0
  147. {esphome-2025.2.2.dist-info → esphome-2025.3.0.dist-info}/entry_points.txt +0 -0
  148. {esphome-2025.2.2.dist-info → esphome-2025.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,156 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import sensor
3
+ import esphome.config_validation as cv
4
+ from esphome.const import (
5
+ CONF_ANGLE,
6
+ CONF_DISTANCE,
7
+ CONF_RESOLUTION,
8
+ CONF_SPEED,
9
+ DEVICE_CLASS_DISTANCE,
10
+ DEVICE_CLASS_SPEED,
11
+ UNIT_DEGREES,
12
+ UNIT_MILLIMETER,
13
+ )
14
+
15
+ from . import CONF_LD2450_ID, LD2450Component
16
+
17
+ DEPENDENCIES = ["ld2450"]
18
+
19
+ CONF_MOVING_TARGET_COUNT = "moving_target_count"
20
+ CONF_STILL_TARGET_COUNT = "still_target_count"
21
+ CONF_TARGET_COUNT = "target_count"
22
+ CONF_X = "x"
23
+ CONF_Y = "y"
24
+
25
+ ICON_ACCOUNT_GROUP = "mdi:account-group"
26
+ ICON_ACCOUNT_SWITCH = "mdi:account-switch"
27
+ ICON_ALPHA_X_BOX_OUTLINE = "mdi:alpha-x-box-outline"
28
+ ICON_ALPHA_Y_BOX_OUTLINE = "mdi:alpha-y-box-outline"
29
+ ICON_FORMAT_TEXT_ROTATION_ANGLE_UP = "mdi:format-text-rotation-angle-up"
30
+ ICON_HUMAN_GREETING_PROXIMITY = "mdi:human-greeting-proximity"
31
+ ICON_MAP_MARKER_ACCOUNT = "mdi:map-marker-account"
32
+ ICON_MAP_MARKER_DISTANCE = "mdi:map-marker-distance"
33
+ ICON_RELATION_ZERO_OR_ONE_TO_ZERO_OR_ONE = "mdi:relation-zero-or-one-to-zero-or-one"
34
+ ICON_SPEEDOMETER_SLOW = "mdi:speedometer-slow"
35
+
36
+ MAX_TARGETS = 3
37
+ MAX_ZONES = 3
38
+
39
+ UNIT_MILLIMETER_PER_SECOND = "mm/s"
40
+
41
+ CONFIG_SCHEMA = cv.Schema(
42
+ {
43
+ cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component),
44
+ cv.Optional(CONF_TARGET_COUNT): sensor.sensor_schema(
45
+ icon=ICON_ACCOUNT_GROUP,
46
+ ),
47
+ cv.Optional(CONF_STILL_TARGET_COUNT): sensor.sensor_schema(
48
+ icon=ICON_HUMAN_GREETING_PROXIMITY,
49
+ ),
50
+ cv.Optional(CONF_MOVING_TARGET_COUNT): sensor.sensor_schema(
51
+ icon=ICON_ACCOUNT_SWITCH,
52
+ ),
53
+ }
54
+ )
55
+
56
+ CONFIG_SCHEMA = CONFIG_SCHEMA.extend(
57
+ {
58
+ cv.Optional(f"target_{n + 1}"): cv.Schema(
59
+ {
60
+ cv.Optional(CONF_X): sensor.sensor_schema(
61
+ device_class=DEVICE_CLASS_DISTANCE,
62
+ unit_of_measurement=UNIT_MILLIMETER,
63
+ icon=ICON_ALPHA_X_BOX_OUTLINE,
64
+ ),
65
+ cv.Optional(CONF_Y): sensor.sensor_schema(
66
+ device_class=DEVICE_CLASS_DISTANCE,
67
+ unit_of_measurement=UNIT_MILLIMETER,
68
+ icon=ICON_ALPHA_Y_BOX_OUTLINE,
69
+ ),
70
+ cv.Optional(CONF_SPEED): sensor.sensor_schema(
71
+ device_class=DEVICE_CLASS_SPEED,
72
+ unit_of_measurement=UNIT_MILLIMETER_PER_SECOND,
73
+ icon=ICON_SPEEDOMETER_SLOW,
74
+ ),
75
+ cv.Optional(CONF_ANGLE): sensor.sensor_schema(
76
+ unit_of_measurement=UNIT_DEGREES,
77
+ icon=ICON_FORMAT_TEXT_ROTATION_ANGLE_UP,
78
+ ),
79
+ cv.Optional(CONF_DISTANCE): sensor.sensor_schema(
80
+ device_class=DEVICE_CLASS_DISTANCE,
81
+ unit_of_measurement=UNIT_MILLIMETER,
82
+ icon=ICON_MAP_MARKER_DISTANCE,
83
+ ),
84
+ cv.Optional(CONF_RESOLUTION): sensor.sensor_schema(
85
+ device_class=DEVICE_CLASS_DISTANCE,
86
+ unit_of_measurement=UNIT_MILLIMETER,
87
+ icon=ICON_RELATION_ZERO_OR_ONE_TO_ZERO_OR_ONE,
88
+ ),
89
+ }
90
+ )
91
+ for n in range(MAX_TARGETS)
92
+ },
93
+ {
94
+ cv.Optional(f"zone_{n + 1}"): cv.Schema(
95
+ {
96
+ cv.Optional(CONF_TARGET_COUNT): sensor.sensor_schema(
97
+ icon=ICON_MAP_MARKER_ACCOUNT,
98
+ ),
99
+ cv.Optional(CONF_STILL_TARGET_COUNT): sensor.sensor_schema(
100
+ icon=ICON_MAP_MARKER_ACCOUNT,
101
+ ),
102
+ cv.Optional(CONF_MOVING_TARGET_COUNT): sensor.sensor_schema(
103
+ icon=ICON_MAP_MARKER_ACCOUNT,
104
+ ),
105
+ }
106
+ )
107
+ for n in range(MAX_ZONES)
108
+ },
109
+ )
110
+
111
+
112
+ async def to_code(config):
113
+ ld2450_component = await cg.get_variable(config[CONF_LD2450_ID])
114
+
115
+ if target_count_config := config.get(CONF_TARGET_COUNT):
116
+ sens = await sensor.new_sensor(target_count_config)
117
+ cg.add(ld2450_component.set_target_count_sensor(sens))
118
+
119
+ if still_target_count_config := config.get(CONF_STILL_TARGET_COUNT):
120
+ sens = await sensor.new_sensor(still_target_count_config)
121
+ cg.add(ld2450_component.set_still_target_count_sensor(sens))
122
+
123
+ if moving_target_count_config := config.get(CONF_MOVING_TARGET_COUNT):
124
+ sens = await sensor.new_sensor(moving_target_count_config)
125
+ cg.add(ld2450_component.set_moving_target_count_sensor(sens))
126
+ for n in range(MAX_TARGETS):
127
+ if target_conf := config.get(f"target_{n + 1}"):
128
+ if x_config := target_conf.get(CONF_X):
129
+ sens = await sensor.new_sensor(x_config)
130
+ cg.add(ld2450_component.set_move_x_sensor(n, sens))
131
+ if y_config := target_conf.get(CONF_Y):
132
+ sens = await sensor.new_sensor(y_config)
133
+ cg.add(ld2450_component.set_move_y_sensor(n, sens))
134
+ if speed_config := target_conf.get(CONF_SPEED):
135
+ sens = await sensor.new_sensor(speed_config)
136
+ cg.add(ld2450_component.set_move_speed_sensor(n, sens))
137
+ if angle_config := target_conf.get(CONF_ANGLE):
138
+ sens = await sensor.new_sensor(angle_config)
139
+ cg.add(ld2450_component.set_move_angle_sensor(n, sens))
140
+ if distance_config := target_conf.get(CONF_DISTANCE):
141
+ sens = await sensor.new_sensor(distance_config)
142
+ cg.add(ld2450_component.set_move_distance_sensor(n, sens))
143
+ if resolution_config := target_conf.get(CONF_RESOLUTION):
144
+ sens = await sensor.new_sensor(resolution_config)
145
+ cg.add(ld2450_component.set_move_resolution_sensor(n, sens))
146
+ for n in range(MAX_ZONES):
147
+ if zone_config := config.get(f"zone_{n + 1}"):
148
+ if target_count_config := zone_config.get(CONF_TARGET_COUNT):
149
+ sens = await sensor.new_sensor(target_count_config)
150
+ cg.add(ld2450_component.set_zone_target_count_sensor(n, sens))
151
+ if still_target_count_config := zone_config.get(CONF_STILL_TARGET_COUNT):
152
+ sens = await sensor.new_sensor(still_target_count_config)
153
+ cg.add(ld2450_component.set_zone_still_target_count_sensor(n, sens))
154
+ if moving_target_count_config := zone_config.get(CONF_MOVING_TARGET_COUNT):
155
+ sens = await sensor.new_sensor(moving_target_count_config)
156
+ cg.add(ld2450_component.set_zone_moving_target_count_sensor(n, sens))
@@ -0,0 +1,45 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import switch
3
+ import esphome.config_validation as cv
4
+ from esphome.const import (
5
+ DEVICE_CLASS_SWITCH,
6
+ ENTITY_CATEGORY_CONFIG,
7
+ ICON_BLUETOOTH,
8
+ ICON_PULSE,
9
+ )
10
+
11
+ from .. import CONF_LD2450_ID, LD2450Component, ld2450_ns
12
+
13
+ BluetoothSwitch = ld2450_ns.class_("BluetoothSwitch", switch.Switch)
14
+ MultiTargetSwitch = ld2450_ns.class_("MultiTargetSwitch", switch.Switch)
15
+
16
+ CONF_BLUETOOTH = "bluetooth"
17
+ CONF_MULTI_TARGET = "multi_target"
18
+
19
+ CONFIG_SCHEMA = {
20
+ cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component),
21
+ cv.Optional(CONF_BLUETOOTH): switch.switch_schema(
22
+ BluetoothSwitch,
23
+ device_class=DEVICE_CLASS_SWITCH,
24
+ entity_category=ENTITY_CATEGORY_CONFIG,
25
+ icon=ICON_BLUETOOTH,
26
+ ),
27
+ cv.Optional(CONF_MULTI_TARGET): switch.switch_schema(
28
+ MultiTargetSwitch,
29
+ device_class=DEVICE_CLASS_SWITCH,
30
+ entity_category=ENTITY_CATEGORY_CONFIG,
31
+ icon=ICON_PULSE,
32
+ ),
33
+ }
34
+
35
+
36
+ async def to_code(config):
37
+ ld2450_component = await cg.get_variable(config[CONF_LD2450_ID])
38
+ if bluetooth_config := config.get(CONF_BLUETOOTH):
39
+ s = await switch.new_switch(bluetooth_config)
40
+ await cg.register_parented(s, config[CONF_LD2450_ID])
41
+ cg.add(ld2450_component.set_bluetooth_switch(s))
42
+ if multi_target_config := config.get(CONF_MULTI_TARGET):
43
+ s = await switch.new_switch(multi_target_config)
44
+ await cg.register_parented(s, config[CONF_LD2450_ID])
45
+ cg.add(ld2450_component.set_multi_target_switch(s))
@@ -0,0 +1,12 @@
1
+ #include "bluetooth_switch.h"
2
+
3
+ namespace esphome {
4
+ namespace ld2450 {
5
+
6
+ void BluetoothSwitch::write_state(bool state) {
7
+ this->publish_state(state);
8
+ this->parent_->set_bluetooth(state);
9
+ }
10
+
11
+ } // namespace ld2450
12
+ } // namespace esphome
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/switch/switch.h"
4
+ #include "../ld2450.h"
5
+
6
+ namespace esphome {
7
+ namespace ld2450 {
8
+
9
+ class BluetoothSwitch : public switch_::Switch, public Parented<LD2450Component> {
10
+ public:
11
+ BluetoothSwitch() = default;
12
+
13
+ protected:
14
+ void write_state(bool state) override;
15
+ };
16
+
17
+ } // namespace ld2450
18
+ } // namespace esphome
@@ -0,0 +1,12 @@
1
+ #include "multi_target_switch.h"
2
+
3
+ namespace esphome {
4
+ namespace ld2450 {
5
+
6
+ void MultiTargetSwitch::write_state(bool state) {
7
+ this->publish_state(state);
8
+ this->parent_->set_multi_target(state);
9
+ }
10
+
11
+ } // namespace ld2450
12
+ } // namespace esphome
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/switch/switch.h"
4
+ #include "../ld2450.h"
5
+
6
+ namespace esphome {
7
+ namespace ld2450 {
8
+
9
+ class MultiTargetSwitch : public switch_::Switch, public Parented<LD2450Component> {
10
+ public:
11
+ MultiTargetSwitch() = default;
12
+
13
+ protected:
14
+ void write_state(bool state) override;
15
+ };
16
+
17
+ } // namespace ld2450
18
+ } // namespace esphome
@@ -0,0 +1,62 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import text_sensor
3
+ import esphome.config_validation as cv
4
+ from esphome.const import (
5
+ CONF_DIRECTION,
6
+ CONF_MAC_ADDRESS,
7
+ CONF_VERSION,
8
+ ENTITY_CATEGORY_DIAGNOSTIC,
9
+ ENTITY_CATEGORY_NONE,
10
+ ICON_BLUETOOTH,
11
+ ICON_CHIP,
12
+ ICON_SIGN_DIRECTION,
13
+ )
14
+
15
+ from . import CONF_LD2450_ID, LD2450Component
16
+
17
+ DEPENDENCIES = ["ld2450"]
18
+
19
+ MAX_TARGETS = 3
20
+
21
+ CONFIG_SCHEMA = cv.Schema(
22
+ {
23
+ cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component),
24
+ cv.Optional(CONF_VERSION): text_sensor.text_sensor_schema(
25
+ entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
26
+ icon=ICON_CHIP,
27
+ ),
28
+ cv.Optional(CONF_MAC_ADDRESS): text_sensor.text_sensor_schema(
29
+ entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
30
+ icon=ICON_BLUETOOTH,
31
+ ),
32
+ }
33
+ )
34
+
35
+ CONFIG_SCHEMA = CONFIG_SCHEMA.extend(
36
+ {
37
+ cv.Optional(f"target_{n + 1}"): cv.Schema(
38
+ {
39
+ cv.Optional(CONF_DIRECTION): text_sensor.text_sensor_schema(
40
+ entity_category=ENTITY_CATEGORY_NONE,
41
+ icon=ICON_SIGN_DIRECTION,
42
+ ),
43
+ }
44
+ )
45
+ for n in range(MAX_TARGETS)
46
+ }
47
+ )
48
+
49
+
50
+ async def to_code(config):
51
+ ld2450_component = await cg.get_variable(config[CONF_LD2450_ID])
52
+ if version_config := config.get(CONF_VERSION):
53
+ sens = await text_sensor.new_text_sensor(version_config)
54
+ cg.add(ld2450_component.set_version_text_sensor(sens))
55
+ if mac_address_config := config.get(CONF_MAC_ADDRESS):
56
+ sens = await text_sensor.new_text_sensor(mac_address_config)
57
+ cg.add(ld2450_component.set_mac_text_sensor(sens))
58
+ for n in range(MAX_TARGETS):
59
+ if direction_conf := config.get(f"target_{n + 1}"):
60
+ if direction_config := direction_conf.get(CONF_DIRECTION):
61
+ sens = await text_sensor.new_text_sensor(direction_config)
62
+ cg.add(ld2450_component.set_direction_text_sensor(n, sens))
@@ -462,8 +462,6 @@ CONF_LVGL_ID = "lvgl_id"
462
462
  CONF_LONG_MODE = "long_mode"
463
463
  CONF_MSGBOXES = "msgboxes"
464
464
  CONF_OBJ = "obj"
465
- CONF_OFFSET_X = "offset_x"
466
- CONF_OFFSET_Y = "offset_y"
467
465
  CONF_ONE_CHECKED = "one_checked"
468
466
  CONF_ONE_LINE = "one_line"
469
467
  CONF_ON_PAUSE = "on_pause"
@@ -19,7 +19,7 @@ static bool get_glyph_dsc_cb(const lv_font_t *font, lv_font_glyph_dsc_t *dsc, ui
19
19
  const auto *gd = fe->get_glyph_data(unicode_letter);
20
20
  if (gd == nullptr)
21
21
  return false;
22
- dsc->adv_w = gd->offset_x + gd->width;
22
+ dsc->adv_w = gd->advance;
23
23
  dsc->ofs_x = gd->offset_x;
24
24
  dsc->ofs_y = fe->height - gd->height - gd->offset_y - fe->baseline;
25
25
  dsc->box_w = gd->width;
@@ -416,37 +416,45 @@ LvglComponent::LvglComponent(std::vector<display::Display *> displays, float buf
416
416
  buffer_frac_(buffer_frac),
417
417
  full_refresh_(full_refresh),
418
418
  resume_on_input_(resume_on_input) {
419
- auto *display = this->displays_[0];
420
- size_t buffer_pixels = display->get_width() * display->get_height() / this->buffer_frac_;
421
- auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8;
422
- this->rotation = display->get_rotation();
423
- if (this->rotation != display::DISPLAY_ROTATION_0_DEGREES) {
424
- this->rotate_buf_ = static_cast<lv_color_t *>(lv_custom_mem_alloc(buf_bytes)); // NOLINT
425
- if (this->rotate_buf_ == nullptr)
426
- return;
427
- }
428
- auto *buf = lv_custom_mem_alloc(buf_bytes); // NOLINT
429
- if (buf == nullptr)
430
- return;
431
- lv_disp_draw_buf_init(&this->draw_buf_, buf, nullptr, buffer_pixels);
419
+ lv_disp_draw_buf_init(&this->draw_buf_, nullptr, nullptr, 0);
432
420
  lv_disp_drv_init(&this->disp_drv_);
433
421
  this->disp_drv_.draw_buf = &this->draw_buf_;
434
422
  this->disp_drv_.user_data = this;
435
423
  this->disp_drv_.full_refresh = this->full_refresh_;
436
424
  this->disp_drv_.flush_cb = static_flush_cb;
437
425
  this->disp_drv_.rounder_cb = rounder_cb;
438
- this->disp_drv_.hor_res = (lv_coord_t) display->get_width();
439
- this->disp_drv_.ver_res = (lv_coord_t) display->get_height();
426
+ this->disp_drv_.hor_res = 0;
427
+ this->disp_drv_.ver_res = 0;
440
428
  this->disp_ = lv_disp_drv_register(&this->disp_drv_);
441
429
  }
442
430
 
443
431
  void LvglComponent::setup() {
444
- if (this->draw_buf_.buf1 == nullptr) {
432
+ ESP_LOGCONFIG(TAG, "LVGL Setup starts");
433
+ auto *display = this->displays_[0];
434
+ auto width = display->get_width();
435
+ auto height = display->get_height();
436
+ size_t buffer_pixels = width * height / this->buffer_frac_;
437
+ auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8;
438
+ auto *buffer = lv_custom_mem_alloc(buf_bytes); // NOLINT
439
+ if (buffer == nullptr) {
445
440
  this->mark_failed();
446
441
  this->status_set_error("Memory allocation failure");
447
442
  return;
448
443
  }
449
- ESP_LOGCONFIG(TAG, "LVGL Setup starts");
444
+ lv_disp_draw_buf_init(&this->draw_buf_, buffer, nullptr, buf_bytes);
445
+ this->disp_drv_.hor_res = width;
446
+ this->disp_drv_.ver_res = height;
447
+ // this->setup_driver_(display->get_width(), display->get_height());
448
+ lv_disp_drv_update(this->disp_, &this->disp_drv_);
449
+ this->rotation = display->get_rotation();
450
+ if (this->rotation != display::DISPLAY_ROTATION_0_DEGREES) {
451
+ this->rotate_buf_ = static_cast<lv_color_t *>(lv_custom_mem_alloc(this->draw_buf_.size)); // NOLINT
452
+ if (this->rotate_buf_ == nullptr) {
453
+ this->mark_failed();
454
+ this->status_set_error("Memory allocation failure");
455
+ return;
456
+ }
457
+ }
450
458
  #if LV_USE_LOG
451
459
  lv_log_register_print_cb([](const char *buf) {
452
460
  auto next = strchr(buf, ')');
@@ -458,8 +466,8 @@ void LvglComponent::setup() {
458
466
  });
459
467
  #endif
460
468
  // Rotation will be handled by our drawing function, so reset the display rotation.
461
- for (auto *display : this->displays_)
462
- display->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);
469
+ for (auto *disp : this->displays_)
470
+ disp->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);
463
471
  this->show_page(0, LV_SCR_LOAD_ANIM_NONE, 0);
464
472
  lv_disp_trig_activity(this->disp_);
465
473
  ESP_LOGCONFIG(TAG, "LVGL Setup complete");
@@ -1,11 +1,9 @@
1
1
  import esphome.config_validation as cv
2
- from esphome.const import CONF_ANGLE, CONF_MODE
2
+ from esphome.const import CONF_ANGLE, CONF_MODE, CONF_OFFSET_X, CONF_OFFSET_Y
3
3
 
4
4
  from ..defines import (
5
5
  CONF_ANTIALIAS,
6
6
  CONF_MAIN,
7
- CONF_OFFSET_X,
8
- CONF_OFFSET_Y,
9
7
  CONF_PIVOT_X,
10
8
  CONF_PIVOT_Y,
11
9
  CONF_SRC,
@@ -550,6 +550,7 @@ canbus::Error MCP2515::set_bitrate_(canbus::CanSpeed can_speed, CanClock can_clo
550
550
  cfg3 = MCP_16MHZ_40KBPS_CFG3;
551
551
  break;
552
552
  case (canbus::CAN_50KBPS): // 50Kbps
553
+ cfg1 = MCP_16MHZ_50KBPS_CFG1;
553
554
  cfg2 = MCP_16MHZ_50KBPS_CFG2;
554
555
  cfg3 = MCP_16MHZ_50KBPS_CFG3;
555
556
  break;
@@ -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.5.1",
94
+ ref="mdns-v1.8.0",
95
95
  path="components/mdns",
96
96
  )
97
97
 
@@ -177,11 +177,15 @@ void SourceSpeaker::set_mute_state(bool mute_state) {
177
177
  this->parent_->get_output_speaker()->set_mute_state(mute_state);
178
178
  }
179
179
 
180
+ bool SourceSpeaker::get_mute_state() { return this->parent_->get_output_speaker()->get_mute_state(); }
181
+
180
182
  void SourceSpeaker::set_volume(float volume) {
181
183
  this->volume_ = volume;
182
184
  this->parent_->get_output_speaker()->set_volume(volume);
183
185
  }
184
186
 
187
+ float SourceSpeaker::get_volume() { return this->parent_->get_output_speaker()->get_volume(); }
188
+
185
189
  size_t SourceSpeaker::process_data_from_source(TickType_t ticks_to_wait) {
186
190
  if (!this->transfer_buffer_.use_count()) {
187
191
  return 0;
@@ -490,7 +494,8 @@ void MixerSpeaker::audio_mixer_task(void *params) {
490
494
  break;
491
495
  }
492
496
 
493
- output_transfer_buffer->transfer_data_to_sink(pdMS_TO_TICKS(TASK_DELAY_MS));
497
+ // Never shift the data in the output transfer buffer to avoid unnecessary, slow data moves
498
+ output_transfer_buffer->transfer_data_to_sink(pdMS_TO_TICKS(TASK_DELAY_MS), false);
494
499
 
495
500
  const uint32_t output_frames_free =
496
501
  this_mixer->audio_stream_info_.value().bytes_to_frames(output_transfer_buffer->free());
@@ -53,9 +53,11 @@ class SourceSpeaker : public speaker::Speaker, public Component {
53
53
 
54
54
  /// @brief Mute state changes are passed to the parent's output speaker
55
55
  void set_mute_state(bool mute_state) override;
56
+ bool get_mute_state() override;
56
57
 
57
58
  /// @brief Volume state changes are passed to the parent's output speaker
58
59
  void set_volume(float volume) override;
60
+ float get_volume() override;
59
61
 
60
62
  void set_pause_state(bool pause_state) override { this->pause_state_ = pause_state; }
61
63
  bool get_pause_state() const override { return this->pause_state_; }
@@ -1,20 +1,21 @@
1
+ from esphome import pins
1
2
  import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
3
  from esphome.components import i2c, sensor
4
+ import esphome.config_validation as cv
4
5
  from esphome.const import (
5
- CONF_ID,
6
- UNIT_MICROTESLA,
7
- UNIT_CELSIUS,
8
- STATE_CLASS_MEASUREMENT,
9
- ICON_MAGNET,
10
- ICON_THERMOMETER,
6
+ CONF_FILTER,
11
7
  CONF_GAIN,
12
- CONF_RESOLUTION,
8
+ CONF_ID,
13
9
  CONF_OVERSAMPLING,
14
- CONF_FILTER,
10
+ CONF_RESOLUTION,
15
11
  CONF_TEMPERATURE,
12
+ CONF_TEMPERATURE_COMPENSATION,
13
+ ICON_MAGNET,
14
+ ICON_THERMOMETER,
15
+ STATE_CLASS_MEASUREMENT,
16
+ UNIT_CELSIUS,
17
+ UNIT_MICROTESLA,
16
18
  )
17
- from esphome import pins
18
19
 
19
20
  CODEOWNERS = ["@functionpointer"]
20
21
  DEPENDENCIES = ["i2c"]
@@ -26,30 +27,46 @@ MLX90393Component = mlx90393_ns.class_(
26
27
  )
27
28
 
28
29
  GAIN = {
29
- "1X": 7,
30
- "1_33X": 6,
31
- "1_67X": 5,
32
- "2X": 4,
33
- "2_5X": 3,
34
- "3X": 2,
35
- "4X": 1,
36
- "5X": 0,
30
+ "1X": 0,
31
+ "1_25X": 1,
32
+ "1_67X": 2,
33
+ "2X": 3,
34
+ "2_5X": 4,
35
+ "3X": 5,
36
+ "3_75X": 6,
37
+ "5X": 7,
37
38
  }
38
39
 
39
40
  RESOLUTION = {
40
- "16BIT": 0,
41
- "17BIT": 1,
42
- "18BIT": 2,
43
- "19BIT": 3,
41
+ "DIV_8": 3,
42
+ "DIV_4": 2,
43
+ "DIV_2": 1,
44
+ "DIV_1": 0,
44
45
  }
45
46
 
46
47
  CONF_X_AXIS = "x_axis"
47
48
  CONF_Y_AXIS = "y_axis"
48
49
  CONF_Z_AXIS = "z_axis"
49
50
  CONF_DRDY_PIN = "drdy_pin"
51
+ CONF_HALLCONF = "hallconf"
52
+
53
+
54
+ def _validate(config):
55
+ if config[CONF_TEMPERATURE_COMPENSATION]:
56
+ for axis in [CONF_X_AXIS, CONF_Y_AXIS, CONF_Z_AXIS]:
57
+ if axis not in config:
58
+ continue
59
+ if (res := config[axis][CONF_RESOLUTION]) in [
60
+ "DIV_8",
61
+ "DIV_4",
62
+ ]:
63
+ raise cv.Invalid(
64
+ f"{axis}: {CONF_RESOLUTION} cannot be {res} with {CONF_TEMPERATURE_COMPENSATION} enabled"
65
+ )
66
+ return config
50
67
 
51
68
 
52
- def mlx90393_axis_schema(default_resolution: str):
69
+ def mlx90393_axis_schema():
53
70
  return sensor.sensor_schema(
54
71
  unit_of_measurement=UNIT_MICROTESLA,
55
72
  accuracy_decimals=0,
@@ -58,7 +75,7 @@ def mlx90393_axis_schema(default_resolution: str):
58
75
  ).extend(
59
76
  cv.Schema(
60
77
  {
61
- cv.Optional(CONF_RESOLUTION, default=default_resolution): cv.enum(
78
+ cv.Optional(CONF_RESOLUTION, default="DIV_4"): cv.enum(
62
79
  RESOLUTION, upper=True, space="_"
63
80
  )
64
81
  }
@@ -66,19 +83,19 @@ def mlx90393_axis_schema(default_resolution: str):
66
83
  )
67
84
 
68
85
 
69
- CONFIG_SCHEMA = (
86
+ CONFIG_SCHEMA = cv.All(
70
87
  cv.Schema(
71
88
  {
72
89
  cv.GenerateID(): cv.declare_id(MLX90393Component),
73
- cv.Optional(CONF_GAIN, default="2_5X"): cv.enum(
74
- GAIN, upper=True, space="_"
75
- ),
90
+ cv.Optional(CONF_GAIN, default="1X"): cv.enum(GAIN, upper=True, space="_"),
76
91
  cv.Optional(CONF_DRDY_PIN): pins.gpio_input_pin_schema,
77
- cv.Optional(CONF_OVERSAMPLING, default=2): cv.int_range(min=0, max=3),
92
+ cv.Optional(CONF_OVERSAMPLING, default=0): cv.int_range(min=0, max=3),
78
93
  cv.Optional(CONF_FILTER, default=6): cv.int_range(min=0, max=7),
79
- cv.Optional(CONF_X_AXIS): mlx90393_axis_schema("19BIT"),
80
- cv.Optional(CONF_Y_AXIS): mlx90393_axis_schema("19BIT"),
81
- cv.Optional(CONF_Z_AXIS): mlx90393_axis_schema("16BIT"),
94
+ cv.Optional(CONF_X_AXIS): mlx90393_axis_schema(),
95
+ cv.Optional(CONF_Y_AXIS): mlx90393_axis_schema(),
96
+ cv.Optional(CONF_Z_AXIS): mlx90393_axis_schema(),
97
+ cv.Optional(CONF_TEMPERATURE_COMPENSATION, default=False): bool,
98
+ cv.Optional(CONF_HALLCONF, default=0xC): cv.one_of(0xC, 0x0),
82
99
  cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
83
100
  unit_of_measurement=UNIT_CELSIUS,
84
101
  accuracy_decimals=1,
@@ -96,7 +113,8 @@ CONFIG_SCHEMA = (
96
113
  },
97
114
  )
98
115
  .extend(cv.polling_component_schema("60s"))
99
- .extend(i2c.i2c_device_schema(0x0C))
116
+ .extend(i2c.i2c_device_schema(0x0C)),
117
+ _validate,
100
118
  )
101
119
 
102
120
 
@@ -111,6 +129,8 @@ async def to_code(config):
111
129
  cg.add(var.set_gain(GAIN[config[CONF_GAIN]]))
112
130
  cg.add(var.set_oversampling(config[CONF_OVERSAMPLING]))
113
131
  cg.add(var.set_filter(config[CONF_FILTER]))
132
+ cg.add(var.set_temperature_compensation(config[CONF_TEMPERATURE_COMPENSATION]))
133
+ cg.add(var.set_hallconf(config[CONF_HALLCONF]))
114
134
 
115
135
  if CONF_X_AXIS in config:
116
136
  sens = await sensor.new_sensor(config[CONF_X_AXIS])
@@ -43,6 +43,10 @@ void MLX90393Cls::setup() {
43
43
  this->mlx_.setDigitalFiltering(this->filter_);
44
44
 
45
45
  this->mlx_.setTemperatureOverSampling(this->temperature_oversampling_);
46
+
47
+ this->mlx_.setTemperatureCompensation(this->temperature_compensation_);
48
+
49
+ this->mlx_.setHallConf(this->hallconf_);
46
50
  }
47
51
 
48
52
  void MLX90393Cls::dump_config() {