esphome 2025.6.0b2__py3-none-any.whl → 2025.6.0b3__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.
@@ -18,7 +18,7 @@ void I2SAudioComponent::setup() {
18
18
 
19
19
  static i2s_port_t next_port_num = I2S_NUM_0;
20
20
  if (next_port_num >= I2S_NUM_MAX) {
21
- ESP_LOGE(TAG, "Too many I2S Audio components");
21
+ ESP_LOGE(TAG, "Too many components");
22
22
  this->mark_failed();
23
23
  return;
24
24
  }
@@ -45,7 +45,7 @@ void I2SAudioMicrophone::setup() {
45
45
  #if SOC_I2S_SUPPORTS_ADC
46
46
  if (this->adc_) {
47
47
  if (this->parent_->get_port() != I2S_NUM_0) {
48
- ESP_LOGE(TAG, "Internal ADC only works on I2S0!");
48
+ ESP_LOGE(TAG, "Internal ADC only works on I2S0");
49
49
  this->mark_failed();
50
50
  return;
51
51
  }
@@ -55,7 +55,7 @@ void I2SAudioMicrophone::setup() {
55
55
  {
56
56
  if (this->pdm_) {
57
57
  if (this->parent_->get_port() != I2S_NUM_0) {
58
- ESP_LOGE(TAG, "PDM only works on I2S0!");
58
+ ESP_LOGE(TAG, "PDM only works on I2S0");
59
59
  this->mark_failed();
60
60
  return;
61
61
  }
@@ -64,14 +64,14 @@ void I2SAudioMicrophone::setup() {
64
64
 
65
65
  this->active_listeners_semaphore_ = xSemaphoreCreateCounting(MAX_LISTENERS, MAX_LISTENERS);
66
66
  if (this->active_listeners_semaphore_ == nullptr) {
67
- ESP_LOGE(TAG, "Failed to create semaphore");
67
+ ESP_LOGE(TAG, "Creating semaphore failed");
68
68
  this->mark_failed();
69
69
  return;
70
70
  }
71
71
 
72
72
  this->event_group_ = xEventGroupCreate();
73
73
  if (this->event_group_ == nullptr) {
74
- ESP_LOGE(TAG, "Failed to create event group");
74
+ ESP_LOGE(TAG, "Creating event group failed");
75
75
  this->mark_failed();
76
76
  return;
77
77
  }
@@ -79,6 +79,15 @@ void I2SAudioMicrophone::setup() {
79
79
  this->configure_stream_settings_();
80
80
  }
81
81
 
82
+ void I2SAudioMicrophone::dump_config() {
83
+ ESP_LOGCONFIG(TAG,
84
+ "Microphone:\n"
85
+ " Pin: %d\n"
86
+ " PDM: %s\n"
87
+ " DC offset correction: %s",
88
+ static_cast<int8_t>(this->din_pin_), YESNO(this->pdm_), YESNO(this->correct_dc_offset_));
89
+ }
90
+
82
91
  void I2SAudioMicrophone::configure_stream_settings_() {
83
92
  uint8_t channel_count = 1;
84
93
  #ifdef USE_I2S_LEGACY
@@ -127,6 +136,7 @@ bool I2SAudioMicrophone::start_driver_() {
127
136
  if (!this->parent_->try_lock()) {
128
137
  return false; // Waiting for another i2s to return lock
129
138
  }
139
+ this->locked_driver_ = true;
130
140
  esp_err_t err;
131
141
 
132
142
  #ifdef USE_I2S_LEGACY
@@ -151,7 +161,7 @@ bool I2SAudioMicrophone::start_driver_() {
151
161
  config.mode = (i2s_mode_t) (config.mode | I2S_MODE_ADC_BUILT_IN);
152
162
  err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr);
153
163
  if (err != ESP_OK) {
154
- ESP_LOGE(TAG, "Error installing I2S driver: %s", esp_err_to_name(err));
164
+ ESP_LOGE(TAG, "Error installing driver: %s", esp_err_to_name(err));
155
165
  return false;
156
166
  }
157
167
 
@@ -174,7 +184,7 @@ bool I2SAudioMicrophone::start_driver_() {
174
184
 
175
185
  err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr);
176
186
  if (err != ESP_OK) {
177
- ESP_LOGE(TAG, "Error installing I2S driver: %s", esp_err_to_name(err));
187
+ ESP_LOGE(TAG, "Error installing driver: %s", esp_err_to_name(err));
178
188
  return false;
179
189
  }
180
190
 
@@ -183,7 +193,7 @@ bool I2SAudioMicrophone::start_driver_() {
183
193
 
184
194
  err = i2s_set_pin(this->parent_->get_port(), &pin_config);
185
195
  if (err != ESP_OK) {
186
- ESP_LOGE(TAG, "Error setting I2S pin: %s", esp_err_to_name(err));
196
+ ESP_LOGE(TAG, "Error setting pin: %s", esp_err_to_name(err));
187
197
  return false;
188
198
  }
189
199
  }
@@ -198,7 +208,7 @@ bool I2SAudioMicrophone::start_driver_() {
198
208
  /* Allocate a new RX channel and get the handle of this channel */
199
209
  err = i2s_new_channel(&chan_cfg, NULL, &this->rx_handle_);
200
210
  if (err != ESP_OK) {
201
- ESP_LOGE(TAG, "Error creating new I2S channel: %s", esp_err_to_name(err));
211
+ ESP_LOGE(TAG, "Error creating channel: %s", esp_err_to_name(err));
202
212
  return false;
203
213
  }
204
214
 
@@ -270,14 +280,14 @@ bool I2SAudioMicrophone::start_driver_() {
270
280
  err = i2s_channel_init_std_mode(this->rx_handle_, &std_cfg);
271
281
  }
272
282
  if (err != ESP_OK) {
273
- ESP_LOGE(TAG, "Error initializing I2S channel: %s", esp_err_to_name(err));
283
+ ESP_LOGE(TAG, "Error initializing channel: %s", esp_err_to_name(err));
274
284
  return false;
275
285
  }
276
286
 
277
287
  /* Before reading data, start the RX channel first */
278
288
  i2s_channel_enable(this->rx_handle_);
279
289
  if (err != ESP_OK) {
280
- ESP_LOGE(TAG, "Error enabling I2S Microphone: %s", esp_err_to_name(err));
290
+ ESP_LOGE(TAG, "Enabling failed: %s", esp_err_to_name(err));
281
291
  return false;
282
292
  }
283
293
  #endif
@@ -304,34 +314,37 @@ void I2SAudioMicrophone::stop_driver_() {
304
314
  if (this->adc_) {
305
315
  err = i2s_adc_disable(this->parent_->get_port());
306
316
  if (err != ESP_OK) {
307
- ESP_LOGW(TAG, "Error disabling ADC - it may not have started: %s", esp_err_to_name(err));
317
+ ESP_LOGW(TAG, "Error disabling ADC: %s", esp_err_to_name(err));
308
318
  }
309
319
  }
310
320
  #endif
311
321
  err = i2s_stop(this->parent_->get_port());
312
322
  if (err != ESP_OK) {
313
- ESP_LOGW(TAG, "Error stopping I2S microphone - it may not have started: %s", esp_err_to_name(err));
323
+ ESP_LOGW(TAG, "Error stopping: %s", esp_err_to_name(err));
314
324
  }
315
325
  err = i2s_driver_uninstall(this->parent_->get_port());
316
326
  if (err != ESP_OK) {
317
- ESP_LOGW(TAG, "Error uninstalling I2S driver - it may not have started: %s", esp_err_to_name(err));
327
+ ESP_LOGW(TAG, "Error uninstalling driver: %s", esp_err_to_name(err));
318
328
  }
319
329
  #else
320
330
  if (this->rx_handle_ != nullptr) {
321
331
  /* Have to stop the channel before deleting it */
322
332
  err = i2s_channel_disable(this->rx_handle_);
323
333
  if (err != ESP_OK) {
324
- ESP_LOGW(TAG, "Error stopping I2S microphone - it may not have started: %s", esp_err_to_name(err));
334
+ ESP_LOGW(TAG, "Error stopping: %s", esp_err_to_name(err));
325
335
  }
326
336
  /* If the handle is not needed any more, delete it to release the channel resources */
327
337
  err = i2s_del_channel(this->rx_handle_);
328
338
  if (err != ESP_OK) {
329
- ESP_LOGW(TAG, "Error deleting I2S channel - it may not have started: %s", esp_err_to_name(err));
339
+ ESP_LOGW(TAG, "Error deleting channel: %s", esp_err_to_name(err));
330
340
  }
331
341
  this->rx_handle_ = nullptr;
332
342
  }
333
343
  #endif
334
- this->parent_->unlock();
344
+ if (this->locked_driver_) {
345
+ this->parent_->unlock();
346
+ this->locked_driver_ = false;
347
+ }
335
348
  }
336
349
 
337
350
  void I2SAudioMicrophone::mic_task(void *params) {
@@ -403,7 +416,7 @@ size_t I2SAudioMicrophone::read_(uint8_t *buf, size_t len, TickType_t ticks_to_w
403
416
  // Ignore ESP_ERR_TIMEOUT if ticks_to_wait = 0, as it will read the data on the next call
404
417
  if (!this->status_has_warning()) {
405
418
  // Avoid spamming the logs with the error message if its repeated
406
- ESP_LOGW(TAG, "Error reading from I2S microphone: %s", esp_err_to_name(err));
419
+ ESP_LOGW(TAG, "Read error: %s", esp_err_to_name(err));
407
420
  }
408
421
  this->status_set_warning();
409
422
  return 0;
@@ -431,19 +444,19 @@ void I2SAudioMicrophone::loop() {
431
444
  uint32_t event_group_bits = xEventGroupGetBits(this->event_group_);
432
445
 
433
446
  if (event_group_bits & MicrophoneEventGroupBits::TASK_STARTING) {
434
- ESP_LOGD(TAG, "Task started, attempting to allocate buffer");
447
+ ESP_LOGV(TAG, "Task started, attempting to allocate buffer");
435
448
  xEventGroupClearBits(this->event_group_, MicrophoneEventGroupBits::TASK_STARTING);
436
449
  }
437
450
 
438
451
  if (event_group_bits & MicrophoneEventGroupBits::TASK_RUNNING) {
439
- ESP_LOGD(TAG, "Task is running and reading data");
452
+ ESP_LOGV(TAG, "Task is running and reading data");
440
453
 
441
454
  xEventGroupClearBits(this->event_group_, MicrophoneEventGroupBits::TASK_RUNNING);
442
455
  this->state_ = microphone::STATE_RUNNING;
443
456
  }
444
457
 
445
458
  if ((event_group_bits & MicrophoneEventGroupBits::TASK_STOPPED)) {
446
- ESP_LOGD(TAG, "Task finished, freeing resources and uninstalling I2S driver");
459
+ ESP_LOGV(TAG, "Task finished, freeing resources and uninstalling driver");
447
460
 
448
461
  vTaskDelete(this->task_handle_);
449
462
  this->task_handle_ = nullptr;
@@ -473,7 +486,8 @@ void I2SAudioMicrophone::loop() {
473
486
  }
474
487
 
475
488
  if (!this->start_driver_()) {
476
- this->status_momentary_error("I2S driver failed to start, unloading it and attempting again in 1 second", 1000);
489
+ ESP_LOGE(TAG, "Driver failed to start; retrying in 1 second");
490
+ this->status_momentary_error("driver_fail", 1000);
477
491
  this->stop_driver_(); // Stop/frees whatever possibly started
478
492
  break;
479
493
  }
@@ -483,7 +497,8 @@ void I2SAudioMicrophone::loop() {
483
497
  &this->task_handle_);
484
498
 
485
499
  if (this->task_handle_ == nullptr) {
486
- this->status_momentary_error("Task failed to start, attempting again in 1 second", 1000);
500
+ ESP_LOGE(TAG, "Task failed to start, retrying in 1 second");
501
+ this->status_momentary_error("task_fail", 1000);
487
502
  this->stop_driver_(); // Stops the driver to return the lock; will be reloaded in next attempt
488
503
  }
489
504
  }
@@ -18,6 +18,7 @@ namespace i2s_audio {
18
18
  class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, public Component {
19
19
  public:
20
20
  void setup() override;
21
+ void dump_config() override;
21
22
  void start() override;
22
23
  void stop() override;
23
24
 
@@ -80,6 +81,7 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub
80
81
  bool pdm_{false};
81
82
 
82
83
  bool correct_dc_offset_;
84
+ bool locked_driver_{false};
83
85
  int32_t dc_offset_{0};
84
86
  };
85
87
 
@@ -110,29 +110,48 @@ void I2SAudioSpeaker::setup() {
110
110
  }
111
111
  }
112
112
 
113
+ void I2SAudioSpeaker::dump_config() {
114
+ ESP_LOGCONFIG(TAG,
115
+ "Speaker:\n"
116
+ " Pin: %d\n"
117
+ " Buffer duration: %" PRIu32,
118
+ static_cast<int8_t>(this->dout_pin_), this->buffer_duration_ms_);
119
+ if (this->timeout_.has_value()) {
120
+ ESP_LOGCONFIG(TAG, " Timeout: %" PRIu32 " ms", this->timeout_.value());
121
+ }
122
+ #ifdef USE_I2S_LEGACY
123
+ #if SOC_I2S_SUPPORTS_DAC
124
+ ESP_LOGCONFIG(TAG, " Internal DAC mode: %d", static_cast<int8_t>(this->internal_dac_mode_));
125
+ #endif
126
+ ESP_LOGCONFIG(TAG, " Communication format: %d", static_cast<int8_t>(this->i2s_comm_fmt_));
127
+ #else
128
+ ESP_LOGCONFIG(TAG, " Communication format: %s", this->i2s_comm_fmt_.c_str());
129
+ #endif
130
+ }
131
+
113
132
  void I2SAudioSpeaker::loop() {
114
133
  uint32_t event_group_bits = xEventGroupGetBits(this->event_group_);
115
134
 
116
135
  if (event_group_bits & SpeakerEventGroupBits::STATE_STARTING) {
117
- ESP_LOGD(TAG, "Starting Speaker");
136
+ ESP_LOGD(TAG, "Starting");
118
137
  this->state_ = speaker::STATE_STARTING;
119
138
  xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::STATE_STARTING);
120
139
  }
121
140
  if (event_group_bits & SpeakerEventGroupBits::STATE_RUNNING) {
122
- ESP_LOGD(TAG, "Started Speaker");
141
+ ESP_LOGD(TAG, "Started");
123
142
  this->state_ = speaker::STATE_RUNNING;
124
143
  xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::STATE_RUNNING);
125
144
  this->status_clear_warning();
126
145
  this->status_clear_error();
127
146
  }
128
147
  if (event_group_bits & SpeakerEventGroupBits::STATE_STOPPING) {
129
- ESP_LOGD(TAG, "Stopping Speaker");
148
+ ESP_LOGD(TAG, "Stopping");
130
149
  this->state_ = speaker::STATE_STOPPING;
131
150
  xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::STATE_STOPPING);
132
151
  }
133
152
  if (event_group_bits & SpeakerEventGroupBits::STATE_STOPPED) {
134
153
  if (!this->task_created_) {
135
- ESP_LOGD(TAG, "Stopped Speaker");
154
+ ESP_LOGD(TAG, "Stopped");
136
155
  this->state_ = speaker::STATE_STOPPED;
137
156
  xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::ALL_BITS);
138
157
  this->speaker_task_handle_ = nullptr;
@@ -140,20 +159,19 @@ void I2SAudioSpeaker::loop() {
140
159
  }
141
160
 
142
161
  if (event_group_bits & SpeakerEventGroupBits::ERR_TASK_FAILED_TO_START) {
143
- this->status_set_error("Failed to start speaker task");
162
+ this->status_set_error("Failed to start task");
144
163
  xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::ERR_TASK_FAILED_TO_START);
145
164
  }
146
165
 
147
166
  if (event_group_bits & SpeakerEventGroupBits::ALL_ERR_ESP_BITS) {
148
167
  uint32_t error_bits = event_group_bits & SpeakerEventGroupBits::ALL_ERR_ESP_BITS;
149
- ESP_LOGW(TAG, "Error writing to I2S: %s", esp_err_to_name(err_bit_to_esp_err(error_bits)));
168
+ ESP_LOGW(TAG, "Writing failed: %s", esp_err_to_name(err_bit_to_esp_err(error_bits)));
150
169
  this->status_set_warning();
151
170
  }
152
171
 
153
172
  if (event_group_bits & SpeakerEventGroupBits::ERR_ESP_NOT_SUPPORTED) {
154
- this->status_set_error("Failed to adjust I2S bus to match the incoming audio");
155
- ESP_LOGE(TAG,
156
- "Incompatible audio format: sample rate = %" PRIu32 ", channels = %" PRIu8 ", bits per sample = %" PRIu8,
173
+ this->status_set_error("Failed to adjust bus to match incoming audio");
174
+ ESP_LOGE(TAG, "Incompatible audio format: sample rate = %" PRIu32 ", channels = %u, bits per sample = %u",
157
175
  this->audio_stream_info_.get_sample_rate(), this->audio_stream_info_.get_channels(),
158
176
  this->audio_stream_info_.get_bits_per_sample());
159
177
  }
@@ -202,7 +220,7 @@ void I2SAudioSpeaker::set_mute_state(bool mute_state) {
202
220
 
203
221
  size_t I2SAudioSpeaker::play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) {
204
222
  if (this->is_failed()) {
205
- ESP_LOGE(TAG, "Cannot play audio, speaker failed to setup");
223
+ ESP_LOGE(TAG, "Setup failed; cannot play audio");
206
224
  return 0;
207
225
  }
208
226
  if (this->state_ != speaker::STATE_RUNNING && this->state_ != speaker::STATE_STARTING) {
@@ -24,6 +24,7 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp
24
24
  float get_setup_priority() const override { return esphome::setup_priority::PROCESSOR; }
25
25
 
26
26
  void setup() override;
27
+ void dump_config() override;
27
28
  void loop() override;
28
29
 
29
30
  void set_buffer_duration(uint32_t buffer_duration_ms) { this->buffer_duration_ms_ = buffer_duration_ms; }
@@ -17,7 +17,7 @@ namespace light {
17
17
 
18
18
  class LightOutput;
19
19
 
20
- enum LightRestoreMode {
20
+ enum LightRestoreMode : uint8_t {
21
21
  LIGHT_RESTORE_DEFAULT_OFF,
22
22
  LIGHT_RESTORE_DEFAULT_ON,
23
23
  LIGHT_ALWAYS_OFF,
@@ -212,12 +212,18 @@ class LightState : public EntityBase, public Component {
212
212
 
213
213
  /// Store the output to allow effects to have more access.
214
214
  LightOutput *output_;
215
- /// Value for storing the index of the currently active effect. 0 if no effect is active
216
- uint32_t active_effect_index_{};
217
215
  /// The currently active transformer for this light (transition/flash).
218
216
  std::unique_ptr<LightTransformer> transformer_{nullptr};
219
- /// Whether the light value should be written in the next cycle.
220
- bool next_write_{true};
217
+ /// List of effects for this light.
218
+ std::vector<LightEffect *> effects_;
219
+ /// Value for storing the index of the currently active effect. 0 if no effect is active
220
+ uint32_t active_effect_index_{};
221
+ /// Default transition length for all transitions in ms.
222
+ uint32_t default_transition_length_{};
223
+ /// Transition length to use for flash transitions.
224
+ uint32_t flash_transition_length_{};
225
+ /// Gamma correction factor for the light.
226
+ float gamma_correct_{};
221
227
 
222
228
  /// Object used to store the persisted values of the light.
223
229
  ESPPreferenceObject rtc_;
@@ -236,19 +242,13 @@ class LightState : public EntityBase, public Component {
236
242
  */
237
243
  CallbackManager<void()> target_state_reached_callback_{};
238
244
 
239
- /// Default transition length for all transitions in ms.
240
- uint32_t default_transition_length_{};
241
- /// Transition length to use for flash transitions.
242
- uint32_t flash_transition_length_{};
243
- /// Gamma correction factor for the light.
244
- float gamma_correct_{};
245
- /// Restore mode of the light.
246
- LightRestoreMode restore_mode_;
247
245
  /// Initial state of the light.
248
246
  optional<LightStateRTCState> initial_state_{};
249
- /// List of effects for this light.
250
- std::vector<LightEffect *> effects_;
251
247
 
248
+ /// Restore mode of the light.
249
+ LightRestoreMode restore_mode_;
250
+ /// Whether the light value should be written in the next cycle.
251
+ bool next_write_{true};
252
252
  // for effects, true if a transformer (transition) is active.
253
253
  bool is_transformer_active_ = false;
254
254
  };
@@ -3,7 +3,6 @@
3
3
 
4
4
  namespace esphome {
5
5
  namespace spi {
6
-
7
6
  #ifdef USE_ARDUINO
8
7
 
9
8
  static const char *const TAG = "spi-esp-arduino";
@@ -38,17 +37,31 @@ class SPIDelegateHw : public SPIDelegate {
38
37
 
39
38
  void write16(uint16_t data) override { this->channel_->transfer16(data); }
40
39
 
41
- #ifdef USE_RP2040
42
40
  void write_array(const uint8_t *ptr, size_t length) override {
43
- // avoid overwriting the supplied buffer
44
- uint8_t *rxbuf = new uint8_t[length]; // NOLINT(cppcoreguidelines-owning-memory)
45
- memcpy(rxbuf, ptr, length);
46
- this->channel_->transfer((void *) rxbuf, length);
47
- delete[] rxbuf; // NOLINT(cppcoreguidelines-owning-memory)
48
- }
41
+ if (length == 1) {
42
+ this->channel_->transfer(*ptr);
43
+ return;
44
+ }
45
+ #ifdef USE_RP2040
46
+ // avoid overwriting the supplied buffer. Use vector for automatic deallocation
47
+ auto rxbuf = std::vector<uint8_t>(length);
48
+ memcpy(rxbuf.data(), ptr, length);
49
+ this->channel_->transfer((void *) rxbuf.data(), length);
50
+ #elif defined(USE_ESP8266)
51
+ // ESP8266 SPI library requires the pointer to be word aligned, but the data may not be
52
+ // so we need to copy the data to a temporary buffer
53
+ if (reinterpret_cast<uintptr_t>(ptr) & 0x3) {
54
+ ESP_LOGVV(TAG, "SPI write buffer not word aligned, copying to temporary buffer");
55
+ auto txbuf = std::vector<uint8_t>(length);
56
+ memcpy(txbuf.data(), ptr, length);
57
+ this->channel_->writeBytes(txbuf.data(), length);
58
+ } else {
59
+ this->channel_->writeBytes(ptr, length);
60
+ }
49
61
  #else
50
- void write_array(const uint8_t *ptr, size_t length) override { this->channel_->writeBytes(ptr, length); }
62
+ this->channel_->writeBytes(ptr, length);
51
63
  #endif
64
+ }
52
65
 
53
66
  void read_array(uint8_t *ptr, size_t length) override { this->channel_->transfer(ptr, length); }
54
67
 
@@ -21,7 +21,7 @@ const int RESTORE_MODE_PERSISTENT_MASK = 0x02;
21
21
  const int RESTORE_MODE_INVERTED_MASK = 0x04;
22
22
  const int RESTORE_MODE_DISABLED_MASK = 0x08;
23
23
 
24
- enum SwitchRestoreMode {
24
+ enum SwitchRestoreMode : uint8_t {
25
25
  SWITCH_ALWAYS_OFF = !RESTORE_MODE_ON_MASK,
26
26
  SWITCH_ALWAYS_ON = RESTORE_MODE_ON_MASK,
27
27
  SWITCH_RESTORE_DEFAULT_OFF = RESTORE_MODE_PERSISTENT_MASK,
@@ -49,12 +49,12 @@ class Switch : public EntityBase, public EntityBase_DeviceClass {
49
49
  */
50
50
  void publish_state(bool state);
51
51
 
52
- /// The current reported state of the binary sensor.
53
- bool state;
54
-
55
52
  /// Indicates whether or not state is to be retrieved from flash and how
56
53
  SwitchRestoreMode restore_mode{SWITCH_RESTORE_DEFAULT_OFF};
57
54
 
55
+ /// The current reported state of the binary sensor.
56
+ bool state;
57
+
58
58
  /** Turn this switch on. This is called by the front-end.
59
59
  *
60
60
  * For implementing switches, please override write_state.
@@ -123,10 +123,16 @@ class Switch : public EntityBase, public EntityBase_DeviceClass {
123
123
  */
124
124
  virtual void write_state(bool state) = 0;
125
125
 
126
- CallbackManager<void(bool)> state_callback_{};
127
- bool inverted_{false};
128
- Deduplicator<bool> publish_dedup_;
126
+ // Pointer first (4 bytes)
129
127
  ESPPreferenceObject rtc_;
128
+
129
+ // CallbackManager (12 bytes on 32-bit - contains vector)
130
+ CallbackManager<void(bool)> state_callback_{};
131
+
132
+ // Small types grouped together
133
+ Deduplicator<bool> publish_dedup_; // 2 bytes (bool has_value_ + bool last_value_)
134
+ bool inverted_{false}; // 1 byte
135
+ // Total: 3 bytes, 1 byte padding
130
136
  };
131
137
 
132
138
  #define LOG_SWITCH(prefix, type, obj) log_switch((TAG), (prefix), LOG_STR_LITERAL(type), (obj))
esphome/const.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Constants used by esphome."""
2
2
 
3
- __version__ = "2025.6.0b2"
3
+ __version__ = "2025.6.0b3"
4
4
 
5
5
  ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
6
6
  VALID_SUBSTITUTIONS_CHARACTERS = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: esphome
3
- Version: 2025.6.0b2
3
+ Version: 2025.6.0b3
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
@@ -5,7 +5,7 @@ esphome/codegen.py,sha256=GePHUM7xdXb_Pil59SHVsXg2F4VBPgkH-Fz2PDX8Z54,1873
5
5
  esphome/config.py,sha256=GsKqzNb4OBxA92eltdGYtP7e9fgtk80QsquhnUesb50,39948
6
6
  esphome/config_helpers.py,sha256=MKf_wzO35nn41FvigXE0iYKDslPgL2ruf8R-EPtTT2I,3256
7
7
  esphome/config_validation.py,sha256=N3za01KZnbbj4GqUAB1y0nW9qHRQUazsPzIVv1ZoxBk,62366
8
- esphome/const.py,sha256=yWoUe4wzMy7SUiZdlxof7PjhMrGErQlWYSLQQ2rJuFo,41817
8
+ esphome/const.py,sha256=v5xXgheq5lPDdWVYJQ2tGTYCMt8JYJklFjTYH1FHoU4,41817
9
9
  esphome/coroutine.py,sha256=HNBqqhaTbpvsOI19bTXltxJCMVtoeqZPe4qTf4CKkAc,9309
10
10
  esphome/cpp_generator.py,sha256=2MbyMVt9hg7cFD0X8885IiJfFNjdqkqjis3P-0oa5L0,31346
11
11
  esphome/cpp_helpers.py,sha256=6C2vNbOIhZKi43xRVlk5hp9GfshfBn-rc5D_ZFUEYaE,4801
@@ -1261,17 +1261,17 @@ esphome/components/i2c_device/__init__.py,sha256=O5TGYNn8F1WOy4xm0ilHSKvMrl6EnTa
1261
1261
  esphome/components/i2c_device/i2c_device.cpp,sha256=Q4RPp_47MII-KQoQBs7Pdt5HHEasRlp-3F_ZvOKgC9c,350
1262
1262
  esphome/components/i2c_device/i2c_device.h,sha256=QY8euzqa5rsehqIHj4nGktDaR7guW2vgGJ_XsT71Src,389
1263
1263
  esphome/components/i2s_audio/__init__.py,sha256=lJHbtVstO5b06cMy52qaaDRW4daoXUjGTRXMbO_-XU0,9335
1264
- esphome/components/i2s_audio/i2s_audio.cpp,sha256=SSTHlZbXo9p1pt_VDGaj5djic0uoHyLGsq8qUzJdpMM,722
1264
+ esphome/components/i2s_audio/i2s_audio.cpp,sha256=iHAdkjg5i8TEtJvOM7WPO_lxgvxr27sv6hx1t79fnTs,712
1265
1265
  esphome/components/i2s_audio/i2s_audio.h,sha256=8qkrVoPFGs95JQqbcSj0-3w5ig6K6HbNeFL46A8un9w,3448
1266
1266
  esphome/components/i2s_audio/media_player/__init__.py,sha256=YKIoFb4ANgc6_jIV3t6iD0BlqW90xXpwRThyoKQQHPs,3720
1267
1267
  esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp,sha256=CiO08AVUZG-egAIOs9OSgYttC1d3xQT871wJoq4718o,7563
1268
1268
  esphome/components/i2s_audio/media_player/i2s_audio_media_player.h,sha256=gmG6n9YU2Mz85CFa3fO7Na2KBdt9fOrGbDg0-C7jwjI,2078
1269
1269
  esphome/components/i2s_audio/microphone/__init__.py,sha256=m62jL72XwxBavk9cDULs2cdcbHHkM96JF5RPiPBHGcg,4281
1270
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp,sha256=eQpQ2jYRJnlA4Fae6r_ZYRZSwefAsrIKVaXFFiA-Wkc,16720
1271
- esphome/components/i2s_audio/microphone/i2s_audio_microphone.h,sha256=QefL91wL9KHO6pN5DCxbrYNV1KsYGmR9cG8CosUe0pY,2348
1270
+ esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp,sha256=TUsYopCDgzRWi4QRtw3hNx5qmsy4eT8hUnEeUvFyiA4,16932
1271
+ esphome/components/i2s_audio/microphone/i2s_audio_microphone.h,sha256=74azu9ZjuKfbE5tPXIMDMQD241EqYU1VtV8gpwfLtHw,2409
1272
1272
  esphome/components/i2s_audio/speaker/__init__.py,sha256=EUWTtCtc3T5zoaHMUnqu-KjJh5nnwKrkUAQi3QYEDi0,6152
1273
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp,sha256=SP--OFpLpgIUZL529WnqjGgfQEXmSB5h8HMkef-qv5c,26847
1274
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h,sha256=VqfZH3A4ZgqeXuhJuiBhGsERKthxF4eJB1HCYDBvU0s,6666
1273
+ esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp,sha256=UGCEScVGIZjSgMdrREjmdDpzLzCwC238oX29_odEuqo,27461
1274
+ esphome/components/i2s_audio/speaker/i2s_audio_speaker.h,sha256=JZLm5X2Anpx4R34eXONlHvzypJvLI8N-MQiZkFhx7B4,6697
1275
1275
  esphome/components/iaqcore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1276
1276
  esphome/components/iaqcore/iaqcore.cpp,sha256=GIrdHKFMo9euldjdQX0xFdvOxAShB6yPVab7oCWGEsw,2246
1277
1277
  esphome/components/iaqcore/iaqcore.h,sha256=wYuMlxOawAHkok41WzryDsV-2a4-YTsG0TU-gfP-ZyE,678
@@ -1511,7 +1511,7 @@ esphome/components/light/light_json_schema.h,sha256=8c8I3idy9-mg1jViEOlJUZu1ajD2
1511
1511
  esphome/components/light/light_output.cpp,sha256=68RwaJIYZJHZi2Dr0CBdyBFbBim4V6lvVYVub4YAzuk,270
1512
1512
  esphome/components/light/light_output.h,sha256=mDajz4kmyDxVlTFJBI49cQKx6DQDBHVwhv_z_gKyAb0,1028
1513
1513
  esphome/components/light/light_state.cpp,sha256=mQWjD_s-YV5YtOpmlX5OlnC5jpIEmKbVcDp-QEK-CSE,11850
1514
- esphome/components/light/light_state.h,sha256=-fSuoYxQ1Kh3zdNxKJndfS-2RnRR84D1C-waChHpPQY,9198
1514
+ esphome/components/light/light_state.h,sha256=KsHXjxVpzKqOvpnJBIjGBe_qPRxqXXjTeNfx6-XpvZ4,9208
1515
1515
  esphome/components/light/light_traits.h,sha256=CA7Cs8LUc8rImkhPJF16L08u4KLDas3b-a5gZEVUtf4,2564
1516
1516
  esphome/components/light/light_transformer.h,sha256=SanY8yirPWyrIdL7anv-tBuT-lIwGm8vJhdwSa93EEc,1801
1517
1517
  esphome/components/light/transformers.h,sha256=E2Fuc2wuf9VYaHIMTAihBq7ucl45Y0K65Y2BlNN8x-U,4745
@@ -2797,7 +2797,7 @@ esphome/components/speed/fan/speed_fan.h,sha256=hjY7VbM4H62p4Wl9XsuGSFodSi82tlH7
2797
2797
  esphome/components/spi/__init__.py,sha256=3yUZTB6XJSBQvsQSHVds5dSgeWdVn3yvcZbyq__sfB4,13799
2798
2798
  esphome/components/spi/spi.cpp,sha256=d-gJ6-lOHfuibBCpiB-1NbHbLxRt0W4G0mVAGwMgUMk,4069
2799
2799
  esphome/components/spi/spi.h,sha256=uyvQGrFOG_aqPj7raEjEEwCtMXpvtcMCCGck-QeqiZI,15297
2800
- esphome/components/spi/spi_arduino.cpp,sha256=uFTGqkPLNht1frVPFq_HANqBnAXsyenmiEqDox7f1og,3328
2800
+ esphome/components/spi/spi_arduino.cpp,sha256=T8qMEtL5gFNTQwTFd4aoezY8Y7cEb3Sx4WyaZQLAYu4,3821
2801
2801
  esphome/components/spi/spi_esp_idf.cpp,sha256=ZKow9phECsh7YtZi8J96wFsYzV8TEhI7-XYe_xPitqo,8821
2802
2802
  esphome/components/spi_device/__init__.py,sha256=jzMNA6ATcdlkobnDfKbCWlif1UGMluD3WH9XkzebshI,1111
2803
2803
  esphome/components/spi_device/spi_device.cpp,sha256=JmjBhuhJeGQI5pBYw81wcqxq6r8xdXWfaaefy32J0PM,810
@@ -2932,7 +2932,7 @@ esphome/components/switch/__init__.py,sha256=MsmIZmG_fBJoNYpLof_PhTCVVnAXQusGNKO
2932
2932
  esphome/components/switch/automation.cpp,sha256=jwWqm_2I21hZVMJ_5VgyMktPNEJHj0b3xuXARpc5k8Q,197
2933
2933
  esphome/components/switch/automation.h,sha256=MG8-giENk7znqhHTeert_JEBPL7C6e0SlglUKAb3rQo,1999
2934
2934
  esphome/components/switch/switch.cpp,sha256=GGccuB8NU1eoI6ap4JvAhyFVTYgTFw62IMdliqtKa1o,3667
2935
- esphome/components/switch/switch.h,sha256=gsxX5QIy1Ot01giVW-7srCQL0-oxzGsQMn-5fZTCZ2I,4743
2935
+ esphome/components/switch/switch.h,sha256=lLrzKALopIjcH0Zq7vjjwCjrKeQsiuLoKLtBQlTxr7M,4986
2936
2936
  esphome/components/switch/binary_sensor/__init__.py,sha256=vSm7ahCF2DzXvYzbdfgAMZzcOimrO-ivfLkLf_q4kMo,760
2937
2937
  esphome/components/switch/binary_sensor/switch_binary_sensor.cpp,sha256=ZPwaqXQTS_PIdBahVr_YMToaxckCMzDJAd7PqIIApls,470
2938
2938
  esphome/components/switch/binary_sensor/switch_binary_sensor.h,sha256=rHmlHpq0LavioIB9pWNBHff4yQXS7-aLfFMSMc0CvT4,539
@@ -3595,9 +3595,9 @@ esphome/dashboard/util/itertools.py,sha256=8eLrWEWmICLtXNxkKdYPQV0c_N4GEz8m9Npnb
3595
3595
  esphome/dashboard/util/password.py,sha256=cQz3b9B-ijTe7zS6BeCW0hc3pWv6JjC78jmnycYYAh8,321
3596
3596
  esphome/dashboard/util/subprocess.py,sha256=T8EW6dbU4LPd2DG1dRrdh8li71tt6J1isn411poMhkk,1022
3597
3597
  esphome/dashboard/util/text.py,sha256=ENDnfN4O0NdA3CKVJjQYabFbwbrsIhVKrAMQe53qYu4,534
3598
- esphome-2025.6.0b2.dist-info/licenses/LICENSE,sha256=HzEjkBInJe44L4WvAOPfhPJJDNj6YbnqFyvGWRzArGM,36664
3599
- esphome-2025.6.0b2.dist-info/METADATA,sha256=WJv_h6dV_s2gEIWv2P15FqC_Bt7L3JHSWNJ_pK0Vz-Y,3680
3600
- esphome-2025.6.0b2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
3601
- esphome-2025.6.0b2.dist-info/entry_points.txt,sha256=mIxVNuWtbYzeEcaWCl-AQ-97aBOWbnYBAK8nbF6P4M0,50
3602
- esphome-2025.6.0b2.dist-info/top_level.txt,sha256=0GSXEW3cnITpgG3qnsSMz0qoqJHAFyfw7Y8MVtEf1Yk,8
3603
- esphome-2025.6.0b2.dist-info/RECORD,,
3598
+ esphome-2025.6.0b3.dist-info/licenses/LICENSE,sha256=HzEjkBInJe44L4WvAOPfhPJJDNj6YbnqFyvGWRzArGM,36664
3599
+ esphome-2025.6.0b3.dist-info/METADATA,sha256=IJwYU8F4CJZgXzX5hXwV5hzXCS3Lki22NTXL31DllxY,3680
3600
+ esphome-2025.6.0b3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
3601
+ esphome-2025.6.0b3.dist-info/entry_points.txt,sha256=mIxVNuWtbYzeEcaWCl-AQ-97aBOWbnYBAK8nbF6P4M0,50
3602
+ esphome-2025.6.0b3.dist-info/top_level.txt,sha256=0GSXEW3cnITpgG3qnsSMz0qoqJHAFyfw7Y8MVtEf1Yk,8
3603
+ esphome-2025.6.0b3.dist-info/RECORD,,