esphome 2025.3.1__py3-none-any.whl → 2025.3.3__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/components/cst226/touchscreen/cst226_touchscreen.cpp +2 -0
- esphome/components/display/display.cpp +2 -2
- esphome/components/ektf2232/touchscreen/ektf2232.cpp +18 -15
- esphome/components/font/__init__.py +23 -9
- esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +12 -7
- esphome/components/ld2450/ld2450.cpp +3 -2
- esphome/components/lvgl/switch/__init__.py +13 -8
- esphome/components/lvgl/switch/lvgl_switch.h +5 -16
- esphome/components/mdns/__init__.py +1 -1
- esphome/components/media_player/media_player.cpp +2 -1
- esphome/components/speaker/media_player/speaker_media_player.cpp +65 -67
- esphome/components/speaker/media_player/speaker_media_player.h +2 -6
- esphome/const.py +1 -1
- {esphome-2025.3.1.dist-info → esphome-2025.3.3.dist-info}/METADATA +1 -1
- {esphome-2025.3.1.dist-info → esphome-2025.3.3.dist-info}/RECORD +19 -19
- {esphome-2025.3.1.dist-info → esphome-2025.3.3.dist-info}/LICENSE +0 -0
- {esphome-2025.3.1.dist-info → esphome-2025.3.3.dist-info}/WHEEL +0 -0
- {esphome-2025.3.1.dist-info → esphome-2025.3.3.dist-info}/entry_points.txt +0 -0
- {esphome-2025.3.1.dist-info → esphome-2025.3.3.dist-info}/top_level.txt +0 -0
@@ -72,6 +72,8 @@ void CST226Touchscreen::continue_setup_() {
|
|
72
72
|
if (this->read16_(0xD1F8, buffer, 4)) {
|
73
73
|
this->x_raw_max_ = buffer[0] + (buffer[1] << 8);
|
74
74
|
this->y_raw_max_ = buffer[2] + (buffer[3] << 8);
|
75
|
+
if (this->swap_x_y_)
|
76
|
+
std::swap(this->x_raw_max_, this->y_raw_max_);
|
75
77
|
} else {
|
76
78
|
this->x_raw_max_ = this->display_->get_native_width();
|
77
79
|
this->y_raw_max_ = this->display_->get_native_height();
|
@@ -555,10 +555,10 @@ void Display::get_text_bounds(int x, int y, const char *text, BaseFont *font, Te
|
|
555
555
|
|
556
556
|
switch (x_align) {
|
557
557
|
case TextAlign::RIGHT:
|
558
|
-
*x1 = x - *width;
|
558
|
+
*x1 = x - *width - x_offset;
|
559
559
|
break;
|
560
560
|
case TextAlign::CENTER_HORIZONTAL:
|
561
|
-
*x1 = x - (*width) / 2;
|
561
|
+
*x1 = x - (*width + x_offset) / 2;
|
562
562
|
break;
|
563
563
|
case TextAlign::LEFT:
|
564
564
|
default:
|
@@ -34,26 +34,29 @@ void EKTF2232Touchscreen::setup() {
|
|
34
34
|
|
35
35
|
// Get touch resolution
|
36
36
|
uint8_t received[4];
|
37
|
-
if (this->x_raw_max_ == this->
|
38
|
-
this->write(GET_X_RES, 4);
|
39
|
-
if (
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
if (this->x_raw_max_ == 0 || this->y_raw_max_ == 0) {
|
38
|
+
auto err = this->write(GET_X_RES, 4);
|
39
|
+
if (err == i2c::ERROR_OK) {
|
40
|
+
err = this->read(received, 4);
|
41
|
+
if (err == i2c::ERROR_OK) {
|
42
|
+
this->x_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4);
|
43
|
+
err = this->write(GET_Y_RES, 4);
|
44
|
+
if (err == i2c::ERROR_OK) {
|
45
|
+
err = this->read(received, 4);
|
46
|
+
if (err == i2c::ERROR_OK) {
|
47
|
+
this->y_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
44
51
|
}
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
if (this->y_raw_max_ == this->y_raw_min_) {
|
49
|
-
this->write(GET_Y_RES, 4);
|
50
|
-
if (this->read(received, 4)) {
|
51
|
-
ESP_LOGE(TAG, "Failed to read Y resolution!");
|
52
|
+
if (err != i2c::ERROR_OK) {
|
53
|
+
ESP_LOGE(TAG, "Failed to read calibration values!");
|
52
54
|
this->interrupt_pin_->detach_interrupt();
|
53
55
|
this->mark_failed();
|
54
56
|
return;
|
55
57
|
}
|
56
|
-
this->
|
58
|
+
if (this->swap_x_y_)
|
59
|
+
std::swap(this->x_raw_max_, this->y_raw_max_);
|
57
60
|
}
|
58
61
|
this->set_power_state(true);
|
59
62
|
}
|
@@ -7,7 +7,15 @@ from pathlib import Path
|
|
7
7
|
import re
|
8
8
|
|
9
9
|
import esphome_glyphsets as glyphsets
|
10
|
-
|
10
|
+
|
11
|
+
# pylint: disable=no-name-in-module
|
12
|
+
from freetype import (
|
13
|
+
FT_LOAD_NO_BITMAP,
|
14
|
+
FT_LOAD_RENDER,
|
15
|
+
FT_LOAD_TARGET_MONO,
|
16
|
+
Face,
|
17
|
+
ft_pixel_mode_mono,
|
18
|
+
)
|
11
19
|
import requests
|
12
20
|
|
13
21
|
from esphome import external_files
|
@@ -204,7 +212,7 @@ def validate_font_config(config):
|
|
204
212
|
if font.get_char_index(x) != 0
|
205
213
|
]
|
206
214
|
|
207
|
-
if font.
|
215
|
+
if not font.is_scalable:
|
208
216
|
sizes = [pt_to_px(x.size) for x in font.available_sizes]
|
209
217
|
if not sizes:
|
210
218
|
raise cv.Invalid(
|
@@ -501,17 +509,23 @@ async def to_code(config):
|
|
501
509
|
glyph_args = {}
|
502
510
|
data = []
|
503
511
|
bpp = config[CONF_BPP]
|
504
|
-
mode = ft_pixel_mode_grays
|
505
512
|
scale = 256 // (1 << bpp)
|
506
513
|
size = config[CONF_SIZE]
|
507
514
|
# create the data array for all glyphs
|
508
515
|
for codepoint in codepoints:
|
509
516
|
font = point_font_map[codepoint]
|
510
|
-
|
511
|
-
|
517
|
+
if not font.is_scalable:
|
518
|
+
sizes = [pt_to_px(x.size) for x in font.available_sizes]
|
519
|
+
if size in sizes:
|
520
|
+
font.select_size(sizes.index(size))
|
521
|
+
else:
|
512
522
|
font.set_pixel_sizes(size, 0)
|
513
|
-
|
514
|
-
|
523
|
+
flags = FT_LOAD_RENDER
|
524
|
+
if bpp != 1:
|
525
|
+
flags |= FT_LOAD_NO_BITMAP
|
526
|
+
else:
|
527
|
+
flags |= FT_LOAD_TARGET_MONO
|
528
|
+
font.load_char(codepoint, flags)
|
515
529
|
width = font.glyph.bitmap.width
|
516
530
|
height = font.glyph.bitmap.rows
|
517
531
|
buffer = font.glyph.bitmap.buffer
|
@@ -535,7 +549,7 @@ async def to_code(config):
|
|
535
549
|
pos += 1
|
536
550
|
ascender = pt_to_px(font.size.ascender)
|
537
551
|
if ascender == 0:
|
538
|
-
if font.
|
552
|
+
if not font.is_scalable:
|
539
553
|
ascender = size
|
540
554
|
else:
|
541
555
|
_LOGGER.error(
|
@@ -585,7 +599,7 @@ async def to_code(config):
|
|
585
599
|
font_height = pt_to_px(base_font.size.height)
|
586
600
|
ascender = pt_to_px(base_font.size.ascender)
|
587
601
|
if font_height == 0:
|
588
|
-
if base_font.
|
602
|
+
if not base_font.is_scalable:
|
589
603
|
font_height = size
|
590
604
|
ascender = font_height
|
591
605
|
else:
|
@@ -60,20 +60,25 @@ void GT911Touchscreen::setup() {
|
|
60
60
|
}
|
61
61
|
}
|
62
62
|
}
|
63
|
-
if (
|
64
|
-
|
63
|
+
if (this->x_raw_max_ == 0 || this->y_raw_max_ == 0) {
|
64
|
+
// no calibration? Attempt to read the max values from the touchscreen.
|
65
65
|
if (err == i2c::ERROR_OK) {
|
66
|
-
err = this->
|
66
|
+
err = this->write(GET_MAX_VALUES, 2);
|
67
67
|
if (err == i2c::ERROR_OK) {
|
68
|
-
|
68
|
+
err = this->read(data, sizeof(data));
|
69
|
+
if (err == i2c::ERROR_OK) {
|
69
70
|
this->x_raw_max_ = encode_uint16(data[1], data[0]);
|
70
|
-
}
|
71
|
-
if (this->y_raw_max_ == this->y_raw_min_) {
|
72
71
|
this->y_raw_max_ = encode_uint16(data[3], data[2]);
|
72
|
+
if (this->swap_x_y_)
|
73
|
+
std::swap(this->x_raw_max_, this->y_raw_max_);
|
73
74
|
}
|
74
|
-
esph_log_d(TAG, "calibration max_x/max_y %d/%d", this->x_raw_max_, this->y_raw_max_);
|
75
75
|
}
|
76
76
|
}
|
77
|
+
if (err != i2c::ERROR_OK) {
|
78
|
+
ESP_LOGE(TAG, "Failed to read calibration values from touchscreen!");
|
79
|
+
this->mark_failed();
|
80
|
+
return;
|
81
|
+
}
|
77
82
|
}
|
78
83
|
if (err != i2c::ERROR_OK) {
|
79
84
|
ESP_LOGE(TAG, "Failed to communicate!");
|
@@ -15,6 +15,7 @@ namespace esphome {
|
|
15
15
|
namespace ld2450 {
|
16
16
|
|
17
17
|
static const char *const TAG = "ld2450";
|
18
|
+
static const char *const NO_MAC("08:05:04:03:02:01");
|
18
19
|
static const char *const UNKNOWN_MAC("unknown");
|
19
20
|
|
20
21
|
// LD2450 UART Serial Commands
|
@@ -614,12 +615,12 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
|
614
615
|
ESP_LOGV(TAG, "MAC address: %s", this->mac_.c_str());
|
615
616
|
#ifdef USE_TEXT_SENSOR
|
616
617
|
if (this->mac_text_sensor_ != nullptr) {
|
617
|
-
this->mac_text_sensor_->publish_state(this->mac_);
|
618
|
+
this->mac_text_sensor_->publish_state(this->mac_ == NO_MAC ? UNKNOWN_MAC : this->mac_);
|
618
619
|
}
|
619
620
|
#endif
|
620
621
|
#ifdef USE_SWITCH
|
621
622
|
if (this->bluetooth_switch_ != nullptr) {
|
622
|
-
this->bluetooth_switch_->publish_state(this->mac_ !=
|
623
|
+
this->bluetooth_switch_->publish_state(this->mac_ != NO_MAC);
|
623
624
|
}
|
624
625
|
#endif
|
625
626
|
break;
|
@@ -1,7 +1,9 @@
|
|
1
1
|
import esphome.codegen as cg
|
2
|
-
from esphome.components.switch import Switch,
|
2
|
+
from esphome.components.switch import Switch, register_switch, switch_schema
|
3
3
|
import esphome.config_validation as cv
|
4
|
+
from esphome.const import CONF_ID
|
4
5
|
from esphome.cpp_generator import MockObj
|
6
|
+
from esphome.cpp_types import Component
|
5
7
|
|
6
8
|
from ..defines import CONF_WIDGET, literal
|
7
9
|
from ..lvcode import (
|
@@ -18,7 +20,7 @@ from ..lvcode import (
|
|
18
20
|
from ..types import LV_EVENT, LV_STATE, lv_pseudo_button_t, lvgl_ns
|
19
21
|
from ..widgets import get_widgets, wait_for_widgets
|
20
22
|
|
21
|
-
LVGLSwitch = lvgl_ns.class_("LVGLSwitch", Switch)
|
23
|
+
LVGLSwitch = lvgl_ns.class_("LVGLSwitch", Switch, Component)
|
22
24
|
CONFIG_SCHEMA = switch_schema(LVGLSwitch).extend(
|
23
25
|
{
|
24
26
|
cv.Required(CONF_WIDGET): cv.use_id(lv_pseudo_button_t),
|
@@ -27,21 +29,24 @@ CONFIG_SCHEMA = switch_schema(LVGLSwitch).extend(
|
|
27
29
|
|
28
30
|
|
29
31
|
async def to_code(config):
|
30
|
-
switch = await new_switch(config)
|
31
32
|
widget = await get_widgets(config, CONF_WIDGET)
|
32
33
|
widget = widget[0]
|
33
34
|
await wait_for_widgets()
|
34
|
-
|
35
|
-
|
35
|
+
switch_id = MockObj(config[CONF_ID], "->")
|
36
|
+
v = literal("v")
|
36
37
|
async with LambdaContext([(cg.bool_, "v")]) as control:
|
37
|
-
with LvConditional(
|
38
|
+
with LvConditional(v) as cond:
|
38
39
|
widget.add_state(LV_STATE.CHECKED)
|
39
40
|
cond.else_()
|
40
41
|
widget.clear_state(LV_STATE.CHECKED)
|
41
42
|
lv.event_send(widget.obj, API_EVENT, cg.nullptr)
|
42
|
-
control.add(
|
43
|
+
control.add(switch_id.publish_state(v))
|
44
|
+
switch = cg.new_Pvariable(config[CONF_ID], await control.get_lambda())
|
45
|
+
await cg.register_component(switch, config)
|
46
|
+
await register_switch(switch, config)
|
47
|
+
async with LambdaContext(EVENT_ARG) as checked_ctx:
|
48
|
+
checked_ctx.add(switch.publish_state(widget.get_value()))
|
43
49
|
async with LvContext() as ctx:
|
44
|
-
lv_add(switch.set_control_lambda(await control.get_lambda()))
|
45
50
|
ctx.add(
|
46
51
|
lvgl_static.add_event_cb(
|
47
52
|
widget.obj,
|
@@ -10,26 +10,15 @@
|
|
10
10
|
namespace esphome {
|
11
11
|
namespace lvgl {
|
12
12
|
|
13
|
-
class LVGLSwitch : public switch_::Switch {
|
13
|
+
class LVGLSwitch : public switch_::Switch, public Component {
|
14
14
|
public:
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
this->state_lambda_(this->initial_state_.value());
|
19
|
-
this->initial_state_.reset();
|
20
|
-
}
|
21
|
-
}
|
15
|
+
LVGLSwitch(std::function<void(bool)> state_lambda) : state_lambda_(std::move(state_lambda)) {}
|
16
|
+
|
17
|
+
void setup() override { this->write_state(this->get_initial_state_with_restore_mode().value_or(false)); }
|
22
18
|
|
23
19
|
protected:
|
24
|
-
void write_state(bool value) override {
|
25
|
-
if (this->state_lambda_ != nullptr) {
|
26
|
-
this->state_lambda_(value);
|
27
|
-
} else {
|
28
|
-
this->initial_state_ = value;
|
29
|
-
}
|
30
|
-
}
|
20
|
+
void write_state(bool value) override { this->state_lambda_(value); }
|
31
21
|
std::function<void(bool)> state_lambda_{};
|
32
|
-
optional<bool> initial_state_{};
|
33
22
|
};
|
34
23
|
|
35
24
|
} // namespace lvgl
|
@@ -56,7 +56,8 @@ const char *media_player_command_to_string(MediaPlayerCommand command) {
|
|
56
56
|
|
57
57
|
void MediaPlayerCall::validate_() {
|
58
58
|
if (this->media_url_.has_value()) {
|
59
|
-
if (this->command_.has_value()) {
|
59
|
+
if (this->command_.has_value() && this->command_.value() != MEDIA_PLAYER_COMMAND_ENQUEUE) {
|
60
|
+
// Don't remove an enqueue command
|
60
61
|
ESP_LOGW(TAG, "MediaPlayerCall: Setting both command and media_url is not needed.");
|
61
62
|
this->command_.reset();
|
62
63
|
}
|
@@ -100,7 +100,7 @@ void SpeakerMediaPlayer::setup() {
|
|
100
100
|
|
101
101
|
if (!this->single_pipeline_()) {
|
102
102
|
this->media_pipeline_ = make_unique<AudioPipeline>(this->media_speaker_, this->buffer_size_,
|
103
|
-
this->task_stack_in_psram_, "
|
103
|
+
this->task_stack_in_psram_, "med", MEDIA_PIPELINE_TASK_PRIORITY);
|
104
104
|
|
105
105
|
if (this->media_pipeline_ == nullptr) {
|
106
106
|
ESP_LOGE(TAG, "Failed to create media pipeline");
|
@@ -138,77 +138,64 @@ void SpeakerMediaPlayer::watch_media_commands_() {
|
|
138
138
|
}
|
139
139
|
|
140
140
|
MediaCallCommand media_command;
|
141
|
-
esp_err_t err = ESP_OK;
|
142
141
|
|
143
142
|
if (xQueueReceive(this->media_control_command_queue_, &media_command, 0) == pdTRUE) {
|
144
|
-
bool
|
145
|
-
bool new_file = media_command.new_file.has_value() && media_command.new_file.value();
|
143
|
+
bool enqueue = media_command.enqueue.has_value() && media_command.enqueue.value();
|
146
144
|
|
147
|
-
if (
|
148
|
-
|
145
|
+
if (media_command.url.has_value() || media_command.file.has_value()) {
|
146
|
+
PlaylistItem playlist_item;
|
147
|
+
if (media_command.url.has_value()) {
|
148
|
+
playlist_item.url = *media_command.url.value();
|
149
|
+
delete media_command.url.value();
|
150
|
+
}
|
151
|
+
if (media_command.file.has_value()) {
|
152
|
+
playlist_item.file = media_command.file.value();
|
153
|
+
}
|
149
154
|
|
150
155
|
if (this->single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) {
|
151
|
-
// Announcement playlist/pipeline
|
152
|
-
|
153
156
|
if (!enqueue) {
|
154
|
-
//
|
157
|
+
// Ensure the loaded next item doesn't start playing, clear the queue, start the file, and unpause
|
155
158
|
this->cancel_timeout("next_ann");
|
156
159
|
this->announcement_playlist_.clear();
|
157
|
-
|
158
|
-
|
159
|
-
PlaylistItem playlist_item;
|
160
|
-
if (new_url) {
|
161
|
-
playlist_item.url = this->announcement_url_;
|
162
|
-
if (!enqueue) {
|
163
|
-
// Not adding to the queue, so directly start playback and internally unpause the pipeline
|
164
|
-
this->announcement_pipeline_->start_url(playlist_item.url.value());
|
165
|
-
this->announcement_pipeline_->set_pause_state(false);
|
166
|
-
}
|
167
|
-
} else {
|
168
|
-
playlist_item.file = this->announcement_file_;
|
169
|
-
if (!enqueue) {
|
170
|
-
// Not adding to the queue, so directly start playback and internally unpause the pipeline
|
160
|
+
if (media_command.file.has_value()) {
|
171
161
|
this->announcement_pipeline_->start_file(playlist_item.file.value());
|
172
|
-
|
162
|
+
} else if (media_command.url.has_value()) {
|
163
|
+
this->announcement_pipeline_->start_url(playlist_item.url.value());
|
173
164
|
}
|
165
|
+
this->announcement_pipeline_->set_pause_state(false);
|
174
166
|
}
|
175
167
|
this->announcement_playlist_.push_back(playlist_item);
|
176
168
|
} else {
|
177
|
-
// Media playlist/pipeline
|
178
|
-
|
179
169
|
if (!enqueue) {
|
180
|
-
//
|
170
|
+
// Ensure the loaded next item doesn't start playing, clear the queue, start the file, and unpause
|
181
171
|
this->cancel_timeout("next_media");
|
182
172
|
this->media_playlist_.clear();
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
173
|
+
if (this->is_paused_) {
|
174
|
+
// If paused, stop the media pipeline and unpause it after confirming its stopped. This avoids playing a
|
175
|
+
// short segment of the paused file before starting the new one.
|
176
|
+
this->media_pipeline_->stop();
|
177
|
+
this->set_retry("unpause_med", 50, 3, [this](const uint8_t remaining_attempts) {
|
178
|
+
if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) {
|
179
|
+
this->media_pipeline_->set_pause_state(false);
|
180
|
+
this->is_paused_ = false;
|
181
|
+
return RetryResult::DONE;
|
182
|
+
}
|
183
|
+
return RetryResult::RETRY;
|
184
|
+
});
|
185
|
+
} else {
|
186
|
+
// Not paused, just directly start the file
|
187
|
+
if (media_command.file.has_value()) {
|
188
|
+
this->media_pipeline_->start_file(playlist_item.file.value());
|
189
|
+
} else if (media_command.url.has_value()) {
|
190
|
+
this->media_pipeline_->start_url(playlist_item.url.value());
|
191
|
+
}
|
199
192
|
this->media_pipeline_->set_pause_state(false);
|
193
|
+
this->is_paused_ = false;
|
200
194
|
}
|
201
195
|
}
|
202
196
|
this->media_playlist_.push_back(playlist_item);
|
203
197
|
}
|
204
198
|
|
205
|
-
if (err != ESP_OK) {
|
206
|
-
ESP_LOGE(TAG, "Error starting the audio pipeline: %s", esp_err_to_name(err));
|
207
|
-
this->status_set_error();
|
208
|
-
} else {
|
209
|
-
this->status_clear_error();
|
210
|
-
}
|
211
|
-
|
212
199
|
return; // Don't process the new file play command further
|
213
200
|
}
|
214
201
|
|
@@ -232,19 +219,37 @@ void SpeakerMediaPlayer::watch_media_commands_() {
|
|
232
219
|
this->is_paused_ = true;
|
233
220
|
break;
|
234
221
|
case media_player::MEDIA_PLAYER_COMMAND_STOP:
|
222
|
+
// Pipelines do not stop immediately after calling the stop command, so confirm its stopped before unpausing.
|
223
|
+
// This avoids an audible short segment playing after receiving the stop command in a paused state.
|
235
224
|
if (this->single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) {
|
236
225
|
if (this->announcement_pipeline_ != nullptr) {
|
237
226
|
this->cancel_timeout("next_ann");
|
238
227
|
this->announcement_playlist_.clear();
|
239
228
|
this->announcement_pipeline_->stop();
|
229
|
+
this->set_retry("unpause_ann", 50, 3, [this](const uint8_t remaining_attempts) {
|
230
|
+
if (this->announcement_pipeline_state_ == AudioPipelineState::STOPPED) {
|
231
|
+
this->announcement_pipeline_->set_pause_state(false);
|
232
|
+
return RetryResult::DONE;
|
233
|
+
}
|
234
|
+
return RetryResult::RETRY;
|
235
|
+
});
|
240
236
|
}
|
241
237
|
} else {
|
242
238
|
if (this->media_pipeline_ != nullptr) {
|
243
239
|
this->cancel_timeout("next_media");
|
244
240
|
this->media_playlist_.clear();
|
245
241
|
this->media_pipeline_->stop();
|
242
|
+
this->set_retry("unpause_med", 50, 3, [this](const uint8_t remaining_attempts) {
|
243
|
+
if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) {
|
244
|
+
this->media_pipeline_->set_pause_state(false);
|
245
|
+
this->is_paused_ = false;
|
246
|
+
return RetryResult::DONE;
|
247
|
+
}
|
248
|
+
return RetryResult::RETRY;
|
249
|
+
});
|
246
250
|
}
|
247
251
|
}
|
252
|
+
|
248
253
|
break;
|
249
254
|
case media_player::MEDIA_PLAYER_COMMAND_TOGGLE:
|
250
255
|
if (this->media_pipeline_ != nullptr) {
|
@@ -361,11 +366,11 @@ void SpeakerMediaPlayer::loop() {
|
|
361
366
|
}
|
362
367
|
|
363
368
|
if (timeout_ms > 0) {
|
364
|
-
// Pause pipeline internally to
|
369
|
+
// Pause pipeline internally to facilitate the delay between items
|
365
370
|
this->announcement_pipeline_->set_pause_state(true);
|
366
|
-
// Internally unpause the pipeline after the delay between playlist items
|
367
|
-
|
368
|
-
|
371
|
+
// Internally unpause the pipeline after the delay between playlist items. Announcements do not follow the
|
372
|
+
// media player's pause state.
|
373
|
+
this->set_timeout("next_ann", timeout_ms, [this]() { this->announcement_pipeline_->set_pause_state(false); });
|
369
374
|
}
|
370
375
|
}
|
371
376
|
} else {
|
@@ -401,9 +406,10 @@ void SpeakerMediaPlayer::loop() {
|
|
401
406
|
}
|
402
407
|
|
403
408
|
if (timeout_ms > 0) {
|
404
|
-
// Pause pipeline internally to
|
409
|
+
// Pause pipeline internally to facilitate the delay between items
|
405
410
|
this->media_pipeline_->set_pause_state(true);
|
406
|
-
// Internally unpause the pipeline after the delay between playlist items
|
411
|
+
// Internally unpause the pipeline after the delay between playlist items, if the media player state is
|
412
|
+
// not paused.
|
407
413
|
this->set_timeout("next_media", timeout_ms,
|
408
414
|
[this]() { this->media_pipeline_->set_pause_state(this->is_paused_); });
|
409
415
|
}
|
@@ -429,12 +435,10 @@ void SpeakerMediaPlayer::play_file(audio::AudioFile *media_file, bool announceme
|
|
429
435
|
|
430
436
|
MediaCallCommand media_command;
|
431
437
|
|
432
|
-
media_command.
|
438
|
+
media_command.file = media_file;
|
433
439
|
if (this->single_pipeline_() || announcement) {
|
434
|
-
this->announcement_file_ = media_file;
|
435
440
|
media_command.announce = true;
|
436
441
|
} else {
|
437
|
-
this->media_file_ = media_file;
|
438
442
|
media_command.announce = false;
|
439
443
|
}
|
440
444
|
media_command.enqueue = enqueue;
|
@@ -456,14 +460,8 @@ void SpeakerMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
|
456
460
|
}
|
457
461
|
|
458
462
|
if (call.get_media_url().has_value()) {
|
459
|
-
std::string
|
460
|
-
|
461
|
-
media_command.new_url = true;
|
462
|
-
if (this->single_pipeline_() || (call.get_announcement().has_value() && call.get_announcement().value())) {
|
463
|
-
this->announcement_url_ = new_uri;
|
464
|
-
} else {
|
465
|
-
this->media_url_ = new_uri;
|
466
|
-
}
|
463
|
+
media_command.url = new std::string(
|
464
|
+
call.get_media_url().value()); // Must be manually deleted after receiving media_command from a queue
|
467
465
|
|
468
466
|
if (call.get_command().has_value()) {
|
469
467
|
if (call.get_command().value() == media_player::MEDIA_PLAYER_COMMAND_ENQUEUE) {
|
@@ -24,8 +24,8 @@ struct MediaCallCommand {
|
|
24
24
|
optional<media_player::MediaPlayerCommand> command;
|
25
25
|
optional<float> volume;
|
26
26
|
optional<bool> announce;
|
27
|
-
optional<
|
28
|
-
optional<
|
27
|
+
optional<std::string *> url; // Must be manually deleted after receiving this struct from a queue
|
28
|
+
optional<audio::AudioFile *> file;
|
29
29
|
optional<bool> enqueue;
|
30
30
|
};
|
31
31
|
|
@@ -109,15 +109,11 @@ class SpeakerMediaPlayer : public Component, public media_player::MediaPlayer {
|
|
109
109
|
|
110
110
|
optional<media_player::MediaPlayerSupportedFormat> media_format_;
|
111
111
|
AudioPipelineState media_pipeline_state_{AudioPipelineState::STOPPED};
|
112
|
-
std::string media_url_{}; // only modified by control function
|
113
|
-
audio::AudioFile *media_file_{}; // only modified by play_file function
|
114
112
|
bool media_repeat_one_{false};
|
115
113
|
uint32_t media_playlist_delay_ms_{0};
|
116
114
|
|
117
115
|
optional<media_player::MediaPlayerSupportedFormat> announcement_format_;
|
118
116
|
AudioPipelineState announcement_pipeline_state_{AudioPipelineState::STOPPED};
|
119
|
-
std::string announcement_url_{}; // only modified by control function
|
120
|
-
audio::AudioFile *announcement_file_{}; // only modified by play_file function
|
121
117
|
bool announcement_repeat_one_{false};
|
122
118
|
uint32_t announcement_playlist_delay_ms_{0};
|
123
119
|
|
esphome/const.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: esphome
|
3
|
-
Version: 2025.3.
|
3
|
+
Version: 2025.3.3
|
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@nabucasa.com>
|
6
6
|
License: MIT
|
@@ -5,7 +5,7 @@ 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
7
|
esphome/config_validation.py,sha256=9KOhLHQXmDbahg6zHynXfXDfAL2bciu35_SHxHrzZ2M,63705
|
8
|
-
esphome/const.py,sha256
|
8
|
+
esphome/const.py,sha256=-khONIbIZaEVV6rouwuo3K6u9_qn4jMlFdB1EY1Y5HY,40762
|
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
|
@@ -568,7 +568,7 @@ esphome/components/cse7766/cse7766.h,sha256=RE_q5Sa2n8PLkQsO3C9Nt11g6PS_5XBIVD1w
|
|
568
568
|
esphome/components/cse7766/sensor.py,sha256=rHZGEUgTD8j6V9u8kTKSfRWQ67HzqIeHa9YaC5j6K70,4082
|
569
569
|
esphome/components/cst226/__init__.py,sha256=Xbt13-GS0lUNexCt3EYip3UvO15P2cdJdepZWoDqBw8,130
|
570
570
|
esphome/components/cst226/touchscreen/__init__.py,sha256=cGkF2fb0drtC0Xnz_quMC-uYSoqnXXMTzzEpjr6aP74,1215
|
571
|
-
esphome/components/cst226/touchscreen/cst226_touchscreen.cpp,sha256=
|
571
|
+
esphome/components/cst226/touchscreen/cst226_touchscreen.cpp,sha256=OsPEVSYsvG6bJmAtkS4muGEQwY31wrg7R0AxctEUohw,2874
|
572
572
|
esphome/components/cst226/touchscreen/cst226_touchscreen.h,sha256=x5q0en-w0ebNgoBznouwrZd1VD_gy9J6accuyQhMcmw,1221
|
573
573
|
esphome/components/cst816/__init__.py,sha256=7XLTtm_EM7-QP8ZfGtLQi1KBroiWOqeRMBTjTbXt-8Q,130
|
574
574
|
esphome/components/cst816/binary_sensor/__init__.py,sha256=xOKwMOe_N3twSMYNb5y2i_tUCQ7umUDA6rUrGg51NAc,190
|
@@ -686,7 +686,7 @@ esphome/components/dht12/dht12.cpp,sha256=l9vUeg6oc_XRIifT6pft_Jjk4WmS08rLkWv_af
|
|
686
686
|
esphome/components/dht12/dht12.h,sha256=zHdQNIDC7nPMblvyEkTfXMeGCLmYRB7ZL_SXuB2PEWY,788
|
687
687
|
esphome/components/dht12/sensor.py,sha256=9P1JtUF2VRYtEE1j8GHlsob1EHF5n3DC7mGuGV_fE_w,1684
|
688
688
|
esphome/components/display/__init__.py,sha256=cKo4ldiSbNxcJKEITCDODtgS9kKzQJoPtJIc7mMapsQ,6760
|
689
|
-
esphome/components/display/display.cpp,sha256=
|
689
|
+
esphome/components/display/display.cpp,sha256=wXZdyEDufmv6QK-R3if2rBl9rPnHU8vzrCaPRQ33_Wk,32394
|
690
690
|
esphome/components/display/display.h,sha256=uIs9FRgOYUXvOuEJ1NWsXtfja0a3SWCdmx-gGbhrfC0,32346
|
691
691
|
esphome/components/display/display_buffer.cpp,sha256=0jL60x2WNyDTNgjK2Iv7R4ZlA57cbIt1-J_QvGFKlbM,1896
|
692
692
|
esphome/components/display/display_buffer.h,sha256=RkFqe72PZtSKR60mWlb79FDqVQQFsefcEOdOMwIjuGc,809
|
@@ -732,7 +732,7 @@ esphome/components/ee895/ee895.h,sha256=PlW9Q8XFN6_V0SJxD3k-upafHEXvSLbvRb5JINp5
|
|
732
732
|
esphome/components/ee895/sensor.py,sha256=UUaWHFHVHqwubCzEJ4da-SzXezojdFc8_QQh70449w4,2172
|
733
733
|
esphome/components/ektf2232/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
734
734
|
esphome/components/ektf2232/touchscreen/__init__.py,sha256=sJg6n62UTHjwDvsFPtJe4tkNxiWqOXrdMjLj6TUufdE,1271
|
735
|
-
esphome/components/ektf2232/touchscreen/ektf2232.cpp,sha256=
|
735
|
+
esphome/components/ektf2232/touchscreen/ektf2232.cpp,sha256=F7uBZmlEn8T3nfkJ96GOVbvP923PmigyvJC_vS1UOIY,3640
|
736
736
|
esphome/components/ektf2232/touchscreen/ektf2232.h,sha256=7Lr7YYdTWZOUUfMdg1nVw2JVjvhVhn2XvZKbMc1GFlY,827
|
737
737
|
esphome/components/emc2101/__init__.py,sha256=2kE5cXQkG9tkU87DFLKxB0cX5WUqdAvZWzZnJaZ9RjQ,2808
|
738
738
|
esphome/components/emc2101/emc2101.cpp,sha256=SdeT5uVNWEQ77lHbtH0KOyckCr1PfHB67Q6zQXqzJRg,6921
|
@@ -952,7 +952,7 @@ esphome/components/fingerprint_grow/binary_sensor.py,sha256=NeVcqVCpmjGdnfimIIWS
|
|
952
952
|
esphome/components/fingerprint_grow/fingerprint_grow.cpp,sha256=xtHEpnp1Ei_5s5SS5Vfxt8vG_PoPMmeUjbOQHWrn5G0,18675
|
953
953
|
esphome/components/fingerprint_grow/fingerprint_grow.h,sha256=UEkLR4Cqas_XYlTLAwscXCAMRoprWeQZEZ_3vTsI-BM,11206
|
954
954
|
esphome/components/fingerprint_grow/sensor.py,sha256=eazvZvdtt1Rl8o3Aw6eYKn-kb2sNDfZKHegxpFFdQeg,2244
|
955
|
-
esphome/components/font/__init__.py,sha256=
|
955
|
+
esphome/components/font/__init__.py,sha256=dfieu9eop8dl0oGvc19EMQVq6qH8HiyA4FrlFOnUMFY,19199
|
956
956
|
esphome/components/font/font.cpp,sha256=dxZID-p7toxsAe3JZIc6syEdleARl-H3IRWoUIFGUOY,5361
|
957
957
|
esphome/components/font/font.h,sha256=lBUD-bX8qK0Us0tVjq9i38EJVG6p9w4npKnW1L_ILx0,2024
|
958
958
|
esphome/components/fs3000/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -1039,7 +1039,7 @@ esphome/components/gt911/binary_sensor/__init__.py,sha256=fx8W9VhBGssxRD21iTQGva
|
|
1039
1039
|
esphome/components/gt911/binary_sensor/gt911_button.cpp,sha256=KACuxHcVbk3TZdSPy-8kO4j0LZZZmdAy4VWMicnaoLY,586
|
1040
1040
|
esphome/components/gt911/binary_sensor/gt911_button.h,sha256=3QCm3g8Ca9VtsKKjWgc_Bre4Dc3RhXgaLt1Mq3iEKd8,714
|
1041
1041
|
esphome/components/gt911/touchscreen/__init__.py,sha256=Hx69_ljCE1F-dP5BzEoQ7vIcOTy9_AsnDBb9FH3pCpU,1155
|
1042
|
-
esphome/components/gt911/touchscreen/gt911_touchscreen.cpp,sha256=
|
1042
|
+
esphome/components/gt911/touchscreen/gt911_touchscreen.cpp,sha256=pxFm2WgskgUy2hK13nAXqp72GpvjH9dbVk-LqYS_ggs,4684
|
1043
1043
|
esphome/components/gt911/touchscreen/gt911_touchscreen.h,sha256=q-ZvP6OEGk8TU9eNfWI5-Bj5lVz-DXkxEGEiSzYr2L0,1026
|
1044
1044
|
esphome/components/haier/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1045
1045
|
esphome/components/haier/automation.h,sha256=xHnMbqHWFwtibKxgqLraPeNlKLWv2_AT7VX0aMVYtr8,3688
|
@@ -1396,7 +1396,7 @@ esphome/components/ld2420/text_sensor/text_sensor.cpp,sha256=T8Hlo3rGbyEpKMlFHTf
|
|
1396
1396
|
esphome/components/ld2420/text_sensor/text_sensor.h,sha256=aK91ri0NvHth3ya0zN1OeX81v1nqveoiJcOfqCpaAJI,672
|
1397
1397
|
esphome/components/ld2450/__init__.py,sha256=5QeRhMvHdL4UVu4Qv80Ly78UOXU28kzWEAPxPKpNVNQ,1280
|
1398
1398
|
esphome/components/ld2450/binary_sensor.py,sha256=SyIw9c-4JqNm8JKuzSKA9rVWaVCGsYAslV0VbhqJnoM,1755
|
1399
|
-
esphome/components/ld2450/ld2450.cpp,sha256=
|
1399
|
+
esphome/components/ld2450/ld2450.cpp,sha256=WMUKdVmBpT6f4RhJTo8Ep0oA4MnwlYfSEYsTbx4MLtc,30079
|
1400
1400
|
esphome/components/ld2450/ld2450.h,sha256=7mTGWij9R__PpeonHR7TbxZkvJVdmIiaAoU7jB5fR2U,7984
|
1401
1401
|
esphome/components/ld2450/sensor.py,sha256=bEowM_OzazFp3kSAnyGtw0W8AsX2K5znbCYU4DObqNQ,6570
|
1402
1402
|
esphome/components/ld2450/text_sensor.py,sha256=msgqwIFvkSrewI7MP_KPKMWdMOEpPFOj0hhsfudUfho,2009
|
@@ -1541,8 +1541,8 @@ esphome/components/lvgl/number/lvgl_number.h,sha256=UshgT5_EvfaA0nWWChjxoyIPy_0W
|
|
1541
1541
|
esphome/components/lvgl/select/__init__.py,sha256=KOlRVSjCt8TFrjrGPywpjKmQUUAzJUHuA_acLCp6-EI,1011
|
1542
1542
|
esphome/components/lvgl/select/lvgl_select.h,sha256=_nqOOVDNKcOEph6-EZ40VhjkgMdFRjVJB3OTl6tVIso,1659
|
1543
1543
|
esphome/components/lvgl/sensor/__init__.py,sha256=TCK3N05hAW1OjDYV1S5DUZd5JcmfpzWrcVwuA6PXf1c,1116
|
1544
|
-
esphome/components/lvgl/switch/__init__.py,sha256=
|
1545
|
-
esphome/components/lvgl/switch/lvgl_switch.h,sha256=
|
1544
|
+
esphome/components/lvgl/switch/__init__.py,sha256=d63-MV2Hbz_fNh_qWTEbe0K_g4eJX0x63TW2XyIrhe0,1909
|
1545
|
+
esphome/components/lvgl/switch/lvgl_switch.h,sha256=EUG9PQfryUD8EHP_GmYMGElOrBQG0Yd8FHyFFfBEvbw,686
|
1546
1546
|
esphome/components/lvgl/text/__init__.py,sha256=6P8kh6XRVX1Falw3Up0YsN4HIb9CyJShXHjNQb_Rsw4,1544
|
1547
1547
|
esphome/components/lvgl/text/lvgl_text.h,sha256=H0tLRmOMCKTelGj-kLF0J6CGoOPQo142cP-CTOk4Rog,914
|
1548
1548
|
esphome/components/lvgl/text_sensor/__init__.py,sha256=UtZwQ09zNCVaR48v7UodRSa-rY-1XF9YBg-jPTRNKRg,1103
|
@@ -1700,7 +1700,7 @@ esphome/components/mcp9808/sensor.py,sha256=71l_lBZ7F3dausUP94mdMUx-1QuGJJqi273u
|
|
1700
1700
|
esphome/components/md5/__init__.py,sha256=UMOzKlaVJtzYULytE5P3aZOdVPKrdJAQb-NLxUQ4UUE,119
|
1701
1701
|
esphome/components/md5/md5.cpp,sha256=4wfJNvWDF_kpq0_mOYpcjSvX3azczAzID3Ow82VFBWk,1711
|
1702
1702
|
esphome/components/md5/md5.h,sha256=eTAX-Ijoj30lVdQQ30wdcYKVNeFvC_0AYOzXw3wGfAQ,1591
|
1703
|
-
esphome/components/mdns/__init__.py,sha256=
|
1703
|
+
esphome/components/mdns/__init__.py,sha256=FZE-Ry4W8diC96M0af5xgPwN1G51TlctWL0vw5SfzYI,2909
|
1704
1704
|
esphome/components/mdns/mdns_component.cpp,sha256=kSNKYHmAAhHTE0UERqH1ZxGbqaPeEWgQ2ox7u3yjdxo,3675
|
1705
1705
|
esphome/components/mdns/mdns_component.h,sha256=C-95CGy4G0lI3PN97akmKtVnET5iiJze3vAMD1LkJSI,1239
|
1706
1706
|
esphome/components/mdns/mdns_esp32.cpp,sha256=5KEGkIa4M8HyHUDH9CYabLtD_NTVlaDQzZk3Nha1aiI,1710
|
@@ -1710,7 +1710,7 @@ esphome/components/mdns/mdns_libretiny.cpp,sha256=j3uX11MTYYO1WEN6X-UyuqMt9i6Fz0
|
|
1710
1710
|
esphome/components/mdns/mdns_rp2040.cpp,sha256=AzSFWtVJtq2dA9wJIFkvZvk8r_7oYbdFVtGVRxNBSgg,1306
|
1711
1711
|
esphome/components/media_player/__init__.py,sha256=5JO0c-8j-kOBXCOaN-FiYlQh0vw9DHEnTuj_muZAalc,8337
|
1712
1712
|
esphome/components/media_player/automation.h,sha256=1aQDiCcXCfbwi2WrU8WyaPnW9MfR95-f9MhFNBhQ3kI,3685
|
1713
|
-
esphome/components/media_player/media_player.cpp,sha256=
|
1713
|
+
esphome/components/media_player/media_player.cpp,sha256=VIaMoEUzX7Z95Ng8iCfBWEG3_2469WETuhokRRF2KP4,4453
|
1714
1714
|
esphome/components/media_player/media_player.h,sha256=dXDuZ2apylAj78YccKfoJzX_qscoUN-5KYGKYxiwYv4,3252
|
1715
1715
|
esphome/components/mhz19/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1716
1716
|
esphome/components/mhz19/mhz19.cpp,sha256=CBBVBMqGUsrc-4PMOaBDuKCAFNr43Kukt3a018kQI0k,3924
|
@@ -2690,8 +2690,8 @@ esphome/components/speaker/media_player/__init__.py,sha256=-bV3Fps2AGFUEW8C35py8
|
|
2690
2690
|
esphome/components/speaker/media_player/audio_pipeline.cpp,sha256=CxWJFkt3IUb4o1w6ajh2rnINUqUSOK6RigEeFEGkMus,22365
|
2691
2691
|
esphome/components/speaker/media_player/audio_pipeline.h,sha256=MYt7_kp4IJDSTnXWqLaXIkbbNkGx6F_imSryFo2UUkc,5000
|
2692
2692
|
esphome/components/speaker/media_player/automation.h,sha256=I8psUHnJ8T3fkM05h1yEYDxb0yWe6Vjz7i30OSVA3Is,683
|
2693
|
-
esphome/components/speaker/media_player/speaker_media_player.cpp,sha256=
|
2694
|
-
esphome/components/speaker/media_player/speaker_media_player.h,sha256=
|
2693
|
+
esphome/components/speaker/media_player/speaker_media_player.cpp,sha256=4qbWSTcEBXKeqxqBF10K_M6C7ONjMev4OAdMyG-HrFo,23489
|
2694
|
+
esphome/components/speaker/media_player/speaker_media_player.h,sha256=wteJb_rXEK2LUTdehGsAMldDl0KLWpP8aySHsPYIIDc,5533
|
2695
2695
|
esphome/components/speed/__init__.py,sha256=Bfyz1MHHvLHj93TfN53E2uhKXKLYtp0k4st6Xb3760o,74
|
2696
2696
|
esphome/components/speed/fan/__init__.py,sha256=zhurjCYLG9V-soV-LF4mEGxqyrcQuQ_KLdFq0LpyAKA,1798
|
2697
2697
|
esphome/components/speed/fan/speed_fan.cpp,sha256=vjrhZZ4Rto6uEmw8396tF9QrAXZvZSKKiIC-_T2LtYc,1472
|
@@ -3474,9 +3474,9 @@ esphome/dashboard/util/itertools.py,sha256=8eLrWEWmICLtXNxkKdYPQV0c_N4GEz8m9Npnb
|
|
3474
3474
|
esphome/dashboard/util/password.py,sha256=cQz3b9B-ijTe7zS6BeCW0hc3pWv6JjC78jmnycYYAh8,321
|
3475
3475
|
esphome/dashboard/util/subprocess.py,sha256=T8EW6dbU4LPd2DG1dRrdh8li71tt6J1isn411poMhkk,1022
|
3476
3476
|
esphome/dashboard/util/text.py,sha256=ENDnfN4O0NdA3CKVJjQYabFbwbrsIhVKrAMQe53qYu4,534
|
3477
|
-
esphome-2025.3.
|
3478
|
-
esphome-2025.3.
|
3479
|
-
esphome-2025.3.
|
3480
|
-
esphome-2025.3.
|
3481
|
-
esphome-2025.3.
|
3482
|
-
esphome-2025.3.
|
3477
|
+
esphome-2025.3.3.dist-info/LICENSE,sha256=HzEjkBInJe44L4WvAOPfhPJJDNj6YbnqFyvGWRzArGM,36664
|
3478
|
+
esphome-2025.3.3.dist-info/METADATA,sha256=zMM-fhpwN7TvL0-7hSWi8VNSeYNlyq-xZUN1oYnFkTk,3689
|
3479
|
+
esphome-2025.3.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
3480
|
+
esphome-2025.3.3.dist-info/entry_points.txt,sha256=mIxVNuWtbYzeEcaWCl-AQ-97aBOWbnYBAK8nbF6P4M0,50
|
3481
|
+
esphome-2025.3.3.dist-info/top_level.txt,sha256=0GSXEW3cnITpgG3qnsSMz0qoqJHAFyfw7Y8MVtEf1Yk,8
|
3482
|
+
esphome-2025.3.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|