esphome 2025.4.0b2__py3-none-any.whl → 2025.4.1__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.
esphome/__main__.py CHANGED
@@ -375,10 +375,12 @@ def upload_program(config, args, host):
375
375
  password = ota_conf.get(CONF_PASSWORD, "")
376
376
 
377
377
  if (
378
- not is_ip_address(CORE.address) # pylint: disable=too-many-boolean-expressions
379
- and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED])
380
- and CONF_MQTT in config
378
+ CONF_MQTT in config # pylint: disable=too-many-boolean-expressions
381
379
  and (not args.device or args.device in ("MQTT", "OTA"))
380
+ and (
381
+ ((config[CONF_MDNS][CONF_DISABLED]) and not is_ip_address(CORE.address))
382
+ or get_port_type(host) == "MQTT"
383
+ )
382
384
  ):
383
385
  from esphome import mqtt
384
386
 
@@ -128,7 +128,7 @@ void AM2315C::update() {
128
128
  data[2] = 0x00;
129
129
  if (this->write(data, 3) != i2c::ERROR_OK) {
130
130
  ESP_LOGE(TAG, "Write failed!");
131
- this->mark_failed();
131
+ this->status_set_warning();
132
132
  return;
133
133
  }
134
134
 
@@ -138,12 +138,12 @@ void AM2315C::update() {
138
138
  uint8_t status = 0;
139
139
  if (this->read(&status, 1) != i2c::ERROR_OK) {
140
140
  ESP_LOGE(TAG, "Read failed!");
141
- this->mark_failed();
141
+ this->status_set_warning();
142
142
  return;
143
143
  }
144
144
  if ((status & 0x80) == 0x80) {
145
145
  ESP_LOGE(TAG, "HW still busy!");
146
- this->mark_failed();
146
+ this->status_set_warning();
147
147
  return;
148
148
  }
149
149
 
@@ -151,7 +151,7 @@ void AM2315C::update() {
151
151
  uint8_t data[7];
152
152
  if (this->read(data, 7) != i2c::ERROR_OK) {
153
153
  ESP_LOGE(TAG, "Read failed!");
154
- this->mark_failed();
154
+ this->status_set_warning();
155
155
  return;
156
156
  }
157
157
 
@@ -265,6 +265,12 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest
265
265
  connection->get_connection_index(), connection->address_str().c_str());
266
266
  return;
267
267
  } else if (connection->state() == espbt::ClientState::CONNECTING) {
268
+ if (connection->disconnect_pending()) {
269
+ ESP_LOGW(TAG, "[%d] [%s] Connection request while pending disconnect, cancelling pending disconnect",
270
+ connection->get_connection_index(), connection->address_str().c_str());
271
+ connection->cancel_pending_disconnect();
272
+ return;
273
+ }
268
274
  ESP_LOGW(TAG, "[%d] [%s] Connection request ignored, already connecting", connection->get_connection_index(),
269
275
  connection->address_str().c_str());
270
276
  return;
@@ -187,7 +187,7 @@ void ENS160Component::update() {
187
187
  }
188
188
  return;
189
189
  case INVALID_OUTPUT:
190
- ESP_LOGE(TAG, "ENS160 Invalid Status - No Invalid Output");
190
+ ESP_LOGE(TAG, "ENS160 Invalid Status - No valid output");
191
191
  this->status_set_warning();
192
192
  return;
193
193
  }
@@ -173,6 +173,8 @@ class ESPBTClient : public ESPBTDeviceListener {
173
173
  virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0;
174
174
  virtual void connect() = 0;
175
175
  virtual void disconnect() = 0;
176
+ bool disconnect_pending() const { return this->want_disconnect_; }
177
+ void cancel_pending_disconnect() { this->want_disconnect_ = false; }
176
178
  virtual void set_state(ClientState st) {
177
179
  this->state_ = st;
178
180
  if (st == ClientState::IDLE) {
@@ -120,6 +120,7 @@ void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_ev
120
120
  void LvglComponent::add_page(LvPageType *page) {
121
121
  this->pages_.push_back(page);
122
122
  page->set_parent(this);
123
+ lv_disp_set_default(this->disp_);
123
124
  page->setup(this->pages_.size() - 1);
124
125
  }
125
126
  void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time) {
@@ -111,7 +111,7 @@ void OnlineImage::update() {
111
111
  case ImageFormat::BMP:
112
112
  accept_mime_type = "image/bmp";
113
113
  break;
114
- #endif // ONLINE_IMAGE_BMP_SUPPORT
114
+ #endif // USE_ONLINE_IMAGE_BMP_SUPPORT
115
115
  #ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
116
116
  case ImageFormat::JPEG:
117
117
  accept_mime_type = "image/jpeg";
@@ -121,7 +121,7 @@ void OnlineImage::update() {
121
121
  case ImageFormat::PNG:
122
122
  accept_mime_type = "image/png";
123
123
  break;
124
- #endif // ONLINE_IMAGE_PNG_SUPPORT
124
+ #endif // USE_ONLINE_IMAGE_PNG_SUPPORT
125
125
  default:
126
126
  accept_mime_type = "image/*";
127
127
  }
@@ -159,7 +159,7 @@ void OnlineImage::update() {
159
159
  ESP_LOGD(TAG, "Allocating BMP decoder");
160
160
  this->decoder_ = make_unique<BmpDecoder>(this);
161
161
  }
162
- #endif // ONLINE_IMAGE_BMP_SUPPORT
162
+ #endif // USE_ONLINE_IMAGE_BMP_SUPPORT
163
163
  #ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
164
164
  if (this->format_ == ImageFormat::JPEG) {
165
165
  ESP_LOGD(TAG, "Allocating JPEG decoder");
@@ -171,7 +171,7 @@ void OnlineImage::update() {
171
171
  ESP_LOGD(TAG, "Allocating PNG decoder");
172
172
  this->decoder_ = make_unique<PngDecoder>(this);
173
173
  }
174
- #endif // ONLINE_IMAGE_PNG_SUPPORT
174
+ #endif // USE_ONLINE_IMAGE_PNG_SUPPORT
175
175
 
176
176
  if (!this->decoder_) {
177
177
  ESP_LOGE(TAG, "Could not instantiate decoder. Image format unsupported: %d", this->format_);
@@ -185,7 +185,7 @@ void OnlineImage::update() {
185
185
  this->download_error_callback_.call();
186
186
  return;
187
187
  }
188
- ESP_LOGI(TAG, "Downloading image (Size: %d)", total_size);
188
+ ESP_LOGI(TAG, "Downloading image (Size: %zu)", total_size);
189
189
  this->start_time_ = ::time(nullptr);
190
190
  }
191
191
 
@@ -1,7 +1,8 @@
1
1
 
2
2
  #ifdef USE_ESP32
3
3
  #include "psram.h"
4
- #ifdef USE_ESP_IDF
4
+ #include <esp_idf_version.h>
5
+ #if defined(USE_ESP_IDF) && ESP_IDF_VERSION_MAJOR >= 5
5
6
  #include <esp_psram.h>
6
7
  #endif // USE_ESP_IDF
7
8
 
@@ -15,7 +16,7 @@ static const char *const TAG = "psram";
15
16
 
16
17
  void PsramComponent::dump_config() {
17
18
  ESP_LOGCONFIG(TAG, "PSRAM:");
18
- #ifdef USE_ESP_IDF
19
+ #if defined(USE_ESP_IDF) && ESP_IDF_VERSION_MAJOR >= 5
19
20
  bool available = esp_psram_is_initialized();
20
21
 
21
22
  ESP_LOGCONFIG(TAG, " Available: %s", YESNO(available));
@@ -52,9 +52,8 @@ void Sml::loop() {
52
52
  break;
53
53
 
54
54
  // remove start/end sequence
55
- this->sml_data_.erase(this->sml_data_.begin(), this->sml_data_.begin() + START_SEQ.size());
56
- this->sml_data_.resize(this->sml_data_.size() - 8);
57
- this->process_sml_file_(this->sml_data_);
55
+ this->process_sml_file_(
56
+ BytesView(this->sml_data_).subview(START_SEQ.size(), this->sml_data_.size() - START_SEQ.size() - 8));
58
57
  }
59
58
  break;
60
59
  };
@@ -66,8 +65,8 @@ void Sml::add_on_data_callback(std::function<void(std::vector<uint8_t>, bool)> &
66
65
  this->data_callbacks_.add(std::move(callback));
67
66
  }
68
67
 
69
- void Sml::process_sml_file_(const bytes &sml_data) {
70
- SmlFile sml_file = SmlFile(sml_data);
68
+ void Sml::process_sml_file_(const BytesView &sml_data) {
69
+ SmlFile sml_file(sml_data);
71
70
  std::vector<ObisInfo> obis_info = sml_file.get_obis_info();
72
71
  this->publish_obis_info_(obis_info);
73
72
 
@@ -75,6 +74,7 @@ void Sml::process_sml_file_(const bytes &sml_data) {
75
74
  }
76
75
 
77
76
  void Sml::log_obis_info_(const std::vector<ObisInfo> &obis_info_vec) {
77
+ #ifdef ESPHOME_LOG_HAS_DEBUG
78
78
  ESP_LOGD(TAG, "OBIS info:");
79
79
  for (auto const &obis_info : obis_info_vec) {
80
80
  std::string info;
@@ -83,6 +83,7 @@ void Sml::log_obis_info_(const std::vector<ObisInfo> &obis_info_vec) {
83
83
  info += " [0x" + bytes_repr(obis_info.value) + "]";
84
84
  ESP_LOGD(TAG, "%s", info.c_str());
85
85
  }
86
+ #endif
86
87
  }
87
88
 
88
89
  void Sml::publish_obis_info_(const std::vector<ObisInfo> &obis_info_vec) {
@@ -92,10 +93,11 @@ void Sml::publish_obis_info_(const std::vector<ObisInfo> &obis_info_vec) {
92
93
  }
93
94
 
94
95
  void Sml::publish_value_(const ObisInfo &obis_info) {
96
+ const auto obis_code = obis_info.code_repr();
95
97
  for (auto const &sml_listener : sml_listeners_) {
96
98
  if ((!sml_listener->server_id.empty()) && (bytes_repr(obis_info.server_id) != sml_listener->server_id))
97
99
  continue;
98
- if (obis_info.code_repr() != sml_listener->obis_code)
100
+ if (obis_code != sml_listener->obis_code)
99
101
  continue;
100
102
  sml_listener->publish_val(obis_info);
101
103
  }
@@ -27,7 +27,7 @@ class Sml : public Component, public uart::UARTDevice {
27
27
  void add_on_data_callback(std::function<void(std::vector<uint8_t>, bool)> &&callback);
28
28
 
29
29
  protected:
30
- void process_sml_file_(const bytes &sml_data);
30
+ void process_sml_file_(const BytesView &sml_data);
31
31
  void log_obis_info_(const std::vector<ObisInfo> &obis_info_vec);
32
32
  void publish_obis_info_(const std::vector<ObisInfo> &obis_info_vec);
33
33
  char check_start_end_bytes_(uint8_t byte);
@@ -5,17 +5,17 @@
5
5
  namespace esphome {
6
6
  namespace sml {
7
7
 
8
- SmlFile::SmlFile(bytes buffer) : buffer_(std::move(buffer)) {
8
+ SmlFile::SmlFile(const BytesView &buffer) : buffer_(buffer) {
9
9
  // extract messages
10
10
  this->pos_ = 0;
11
11
  while (this->pos_ < this->buffer_.size()) {
12
12
  if (this->buffer_[this->pos_] == 0x00)
13
13
  break; // EndOfSmlMsg
14
14
 
15
- SmlNode message = SmlNode();
15
+ SmlNode message;
16
16
  if (!this->setup_node(&message))
17
17
  break;
18
- this->messages.emplace_back(message);
18
+ this->messages.emplace_back(std::move(message));
19
19
  }
20
20
  }
21
21
 
@@ -62,22 +62,20 @@ bool SmlFile::setup_node(SmlNode *node) {
62
62
  return false;
63
63
 
64
64
  node->type = type;
65
- node->nodes.clear();
66
- node->value_bytes.clear();
67
65
 
68
66
  if (type == SML_LIST) {
69
67
  node->nodes.reserve(length);
70
68
  for (size_t i = 0; i != length; i++) {
71
- SmlNode child_node = SmlNode();
69
+ SmlNode child_node;
72
70
  if (!this->setup_node(&child_node))
73
71
  return false;
74
- node->nodes.emplace_back(child_node);
72
+ node->nodes.emplace_back(std::move(child_node));
75
73
  }
76
74
  } else {
77
75
  // Value starts at the current position
78
76
  // Value ends "length" bytes later,
79
77
  // (since the TL field is counted but already subtracted from length)
80
- node->value_bytes = bytes(this->buffer_.begin() + this->pos_, this->buffer_.begin() + this->pos_ + length);
78
+ node->value_bytes = buffer_.subview(this->pos_, length);
81
79
  // Increment the pointer past all consumed bytes
82
80
  this->pos_ += length;
83
81
  }
@@ -87,14 +85,14 @@ bool SmlFile::setup_node(SmlNode *node) {
87
85
  std::vector<ObisInfo> SmlFile::get_obis_info() {
88
86
  std::vector<ObisInfo> obis_info;
89
87
  for (auto const &message : messages) {
90
- SmlNode message_body = message.nodes[3];
88
+ const auto &message_body = message.nodes[3];
91
89
  uint16_t message_type = bytes_to_uint(message_body.nodes[0].value_bytes);
92
90
  if (message_type != SML_GET_LIST_RES)
93
91
  continue;
94
92
 
95
- SmlNode get_list_response = message_body.nodes[1];
96
- bytes server_id = get_list_response.nodes[1].value_bytes;
97
- SmlNode val_list = get_list_response.nodes[4];
93
+ const auto &get_list_response = message_body.nodes[1];
94
+ const auto &server_id = get_list_response.nodes[1].value_bytes;
95
+ const auto &val_list = get_list_response.nodes[4];
98
96
 
99
97
  for (auto const &val_list_entry : val_list.nodes) {
100
98
  obis_info.emplace_back(server_id, val_list_entry);
@@ -103,7 +101,7 @@ std::vector<ObisInfo> SmlFile::get_obis_info() {
103
101
  return obis_info;
104
102
  }
105
103
 
106
- std::string bytes_repr(const bytes &buffer) {
104
+ std::string bytes_repr(const BytesView &buffer) {
107
105
  std::string repr;
108
106
  for (auto const value : buffer) {
109
107
  repr += str_sprintf("%02x", value & 0xff);
@@ -111,7 +109,7 @@ std::string bytes_repr(const bytes &buffer) {
111
109
  return repr;
112
110
  }
113
111
 
114
- uint64_t bytes_to_uint(const bytes &buffer) {
112
+ uint64_t bytes_to_uint(const BytesView &buffer) {
115
113
  uint64_t val = 0;
116
114
  for (auto const value : buffer) {
117
115
  val = (val << 8) + value;
@@ -119,7 +117,7 @@ uint64_t bytes_to_uint(const bytes &buffer) {
119
117
  return val;
120
118
  }
121
119
 
122
- int64_t bytes_to_int(const bytes &buffer) {
120
+ int64_t bytes_to_int(const BytesView &buffer) {
123
121
  uint64_t tmp = bytes_to_uint(buffer);
124
122
  int64_t val;
125
123
 
@@ -135,14 +133,14 @@ int64_t bytes_to_int(const bytes &buffer) {
135
133
  return val;
136
134
  }
137
135
 
138
- std::string bytes_to_string(const bytes &buffer) { return std::string(buffer.begin(), buffer.end()); }
136
+ std::string bytes_to_string(const BytesView &buffer) { return std::string(buffer.begin(), buffer.end()); }
139
137
 
140
- ObisInfo::ObisInfo(bytes server_id, SmlNode val_list_entry) : server_id(std::move(server_id)) {
138
+ ObisInfo::ObisInfo(const BytesView &server_id, const SmlNode &val_list_entry) : server_id(server_id) {
141
139
  this->code = val_list_entry.nodes[0].value_bytes;
142
140
  this->status = val_list_entry.nodes[1].value_bytes;
143
141
  this->unit = bytes_to_uint(val_list_entry.nodes[3].value_bytes);
144
142
  this->scaler = bytes_to_int(val_list_entry.nodes[4].value_bytes);
145
- SmlNode value_node = val_list_entry.nodes[5];
143
+ const auto &value_node = val_list_entry.nodes[5];
146
144
  this->value = value_node.value_bytes;
147
145
  this->value_type = value_node.type;
148
146
  }
@@ -1,5 +1,6 @@
1
1
  #pragma once
2
2
 
3
+ #include <cassert>
3
4
  #include <cstdint>
4
5
  #include <cstdio>
5
6
  #include <string>
@@ -11,44 +12,73 @@ namespace sml {
11
12
 
12
13
  using bytes = std::vector<uint8_t>;
13
14
 
15
+ class BytesView {
16
+ public:
17
+ BytesView() noexcept = default;
18
+
19
+ explicit BytesView(const uint8_t *first, size_t count) noexcept : data_{first}, count_{count} {}
20
+
21
+ explicit BytesView(const bytes &bytes) noexcept : data_{bytes.data()}, count_{bytes.size()} {}
22
+
23
+ size_t size() const noexcept { return count_; }
24
+
25
+ uint8_t operator[](size_t index) const noexcept {
26
+ assert(index < count_);
27
+ return data_[index];
28
+ }
29
+
30
+ BytesView subview(size_t offset, size_t count) const noexcept {
31
+ assert(offset + count <= count_);
32
+ return BytesView{data_ + offset, count};
33
+ }
34
+
35
+ const uint8_t *begin() const noexcept { return data_; }
36
+
37
+ const uint8_t *end() const noexcept { return data_ + count_; }
38
+
39
+ private:
40
+ const uint8_t *data_ = nullptr;
41
+ size_t count_ = 0;
42
+ };
43
+
14
44
  class SmlNode {
15
45
  public:
16
46
  uint8_t type;
17
- bytes value_bytes;
47
+ BytesView value_bytes;
18
48
  std::vector<SmlNode> nodes;
19
49
  };
20
50
 
21
51
  class ObisInfo {
22
52
  public:
23
- ObisInfo(bytes server_id, SmlNode val_list_entry);
24
- bytes server_id;
25
- bytes code;
26
- bytes status;
53
+ ObisInfo(const BytesView &server_id, const SmlNode &val_list_entry);
54
+ BytesView server_id;
55
+ BytesView code;
56
+ BytesView status;
27
57
  char unit;
28
58
  char scaler;
29
- bytes value;
59
+ BytesView value;
30
60
  uint16_t value_type;
31
61
  std::string code_repr() const;
32
62
  };
33
63
 
34
64
  class SmlFile {
35
65
  public:
36
- SmlFile(bytes buffer);
66
+ SmlFile(const BytesView &buffer);
37
67
  bool setup_node(SmlNode *node);
38
68
  std::vector<SmlNode> messages;
39
69
  std::vector<ObisInfo> get_obis_info();
40
70
 
41
71
  protected:
42
- const bytes buffer_;
72
+ const BytesView buffer_;
43
73
  size_t pos_;
44
74
  };
45
75
 
46
- std::string bytes_repr(const bytes &buffer);
76
+ std::string bytes_repr(const BytesView &buffer);
47
77
 
48
- uint64_t bytes_to_uint(const bytes &buffer);
78
+ uint64_t bytes_to_uint(const BytesView &buffer);
49
79
 
50
- int64_t bytes_to_int(const bytes &buffer);
80
+ int64_t bytes_to_int(const BytesView &buffer);
51
81
 
52
- std::string bytes_to_string(const bytes &buffer);
82
+ std::string bytes_to_string(const BytesView &buffer);
53
83
  } // namespace sml
54
84
  } // namespace esphome
@@ -6,6 +6,7 @@
6
6
  #include <cinttypes>
7
7
  #include <cstdint>
8
8
  #ifdef USE_ESP32
9
+ #include <soc/soc_caps.h>
9
10
  #include "esp_idf_version.h"
10
11
  #include "esp_task_wdt.h"
11
12
  #endif
@@ -40,7 +41,7 @@ void WatchdogManager::set_timeout_(uint32_t timeout_ms) {
40
41
  #if ESP_IDF_VERSION_MAJOR >= 5
41
42
  esp_task_wdt_config_t wdt_config = {
42
43
  .timeout_ms = timeout_ms,
43
- .idle_core_mask = 0x03,
44
+ .idle_core_mask = (1 << SOC_CPU_CORES_NUM) - 1,
44
45
  .trigger_panic = true,
45
46
  };
46
47
  esp_task_wdt_reconfigure(&wdt_config);
@@ -1499,30 +1499,9 @@ def dimensions(value):
1499
1499
 
1500
1500
 
1501
1501
  def directory(value):
1502
- import json
1503
-
1504
1502
  value = string(value)
1505
1503
  path = CORE.relative_config_path(value)
1506
1504
 
1507
- if CORE.vscode and (
1508
- not CORE.ace or os.path.abspath(path) == os.path.abspath(CORE.config_path)
1509
- ):
1510
- print(
1511
- json.dumps(
1512
- {
1513
- "type": "check_directory_exists",
1514
- "path": path,
1515
- }
1516
- )
1517
- )
1518
- data = json.loads(input())
1519
- assert data["type"] == "directory_exists_response"
1520
- if data["content"]:
1521
- return value
1522
- raise Invalid(
1523
- f"Could not find directory '{path}'. Please make sure it exists (full path: {os.path.abspath(path)})."
1524
- )
1525
-
1526
1505
  if not os.path.exists(path):
1527
1506
  raise Invalid(
1528
1507
  f"Could not find directory '{path}'. Please make sure it exists (full path: {os.path.abspath(path)})."
@@ -1535,30 +1514,9 @@ def directory(value):
1535
1514
 
1536
1515
 
1537
1516
  def file_(value):
1538
- import json
1539
-
1540
1517
  value = string(value)
1541
1518
  path = CORE.relative_config_path(value)
1542
1519
 
1543
- if CORE.vscode and (
1544
- not CORE.ace or os.path.abspath(path) == os.path.abspath(CORE.config_path)
1545
- ):
1546
- print(
1547
- json.dumps(
1548
- {
1549
- "type": "check_file_exists",
1550
- "path": path,
1551
- }
1552
- )
1553
- )
1554
- data = json.loads(input())
1555
- assert data["type"] == "file_exists_response"
1556
- if data["content"]:
1557
- return value
1558
- raise Invalid(
1559
- f"Could not find file '{path}'. Please make sure it exists (full path: {os.path.abspath(path)})."
1560
- )
1561
-
1562
1520
  if not os.path.exists(path):
1563
1521
  raise Invalid(
1564
1522
  f"Could not find file '{path}'. Please make sure it exists (full path: {os.path.abspath(path)})."
esphome/const.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Constants used by esphome."""
2
2
 
3
- __version__ = "2025.4.0b2"
3
+ __version__ = "2025.4.1"
4
4
 
5
5
  ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
6
6
  VALID_SUBSTITUTIONS_CHARACTERS = (
esphome/core/__init__.py CHANGED
@@ -475,7 +475,6 @@ class EsphomeCore:
475
475
  self.dashboard = False
476
476
  # True if command is run from vscode api
477
477
  self.vscode = False
478
- self.ace = False
479
478
  # The name of the node
480
479
  self.name: Optional[str] = None
481
480
  # The friendly name of the node
esphome/log.py CHANGED
@@ -74,13 +74,14 @@ def setup_log(
74
74
 
75
75
  colorama.init()
76
76
 
77
- if log_level == logging.DEBUG:
77
+ # Setup logging - will map log level from string to constant
78
+ logging.basicConfig(level=log_level)
79
+
80
+ if logging.root.level == logging.DEBUG:
78
81
  CORE.verbose = True
79
- elif log_level == logging.CRITICAL:
82
+ elif logging.root.level == logging.CRITICAL:
80
83
  CORE.quiet = True
81
84
 
82
- logging.basicConfig(level=log_level)
83
-
84
85
  logging.getLogger("urllib3").setLevel(logging.WARNING)
85
86
 
86
87
  logging.getLogger().handlers[0].setFormatter(
esphome/vscode.py CHANGED
@@ -78,28 +78,47 @@ def _print_file_read_event(path: str) -> None:
78
78
  )
79
79
 
80
80
 
81
+ def _request_and_get_stream_on_stdin(fname: str) -> StringIO:
82
+ _print_file_read_event(fname)
83
+ raw_yaml_stream = StringIO(_read_file_content_from_json_on_stdin())
84
+ return raw_yaml_stream
85
+
86
+
87
+ def _vscode_loader(fname: str) -> dict[str, Any]:
88
+ raw_yaml_stream = _request_and_get_stream_on_stdin(fname)
89
+ # it is required to set the name on StringIO so document on start_mark
90
+ # is set properly. Otherwise it is initialized with "<file>"
91
+ raw_yaml_stream.name = fname
92
+ return parse_yaml(fname, raw_yaml_stream, _vscode_loader)
93
+
94
+
95
+ def _ace_loader(fname: str) -> dict[str, Any]:
96
+ raw_yaml_stream = _request_and_get_stream_on_stdin(fname)
97
+ return parse_yaml(fname, raw_yaml_stream)
98
+
99
+
81
100
  def read_config(args):
82
101
  while True:
83
102
  CORE.reset()
84
103
  data = json.loads(input())
85
- assert data["type"] == "validate"
104
+ assert data["type"] == "validate" or data["type"] == "exit"
105
+ if data["type"] == "exit":
106
+ return
86
107
  CORE.vscode = True
87
- CORE.ace = args.ace
88
- f = data["file"]
89
- if CORE.ace:
90
- CORE.config_path = os.path.join(args.configuration, f)
108
+ if args.ace: # Running from ESPHome Compiler dashboard, not vscode
109
+ CORE.config_path = os.path.join(args.configuration, data["file"])
110
+ loader = _ace_loader
91
111
  else:
92
112
  CORE.config_path = data["file"]
113
+ loader = _vscode_loader
93
114
 
94
115
  file_name = CORE.config_path
95
- _print_file_read_event(file_name)
96
- raw_yaml = _read_file_content_from_json_on_stdin()
97
116
  command_line_substitutions: dict[str, Any] = (
98
117
  dict(args.substitution) if args.substitution else {}
99
118
  )
100
119
  vs = VSCodeResult()
101
120
  try:
102
- config = parse_yaml(file_name, StringIO(raw_yaml))
121
+ config = loader(file_name)
103
122
  res = validate_config(config, command_line_substitutions)
104
123
  except Exception as err: # pylint: disable=broad-except
105
124
  vs.add_yaml_error(str(err))
esphome/yaml_util.py CHANGED
@@ -3,12 +3,12 @@ from __future__ import annotations
3
3
  import fnmatch
4
4
  import functools
5
5
  import inspect
6
- from io import TextIOWrapper
6
+ from io import BytesIO, TextIOBase, TextIOWrapper
7
7
  from ipaddress import _BaseAddress
8
8
  import logging
9
9
  import math
10
10
  import os
11
- from typing import Any
11
+ from typing import Any, Callable
12
12
  import uuid
13
13
 
14
14
  import yaml
@@ -69,7 +69,10 @@ class ESPForceValue:
69
69
  pass
70
70
 
71
71
 
72
- def make_data_base(value, from_database: ESPHomeDataBase = None):
72
+ def make_data_base(
73
+ value, from_database: ESPHomeDataBase = None
74
+ ) -> ESPHomeDataBase | Any:
75
+ """Wrap a value in a ESPHomeDataBase object."""
73
76
  try:
74
77
  value = add_class_to_obj(value, ESPHomeDataBase)
75
78
  if from_database is not None:
@@ -102,6 +105,11 @@ def _add_data_ref(fn):
102
105
  class ESPHomeLoaderMixin:
103
106
  """Loader class that keeps track of line numbers."""
104
107
 
108
+ def __init__(self, name: str, yaml_loader: Callable[[str], dict[str, Any]]) -> None:
109
+ """Initialize the loader."""
110
+ self.name = name
111
+ self.yaml_loader = yaml_loader
112
+
105
113
  @_add_data_ref
106
114
  def construct_yaml_int(self, node):
107
115
  return super().construct_yaml_int(node)
@@ -127,7 +135,7 @@ class ESPHomeLoaderMixin:
127
135
  return super().construct_yaml_seq(node)
128
136
 
129
137
  @_add_data_ref
130
- def construct_yaml_map(self, node):
138
+ def construct_yaml_map(self, node: yaml.MappingNode) -> OrderedDict[str, Any]:
131
139
  """Traverses the given mapping node and returns a list of constructed key-value pairs."""
132
140
  assert isinstance(node, yaml.MappingNode)
133
141
  # A list of key-value pairs we find in the current mapping
@@ -231,7 +239,7 @@ class ESPHomeLoaderMixin:
231
239
  return OrderedDict(pairs)
232
240
 
233
241
  @_add_data_ref
234
- def construct_env_var(self, node):
242
+ def construct_env_var(self, node: yaml.Node) -> str:
235
243
  args = node.value.split()
236
244
  # Check for a default value
237
245
  if len(args) > 1:
@@ -243,23 +251,23 @@ class ESPHomeLoaderMixin:
243
251
  )
244
252
 
245
253
  @property
246
- def _directory(self):
254
+ def _directory(self) -> str:
247
255
  return os.path.dirname(self.name)
248
256
 
249
- def _rel_path(self, *args):
257
+ def _rel_path(self, *args: str) -> str:
250
258
  return os.path.join(self._directory, *args)
251
259
 
252
260
  @_add_data_ref
253
- def construct_secret(self, node):
261
+ def construct_secret(self, node: yaml.Node) -> str:
254
262
  try:
255
- secrets = _load_yaml_internal(self._rel_path(SECRET_YAML))
263
+ secrets = self.yaml_loader(self._rel_path(SECRET_YAML))
256
264
  except EsphomeError as e:
257
265
  if self.name == CORE.config_path:
258
266
  raise e
259
267
  try:
260
268
  main_config_dir = os.path.dirname(CORE.config_path)
261
269
  main_secret_yml = os.path.join(main_config_dir, SECRET_YAML)
262
- secrets = _load_yaml_internal(main_secret_yml)
270
+ secrets = self.yaml_loader(main_secret_yml)
263
271
  except EsphomeError as er:
264
272
  raise EsphomeError(f"{e}\n{er}") from er
265
273
 
@@ -272,7 +280,9 @@ class ESPHomeLoaderMixin:
272
280
  return val
273
281
 
274
282
  @_add_data_ref
275
- def construct_include(self, node):
283
+ def construct_include(
284
+ self, node: yaml.Node
285
+ ) -> dict[str, Any] | OrderedDict[str, Any]:
276
286
  from esphome.const import CONF_VARS
277
287
 
278
288
  def extract_file_vars(node):
@@ -290,71 +300,93 @@ class ESPHomeLoaderMixin:
290
300
  else:
291
301
  file, vars = node.value, None
292
302
 
293
- result = _load_yaml_internal(self._rel_path(file))
303
+ result = self.yaml_loader(self._rel_path(file))
294
304
  if not vars:
295
305
  vars = {}
296
306
  result = substitute_vars(result, vars)
297
307
  return result
298
308
 
299
309
  @_add_data_ref
300
- def construct_include_dir_list(self, node):
310
+ def construct_include_dir_list(self, node: yaml.Node) -> list[dict[str, Any]]:
301
311
  files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml"))
302
- return [_load_yaml_internal(f) for f in files]
312
+ return [self.yaml_loader(f) for f in files]
303
313
 
304
314
  @_add_data_ref
305
- def construct_include_dir_merge_list(self, node):
315
+ def construct_include_dir_merge_list(self, node: yaml.Node) -> list[dict[str, Any]]:
306
316
  files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml"))
307
317
  merged_list = []
308
318
  for fname in files:
309
- loaded_yaml = _load_yaml_internal(fname)
319
+ loaded_yaml = self.yaml_loader(fname)
310
320
  if isinstance(loaded_yaml, list):
311
321
  merged_list.extend(loaded_yaml)
312
322
  return merged_list
313
323
 
314
324
  @_add_data_ref
315
- def construct_include_dir_named(self, node):
325
+ def construct_include_dir_named(
326
+ self, node: yaml.Node
327
+ ) -> OrderedDict[str, dict[str, Any]]:
316
328
  files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml"))
317
329
  mapping = OrderedDict()
318
330
  for fname in files:
319
331
  filename = os.path.splitext(os.path.basename(fname))[0]
320
- mapping[filename] = _load_yaml_internal(fname)
332
+ mapping[filename] = self.yaml_loader(fname)
321
333
  return mapping
322
334
 
323
335
  @_add_data_ref
324
- def construct_include_dir_merge_named(self, node):
336
+ def construct_include_dir_merge_named(
337
+ self, node: yaml.Node
338
+ ) -> OrderedDict[str, dict[str, Any]]:
325
339
  files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml"))
326
340
  mapping = OrderedDict()
327
341
  for fname in files:
328
- loaded_yaml = _load_yaml_internal(fname)
342
+ loaded_yaml = self.yaml_loader(fname)
329
343
  if isinstance(loaded_yaml, dict):
330
344
  mapping.update(loaded_yaml)
331
345
  return mapping
332
346
 
333
347
  @_add_data_ref
334
- def construct_lambda(self, node):
348
+ def construct_lambda(self, node: yaml.Node) -> Lambda:
335
349
  return Lambda(str(node.value))
336
350
 
337
351
  @_add_data_ref
338
- def construct_force(self, node):
352
+ def construct_force(self, node: yaml.Node) -> ESPForceValue:
339
353
  obj = self.construct_scalar(node)
340
354
  return add_class_to_obj(obj, ESPForceValue)
341
355
 
342
356
  @_add_data_ref
343
- def construct_extend(self, node):
357
+ def construct_extend(self, node: yaml.Node) -> Extend:
344
358
  return Extend(str(node.value))
345
359
 
346
360
  @_add_data_ref
347
- def construct_remove(self, node):
361
+ def construct_remove(self, node: yaml.Node) -> Remove:
348
362
  return Remove(str(node.value))
349
363
 
350
364
 
351
365
  class ESPHomeLoader(ESPHomeLoaderMixin, FastestAvailableSafeLoader):
352
366
  """Loader class that keeps track of line numbers."""
353
367
 
368
+ def __init__(
369
+ self,
370
+ stream: TextIOBase | BytesIO,
371
+ name: str,
372
+ yaml_loader: Callable[[str], dict[str, Any]],
373
+ ) -> None:
374
+ FastestAvailableSafeLoader.__init__(self, stream)
375
+ ESPHomeLoaderMixin.__init__(self, name, yaml_loader)
376
+
354
377
 
355
378
  class ESPHomePurePythonLoader(ESPHomeLoaderMixin, PurePythonLoader):
356
379
  """Loader class that keeps track of line numbers."""
357
380
 
381
+ def __init__(
382
+ self,
383
+ stream: TextIOBase | BytesIO,
384
+ name: str,
385
+ yaml_loader: Callable[[str], dict[str, Any]],
386
+ ) -> None:
387
+ PurePythonLoader.__init__(self, stream)
388
+ ESPHomeLoaderMixin.__init__(self, name, yaml_loader)
389
+
358
390
 
359
391
  for _loader in (ESPHomeLoader, ESPHomePurePythonLoader):
360
392
  _loader.add_constructor("tag:yaml.org,2002:int", _loader.construct_yaml_int)
@@ -388,17 +420,30 @@ def load_yaml(fname: str, clear_secrets: bool = True) -> Any:
388
420
  return _load_yaml_internal(fname)
389
421
 
390
422
 
391
- def parse_yaml(file_name: str, file_handle: TextIOWrapper) -> Any:
423
+ def _load_yaml_internal(fname: str) -> Any:
424
+ """Load a YAML file."""
425
+ try:
426
+ with open(fname, encoding="utf-8") as f_handle:
427
+ return parse_yaml(fname, f_handle)
428
+ except (UnicodeDecodeError, OSError) as err:
429
+ raise EsphomeError(f"Error reading file {fname}: {err}") from err
430
+
431
+
432
+ def parse_yaml(
433
+ file_name: str, file_handle: TextIOWrapper, yaml_loader=_load_yaml_internal
434
+ ) -> Any:
392
435
  """Parse a YAML file."""
393
436
  try:
394
- return _load_yaml_internal_with_type(ESPHomeLoader, file_name, file_handle)
437
+ return _load_yaml_internal_with_type(
438
+ ESPHomeLoader, file_name, file_handle, yaml_loader
439
+ )
395
440
  except EsphomeError:
396
441
  # Loading failed, so we now load with the Python loader which has more
397
442
  # readable exceptions
398
443
  # Rewind the stream so we can try again
399
444
  file_handle.seek(0, 0)
400
445
  return _load_yaml_internal_with_type(
401
- ESPHomePurePythonLoader, file_name, file_handle
446
+ ESPHomePurePythonLoader, file_name, file_handle, yaml_loader
402
447
  )
403
448
 
404
449
 
@@ -435,23 +480,14 @@ def substitute_vars(config, vars):
435
480
  return result
436
481
 
437
482
 
438
- def _load_yaml_internal(fname: str) -> Any:
439
- """Load a YAML file."""
440
- try:
441
- with open(fname, encoding="utf-8") as f_handle:
442
- return parse_yaml(fname, f_handle)
443
- except (UnicodeDecodeError, OSError) as err:
444
- raise EsphomeError(f"Error reading file {fname}: {err}") from err
445
-
446
-
447
483
  def _load_yaml_internal_with_type(
448
484
  loader_type: type[ESPHomeLoader] | type[ESPHomePurePythonLoader],
449
485
  fname: str,
450
486
  content: TextIOWrapper,
487
+ yaml_loader: Any,
451
488
  ) -> Any:
452
489
  """Load a YAML file."""
453
- loader = loader_type(content)
454
- loader.name = fname
490
+ loader = loader_type(content, fname, yaml_loader)
455
491
  try:
456
492
  return loader.get_single_data() or OrderedDict()
457
493
  except yaml.YAMLError as exc:
@@ -470,7 +506,7 @@ def dump(dict_, show_secrets=False):
470
506
  )
471
507
 
472
508
 
473
- def _is_file_valid(name):
509
+ def _is_file_valid(name: str) -> bool:
474
510
  """Decide if a file is valid."""
475
511
  return not name.startswith(".")
476
512
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: esphome
3
- Version: 2025.4.0b2
3
+ Version: 2025.4.1
4
4
  Summary: ESPHome is a system to configure your microcontrollers by simple yet powerful configuration files and control them remotely through Home Automation systems.
5
5
  Author-email: The ESPHome Authors <esphome@openhomefoundation.org>
6
6
  License: MIT
@@ -39,7 +39,7 @@ Requires-Dist: esptool==4.8.1
39
39
  Requires-Dist: click==8.1.7
40
40
  Requires-Dist: esphome-dashboard==20250415.0
41
41
  Requires-Dist: aioesphomeapi==29.10.0
42
- Requires-Dist: zeroconf==0.146.4
42
+ Requires-Dist: zeroconf==0.146.5
43
43
  Requires-Dist: puremagic==1.28
44
44
  Requires-Dist: ruamel.yaml==0.18.10
45
45
  Requires-Dist: esphome-glyphsets==0.2.0
@@ -1,11 +1,11 @@
1
1
  esphome/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- esphome/__main__.py,sha256=3PVf9SDEDgPHvXJdGE0dCboamTgRVEWhfmMcY8T3pLw,32587
2
+ esphome/__main__.py,sha256=u8FUFrXqmO17I_HIFz_t8N-O7Cma7QiHzCnW4ARp_VQ,32617
3
3
  esphome/automation.py,sha256=9xmW3AmWDd2oKB7zF-UITYIiSci8ys8qiylK-rcU7Rg,15689
4
4
  esphome/codegen.py,sha256=GePHUM7xdXb_Pil59SHVsXg2F4VBPgkH-Fz2PDX8Z54,1873
5
5
  esphome/config.py,sha256=fFrDYbhWY1xn_onAl_0jwlg9D8NkK_FdKULTlnjZtxs,39832
6
6
  esphome/config_helpers.py,sha256=MKf_wzO35nn41FvigXE0iYKDslPgL2ruf8R-EPtTT2I,3256
7
- esphome/config_validation.py,sha256=9KOhLHQXmDbahg6zHynXfXDfAL2bciu35_SHxHrzZ2M,63705
8
- esphome/const.py,sha256=U00foWVg7L2J3h7o4-5e48t8gl8y0deYApkPsFP3dFg,40830
7
+ esphome/config_validation.py,sha256=cjOlphJs-ybsA2VlXXPY-lYq80Vm2uPJ8oIXtWhiPU4,62490
8
+ esphome/const.py,sha256=UC1S6lqRz-unu1Uod0Ml5ej8ZG7qAToiFVU2iLZBNbc,40828
9
9
  esphome/coroutine.py,sha256=j_14z8dIIzIBeuNO30D4c1RJvMMt1xZFZ58Evd-EvJA,9344
10
10
  esphome/cpp_generator.py,sha256=1g-y3fxWSrd5Kpbz6DrJXaQajjuwQiTIaTRIz9n7svI,31237
11
11
  esphome/cpp_helpers.py,sha256=6C2vNbOIhZKi43xRVlk5hp9GfshfBn-rc5D_ZFUEYaE,4801
@@ -16,7 +16,7 @@ esphome/final_validate.py,sha256=EPhbU4xyEL3POdSY7oygyAIVvkeYM7qH-6eZWb76DFE,189
16
16
  esphome/git.py,sha256=rKb5JUc05nbRlvR4tRWGL851ANZUYuS7YZp5Tm5wHjE,6296
17
17
  esphome/helpers.py,sha256=2mQ0eyOLjdjaLRL6jdcJfg4UMnqEFY8ORrmEGc5yNHc,12435
18
18
  esphome/loader.py,sha256=5C-agEUY5AnES6Tdn8KTfot89HIQPeGYu8W1s4ZqT9M,6821
19
- esphome/log.py,sha256=HByzlt3RWl0bVsBnu43veUpVHSCdBjL9W6gYEhdNJkE,2098
19
+ esphome/log.py,sha256=XqVmsRvi4hHUkjcjwTSFBYbbXonNeoRKPE9bx9kfWf0,2181
20
20
  esphome/mqtt.py,sha256=jjmdEk-_ov_pAuy-FqNPQlPB1VOJEs8iFi4pe2gdiTM,9223
21
21
  esphome/pins.py,sha256=wO0d-2qn0fhT6WEN0H0AmYRSH90jW154hZT7RewMGYI,10713
22
22
  esphome/platformio_api.py,sha256=OEWhPZ2NQnTrZ3Vtm0IqW0E-xE7EyVhs5w3OtT2xfDY,11905
@@ -25,10 +25,10 @@ esphome/storage_json.py,sha256=VyIQDo7hHTIYEeLJTO5cq6I_nOWTlvFVvxqvXd6cgg4,10124
25
25
  esphome/types.py,sha256=xJaCRRyYuJiRo32mns9v-YeYB6w12NAT8vMSk9ZmJl8,430
26
26
  esphome/util.py,sha256=sKW1kNMRle3bOGrw9Rga32ZfSDXYMbQeQeVKxFEumJs,9329
27
27
  esphome/voluptuous_schema.py,sha256=Z5nhm8lM4H4D-RB7hi4aCKgPiVLuIZ5EULkC0X4QUjY,9345
28
- esphome/vscode.py,sha256=612-o7AVyoh1Fmg-ZXYxKVWUc5fcoumsnunpMv7MQuo,3251
28
+ esphome/vscode.py,sha256=NtCZkDwckoHrM9ZPmyMBE0q29nqd899VjvISkojsLMw,3991
29
29
  esphome/wizard.py,sha256=BO89_Y9Z6T8kvC5ZrQGPZzT5Rl9vXpte9L2hqr6CeOk,15349
30
30
  esphome/writer.py,sha256=nJSeC5kZesf9EL4nbsWwhMRq7wPnZPjhP0gLZbVTkvI,10999
31
- esphome/yaml_util.py,sha256=4lCUmBYsbdbxW4yjEAQGcYXhKI3KFkwSzT_N31UojFs,21523
31
+ esphome/yaml_util.py,sha256=pHw9fJzU0sr180ntmdLZh7k7HQ5giSHkCJzdIgTi_jg,22919
32
32
  esphome/zeroconf.py,sha256=IuAKqtvDCi4uvLKCbLxrP-DFrXVm1I9icbryrCkenAA,6383
33
33
  esphome/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  esphome/components/a01nyub/__init__.py,sha256=d_xNluCS0T63CxdXJGuw7raK7G9vAEwXNJpnA9GthzA,34
@@ -143,7 +143,7 @@ esphome/components/alpha3/alpha3.cpp,sha256=1zSC6RmxRxmLFFwRq-pY1BbUWqNiB6ZMOkzf
143
143
  esphome/components/alpha3/alpha3.h,sha256=tiCloEGqw9rHdIOocRskj50Z32DiWo6aVUjUk-tRAb8,3405
144
144
  esphome/components/alpha3/sensor.py,sha256=6qSx-_JzQ0wK8aml1LLHqm-u0L0ABX3o8dgqqwdpNvQ,2749
145
145
  esphome/components/am2315c/__init__.py,sha256=_LBsZwU4Hpwdgs3o5uioFVeClSE5fK8k_FZB2MWSADE,30
146
- esphome/components/am2315c/am2315c.cpp,sha256=_fQDCMiy6OfTmnWFEz8RG78oygM2SKSvShkp3FLgKaA,5501
146
+ esphome/components/am2315c/am2315c.cpp,sha256=azPE7NUg2saRKmzz5p7hpIu6eMcyglu4OqnV7BMLj4w,5529
147
147
  esphome/components/am2315c/am2315c.h,sha256=xJyLj_vUnDACJ0LehomCzXKWnqWYUmmr9OvjpfdrteQ,2047
148
148
  esphome/components/am2315c/sensor.py,sha256=Y3tt7aOi12IsrfbS9fAHec9BkV0hz3PfmviT-nDyfX0,1702
149
149
  esphome/components/am2320/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -380,7 +380,7 @@ esphome/components/ble_scanner/text_sensor.py,sha256=yOB-AMBbNwJ0K9zYXh3ZedA42Os
380
380
  esphome/components/bluetooth_proxy/__init__.py,sha256=yBpHNPhRuw7B_LKUvGFZLnrqItID31kQG-DTT679uu8,3282
381
381
  esphome/components/bluetooth_proxy/bluetooth_connection.cpp,sha256=KBSjOMljcqOsJ0hDSuJjhi8A9GK0_JnL9CPMfs1CDkc,11223
382
382
  esphome/components/bluetooth_proxy/bluetooth_connection.h,sha256=oR0r7QAUNABFMKB_anI_l7lI-iOE6RbyBPkDozoC14Y,1171
383
- esphome/components/bluetooth_proxy/bluetooth_proxy.cpp,sha256=Y6IEGD1-jzbcOYM4vHib0fHO2NSDZCu0RRN6JPSyPsU,22136
383
+ esphome/components/bluetooth_proxy/bluetooth_proxy.cpp,sha256=J5365iSzQ6C61hAAHqnd1jBhjPqp0dsmiat0mDLWv_Q,22466
384
384
  esphome/components/bluetooth_proxy/bluetooth_proxy.h,sha256=lEx8Qx2fcjkBU24vT39VUUuwkVJdQ2cB0lG9hTp0lM8,5144
385
385
  esphome/components/bme280_base/__init__.py,sha256=KQhkrj8Ny2lMRUdJXaem5z3-fiR2J82b9AGe58xnZgE,3688
386
386
  esphome/components/bme280_base/bme280_base.cpp,sha256=st3cMKvdG49rHF-pRfplpqhcFAfLZ_YxNmGouiPUQH4,12989
@@ -754,7 +754,7 @@ esphome/components/endstop/endstop_cover.h,sha256=RRAAHaZRkRjH9Q2KMLDCoGnQ44Z_lC
754
754
  esphome/components/ens160/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
755
755
  esphome/components/ens160/sensor.py,sha256=JmqJW89ItAMvLqzpgrwWuLsNJctyV-_6i18t4rb-KcA,164
756
756
  esphome/components/ens160_base/__init__.py,sha256=VGWuu4IdB7GWLOns49nmj1dWQAUD3FmTYyyxYRRqMAI,2473
757
- esphome/components/ens160_base/ens160_base.cpp,sha256=SbEkBiH0BI8SLUIxsP7bNSyLOBkcAWtSBALqWlwVwts,9984
757
+ esphome/components/ens160_base/ens160_base.cpp,sha256=PRgqcB07kwVCQuquMFx5SjtT8j5ON3ZB-a6x2m2yn0M,9982
758
758
  esphome/components/ens160_base/ens160_base.h,sha256=u8rmUObUBj9JtxNJLjGS_Mv4ZhSmd0R9NwJeNX4D-yo,1732
759
759
  esphome/components/ens160_i2c/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
760
760
  esphome/components/ens160_i2c/ens160_i2c.cpp,sha256=qXi0VlzYvveeoNPMJh6DmGM_QG-Zc15aKL7T9HS76-0,932
@@ -842,7 +842,7 @@ esphome/components/esp32_ble_server/ble_service.h,sha256=BvKpr2fsUlNnviH9gdokI7I
842
842
  esphome/components/esp32_ble_tracker/__init__.py,sha256=mfStrLvJxJcTc1koz1grSqbslqG0SxCpQfi1899vRZk,14649
843
843
  esphome/components/esp32_ble_tracker/automation.h,sha256=0pDA6EX__f14sT0KJwcnqg7UOsueKjjegHPznQj9biw,3795
844
844
  esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp,sha256=-h-yvcDYOCk9zKLmMo45aroEg5vguELxJ3YiW8X-mYA,27960
845
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h,sha256=tsiHIew8JftoOwHDI9AcD8CSKQLTqnxTHONdvwPix0g,9348
845
+ esphome/components/esp32_ble_tracker/esp32_ble_tracker.h,sha256=D5YTrA5WROUkupXP5uW5y_xqAmfAoT3xxuHHsQ0-Dso,9488
846
846
  esphome/components/esp32_camera/__init__.py,sha256=JL1umjoPo8qLDUaFYQWI34j-ItCshy8COQgn2sa3csM,12630
847
847
  esphome/components/esp32_camera/esp32_camera.cpp,sha256=Ba2nu453rF4FDSlIJwD5sLnzE8ru4kKK4xVCvMdoyac,16960
848
848
  esphome/components/esp32_camera/esp32_camera.h,sha256=3-MKRSBcjDgI3I0uKmt0bGSfp2t6B85Zsjr06tmpa9Q,7590
@@ -1524,7 +1524,7 @@ esphome/components/lvgl/helpers.py,sha256=XI3C5IHwoSVlgR32kMxeXTZWK6iW112nmWv5wB
1524
1524
  esphome/components/lvgl/keypads.py,sha256=jtQjAG4vbTzI5Pr1IBfrEEPzV_0k4wkKfCMfsef6VT4,2124
1525
1525
  esphome/components/lvgl/lv_validation.py,sha256=8FoODFSzpxWUzRcwk7zOmv6TIpN9yXaHDIJjoCifOiA,13843
1526
1526
  esphome/components/lvgl/lvcode.py,sha256=pTpwXB0ZehgHVMF1y-fAvaTZPTbWfwA-iZwTbl2W9hI,10118
1527
- esphome/components/lvgl/lvgl_esphome.cpp,sha256=ZxJ-bm7wTxIbNST4uPLlhvGysfqOVqKyg1AOJzQe0aE,19253
1527
+ esphome/components/lvgl/lvgl_esphome.cpp,sha256=ffClk2SbGPxafbMZRshkkO-4MESBih4ADsfVpbj7cAg,19289
1528
1528
  esphome/components/lvgl/lvgl_esphome.h,sha256=8a5DaKfK0jWa1dQsA0bC0aw_RoPrLXC5vcBzVi4CCXU,13927
1529
1529
  esphome/components/lvgl/lvgl_hal.h,sha256=aZqWpSmKKAB-ZfNxxgxjgASTtLpAZjXJKuoTiPB0qqU,431
1530
1530
  esphome/components/lvgl/lvgl_proxy.h,sha256=JPmVBVh5zD5nraJCN7PqXVmQQlc4CPJe_X9tA6IAtXQ,547
@@ -2028,7 +2028,7 @@ esphome/components/online_image/image_decoder.cpp,sha256=p_693Ac8F-vs2n_1AZ7E57H
2028
2028
  esphome/components/online_image/image_decoder.h,sha256=A8sU-3m5dkyR8S2wXbeR7v7C5mRSLxrvfvsBPYz3a90,3798
2029
2029
  esphome/components/online_image/jpeg_image.cpp,sha256=1qDTfzp7H6oxuRVBVXXgglourmlcBO4uvxQK6YLDFl4,2867
2030
2030
  esphome/components/online_image/jpeg_image.h,sha256=RxlXrSxgd_j7tXYMGdkU1gVmkWB6Jc0YHuq13NrY9fc,741
2031
- esphome/components/online_image/online_image.cpp,sha256=4gJksrHknRF4ZxKRL8gnBMsh_kKY_YV5177tIrr4hzw,10568
2031
+ esphome/components/online_image/online_image.cpp,sha256=NpXUoKdbIJRdPcY5tQ-fxa6WLpTYeRs8sHJnNP2M2pA,10585
2032
2032
  esphome/components/online_image/online_image.h,sha256=40F0zWRI0p6A8pFfQdQ1eD5tnwgCxBDbeNcpCHgeUzk,7177
2033
2033
  esphome/components/online_image/png_image.cpp,sha256=ysXfjX05YPuZaG0wxHg0EiPlj3HlddQqUdDG25W1jpY,2432
2034
2034
  esphome/components/online_image/png_image.h,sha256=oDyTIkyOB2MiKxZ9YmctwN7sbc_E7Qz0PvFxWg9Lip8,783
@@ -2197,7 +2197,7 @@ esphome/components/prometheus/__init__.py,sha256=V3QD6_RZk7tY7PDuKNbQzzimbgRJ0hk
2197
2197
  esphome/components/prometheus/prometheus_handler.cpp,sha256=CYECmgJoD3rXlcBN5GPrDStNuIT34JAAOmpjLL27F64,30420
2198
2198
  esphome/components/prometheus/prometheus_handler.h,sha256=iw1ecV2tnDMA1H6kk59P0I-fE-P8bOrHkRnURi3epRg,6773
2199
2199
  esphome/components/psram/__init__.py,sha256=fmi0xiOuhBdYMt5Wab9PetwRLCbPEz7PtmZHf0CEXzo,3983
2200
- esphome/components/psram/psram.cpp,sha256=S4KxEKxGihvP4GMvpmgGe6KluasB7XUTPpiqtHYS1bs,1408
2200
+ esphome/components/psram/psram.cpp,sha256=ryng74NZ0ok4miBDb21vgwDjl2IWFirZXeh3S4tNfNY,1509
2201
2201
  esphome/components/psram/psram.h,sha256=LdElwxbKK68o4J9sdmMX8RZn5D94lXhCCSDm83Ge2jc,239
2202
2202
  esphome/components/pulse_counter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2203
2203
  esphome/components/pulse_counter/automation.h,sha256=y-QRATOjByPNkmMaTlaIwvO3q1hpJyifb39GV85CS7c,644
@@ -2655,10 +2655,10 @@ esphome/components/sm300d2/sm300d2.h,sha256=YDd_1VQ0Bq0KhWgtvsJLmuXdIRG8purGyxmU
2655
2655
  esphome/components/sml/__init__.py,sha256=ibRZmFRQFxOAJ9-YC_00_FYUGQSn2UcFy_9mAKfEg3g,1795
2656
2656
  esphome/components/sml/automation.h,sha256=lY2a8F41GCJB03oPWj4fBJ_3VlXgSc7HKwkVzVmPLqc,411
2657
2657
  esphome/components/sml/constants.h,sha256=bBhl2KSbp7c44Ah4qcVxGwVGMq5na8JgSLwu-Zk-uUE,639
2658
- esphome/components/sml/sml.cpp,sha256=Th5Q5VbkGt8RsNOCWFDRFFmTbTZj0NH6JRH1A2tSlNE,4209
2659
- esphome/components/sml/sml.h,sha256=UWA0WZEwiMk2NWgCm9nUCQyJa6DUSxJwhV_W9EE3l1E,1326
2660
- esphome/components/sml/sml_parser.cpp,sha256=Xb7habP5AXdpFn7yJ1tnFAkPxMBTgcDoAI-0FoHD5Fw,5111
2661
- esphome/components/sml/sml_parser.h,sha256=9HlTT3dcbn8jnnvwIARwzBC7wasi2UUZrCj6tTXN--E,955
2658
+ esphome/components/sml/sml.cpp,sha256=G0AYjyk8VvP1V_BEKgsXe_eH-P-MouyZENciorrUAHg,4210
2659
+ esphome/components/sml/sml.h,sha256=5xTtlwcoKVfvBN3IXoB6gKIvni85edLL6z_865SqNaE,1330
2660
+ esphome/components/sml/sml_parser.cpp,sha256=oNOcV2mPUzXNY0oYRfOxHM9i51ODw3vWNdxeyhH9N7M,5051
2661
+ esphome/components/sml/sml_parser.h,sha256=bZk5KCQnIjlRUEjnIR2SfpSCe835BqJAlTVGvFkJ3i0,1812
2662
2662
  esphome/components/sml/sensor/__init__.py,sha256=jlZBTGgveDgAtiLdpJzyumU4DiKyZgvTOY6m3q09arg,910
2663
2663
  esphome/components/sml/sensor/sml_sensor.cpp,sha256=onWh6gi584Qy8TaYgnRi5K4nMUkS39P8_liCTTKW5JM,1106
2664
2664
  esphome/components/sml/sensor/sml_sensor.h,sha256=QypjAdqlNPIVLP77YuxASVRJVwjITCuoc5q0MvzUjNY,420
@@ -3220,7 +3220,7 @@ esphome/components/wake_on_lan/button.py,sha256=QQwzh-kUVI8RJVxCP_JpQUk0A9lDDf-c
3220
3220
  esphome/components/wake_on_lan/wake_on_lan.cpp,sha256=6rxv_zyBNuYUn-DoahTna0qusEkw4KuU9ccvWU3ZZTY,3114
3221
3221
  esphome/components/wake_on_lan/wake_on_lan.h,sha256=46_1RmAkbCIzHZc0m4ZuJgdO2QHkiWjGuB7hw7MgKZM,984
3222
3222
  esphome/components/watchdog/__init__.py,sha256=phrvkU9sRMp2iVLKx5pNCG11R1HtrJChggVbad-OVWA,26
3223
- esphome/components/watchdog/watchdog.cpp,sha256=oQlZLqWN3CiiyKqn_R77K_IOtjKJbrzPvcc8dKWL1r8,1633
3223
+ esphome/components/watchdog/watchdog.cpp,sha256=A8--WFI3ccw62n7A-MZSmwtO_I2g2rC4bpEUB-kbEWo,1683
3224
3224
  esphome/components/watchdog/watchdog.h,sha256=8Ro3Kgi9C1bYFBkNEeKc188EK63uI48VuzhF5yHPuCk,400
3225
3225
  esphome/components/waveshare_epaper/__init__.py,sha256=4Nn7UhpMJ9oSbuLdyVEW7G9PlIey2v33SWRNVizt9Oc,30
3226
3226
  esphome/components/waveshare_epaper/display.py,sha256=DBEN5glBcXQBvv0bwLcddNzP-fkeyk-yKeHsfPXw1nM,9794
@@ -3423,7 +3423,7 @@ esphome/components/zyaura/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
3423
3423
  esphome/components/zyaura/sensor.py,sha256=cSmO4ozYdi4ZD7NK4lmYjswWVmJoDvEruU1HhGrZSE0,2476
3424
3424
  esphome/components/zyaura/zyaura.cpp,sha256=F7WM8XAZ5MYuCD3eERm2_IA-O7sP1i-A-yF5TV4PqX8,3679
3425
3425
  esphome/components/zyaura/zyaura.h,sha256=yWrcYj_CnLDyopkuIVySJy5dB-R5X9zwm5fWjBDTSts,2384
3426
- esphome/core/__init__.py,sha256=L4pbrSzT5rq3ba3Xm1N5xiRx4m5a4pKN5wBwvUwWZLU,26760
3426
+ esphome/core/__init__.py,sha256=RCYQQQLlJxABwGyhSQJ9-kCwMOZL-uSVhBEnHUfEeOU,26735
3427
3427
  esphome/core/application.cpp,sha256=DOhq0rTYu_dNcUCavHYVYASQZ5QzVOXMWVTaO7YTdnM,4680
3428
3428
  esphome/core/application.h,sha256=jepd6I9BBa48ByAXoLnUE7ddtlHiUS5uuKaMaJOD0x0,17721
3429
3429
  esphome/core/automation.h,sha256=UQQD9De3eiaopvzYQG89SxkBfnL5QaiR6bvkk2RxV8k,7332
@@ -3481,9 +3481,9 @@ esphome/dashboard/util/itertools.py,sha256=8eLrWEWmICLtXNxkKdYPQV0c_N4GEz8m9Npnb
3481
3481
  esphome/dashboard/util/password.py,sha256=cQz3b9B-ijTe7zS6BeCW0hc3pWv6JjC78jmnycYYAh8,321
3482
3482
  esphome/dashboard/util/subprocess.py,sha256=T8EW6dbU4LPd2DG1dRrdh8li71tt6J1isn411poMhkk,1022
3483
3483
  esphome/dashboard/util/text.py,sha256=ENDnfN4O0NdA3CKVJjQYabFbwbrsIhVKrAMQe53qYu4,534
3484
- esphome-2025.4.0b2.dist-info/licenses/LICENSE,sha256=HzEjkBInJe44L4WvAOPfhPJJDNj6YbnqFyvGWRzArGM,36664
3485
- esphome-2025.4.0b2.dist-info/METADATA,sha256=QDzQqlrluTWB6o0YzPZysWvsFSvlhigg7_zgG0ifL34,3673
3486
- esphome-2025.4.0b2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
3487
- esphome-2025.4.0b2.dist-info/entry_points.txt,sha256=mIxVNuWtbYzeEcaWCl-AQ-97aBOWbnYBAK8nbF6P4M0,50
3488
- esphome-2025.4.0b2.dist-info/top_level.txt,sha256=0GSXEW3cnITpgG3qnsSMz0qoqJHAFyfw7Y8MVtEf1Yk,8
3489
- esphome-2025.4.0b2.dist-info/RECORD,,
3484
+ esphome-2025.4.1.dist-info/licenses/LICENSE,sha256=HzEjkBInJe44L4WvAOPfhPJJDNj6YbnqFyvGWRzArGM,36664
3485
+ esphome-2025.4.1.dist-info/METADATA,sha256=jj3WZGaXL8BXOWuytPx-HxMTDPq2ycMg7c89WNWW0EM,3671
3486
+ esphome-2025.4.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
3487
+ esphome-2025.4.1.dist-info/entry_points.txt,sha256=mIxVNuWtbYzeEcaWCl-AQ-97aBOWbnYBAK8nbF6P4M0,50
3488
+ esphome-2025.4.1.dist-info/top_level.txt,sha256=0GSXEW3cnITpgG3qnsSMz0qoqJHAFyfw7Y8MVtEf1Yk,8
3489
+ esphome-2025.4.1.dist-info/RECORD,,