esphome 2025.2.1__py3-none-any.whl → 2025.3.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 (140) 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 +9 -0
  5. esphome/components/api/api_pb2.h +1 -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/audio_reader.cpp +7 -7
  11. esphome/components/audio/audio_reader.h +1 -1
  12. esphome/components/bluetooth_proxy/bluetooth_proxy.h +8 -0
  13. esphome/components/bmp085/bmp085.cpp +1 -1
  14. esphome/components/chsc6x/__init__.py +2 -0
  15. esphome/components/chsc6x/chsc6x_touchscreen.cpp +47 -0
  16. esphome/components/chsc6x/chsc6x_touchscreen.h +34 -0
  17. esphome/components/chsc6x/touchscreen.py +33 -0
  18. esphome/components/climate/__init__.py +0 -1
  19. esphome/components/cst816/binary_sensor/__init__.py +2 -25
  20. esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +3 -14
  21. esphome/components/cst816/touchscreen/cst816_touchscreen.h +0 -4
  22. esphome/components/esp32_ble_beacon/__init__.py +3 -1
  23. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +2 -2
  24. esphome/components/esp8266/gpio.py +1 -2
  25. esphome/components/font/__init__.py +185 -185
  26. esphome/components/font/font.cpp +4 -4
  27. esphome/components/font/font.h +1 -0
  28. esphome/components/haier/climate.py +11 -10
  29. esphome/components/hbridge/switch/hbridge_switch.cpp +2 -2
  30. esphome/components/heatpumpir/climate.py +2 -1
  31. esphome/components/heatpumpir/heatpumpir.cpp +1 -0
  32. esphome/components/heatpumpir/heatpumpir.h +1 -0
  33. esphome/components/i2c/__init__.py +6 -6
  34. esphome/components/i2c/i2c_bus_esp_idf.cpp +6 -2
  35. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
  36. esphome/components/ili9xxx/display.py +1 -0
  37. esphome/components/ili9xxx/ili9xxx_display.h +5 -0
  38. esphome/components/ili9xxx/ili9xxx_init.h +59 -0
  39. esphome/components/ld2450/__init__.py +51 -0
  40. esphome/components/ld2450/binary_sensor.py +47 -0
  41. esphome/components/ld2450/button/__init__.py +45 -0
  42. esphome/components/ld2450/button/reset_button.cpp +9 -0
  43. esphome/components/ld2450/button/reset_button.h +18 -0
  44. esphome/components/ld2450/button/restart_button.cpp +9 -0
  45. esphome/components/ld2450/button/restart_button.h +18 -0
  46. esphome/components/ld2450/ld2450.cpp +876 -0
  47. esphome/components/ld2450/ld2450.h +234 -0
  48. esphome/components/ld2450/number/__init__.py +121 -0
  49. esphome/components/ld2450/number/presence_timeout_number.cpp +12 -0
  50. esphome/components/ld2450/number/presence_timeout_number.h +18 -0
  51. esphome/components/ld2450/number/zone_coordinate_number.cpp +14 -0
  52. esphome/components/ld2450/number/zone_coordinate_number.h +19 -0
  53. esphome/components/ld2450/select/__init__.py +56 -0
  54. esphome/components/ld2450/select/baud_rate_select.cpp +12 -0
  55. esphome/components/ld2450/select/baud_rate_select.h +18 -0
  56. esphome/components/ld2450/select/zone_type_select.cpp +12 -0
  57. esphome/components/ld2450/select/zone_type_select.h +18 -0
  58. esphome/components/ld2450/sensor.py +156 -0
  59. esphome/components/ld2450/switch/__init__.py +45 -0
  60. esphome/components/ld2450/switch/bluetooth_switch.cpp +12 -0
  61. esphome/components/ld2450/switch/bluetooth_switch.h +18 -0
  62. esphome/components/ld2450/switch/multi_target_switch.cpp +12 -0
  63. esphome/components/ld2450/switch/multi_target_switch.h +18 -0
  64. esphome/components/ld2450/text_sensor.py +62 -0
  65. esphome/components/ltr390/ltr390.cpp +7 -7
  66. esphome/components/ltr390/ltr390.h +0 -1
  67. esphome/components/lvgl/defines.py +0 -2
  68. esphome/components/lvgl/font.cpp +1 -1
  69. esphome/components/lvgl/lvgl_esphome.cpp +27 -19
  70. esphome/components/lvgl/widgets/img.py +1 -3
  71. esphome/components/mcp2515/mcp2515.cpp +1 -0
  72. esphome/components/mlx90393/sensor.py +53 -33
  73. esphome/components/mlx90393/sensor_mlx90393.cpp +4 -0
  74. esphome/components/mlx90393/sensor_mlx90393.h +8 -3
  75. esphome/components/mqtt/__init__.py +2 -2
  76. esphome/components/msa3xx/__init__.py +189 -0
  77. esphome/components/msa3xx/binary_sensor.py +40 -0
  78. esphome/components/msa3xx/msa3xx.cpp +417 -0
  79. esphome/components/msa3xx/msa3xx.h +311 -0
  80. esphome/components/msa3xx/sensor.py +42 -0
  81. esphome/components/msa3xx/text_sensor.py +38 -0
  82. esphome/components/nfc/binary_sensor/__init__.py +4 -4
  83. esphome/components/opentherm/binary_sensor/__init__.py +4 -4
  84. esphome/components/opentherm/generate.py +6 -6
  85. esphome/components/opentherm/sensor/__init__.py +5 -6
  86. esphome/components/packages/__init__.py +35 -11
  87. esphome/components/pn532/binary_sensor.py +4 -4
  88. esphome/components/rc522/binary_sensor.py +4 -4
  89. esphome/components/socket/bsd_sockets_impl.cpp +1 -0
  90. esphome/components/socket/lwip_sockets_impl.cpp +1 -0
  91. esphome/components/socket/socket.h +3 -1
  92. esphome/components/ssd1306_base/__init__.py +7 -7
  93. esphome/components/thermostat/climate.py +1 -1
  94. esphome/components/tmp1075/tmp1075.cpp +7 -11
  95. esphome/components/tmp1075/tmp1075.h +1 -2
  96. esphome/components/tormatic/__init__.py +1 -0
  97. esphome/components/tormatic/cover.py +47 -0
  98. esphome/components/tormatic/tormatic_cover.cpp +355 -0
  99. esphome/components/tormatic/tormatic_cover.h +60 -0
  100. esphome/components/tormatic/tormatic_protocol.h +211 -0
  101. esphome/components/touchscreen/binary_sensor/__init__.py +3 -0
  102. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.cpp +7 -1
  103. esphome/components/touchscreen/binary_sensor/touchscreen_binary_sensor.h +3 -1
  104. esphome/components/touchscreen/touchscreen.cpp +3 -4
  105. esphome/components/udp/udp_component.h +4 -1
  106. esphome/components/web_server/list_entities.cpp +70 -66
  107. esphome/components/web_server/list_entities.h +43 -22
  108. esphome/components/web_server/web_server.cpp +345 -68
  109. esphome/components/web_server/web_server.h +138 -6
  110. esphome/components/web_server_base/__init__.py +1 -1
  111. esphome/components/web_server_idf/__init__.py +2 -0
  112. esphome/components/web_server_idf/web_server_idf.cpp +177 -30
  113. esphome/components/web_server_idf/web_server_idf.h +53 -4
  114. esphome/config_validation.py +23 -125
  115. esphome/const.py +5 -1
  116. esphome/core/config.py +12 -4
  117. esphome/core/defines.h +1 -1
  118. esphome/core/helpers.h +5 -3
  119. esphome/core/time.cpp +1 -0
  120. esphome/cpp_generator.py +3 -3
  121. esphome/dashboard/core.py +30 -21
  122. esphome/dashboard/dns.py +7 -1
  123. esphome/dashboard/entries.py +83 -16
  124. esphome/dashboard/settings.py +0 -4
  125. esphome/dashboard/status/mdns.py +43 -14
  126. esphome/dashboard/status/mqtt.py +22 -9
  127. esphome/dashboard/status/ping.py +54 -10
  128. esphome/dashboard/web_server.py +56 -24
  129. esphome/storage_json.py +4 -0
  130. esphome/wizard.py +13 -17
  131. esphome/writer.py +1 -3
  132. esphome/yaml_util.py +36 -33
  133. esphome/zeroconf.py +9 -21
  134. {esphome-2025.2.1.dist-info → esphome-2025.3.0b1.dist-info}/METADATA +5 -5
  135. {esphome-2025.2.1.dist-info → esphome-2025.3.0b1.dist-info}/RECORD +139 -99
  136. esphome/components/cst816/binary_sensor/cst816_button.h +0 -27
  137. {esphome-2025.2.1.dist-info → esphome-2025.3.0b1.dist-info}/LICENSE +0 -0
  138. {esphome-2025.2.1.dist-info → esphome-2025.3.0b1.dist-info}/WHEEL +0 -0
  139. {esphome-2025.2.1.dist-info → esphome-2025.3.0b1.dist-info}/entry_points.txt +0 -0
  140. {esphome-2025.2.1.dist-info → esphome-2025.3.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,311 @@
1
+ #pragma once
2
+
3
+ #include "esphome/core/component.h"
4
+ #include "esphome/components/i2c/i2c.h"
5
+ #include "esphome/core/automation.h"
6
+
7
+ #ifdef USE_BINARY_SENSOR
8
+ #include "esphome/components/binary_sensor/binary_sensor.h"
9
+ #endif
10
+ #ifdef USE_SENSOR
11
+ #include "esphome/components/sensor/sensor.h"
12
+ #endif
13
+ #ifdef USE_TEXT_SENSOR
14
+ #include "esphome/components/text_sensor/text_sensor.h"
15
+ #endif
16
+
17
+ namespace esphome {
18
+ namespace msa3xx {
19
+
20
+ // Combined register map of MSA301 and MSA311
21
+ // Differences
22
+ // What | MSA301 | MSA11 |
23
+ // - Resolution | 14-bit | 12-bit |
24
+ //
25
+
26
+ // I2c address
27
+ enum class Model : uint8_t {
28
+ MSA301 = 0x26,
29
+ MSA311 = 0x62,
30
+ };
31
+
32
+ // Combined MSA301 and MSA311 register map
33
+ enum class RegisterMap : uint8_t {
34
+ SOFT_RESET = 0x00,
35
+ PART_ID = 0x01,
36
+ ACC_X_LSB = 0x02,
37
+ ACC_X_MSB = 0x03,
38
+ ACC_Y_LSB = 0x04,
39
+ ACC_Y_MSB = 0x05,
40
+ ACC_Z_LSB = 0x06,
41
+ ACC_Z_MSB = 0x07,
42
+ MOTION_INTERRUPT = 0x09,
43
+ DATA_INTERRUPT = 0x0A,
44
+ TAP_ACTIVE_STATUS = 0x0B,
45
+ ORIENTATION_STATUS = 0x0C,
46
+ RESOLUTION_RANGE_CONFIG = 0x0D,
47
+ RANGE_RESOLUTION = 0x0F,
48
+ ODR = 0x10,
49
+ POWER_MODE_BANDWIDTH = 0x11,
50
+ SWAP_POLARITY = 0x12,
51
+ INT_SET_0 = 0x16,
52
+ INT_SET_1 = 0x17,
53
+ INT_MAP_0 = 0x19,
54
+ INT_MAP_1 = 0x1A,
55
+ INT_CONFIG = 0x20,
56
+ INT_LATCH = 0x21,
57
+ FREEFALL_DURATION = 0x22,
58
+ FREEFALL_THRESHOLD = 0x23,
59
+ FREEFALL_HYSTERESIS = 0x24,
60
+ ACTIVE_DURATION = 0x27,
61
+ ACTIVE_THRESHOLD = 0x28,
62
+ TAP_DURATION = 0x2A,
63
+ TAP_THRESHOLD = 0x2B,
64
+ ORIENTATION_CONFIG = 0x2C,
65
+ Z_BLOCK = 0x2D,
66
+ OFFSET_COMP_X = 0x38,
67
+ OFFSET_COMP_Y = 0x39,
68
+ OFFSET_COMP_Z = 0x3A,
69
+ };
70
+
71
+ enum class Range : uint8_t {
72
+ RANGE_2G = 0b00,
73
+ RANGE_4G = 0b01,
74
+ RANGE_8G = 0b10,
75
+ RANGE_16G = 0b11,
76
+ };
77
+
78
+ enum class Resolution : uint8_t {
79
+ RES_14BIT = 0b00,
80
+ RES_12BIT = 0b01,
81
+ RES_10BIT = 0b10,
82
+ RES_8BIT = 0b11,
83
+ };
84
+
85
+ enum class PowerMode : uint8_t {
86
+ NORMAL = 0b00,
87
+ LOW_POWER = 0b01,
88
+ SUSPEND = 0b11,
89
+ };
90
+
91
+ enum class Bandwidth : uint8_t {
92
+ BW_1_95HZ = 0b0000,
93
+ BW_3_9HZ = 0b0011,
94
+ BW_7_81HZ = 0b0100,
95
+ BW_15_63HZ = 0b0101,
96
+ BW_31_25HZ = 0b0110,
97
+ BW_62_5HZ = 0b0111,
98
+ BW_125HZ = 0b1000,
99
+ BW_250HZ = 0b1001,
100
+ BW_500HZ = 0b1010,
101
+ };
102
+
103
+ enum class DataRate : uint8_t {
104
+ ODR_1HZ = 0b0000, // not available in normal mode
105
+ ODR_1_95HZ = 0b0001, // not available in normal mode
106
+ ODR_3_9HZ = 0b0010,
107
+ ODR_7_81HZ = 0b0011,
108
+ ODR_15_63HZ = 0b0100,
109
+ ODR_31_25HZ = 0b0101,
110
+ ODR_62_5HZ = 0b0110,
111
+ ODR_125HZ = 0b0111,
112
+ ODR_250HZ = 0b1000,
113
+ ODR_500HZ = 0b1001, // not available in low power mode
114
+ ODR_1000HZ = 0b1010, // not available in low power mode
115
+ };
116
+
117
+ enum class OrientationXY : uint8_t {
118
+ PORTRAIT_UPRIGHT = 0b00,
119
+ PORTRAIT_UPSIDE_DOWN = 0b01,
120
+ LANDSCAPE_LEFT = 0b10,
121
+ LANDSCAPE_RIGHT = 0b11,
122
+ };
123
+
124
+ union Orientation {
125
+ struct {
126
+ OrientationXY xy : 2;
127
+ bool z : 1;
128
+ uint8_t reserved : 5;
129
+ } __attribute__((packed));
130
+ uint8_t raw;
131
+ };
132
+
133
+ // 0x09
134
+ union RegMotionInterrupt {
135
+ struct {
136
+ bool freefall_interrupt : 1;
137
+ bool reserved_1 : 1;
138
+ bool active_interrupt : 1;
139
+ bool reserved_3 : 1;
140
+ bool double_tap_interrupt : 1;
141
+ bool single_tap_interrupt : 1;
142
+ bool orientation_interrupt : 1;
143
+ bool reserved_7 : 1;
144
+ } __attribute__((packed));
145
+ uint8_t raw;
146
+ };
147
+
148
+ // 0x0C
149
+ union RegOrientationStatus {
150
+ struct {
151
+ uint8_t reserved_0_3 : 4;
152
+ OrientationXY orient_xy : 2;
153
+ bool orient_z : 1;
154
+ uint8_t reserved_7 : 1;
155
+ } __attribute__((packed));
156
+ uint8_t raw{0x00};
157
+ };
158
+
159
+ // 0x0f
160
+ union RegRangeResolution {
161
+ struct {
162
+ Range range : 2;
163
+ Resolution resolution : 2;
164
+ uint8_t reserved_2 : 4;
165
+ } __attribute__((packed));
166
+ uint8_t raw{0x00};
167
+ };
168
+
169
+ // 0x10
170
+ union RegOutputDataRate {
171
+ struct {
172
+ DataRate odr : 4;
173
+ uint8_t reserved_4 : 1;
174
+ bool z_axis_disable : 1;
175
+ bool y_axis_disable : 1;
176
+ bool x_axis_disable : 1;
177
+ } __attribute__((packed));
178
+ uint8_t raw{0xde};
179
+ };
180
+
181
+ // 0x11
182
+ union RegPowerModeBandwidth {
183
+ struct {
184
+ uint8_t reserved_0 : 1;
185
+ Bandwidth low_power_bandwidth : 4;
186
+ uint8_t reserved_5 : 1;
187
+ PowerMode power_mode : 2;
188
+ } __attribute__((packed));
189
+ uint8_t raw{0xde};
190
+ };
191
+
192
+ // 0x12
193
+ union RegSwapPolarity {
194
+ struct {
195
+ bool x_y_swap : 1;
196
+ bool z_polarity : 1;
197
+ bool y_polarity : 1;
198
+ bool x_polarity : 1;
199
+ uint8_t reserved : 4;
200
+ } __attribute__((packed));
201
+ uint8_t raw{0};
202
+ };
203
+
204
+ // 0x2a
205
+ union RegTapDuration {
206
+ struct {
207
+ uint8_t duration : 3;
208
+ uint8_t reserved : 3;
209
+ bool tap_shock : 1;
210
+ bool tap_quiet : 1;
211
+ } __attribute__((packed));
212
+ uint8_t raw{0x04};
213
+ };
214
+
215
+ class MSA3xxComponent : public PollingComponent, public i2c::I2CDevice {
216
+ public:
217
+ void setup() override;
218
+ void dump_config() override;
219
+
220
+ void loop() override;
221
+ void update() override;
222
+
223
+ float get_setup_priority() const override;
224
+
225
+ void set_model(Model model) { this->model_ = model; }
226
+ void set_offset(float offset_x, float offset_y, float offset_z);
227
+ void set_range(Range range) { this->range_ = range; }
228
+ void set_bandwidth(Bandwidth bandwidth) { this->bandwidth_ = bandwidth; }
229
+ void set_resolution(Resolution resolution) { this->resolution_ = resolution; }
230
+ void set_transform(bool mirror_x, bool mirror_y, bool mirror_z, bool swap_xy);
231
+
232
+ #ifdef USE_BINARY_SENSOR
233
+ SUB_BINARY_SENSOR(tap)
234
+ SUB_BINARY_SENSOR(double_tap)
235
+ SUB_BINARY_SENSOR(active)
236
+ #endif
237
+
238
+ #ifdef USE_SENSOR
239
+ SUB_SENSOR(acceleration_x)
240
+ SUB_SENSOR(acceleration_y)
241
+ SUB_SENSOR(acceleration_z)
242
+ #endif
243
+
244
+ #ifdef USE_TEXT_SENSOR
245
+ SUB_TEXT_SENSOR(orientation_xy)
246
+ SUB_TEXT_SENSOR(orientation_z)
247
+ #endif
248
+
249
+ Trigger<> *get_tap_trigger() { return &this->tap_trigger_; }
250
+ Trigger<> *get_double_tap_trigger() { return &this->double_tap_trigger_; }
251
+ Trigger<> *get_orientation_trigger() { return &this->orientation_trigger_; }
252
+ Trigger<> *get_freefall_trigger() { return &this->freefall_trigger_; }
253
+ Trigger<> *get_active_trigger() { return &this->active_trigger_; }
254
+
255
+ protected:
256
+ Model model_{Model::MSA311};
257
+
258
+ PowerMode power_mode_{PowerMode::NORMAL};
259
+ DataRate data_rate_{DataRate::ODR_250HZ};
260
+ Bandwidth bandwidth_{Bandwidth::BW_250HZ};
261
+ Range range_{Range::RANGE_2G};
262
+ Resolution resolution_{Resolution::RES_14BIT};
263
+ float offset_x_, offset_y_, offset_z_; // in m/s²
264
+ RegSwapPolarity swap_;
265
+
266
+ struct {
267
+ int scale_factor_exp;
268
+ uint8_t accel_data_width;
269
+ } device_params_{};
270
+
271
+ struct {
272
+ int16_t lsb_x, lsb_y, lsb_z;
273
+ float x, y, z;
274
+ } data_{};
275
+
276
+ struct {
277
+ RegMotionInterrupt motion_int;
278
+ RegOrientationStatus orientation;
279
+ RegOrientationStatus orientation_old;
280
+
281
+ uint32_t last_tap_ms{0};
282
+ uint32_t last_double_tap_ms{0};
283
+ uint32_t last_action_ms{0};
284
+
285
+ bool never_published{true};
286
+ } status_{};
287
+
288
+ void setup_odr_(DataRate rate);
289
+ void setup_power_mode_bandwidth_(PowerMode power_mode, Bandwidth bandwidth);
290
+ void setup_range_resolution_(Range range, Resolution resolution);
291
+ void setup_offset_(float offset_x, float offset_y, float offset_z);
292
+
293
+ bool read_data_();
294
+ bool read_motion_status_();
295
+
296
+ int64_t twos_complement_(uint64_t value, uint8_t bits);
297
+
298
+ //
299
+ // Actons / Triggers
300
+ //
301
+ Trigger<> tap_trigger_;
302
+ Trigger<> double_tap_trigger_;
303
+ Trigger<> orientation_trigger_;
304
+ Trigger<> freefall_trigger_;
305
+ Trigger<> active_trigger_;
306
+
307
+ void process_motions_(RegMotionInterrupt old);
308
+ };
309
+
310
+ } // namespace msa3xx
311
+ } // namespace esphome
@@ -0,0 +1,42 @@
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_ACCELERATION_X,
6
+ CONF_ACCELERATION_Y,
7
+ CONF_ACCELERATION_Z,
8
+ CONF_NAME,
9
+ ICON_BRIEFCASE_DOWNLOAD,
10
+ STATE_CLASS_MEASUREMENT,
11
+ UNIT_METER_PER_SECOND_SQUARED,
12
+ )
13
+
14
+ from . import CONF_MSA3XX_ID, MSA_SENSOR_SCHEMA
15
+
16
+ CODEOWNERS = ["@latonita"]
17
+ DEPENDENCIES = ["msa3xx"]
18
+
19
+ ACCELERATION_SENSORS = (CONF_ACCELERATION_X, CONF_ACCELERATION_Y, CONF_ACCELERATION_Z)
20
+
21
+ accel_schema = cv.maybe_simple_value(
22
+ sensor.sensor_schema(
23
+ unit_of_measurement=UNIT_METER_PER_SECOND_SQUARED,
24
+ icon=ICON_BRIEFCASE_DOWNLOAD,
25
+ accuracy_decimals=2,
26
+ state_class=STATE_CLASS_MEASUREMENT,
27
+ ),
28
+ key=CONF_NAME,
29
+ )
30
+
31
+
32
+ CONFIG_SCHEMA = MSA_SENSOR_SCHEMA.extend(
33
+ {cv.Optional(sensor): accel_schema for sensor in ACCELERATION_SENSORS}
34
+ )
35
+
36
+
37
+ async def to_code(config):
38
+ hub = await cg.get_variable(config[CONF_MSA3XX_ID])
39
+ for accel_key in ACCELERATION_SENSORS:
40
+ if accel_key in config:
41
+ sens = await sensor.new_sensor(config[accel_key])
42
+ cg.add(getattr(hub, f"set_{accel_key}_sensor")(sens))
@@ -0,0 +1,38 @@
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 CONF_NAME
5
+
6
+ from . import CONF_MSA3XX_ID, MSA_SENSOR_SCHEMA
7
+
8
+ CODEOWNERS = ["@latonita"]
9
+ DEPENDENCIES = ["msa3xx"]
10
+
11
+ CONF_ORIENTATION_XY = "orientation_xy"
12
+ CONF_ORIENTATION_Z = "orientation_z"
13
+ ICON_SCREEN_ROTATION = "mdi:screen-rotation"
14
+
15
+ ORIENTATION_SENSORS = (CONF_ORIENTATION_XY, CONF_ORIENTATION_Z)
16
+
17
+ CONFIG_SCHEMA = MSA_SENSOR_SCHEMA.extend(
18
+ {
19
+ cv.Optional(sensor): cv.maybe_simple_value(
20
+ text_sensor.text_sensor_schema(icon=ICON_SCREEN_ROTATION),
21
+ key=CONF_NAME,
22
+ )
23
+ for sensor in ORIENTATION_SENSORS
24
+ }
25
+ )
26
+
27
+
28
+ async def setup_conf(config, key, hub):
29
+ if sensor_config := config.get(key):
30
+ var = await text_sensor.new_text_sensor(sensor_config)
31
+ cg.add(getattr(hub, f"set_{key}_text_sensor")(var))
32
+
33
+
34
+ async def to_code(config):
35
+ hub = await cg.get_variable(config[CONF_MSA3XX_ID])
36
+
37
+ for key in ORIENTATION_SENSORS:
38
+ await setup_conf(config, key, hub)
@@ -1,9 +1,10 @@
1
1
  import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
2
  from esphome.components import binary_sensor
3
+ import esphome.config_validation as cv
4
4
  from esphome.const import CONF_UID
5
5
  from esphome.core import HexInt
6
- from .. import nfc_ns, Nfcc, NfcTagListener
6
+
7
+ from .. import Nfcc, NfcTagListener, nfc_ns
7
8
 
8
9
  DEPENDENCIES = ["nfc"]
9
10
 
@@ -25,8 +26,7 @@ def validate_uid(value):
25
26
  for x in value.split("-"):
26
27
  if len(x) != 2:
27
28
  raise cv.Invalid(
28
- "Each part (separated by '-') of the UID must be two characters "
29
- "long."
29
+ "Each part (separated by '-') of the UID must be two characters long."
30
30
  )
31
31
  try:
32
32
  x = int(x, 16)
@@ -1,8 +1,9 @@
1
1
  from typing import Any
2
2
 
3
- import esphome.config_validation as cv
4
3
  from esphome.components import binary_sensor
5
- from .. import const, schema, validate, generate
4
+ import esphome.config_validation as cv
5
+
6
+ from .. import const, generate, schema, validate
6
7
 
7
8
  DEPENDENCIES = [const.OPENTHERM]
8
9
  COMPONENT_TYPE = const.BINARY_SENSOR
@@ -11,8 +12,7 @@ COMPONENT_TYPE = const.BINARY_SENSOR
11
12
  def get_entity_validation_schema(entity: schema.BinarySensorSchema) -> cv.Schema:
12
13
  return binary_sensor.binary_sensor_schema(
13
14
  device_class=(
14
- entity.device_class
15
- or binary_sensor._UNDEF # pylint: disable=protected-access
15
+ entity.device_class or binary_sensor._UNDEF # pylint: disable=protected-access
16
16
  ),
17
17
  icon=(entity.icon or binary_sensor._UNDEF), # pylint: disable=protected-access
18
18
  )
@@ -3,8 +3,9 @@ from typing import Any, Callable, Optional
3
3
 
4
4
  import esphome.codegen as cg
5
5
  from esphome.const import CONF_ID
6
+
6
7
  from . import const
7
- from .schema import TSchema, SettingSchema
8
+ from .schema import SettingSchema, TSchema
8
9
 
9
10
  opentherm_ns = cg.esphome_ns.namespace("opentherm")
10
11
  OpenthermHub = opentherm_ns.class_("OpenthermHub", cg.Component)
@@ -112,11 +113,10 @@ def add_messages(hub: cg.MockObj, keys: list[str], schemas: dict[str, TSchema]):
112
113
  msg_expr = cg.RawExpression(f"esphome::opentherm::MessageId::{msg}")
113
114
  if keep_updated:
114
115
  cg.add(hub.add_repeating_message(msg_expr))
116
+ elif order is not None:
117
+ cg.add(hub.add_initial_message(msg_expr, order))
115
118
  else:
116
- if order is not None:
117
- cg.add(hub.add_initial_message(msg_expr, order))
118
- else:
119
- cg.add(hub.add_initial_message(msg_expr))
119
+ cg.add(hub.add_initial_message(msg_expr))
120
120
 
121
121
 
122
122
  def add_property_set(var: cg.MockObj, config_key: str, config: dict[str, Any]) -> None:
@@ -128,7 +128,7 @@ Create = Callable[[dict[str, Any], str, cg.MockObj], Awaitable[cg.Pvariable]]
128
128
 
129
129
 
130
130
  def create_only_conf(
131
- create: Callable[[dict[str, Any]], Awaitable[cg.Pvariable]]
131
+ create: Callable[[dict[str, Any]], Awaitable[cg.Pvariable]],
132
132
  ) -> Create:
133
133
  return lambda conf, _key, _hub: create(conf)
134
134
 
@@ -1,8 +1,9 @@
1
1
  from typing import Any
2
2
 
3
- import esphome.config_validation as cv
4
3
  from esphome.components import sensor
5
- from .. import const, schema, validate, generate
4
+ import esphome.config_validation as cv
5
+
6
+ from .. import const, generate, schema, validate
6
7
 
7
8
  DEPENDENCIES = [const.OPENTHERM]
8
9
  COMPONENT_TYPE = const.SENSOR
@@ -22,11 +23,9 @@ MSG_DATA_TYPES = {
22
23
 
23
24
  def get_entity_validation_schema(entity: schema.SensorSchema) -> cv.Schema:
24
25
  return sensor.sensor_schema(
25
- unit_of_measurement=entity.unit_of_measurement
26
- or sensor._UNDEF, # pylint: disable=protected-access
26
+ unit_of_measurement=entity.unit_of_measurement or sensor._UNDEF, # pylint: disable=protected-access
27
27
  accuracy_decimals=entity.accuracy_decimals,
28
- device_class=entity.device_class
29
- or sensor._UNDEF, # pylint: disable=protected-access
28
+ device_class=entity.device_class or sensor._UNDEF, # pylint: disable=protected-access
30
29
  icon=entity.icon or sensor._UNDEF, # pylint: disable=protected-access
31
30
  state_class=entity.state_class,
32
31
  ).extend(
@@ -1,8 +1,8 @@
1
1
  from pathlib import Path
2
2
 
3
- import esphome.config_validation as cv
4
3
  from esphome import git, yaml_util
5
4
  from esphome.config_helpers import merge_config
5
+ import esphome.config_validation as cv
6
6
  from esphome.const import (
7
7
  CONF_ESPHOME,
8
8
  CONF_FILE,
@@ -10,12 +10,14 @@ from esphome.const import (
10
10
  CONF_MIN_VERSION,
11
11
  CONF_PACKAGES,
12
12
  CONF_PASSWORD,
13
+ CONF_PATH,
13
14
  CONF_REF,
14
15
  CONF_REFRESH,
15
16
  CONF_URL,
16
17
  CONF_USERNAME,
18
+ CONF_VARS,
19
+ __version__ as ESPHOME_VERSION,
17
20
  )
18
- from esphome.const import __version__ as ESPHOME_VERSION
19
21
  from esphome.core import EsphomeError
20
22
 
21
23
  DOMAIN = CONF_PACKAGES
@@ -74,7 +76,19 @@ BASE_SCHEMA = cv.All(
74
76
  cv.Optional(CONF_PASSWORD): cv.string,
75
77
  cv.Exclusive(CONF_FILE, "files"): validate_yaml_filename,
76
78
  cv.Exclusive(CONF_FILES, "files"): cv.All(
77
- cv.ensure_list(validate_yaml_filename),
79
+ cv.ensure_list(
80
+ cv.Any(
81
+ validate_yaml_filename,
82
+ cv.Schema(
83
+ {
84
+ cv.Required(CONF_PATH): validate_yaml_filename,
85
+ cv.Optional(CONF_VARS, default={}): cv.Schema(
86
+ {cv.string: cv.string}
87
+ ),
88
+ }
89
+ ),
90
+ )
91
+ ),
78
92
  cv.Length(min=1),
79
93
  ),
80
94
  cv.Optional(CONF_REF): cv.git_ref,
@@ -106,16 +120,25 @@ def _process_base_package(config: dict) -> dict:
106
120
  username=config.get(CONF_USERNAME),
107
121
  password=config.get(CONF_PASSWORD),
108
122
  )
109
- files: list[str] = config[CONF_FILES]
123
+ files = []
124
+
125
+ for file in config[CONF_FILES]:
126
+ if isinstance(file, str):
127
+ files.append({CONF_PATH: file, CONF_VARS: {}})
128
+ else:
129
+ files.append(file)
110
130
 
111
131
  def get_packages(files) -> dict:
112
132
  packages = {}
113
- for file in files:
114
- yaml_file: Path = repo_dir / file
133
+ for idx, file in enumerate(files):
134
+ filename = file[CONF_PATH]
135
+ yaml_file: Path = repo_dir / filename
136
+ vars = file.get(CONF_VARS, {})
115
137
 
116
138
  if not yaml_file.is_file():
117
139
  raise cv.Invalid(
118
- f"{file} does not exist in repository", path=[CONF_FILES]
140
+ f"{filename} does not exist in repository",
141
+ path=[CONF_FILES, idx, CONF_PATH],
119
142
  )
120
143
 
121
144
  try:
@@ -131,11 +154,12 @@ def _process_base_package(config: dict) -> dict:
131
154
  raise cv.Invalid(
132
155
  f"Current ESPHome Version is too old to use this package: {ESPHOME_VERSION} < {min_version}"
133
156
  )
134
-
135
- packages[file] = new_yaml
157
+ vars = {k: str(v) for k, v in vars.items()}
158
+ new_yaml = yaml_util.substitute_vars(new_yaml, vars)
159
+ packages[f"{filename}{idx}"] = new_yaml
136
160
  except EsphomeError as e:
137
161
  raise cv.Invalid(
138
- f"{file} is not a valid YAML file. Please check the file contents.\n{e}"
162
+ f"{filename} is not a valid YAML file. Please check the file contents.\n{e}"
139
163
  ) from e
140
164
  return packages
141
165
 
@@ -154,7 +178,7 @@ def _process_base_package(config: dict) -> dict:
154
178
  error = er
155
179
 
156
180
  if packages is None:
157
- raise cv.Invalid(f"Failed to load packages. {error}")
181
+ raise cv.Invalid(f"Failed to load packages. {error}", path=error.path)
158
182
 
159
183
  return {"packages": packages}
160
184
 
@@ -1,9 +1,10 @@
1
1
  import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
2
  from esphome.components import binary_sensor
3
+ import esphome.config_validation as cv
4
4
  from esphome.const import CONF_UID
5
5
  from esphome.core import HexInt
6
- from . import pn532_ns, PN532, CONF_PN532_ID
6
+
7
+ from . import CONF_PN532_ID, PN532, pn532_ns
7
8
 
8
9
  DEPENDENCIES = ["pn532"]
9
10
 
@@ -13,8 +14,7 @@ def validate_uid(value):
13
14
  for x in value.split("-"):
14
15
  if len(x) != 2:
15
16
  raise cv.Invalid(
16
- "Each part (separated by '-') of the UID must be two characters "
17
- "long."
17
+ "Each part (separated by '-') of the UID must be two characters long."
18
18
  )
19
19
  try:
20
20
  x = int(x, 16)
@@ -1,9 +1,10 @@
1
1
  import esphome.codegen as cg
2
- import esphome.config_validation as cv
3
2
  from esphome.components import binary_sensor
3
+ import esphome.config_validation as cv
4
4
  from esphome.const import CONF_UID
5
5
  from esphome.core import HexInt
6
- from . import rc522_ns, RC522, CONF_RC522_ID
6
+
7
+ from . import CONF_RC522_ID, RC522, rc522_ns
7
8
 
8
9
  DEPENDENCIES = ["rc522"]
9
10
 
@@ -13,8 +14,7 @@ def validate_uid(value):
13
14
  for x in value.split("-"):
14
15
  if len(x) != 2:
15
16
  raise cv.Invalid(
16
- "Each part (separated by '-') of the UID must be two characters "
17
- "long."
17
+ "Each part (separated by '-') of the UID must be two characters long."
18
18
  )
19
19
  try:
20
20
  x = int(x, 16)
@@ -46,6 +46,7 @@ class BSDSocketImpl : public Socket {
46
46
  close(); // NOLINT(clang-analyzer-optin.cplusplus.VirtualCall)
47
47
  }
48
48
  }
49
+ int connect(const struct sockaddr *addr, socklen_t addrlen) override { return ::connect(fd_, addr, addrlen); }
49
50
  std::unique_ptr<Socket> accept(struct sockaddr *addr, socklen_t *addrlen) override {
50
51
  int fd = ::accept(fd_, addr, addrlen);
51
52
  if (fd == -1)
@@ -39,6 +39,7 @@ class LwIPSocketImpl : public Socket {
39
39
  close(); // NOLINT(clang-analyzer-optin.cplusplus.VirtualCall)
40
40
  }
41
41
  }
42
+ int connect(const struct sockaddr *addr, socklen_t addrlen) override { return lwip_connect(fd_, addr, addrlen); }
42
43
  std::unique_ptr<Socket> accept(struct sockaddr *addr, socklen_t *addrlen) override {
43
44
  int fd = lwip_accept(fd_, addr, addrlen);
44
45
  if (fd == -1)
@@ -21,7 +21,9 @@ class Socket {
21
21
  virtual int close() = 0;
22
22
  // not supported yet:
23
23
  // virtual int connect(const std::string &address) = 0;
24
- // virtual int connect(const struct sockaddr *addr, socklen_t addrlen) = 0;
24
+ #if defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS)
25
+ virtual int connect(const struct sockaddr *addr, socklen_t addrlen) = 0;
26
+ #endif
25
27
  virtual int shutdown(int how) = 0;
26
28
 
27
29
  virtual int getpeername(struct sockaddr *addr, socklen_t *addrlen) = 0;