esphome 2025.3.0b1__py3-none-any.whl → 2025.3.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.
- esphome/components/api/api_pb2.cpp +24 -0
- esphome/components/api/api_pb2.h +3 -0
- esphome/components/audio/__init__.py +1 -1
- esphome/components/audio/audio_decoder.cpp +43 -11
- esphome/components/audio/audio_reader.cpp +2 -2
- esphome/components/audio/audio_resampler.cpp +4 -2
- esphome/components/audio/audio_transfer_buffer.cpp +19 -9
- esphome/components/audio/audio_transfer_buffer.h +7 -2
- esphome/components/font/__init__.py +51 -68
- esphome/components/graph/graph.cpp +4 -0
- esphome/components/graph/graph.h +4 -0
- esphome/components/mdns/__init__.py +1 -1
- esphome/components/mixer/speaker/mixer_speaker.cpp +6 -1
- esphome/components/mixer/speaker/mixer_speaker.h +2 -0
- esphome/components/resampler/speaker/resampler_speaker.h +2 -0
- esphome/components/speaker/speaker.h +2 -2
- esphome/const.py +1 -1
- esphome/core/helpers.h +19 -0
- {esphome-2025.3.0b1.dist-info → esphome-2025.3.0b3.dist-info}/METADATA +4 -4
- {esphome-2025.3.0b1.dist-info → esphome-2025.3.0b3.dist-info}/RECORD +24 -24
- {esphome-2025.3.0b1.dist-info → esphome-2025.3.0b3.dist-info}/LICENSE +0 -0
- {esphome-2025.3.0b1.dist-info → esphome-2025.3.0b3.dist-info}/WHEEL +0 -0
- {esphome-2025.3.0b1.dist-info → esphome-2025.3.0b3.dist-info}/entry_points.txt +0 -0
- {esphome-2025.3.0b1.dist-info → esphome-2025.3.0b3.dist-info}/top_level.txt +0 -0
@@ -7094,6 +7094,16 @@ void VoiceAssistantTimerEventResponse::dump_to(std::string &out) const {
|
|
7094
7094
|
out.append("}");
|
7095
7095
|
}
|
7096
7096
|
#endif
|
7097
|
+
bool VoiceAssistantAnnounceRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
7098
|
+
switch (field_id) {
|
7099
|
+
case 4: {
|
7100
|
+
this->start_conversation = value.as_bool();
|
7101
|
+
return true;
|
7102
|
+
}
|
7103
|
+
default:
|
7104
|
+
return false;
|
7105
|
+
}
|
7106
|
+
}
|
7097
7107
|
bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
7098
7108
|
switch (field_id) {
|
7099
7109
|
case 1: {
|
@@ -7104,6 +7114,10 @@ bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLength
|
|
7104
7114
|
this->text = value.as_string();
|
7105
7115
|
return true;
|
7106
7116
|
}
|
7117
|
+
case 3: {
|
7118
|
+
this->preannounce_media_id = value.as_string();
|
7119
|
+
return true;
|
7120
|
+
}
|
7107
7121
|
default:
|
7108
7122
|
return false;
|
7109
7123
|
}
|
@@ -7111,6 +7125,8 @@ bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLength
|
|
7111
7125
|
void VoiceAssistantAnnounceRequest::encode(ProtoWriteBuffer buffer) const {
|
7112
7126
|
buffer.encode_string(1, this->media_id);
|
7113
7127
|
buffer.encode_string(2, this->text);
|
7128
|
+
buffer.encode_string(3, this->preannounce_media_id);
|
7129
|
+
buffer.encode_bool(4, this->start_conversation);
|
7114
7130
|
}
|
7115
7131
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
7116
7132
|
void VoiceAssistantAnnounceRequest::dump_to(std::string &out) const {
|
@@ -7123,6 +7139,14 @@ void VoiceAssistantAnnounceRequest::dump_to(std::string &out) const {
|
|
7123
7139
|
out.append(" text: ");
|
7124
7140
|
out.append("'").append(this->text).append("'");
|
7125
7141
|
out.append("\n");
|
7142
|
+
|
7143
|
+
out.append(" preannounce_media_id: ");
|
7144
|
+
out.append("'").append(this->preannounce_media_id).append("'");
|
7145
|
+
out.append("\n");
|
7146
|
+
|
7147
|
+
out.append(" start_conversation: ");
|
7148
|
+
out.append(YESNO(this->start_conversation));
|
7149
|
+
out.append("\n");
|
7126
7150
|
out.append("}");
|
7127
7151
|
}
|
7128
7152
|
#endif
|
esphome/components/api/api_pb2.h
CHANGED
@@ -1832,6 +1832,8 @@ class VoiceAssistantAnnounceRequest : public ProtoMessage {
|
|
1832
1832
|
public:
|
1833
1833
|
std::string media_id{};
|
1834
1834
|
std::string text{};
|
1835
|
+
std::string preannounce_media_id{};
|
1836
|
+
bool start_conversation{false};
|
1835
1837
|
void encode(ProtoWriteBuffer buffer) const override;
|
1836
1838
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
1837
1839
|
void dump_to(std::string &out) const override;
|
@@ -1839,6 +1841,7 @@ class VoiceAssistantAnnounceRequest : public ProtoMessage {
|
|
1839
1841
|
|
1840
1842
|
protected:
|
1841
1843
|
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
1844
|
+
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
1842
1845
|
};
|
1843
1846
|
class VoiceAssistantAnnounceFinished : public ProtoMessage {
|
1844
1847
|
public:
|
@@ -66,19 +66,30 @@ esp_err_t AudioDecoder::start(AudioFileType audio_file_type) {
|
|
66
66
|
case AudioFileType::FLAC:
|
67
67
|
this->flac_decoder_ = make_unique<esp_audio_libs::flac::FLACDecoder>();
|
68
68
|
this->free_buffer_required_ =
|
69
|
-
this->output_transfer_buffer_->capacity(); //
|
69
|
+
this->output_transfer_buffer_->capacity(); // Adjusted and reallocated after reading the header
|
70
70
|
break;
|
71
71
|
#endif
|
72
72
|
#ifdef USE_AUDIO_MP3_SUPPORT
|
73
73
|
case AudioFileType::MP3:
|
74
74
|
this->mp3_decoder_ = esp_audio_libs::helix_decoder::MP3InitDecoder();
|
75
|
+
|
76
|
+
// MP3 always has 1152 samples per chunk
|
75
77
|
this->free_buffer_required_ = 1152 * sizeof(int16_t) * 2; // samples * size per sample * channels
|
78
|
+
|
79
|
+
// Always reallocate the output transfer buffer to the smallest necessary size
|
80
|
+
this->output_transfer_buffer_->reallocate(this->free_buffer_required_);
|
76
81
|
break;
|
77
82
|
#endif
|
78
83
|
case AudioFileType::WAV:
|
79
84
|
this->wav_decoder_ = make_unique<esp_audio_libs::wav_decoder::WAVDecoder>();
|
80
85
|
this->wav_decoder_->reset();
|
86
|
+
|
87
|
+
// Processing WAVs doesn't actually require a specific amount of buffer size, as it is already in PCM format.
|
88
|
+
// Thus, we don't reallocate to a minimum size.
|
81
89
|
this->free_buffer_required_ = 1024;
|
90
|
+
if (this->output_transfer_buffer_->capacity() < this->free_buffer_required_) {
|
91
|
+
this->output_transfer_buffer_->reallocate(this->free_buffer_required_);
|
92
|
+
}
|
82
93
|
break;
|
83
94
|
case AudioFileType::NONE:
|
84
95
|
default:
|
@@ -116,10 +127,18 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) {
|
|
116
127
|
|
117
128
|
uint32_t decoding_start = millis();
|
118
129
|
|
130
|
+
bool first_loop_iteration = true;
|
131
|
+
|
132
|
+
size_t bytes_processed = 0;
|
133
|
+
size_t bytes_available_before_processing = 0;
|
134
|
+
|
119
135
|
while (state == FileDecoderState::MORE_TO_PROCESS) {
|
120
136
|
// Transfer decoded out
|
121
137
|
if (!this->pause_output_) {
|
122
|
-
|
138
|
+
// Never shift the data in the output transfer buffer to avoid unnecessary, slow data moves
|
139
|
+
size_t bytes_written =
|
140
|
+
this->output_transfer_buffer_->transfer_data_to_sink(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS), false);
|
141
|
+
|
123
142
|
if (this->audio_stream_info_.has_value()) {
|
124
143
|
this->accumulated_frames_written_ += this->audio_stream_info_.value().bytes_to_frames(bytes_written);
|
125
144
|
this->playback_ms_ +=
|
@@ -138,12 +157,24 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) {
|
|
138
157
|
|
139
158
|
// Decode more audio
|
140
159
|
|
141
|
-
|
160
|
+
// Only shift data on the first loop iteration to avoid unnecessary, slow moves
|
161
|
+
size_t bytes_read = this->input_transfer_buffer_->transfer_data_from_source(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS),
|
162
|
+
first_loop_iteration);
|
142
163
|
|
143
|
-
if ((this->
|
164
|
+
if (!first_loop_iteration && (this->input_transfer_buffer_->available() < bytes_processed)) {
|
165
|
+
// Less data is available than what was processed in last iteration, so don't attempt to decode.
|
166
|
+
// This attempts to avoid the decoder from consistently trying to decode an incomplete frame. The transfer buffer
|
167
|
+
// will shift the remaining data to the start and copy more from the source the next time the decode function is
|
168
|
+
// called
|
169
|
+
break;
|
170
|
+
}
|
171
|
+
|
172
|
+
bytes_available_before_processing = this->input_transfer_buffer_->available();
|
173
|
+
|
174
|
+
if ((this->potentially_failed_count_ > 10) && (bytes_read == 0)) {
|
144
175
|
// Failed to decode in last attempt and there is no new data
|
145
176
|
|
146
|
-
if (this->input_transfer_buffer_->free() == 0) {
|
177
|
+
if ((this->input_transfer_buffer_->free() == 0) && first_loop_iteration) {
|
147
178
|
// The input buffer is full. Since it previously failed on the exact same data, we can never recover
|
148
179
|
state = FileDecoderState::FAILED;
|
149
180
|
} else {
|
@@ -175,6 +206,9 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) {
|
|
175
206
|
}
|
176
207
|
}
|
177
208
|
|
209
|
+
first_loop_iteration = false;
|
210
|
+
bytes_processed = bytes_available_before_processing - this->input_transfer_buffer_->available();
|
211
|
+
|
178
212
|
if (state == FileDecoderState::POTENTIALLY_FAILED) {
|
179
213
|
++this->potentially_failed_count_;
|
180
214
|
} else if (state == FileDecoderState::END_OF_FILE) {
|
@@ -207,13 +241,11 @@ FileDecoderState AudioDecoder::decode_flac_() {
|
|
207
241
|
size_t bytes_consumed = this->flac_decoder_->get_bytes_index();
|
208
242
|
this->input_transfer_buffer_->decrease_buffer_length(bytes_consumed);
|
209
243
|
|
244
|
+
// Reallocate the output transfer buffer to the smallest necessary size
|
210
245
|
this->free_buffer_required_ = flac_decoder_->get_output_buffer_size_bytes();
|
211
|
-
if (this->output_transfer_buffer_->
|
212
|
-
//
|
213
|
-
|
214
|
-
// Couldn't reallocate output buffer
|
215
|
-
return FileDecoderState::FAILED;
|
216
|
-
}
|
246
|
+
if (!this->output_transfer_buffer_->reallocate(this->free_buffer_required_)) {
|
247
|
+
// Couldn't reallocate output buffer
|
248
|
+
return FileDecoderState::FAILED;
|
217
249
|
}
|
218
250
|
|
219
251
|
this->audio_stream_info_ =
|
@@ -259,14 +259,14 @@ AudioReaderState AudioReader::file_read_() {
|
|
259
259
|
}
|
260
260
|
|
261
261
|
AudioReaderState AudioReader::http_read_() {
|
262
|
-
this->output_transfer_buffer_->transfer_data_to_sink(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS));
|
262
|
+
this->output_transfer_buffer_->transfer_data_to_sink(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS), false);
|
263
263
|
|
264
264
|
if (esp_http_client_is_complete_data_received(this->client_)) {
|
265
265
|
if (this->output_transfer_buffer_->available() == 0) {
|
266
266
|
this->cleanup_connection_();
|
267
267
|
return AudioReaderState::FINISHED;
|
268
268
|
}
|
269
|
-
} else {
|
269
|
+
} else if (this->output_transfer_buffer_->free() > 0) {
|
270
270
|
size_t bytes_to_read = this->output_transfer_buffer_->free();
|
271
271
|
int received_len =
|
272
272
|
esp_http_client_read(this->client_, (char *) this->output_transfer_buffer_->get_buffer_end(), bytes_to_read);
|
@@ -93,8 +93,9 @@ AudioResamplerState AudioResampler::resample(bool stop_gracefully, int32_t *ms_d
|
|
93
93
|
}
|
94
94
|
|
95
95
|
if (!this->pause_output_) {
|
96
|
-
// Move audio data to the sink
|
97
|
-
|
96
|
+
// Move audio data to the sink without shifting the data in the output transfer buffer to avoid unnecessary, slow
|
97
|
+
// data moves
|
98
|
+
this->output_transfer_buffer_->transfer_data_to_sink(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS), false);
|
98
99
|
} else {
|
99
100
|
// If paused, block to avoid wasting CPU resources
|
100
101
|
delay(READ_WRITE_TIMEOUT_MS);
|
@@ -115,6 +116,7 @@ AudioResamplerState AudioResampler::resample(bool stop_gracefully, int32_t *ms_d
|
|
115
116
|
|
116
117
|
if ((this->input_stream_info_.get_sample_rate() != this->output_stream_info_.get_sample_rate()) ||
|
117
118
|
(this->input_stream_info_.get_bits_per_sample() != this->output_stream_info_.get_bits_per_sample())) {
|
119
|
+
// Adjust gain by -3 dB to avoid clipping due to the resampling process
|
118
120
|
esp_audio_libs::resampler::ResamplerResults results =
|
119
121
|
this->resampler_->resample(this->input_transfer_buffer_->get_buffer_start(),
|
120
122
|
this->output_transfer_buffer_->get_buffer_end(), frames_available, frames_free, -3);
|
@@ -33,12 +33,17 @@ size_t AudioTransferBuffer::free() const {
|
|
33
33
|
if (this->buffer_size_ == 0) {
|
34
34
|
return 0;
|
35
35
|
}
|
36
|
-
return this->buffer_size_ - (this->buffer_length_
|
36
|
+
return this->buffer_size_ - (this->buffer_length_ + (this->data_start_ - this->buffer_));
|
37
37
|
}
|
38
38
|
|
39
39
|
void AudioTransferBuffer::decrease_buffer_length(size_t bytes) {
|
40
40
|
this->buffer_length_ -= bytes;
|
41
|
-
this->
|
41
|
+
if (this->buffer_length_ > 0) {
|
42
|
+
this->data_start_ += bytes;
|
43
|
+
} else {
|
44
|
+
// All the data in the buffer has been consumed, reset the start pointer
|
45
|
+
this->data_start_ = this->buffer_;
|
46
|
+
}
|
42
47
|
}
|
43
48
|
|
44
49
|
void AudioTransferBuffer::increase_buffer_length(size_t bytes) { this->buffer_length_ += bytes; }
|
@@ -71,7 +76,7 @@ bool AudioTransferBuffer::has_buffered_data() const {
|
|
71
76
|
|
72
77
|
bool AudioTransferBuffer::reallocate(size_t new_buffer_size) {
|
73
78
|
if (this->buffer_length_ > 0) {
|
74
|
-
//
|
79
|
+
// Buffer currently has data, so reallocation is impossible
|
75
80
|
return false;
|
76
81
|
}
|
77
82
|
this->deallocate_buffer_();
|
@@ -106,12 +111,14 @@ void AudioTransferBuffer::deallocate_buffer_() {
|
|
106
111
|
this->buffer_length_ = 0;
|
107
112
|
}
|
108
113
|
|
109
|
-
size_t AudioSourceTransferBuffer::transfer_data_from_source(TickType_t ticks_to_wait) {
|
110
|
-
|
111
|
-
|
112
|
-
|
114
|
+
size_t AudioSourceTransferBuffer::transfer_data_from_source(TickType_t ticks_to_wait, bool pre_shift) {
|
115
|
+
if (pre_shift) {
|
116
|
+
// Shift data in buffer to start
|
117
|
+
if (this->buffer_length_ > 0) {
|
118
|
+
memmove(this->buffer_, this->data_start_, this->buffer_length_);
|
119
|
+
}
|
120
|
+
this->data_start_ = this->buffer_;
|
113
121
|
}
|
114
|
-
this->data_start_ = this->buffer_;
|
115
122
|
|
116
123
|
size_t bytes_to_read = this->free();
|
117
124
|
size_t bytes_read = 0;
|
@@ -125,7 +132,7 @@ size_t AudioSourceTransferBuffer::transfer_data_from_source(TickType_t ticks_to_
|
|
125
132
|
return bytes_read;
|
126
133
|
}
|
127
134
|
|
128
|
-
size_t AudioSinkTransferBuffer::transfer_data_to_sink(TickType_t ticks_to_wait) {
|
135
|
+
size_t AudioSinkTransferBuffer::transfer_data_to_sink(TickType_t ticks_to_wait, bool post_shift) {
|
129
136
|
size_t bytes_written = 0;
|
130
137
|
if (this->available()) {
|
131
138
|
#ifdef USE_SPEAKER
|
@@ -139,11 +146,14 @@ size_t AudioSinkTransferBuffer::transfer_data_to_sink(TickType_t ticks_to_wait)
|
|
139
146
|
}
|
140
147
|
|
141
148
|
this->decrease_buffer_length(bytes_written);
|
149
|
+
}
|
142
150
|
|
151
|
+
if (post_shift) {
|
143
152
|
// Shift unwritten data to the start of the buffer
|
144
153
|
memmove(this->buffer_, this->data_start_, this->buffer_length_);
|
145
154
|
this->data_start_ = this->buffer_;
|
146
155
|
}
|
156
|
+
|
147
157
|
return bytes_written;
|
148
158
|
}
|
149
159
|
|
@@ -60,6 +60,7 @@ class AudioTransferBuffer {
|
|
60
60
|
|
61
61
|
protected:
|
62
62
|
/// @brief Allocates the transfer buffer in external memory, if available.
|
63
|
+
/// @param buffer_size The number of bytes to allocate
|
63
64
|
/// @return True is successful, false otherwise.
|
64
65
|
bool allocate_buffer_(size_t buffer_size);
|
65
66
|
|
@@ -89,8 +90,10 @@ class AudioSinkTransferBuffer : public AudioTransferBuffer {
|
|
89
90
|
|
90
91
|
/// @brief Writes any available data in the transfer buffer to the sink.
|
91
92
|
/// @param ticks_to_wait FreeRTOS ticks to block while waiting for the sink to have enough space
|
93
|
+
/// @param post_shift If true, all remaining data is moved to the start of the buffer after transferring to the sink.
|
94
|
+
/// Defaults to true.
|
92
95
|
/// @return Number of bytes written
|
93
|
-
size_t transfer_data_to_sink(TickType_t ticks_to_wait);
|
96
|
+
size_t transfer_data_to_sink(TickType_t ticks_to_wait, bool post_shift = true);
|
94
97
|
|
95
98
|
/// @brief Adds a ring buffer as the transfer buffer's sink.
|
96
99
|
/// @param ring_buffer weak_ptr to the allocated ring buffer
|
@@ -125,8 +128,10 @@ class AudioSourceTransferBuffer : public AudioTransferBuffer {
|
|
125
128
|
|
126
129
|
/// @brief Reads any available data from the sink into the transfer buffer.
|
127
130
|
/// @param ticks_to_wait FreeRTOS ticks to block while waiting for the source to have enough data
|
131
|
+
/// @param pre_shift If true, any unwritten data is moved to the start of the buffer before transferring from the
|
132
|
+
/// source. Defaults to true.
|
128
133
|
/// @return Number of bytes read
|
129
|
-
size_t transfer_data_from_source(TickType_t ticks_to_wait);
|
134
|
+
size_t transfer_data_from_source(TickType_t ticks_to_wait, bool pre_shift = true);
|
130
135
|
|
131
136
|
/// @brief Adds a ring buffer as the transfer buffer's source.
|
132
137
|
/// @param ring_buffer weak_ptr to the allocated ring buffer
|
@@ -146,6 +146,13 @@ def check_missing_glyphs(file, codepoints, warning: bool = False):
|
|
146
146
|
raise cv.Invalid(message)
|
147
147
|
|
148
148
|
|
149
|
+
def pt_to_px(pt):
|
150
|
+
"""
|
151
|
+
Convert a point size to pixels, rounding up to the nearest pixel
|
152
|
+
"""
|
153
|
+
return (pt + 63) // 64
|
154
|
+
|
155
|
+
|
149
156
|
def validate_font_config(config):
|
150
157
|
"""
|
151
158
|
Check for duplicate codepoints, then check that all requested codepoints actually
|
@@ -172,42 +179,43 @@ def validate_font_config(config):
|
|
172
179
|
)
|
173
180
|
# Make setpoints and glyphspoints disjoint
|
174
181
|
setpoints.difference_update(glyphspoints)
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
check_missing_glyphs(fileconf, glyphspoints)
|
190
|
-
# A missing glyph from a set is a warning.
|
191
|
-
if not config[CONF_IGNORE_MISSING_GLYPHS]:
|
192
|
-
check_missing_glyphs(fileconf, setpoints, warning=True)
|
182
|
+
# check that glyphs are actually present
|
183
|
+
# Check extras against their own font, exclude from parent font codepoints
|
184
|
+
for extra in config[CONF_EXTRAS]:
|
185
|
+
points = {ord(x) for x in flatten(extra[CONF_GLYPHS])}
|
186
|
+
glyphspoints.difference_update(points)
|
187
|
+
setpoints.difference_update(points)
|
188
|
+
check_missing_glyphs(extra[CONF_FILE], points)
|
189
|
+
|
190
|
+
# A named glyph that can't be provided is an error
|
191
|
+
|
192
|
+
check_missing_glyphs(fileconf, glyphspoints)
|
193
|
+
# A missing glyph from a set is a warning.
|
194
|
+
if not config[CONF_IGNORE_MISSING_GLYPHS]:
|
195
|
+
check_missing_glyphs(fileconf, setpoints, warning=True)
|
193
196
|
|
194
197
|
# Populate the default after the above checks so that use of the default doesn't trigger errors
|
198
|
+
font = FONT_CACHE[fileconf]
|
195
199
|
if not config[CONF_GLYPHS] and not config[CONF_GLYPHSETS]:
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
font
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
200
|
+
# set a default glyphset, intersected with what the font actually offers
|
201
|
+
config[CONF_GLYPHS] = [
|
202
|
+
chr(x)
|
203
|
+
for x in glyphsets.unicodes_per_glyphset(DEFAULT_GLYPHSET)
|
204
|
+
if font.get_char_index(x) != 0
|
205
|
+
]
|
206
|
+
|
207
|
+
if font.has_fixed_sizes:
|
208
|
+
sizes = [pt_to_px(x.size) for x in font.available_sizes]
|
209
|
+
if not sizes:
|
210
|
+
raise cv.Invalid(
|
211
|
+
f"Font {FontCache.get_name(fileconf)} has no available sizes"
|
212
|
+
)
|
213
|
+
if CONF_SIZE not in config:
|
214
|
+
config[CONF_SIZE] = sizes[0]
|
215
|
+
elif config[CONF_SIZE] not in sizes:
|
216
|
+
sizes = ", ".join(str(x) for x in sizes)
|
209
217
|
raise cv.Invalid(
|
210
|
-
"
|
218
|
+
f"Font {FontCache.get_name(fileconf)} only has size{'s' if len(sizes) != 1 else ''} {sizes} available"
|
211
219
|
)
|
212
220
|
elif CONF_SIZE not in config:
|
213
221
|
config[CONF_SIZE] = 20
|
@@ -215,14 +223,7 @@ def validate_font_config(config):
|
|
215
223
|
return config
|
216
224
|
|
217
225
|
|
218
|
-
FONT_EXTENSIONS = (".ttf", ".woff", ".otf")
|
219
|
-
BITMAP_EXTENSIONS = (".bdf", ".pcf")
|
220
|
-
|
221
|
-
|
222
|
-
def validate_bitmap_file(value):
|
223
|
-
if not any(map(value.lower().endswith, BITMAP_EXTENSIONS)):
|
224
|
-
raise cv.Invalid(f"Only {', '.join(BITMAP_EXTENSIONS)} files are supported.")
|
225
|
-
return CORE.relative_config_path(cv.file_(value))
|
226
|
+
FONT_EXTENSIONS = (".ttf", ".woff", ".otf", "bdf", ".pcf")
|
226
227
|
|
227
228
|
|
228
229
|
def validate_truetype_file(value):
|
@@ -246,7 +247,6 @@ def add_local_file(value):
|
|
246
247
|
|
247
248
|
|
248
249
|
TYPE_LOCAL = "local"
|
249
|
-
TYPE_LOCAL_BITMAP = "local_bitmap"
|
250
250
|
TYPE_GFONTS = "gfonts"
|
251
251
|
TYPE_WEB = "web"
|
252
252
|
LOCAL_SCHEMA = cv.All(
|
@@ -258,15 +258,6 @@ LOCAL_SCHEMA = cv.All(
|
|
258
258
|
add_local_file,
|
259
259
|
)
|
260
260
|
|
261
|
-
LOCAL_BITMAP_SCHEMA = cv.All(
|
262
|
-
cv.Schema(
|
263
|
-
{
|
264
|
-
cv.Required(CONF_PATH): validate_bitmap_file,
|
265
|
-
}
|
266
|
-
),
|
267
|
-
add_local_file,
|
268
|
-
)
|
269
|
-
|
270
261
|
FULLPATH_SCHEMA = cv.maybe_simple_value(
|
271
262
|
{cv.Required(CONF_PATH): cv.string}, key=CONF_PATH
|
272
263
|
)
|
@@ -403,15 +394,6 @@ def validate_file_shorthand(value):
|
|
403
394
|
}
|
404
395
|
)
|
405
396
|
|
406
|
-
extension = Path(value).suffix
|
407
|
-
if extension in BITMAP_EXTENSIONS:
|
408
|
-
return font_file_schema(
|
409
|
-
{
|
410
|
-
CONF_TYPE: TYPE_LOCAL_BITMAP,
|
411
|
-
CONF_PATH: value,
|
412
|
-
}
|
413
|
-
)
|
414
|
-
|
415
397
|
return font_file_schema(
|
416
398
|
{
|
417
399
|
CONF_TYPE: TYPE_LOCAL,
|
@@ -424,7 +406,6 @@ TYPED_FILE_SCHEMA = cv.typed_schema(
|
|
424
406
|
{
|
425
407
|
TYPE_LOCAL: LOCAL_SCHEMA,
|
426
408
|
TYPE_GFONTS: GFONTS_SCHEMA,
|
427
|
-
TYPE_LOCAL_BITMAP: LOCAL_BITMAP_SCHEMA,
|
428
409
|
TYPE_WEB: WEB_FONT_SCHEMA,
|
429
410
|
}
|
430
411
|
)
|
@@ -522,11 +503,13 @@ async def to_code(config):
|
|
522
503
|
bpp = config[CONF_BPP]
|
523
504
|
mode = ft_pixel_mode_grays
|
524
505
|
scale = 256 // (1 << bpp)
|
506
|
+
size = config[CONF_SIZE]
|
525
507
|
# create the data array for all glyphs
|
526
508
|
for codepoint in codepoints:
|
527
509
|
font = point_font_map[codepoint]
|
528
|
-
|
529
|
-
|
510
|
+
format = font.get_format().decode("utf-8")
|
511
|
+
if format != "PCF":
|
512
|
+
font.set_pixel_sizes(size, 0)
|
530
513
|
font.load_char(codepoint)
|
531
514
|
font.glyph.render(mode)
|
532
515
|
width = font.glyph.bitmap.width
|
@@ -550,17 +533,17 @@ async def to_code(config):
|
|
550
533
|
if pixel & (1 << (bpp - bit_num - 1)):
|
551
534
|
glyph_data[pos // 8] |= 0x80 >> (pos % 8)
|
552
535
|
pos += 1
|
553
|
-
ascender = font.size.ascender
|
536
|
+
ascender = pt_to_px(font.size.ascender)
|
554
537
|
if ascender == 0:
|
555
538
|
if font.has_fixed_sizes:
|
556
|
-
ascender =
|
539
|
+
ascender = size
|
557
540
|
else:
|
558
541
|
_LOGGER.error(
|
559
542
|
"Unable to determine ascender of font %s", config[CONF_FILE]
|
560
543
|
)
|
561
544
|
glyph_args[codepoint] = GlyphInfo(
|
562
545
|
len(data),
|
563
|
-
font.glyph.metrics.horiAdvance
|
546
|
+
pt_to_px(font.glyph.metrics.horiAdvance),
|
564
547
|
font.glyph.bitmap_left,
|
565
548
|
ascender - font.glyph.bitmap_top,
|
566
549
|
width,
|
@@ -599,11 +582,11 @@ async def to_code(config):
|
|
599
582
|
|
600
583
|
glyphs = cg.static_const_array(config[CONF_RAW_GLYPH_ID], glyph_initializer)
|
601
584
|
|
602
|
-
font_height = base_font.size.height
|
603
|
-
ascender = base_font.size.ascender
|
585
|
+
font_height = pt_to_px(base_font.size.height)
|
586
|
+
ascender = pt_to_px(base_font.size.ascender)
|
604
587
|
if font_height == 0:
|
605
588
|
if base_font.has_fixed_sizes:
|
606
|
-
font_height =
|
589
|
+
font_height = size
|
607
590
|
ascender = font_height
|
608
591
|
else:
|
609
592
|
_LOGGER.error("Unable to determine height of font %s", config[CONF_FILE])
|
@@ -132,6 +132,10 @@ void Graph::draw(Display *buff, uint16_t x_offset, uint16_t y_offset, Color colo
|
|
132
132
|
yrange = ymax - ymin;
|
133
133
|
}
|
134
134
|
|
135
|
+
// Store graph limts
|
136
|
+
this->graph_limit_max_ = ymax;
|
137
|
+
this->graph_limit_min_ = ymin;
|
138
|
+
|
135
139
|
/// Draw grid
|
136
140
|
if (!std::isnan(this->gridspacing_y_)) {
|
137
141
|
for (int y = yn; y <= ym; y++) {
|
esphome/components/graph/graph.h
CHANGED
@@ -161,11 +161,15 @@ class Graph : public Component {
|
|
161
161
|
uint32_t get_duration() { return duration_; }
|
162
162
|
uint32_t get_width() { return width_; }
|
163
163
|
uint32_t get_height() { return height_; }
|
164
|
+
float get_graph_limit_min() { return graph_limit_min_; }
|
165
|
+
float get_graph_limit_max() { return graph_limit_max_; }
|
164
166
|
|
165
167
|
protected:
|
166
168
|
uint32_t duration_; /// in seconds
|
167
169
|
uint32_t width_; /// in pixels
|
168
170
|
uint32_t height_; /// in pixels
|
171
|
+
float graph_limit_min_{NAN};
|
172
|
+
float graph_limit_max_{NAN};
|
169
173
|
float min_value_{NAN};
|
170
174
|
float max_value_{NAN};
|
171
175
|
float min_range_{1.0};
|
@@ -177,11 +177,15 @@ void SourceSpeaker::set_mute_state(bool mute_state) {
|
|
177
177
|
this->parent_->get_output_speaker()->set_mute_state(mute_state);
|
178
178
|
}
|
179
179
|
|
180
|
+
bool SourceSpeaker::get_mute_state() { return this->parent_->get_output_speaker()->get_mute_state(); }
|
181
|
+
|
180
182
|
void SourceSpeaker::set_volume(float volume) {
|
181
183
|
this->volume_ = volume;
|
182
184
|
this->parent_->get_output_speaker()->set_volume(volume);
|
183
185
|
}
|
184
186
|
|
187
|
+
float SourceSpeaker::get_volume() { return this->parent_->get_output_speaker()->get_volume(); }
|
188
|
+
|
185
189
|
size_t SourceSpeaker::process_data_from_source(TickType_t ticks_to_wait) {
|
186
190
|
if (!this->transfer_buffer_.use_count()) {
|
187
191
|
return 0;
|
@@ -490,7 +494,8 @@ void MixerSpeaker::audio_mixer_task(void *params) {
|
|
490
494
|
break;
|
491
495
|
}
|
492
496
|
|
493
|
-
|
497
|
+
// Never shift the data in the output transfer buffer to avoid unnecessary, slow data moves
|
498
|
+
output_transfer_buffer->transfer_data_to_sink(pdMS_TO_TICKS(TASK_DELAY_MS), false);
|
494
499
|
|
495
500
|
const uint32_t output_frames_free =
|
496
501
|
this_mixer->audio_stream_info_.value().bytes_to_frames(output_transfer_buffer->free());
|
@@ -53,9 +53,11 @@ class SourceSpeaker : public speaker::Speaker, public Component {
|
|
53
53
|
|
54
54
|
/// @brief Mute state changes are passed to the parent's output speaker
|
55
55
|
void set_mute_state(bool mute_state) override;
|
56
|
+
bool get_mute_state() override;
|
56
57
|
|
57
58
|
/// @brief Volume state changes are passed to the parent's output speaker
|
58
59
|
void set_volume(float volume) override;
|
60
|
+
float get_volume() override;
|
59
61
|
|
60
62
|
void set_pause_state(bool pause_state) override { this->pause_state_ = pause_state; }
|
61
63
|
bool get_pause_state() const override { return this->pause_state_; }
|
@@ -34,9 +34,11 @@ class ResamplerSpeaker : public Component, public speaker::Speaker {
|
|
34
34
|
|
35
35
|
/// @brief Mute state changes are passed to the parent's output speaker
|
36
36
|
void set_mute_state(bool mute_state) override;
|
37
|
+
bool get_mute_state() override { return this->output_speaker_->get_mute_state(); }
|
37
38
|
|
38
39
|
/// @brief Volume state changes are passed to the parent's output speaker
|
39
40
|
void set_volume(float volume) override;
|
41
|
+
float get_volume() override { return this->output_speaker_->get_volume(); }
|
40
42
|
|
41
43
|
void set_output_speaker(speaker::Speaker *speaker) { this->output_speaker_ = speaker; }
|
42
44
|
void set_task_stack_in_psram(bool task_stack_in_psram) { this->task_stack_in_psram_ = task_stack_in_psram; }
|
@@ -76,7 +76,7 @@ class Speaker {
|
|
76
76
|
}
|
77
77
|
#endif
|
78
78
|
};
|
79
|
-
float get_volume() { return this->volume_; }
|
79
|
+
virtual float get_volume() { return this->volume_; }
|
80
80
|
|
81
81
|
virtual void set_mute_state(bool mute_state) {
|
82
82
|
this->mute_state_ = mute_state;
|
@@ -90,7 +90,7 @@ class Speaker {
|
|
90
90
|
}
|
91
91
|
#endif
|
92
92
|
}
|
93
|
-
bool get_mute_state() { return this->mute_state_; }
|
93
|
+
virtual bool get_mute_state() { return this->mute_state_; }
|
94
94
|
|
95
95
|
#ifdef USE_AUDIO_DAC
|
96
96
|
void set_audio_dac(audio_dac::AudioDac *audio_dac) { this->audio_dac_ = audio_dac; }
|
esphome/const.py
CHANGED
esphome/core/helpers.h
CHANGED
@@ -719,6 +719,25 @@ template<class T> class RAMAllocator {
|
|
719
719
|
return ptr;
|
720
720
|
}
|
721
721
|
|
722
|
+
T *reallocate(T *p, size_t n) { return this->reallocate(p, n, sizeof(T)); }
|
723
|
+
|
724
|
+
T *reallocate(T *p, size_t n, size_t manual_size) {
|
725
|
+
size_t size = n * sizeof(T);
|
726
|
+
T *ptr = nullptr;
|
727
|
+
#ifdef USE_ESP32
|
728
|
+
if (this->flags_ & Flags::ALLOC_EXTERNAL) {
|
729
|
+
ptr = static_cast<T *>(heap_caps_realloc(p, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
|
730
|
+
}
|
731
|
+
if (ptr == nullptr && this->flags_ & Flags::ALLOC_INTERNAL) {
|
732
|
+
ptr = static_cast<T *>(heap_caps_realloc(p, size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT));
|
733
|
+
}
|
734
|
+
#else
|
735
|
+
// Ignore ALLOC_EXTERNAL/ALLOC_INTERNAL flags if external allocation is not supported
|
736
|
+
ptr = static_cast<T *>(realloc(p, size)); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
|
737
|
+
#endif
|
738
|
+
return ptr;
|
739
|
+
}
|
740
|
+
|
722
741
|
void deallocate(T *p, size_t n) {
|
723
742
|
free(p); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc)
|
724
743
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: esphome
|
3
|
-
Version: 2025.3.
|
3
|
+
Version: 2025.3.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@nabucasa.com>
|
6
6
|
License: MIT
|
@@ -23,13 +23,13 @@ Classifier: Topic :: Home Automation
|
|
23
23
|
Requires-Python: >=3.9.0
|
24
24
|
Description-Content-Type: text/markdown
|
25
25
|
License-File: LICENSE
|
26
|
-
Requires-Dist: cryptography ==
|
26
|
+
Requires-Dist: cryptography ==44.0.2
|
27
27
|
Requires-Dist: voluptuous ==0.14.2
|
28
28
|
Requires-Dist: PyYAML ==6.0.2
|
29
29
|
Requires-Dist: paho-mqtt ==1.6.1
|
30
30
|
Requires-Dist: colorama ==0.4.6
|
31
31
|
Requires-Dist: icmplib ==3.0.4
|
32
|
-
Requires-Dist: tornado ==6.4
|
32
|
+
Requires-Dist: tornado ==6.4.2
|
33
33
|
Requires-Dist: tzlocal ==5.2
|
34
34
|
Requires-Dist: tzdata >=2021.1
|
35
35
|
Requires-Dist: pyserial ==3.5
|
@@ -37,7 +37,7 @@ Requires-Dist: platformio ==6.1.16
|
|
37
37
|
Requires-Dist: esptool ==4.8.1
|
38
38
|
Requires-Dist: click ==8.1.7
|
39
39
|
Requires-Dist: esphome-dashboard ==20250212.0
|
40
|
-
Requires-Dist: aioesphomeapi ==29.
|
40
|
+
Requires-Dist: aioesphomeapi ==29.6.0
|
41
41
|
Requires-Dist: zeroconf ==0.146.1
|
42
42
|
Requires-Dist: puremagic ==1.27
|
43
43
|
Requires-Dist: ruamel.yaml ==0.18.6
|
@@ -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=gRnH5u1m9aFv6gSK3arX-BBWulzgNpPYP88e5YWZkRo,40764
|
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
|
@@ -187,8 +187,8 @@ esphome/components/api/api_connection.h,sha256=32R1sK8nuRgfFY4Epu8mP92D6xYxkaa1J
|
|
187
187
|
esphome/components/api/api_frame_helper.cpp,sha256=KspV-UWWUkMXk23gNzsZt-hedf1Kld3L-1zUT6VVgbo,33019
|
188
188
|
esphome/components/api/api_frame_helper.h,sha256=bn6Q2TvN6fulMFGUSm7fsxwlURlQAjl8EmMSPAj5uls,5543
|
189
189
|
esphome/components/api/api_noise_context.h,sha256=0i3J3wchJitnQBTJeQm1380t0duhsz7WxJDrlUBF8mE,405
|
190
|
-
esphome/components/api/api_pb2.cpp,sha256=
|
191
|
-
esphome/components/api/api_pb2.h,sha256=
|
190
|
+
esphome/components/api/api_pb2.cpp,sha256=8o0AeBOfenhR6wwRgRcqZ1pa0Mfnxk8Ur24_b9_K-b4,246814
|
191
|
+
esphome/components/api/api_pb2.h,sha256=U1XsowoK_R0loAeomzaKzOL54Ap7L-s839GFc6QidS0,70724
|
192
192
|
esphome/components/api/api_pb2_service.cpp,sha256=xYIanFE-N_3LRJgp-1_5Ey88_BMlYZao1QjztZEaNPo,53963
|
193
193
|
esphome/components/api/api_pb2_service.h,sha256=XgdMInOdOxFQZ0X7EDt8rQWX9Z0TSS2LDWsga5vNckg,22581
|
194
194
|
esphome/components/api/api_server.cpp,sha256=bg8zJLznGBt-Io1IbaODwK1veeM3dXBRb_oQwvbhhhc,11311
|
@@ -250,17 +250,17 @@ esphome/components/atm90e32/sensor.py,sha256=w_EO5YH8pD_eswo7hKN0R_CGBrpxiIURMyG
|
|
250
250
|
esphome/components/atm90e32/button/__init__.py,sha256=JeiwKgbG4jAu00wKXTc9IE4-fyb5cUqfKKygasxqI7w,1434
|
251
251
|
esphome/components/atm90e32/button/atm90e32_button.cpp,sha256=uAKV5NiBBR6T1-scHJtFwW4gVIlZulyncLR2xluKAT8,551
|
252
252
|
esphome/components/atm90e32/button/atm90e32_button.h,sha256=aEzRVASEwVsIDCLQyLbRjRwDtfOVEb0vLdnV1DnmSYM,634
|
253
|
-
esphome/components/audio/__init__.py,sha256=
|
253
|
+
esphome/components/audio/__init__.py,sha256=2vSC3U8ZhLG3lgN3MCJcIrnsRj7n0Bf6GAee95LHhCE,3729
|
254
254
|
esphome/components/audio/audio.cpp,sha256=McWhPhfL41LchHiFqS_96W_cmL5zgs4KrDN3u5WZTQU,2212
|
255
255
|
esphome/components/audio/audio.h,sha256=8h4vtUxwHz89T9AUSHuUv_ajDrqSJDw57Hqt5G-fbw4,6180
|
256
|
-
esphome/components/audio/audio_decoder.cpp,sha256=
|
256
|
+
esphome/components/audio/audio_decoder.cpp,sha256=OEfJYRCCT3bFDHrETdjIzpf2SYa92bBPINcGMP_49EI,14922
|
257
257
|
esphome/components/audio/audio_decoder.h,sha256=hpPJjrHsK_N2crCVvsrlu7zivx4oQHQz5hr-mlW6fl0,5351
|
258
|
-
esphome/components/audio/audio_reader.cpp,sha256=
|
258
|
+
esphome/components/audio/audio_reader.cpp,sha256=c8bk2EdfNh3TTafGKyWOvEEbrzMFpo7H8uP1P4ia4Kk,8837
|
259
259
|
esphome/components/audio/audio_reader.h,sha256=1FwkJAunr3OOy2DGOmlKHfD3cwOrmBVPQvDj7Z0DTuk,3188
|
260
|
-
esphome/components/audio/audio_resampler.cpp,sha256=
|
260
|
+
esphome/components/audio/audio_resampler.cpp,sha256=7Ygx683D8nMLCgAzv4aphUAxGZabjRhLYwJzlj3fWZU,6896
|
261
261
|
esphome/components/audio/audio_resampler.h,sha256=0tJRuN39XDl1148jGytNVt_U8blkwSlCdiCIVqba8H0,4288
|
262
|
-
esphome/components/audio/audio_transfer_buffer.cpp,sha256=
|
263
|
-
esphome/components/audio/audio_transfer_buffer.h,sha256=
|
262
|
+
esphome/components/audio/audio_transfer_buffer.cpp,sha256=ECdf825_lf5VAte-C_-rpL_PcQH5H2jghD7pge19eb4,4890
|
263
|
+
esphome/components/audio/audio_transfer_buffer.h,sha256=Bbo4SX8G9YNiGEX69UW0hHoVGKNLS6WibUMZqfGhsHU,5739
|
264
264
|
esphome/components/audio_adc/__init__.py,sha256=OZiwnU7-mCWxrjIFsp4HsKdUTvtwo4lxoGS3cylL9_E,1195
|
265
265
|
esphome/components/audio_adc/audio_adc.h,sha256=BpdWqyewyVX48IN2J3BEeZ5EB9Yhu0pKsa8VCjxx8r8,284
|
266
266
|
esphome/components/audio_adc/automation.h,sha256=oJ6yN2M4B-z3Up--H0oUKrP8HROEe8aqOtOCGMj00Yg,537
|
@@ -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=r7IpPuAOAJuPyz9tvnb_q9T9QTLuH2-ti-D3iDGOG9A,18893
|
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
|
@@ -1014,8 +1014,8 @@ esphome/components/gps/time/__init__.py,sha256=iuZWg8qhi8uMoah4B2z4OyAsXndE9z6oH
|
|
1014
1014
|
esphome/components/gps/time/gps_time.cpp,sha256=XEslYAhMq8ZViWF0QfoO95JiISUj0TLeuRcU4CnJq_8,958
|
1015
1015
|
esphome/components/gps/time/gps_time.h,sha256=LTbCT36s68Sjifw0Qv6yxo5aiv2NK6Zreh1Rmtkxsqk,624
|
1016
1016
|
esphome/components/graph/__init__.py,sha256=cxfJJTEGoaQ_3EAo5_cWUvLWAUjeoNyI4mqoxwkm_cc,7819
|
1017
|
-
esphome/components/graph/graph.cpp,sha256=
|
1018
|
-
esphome/components/graph/graph.h,sha256=
|
1017
|
+
esphome/components/graph/graph.cpp,sha256=khFAaKpn7t67RtQFtbp-5GnjxGcTHHQS19hYjj4yJVc,12331
|
1018
|
+
esphome/components/graph/graph.h,sha256=_QYsue2vhTKTLdKW39b_JVcPMwzhlyx5201fIuYJMrw,6201
|
1019
1019
|
esphome/components/graphical_display_menu/__init__.py,sha256=YGbv_JsuWmW3HumvMZq0EwJszFmaXGbNYrrl9OPhNEc,3557
|
1020
1020
|
esphome/components/graphical_display_menu/graphical_display_menu.cpp,sha256=_1xbdf6a_krZS-xD8D4kRW32QPz68zWs-MrXLOYYThU,9146
|
1021
1021
|
esphome/components/graphical_display_menu/graphical_display_menu.h,sha256=wxHyShfCIFDgvppSatvxAYPSnGNjYF9uuh-sloI53MI,2957
|
@@ -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=W8e7xs4Zl1eRRdvMthYrmHXPUCmbaqTg_vfB7QAG8xw,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
|
@@ -1770,8 +1770,8 @@ esphome/components/mitsubishi/mitsubishi.h,sha256=DDSRb5mYr2RsocbBTQahdGJaHtH-k6
|
|
1770
1770
|
esphome/components/mixer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1771
1771
|
esphome/components/mixer/speaker/__init__.py,sha256=DhnzGW-FbnvPZujuaVusNPA2VmsqQoqMp9IHYeL8zfs,5701
|
1772
1772
|
esphome/components/mixer/speaker/automation.h,sha256=cqmoTEvMNipbgyD50kxumgyk95R8C3OuO5jdxFJDL1c,503
|
1773
|
-
esphome/components/mixer/speaker/mixer_speaker.cpp,sha256=
|
1774
|
-
esphome/components/mixer/speaker/mixer_speaker.h,sha256
|
1773
|
+
esphome/components/mixer/speaker/mixer_speaker.cpp,sha256=IiyFORg63uESGT2_tDZ5bFSIXSTlpuFSbrneBrqTFew,26145
|
1774
|
+
esphome/components/mixer/speaker/mixer_speaker.h,sha256=mbu6UBIRpLlVDffJRf0OJvzmjgKKukPG45y18rTw4Xs,10081
|
1775
1775
|
esphome/components/mlx90393/__init__.py,sha256=Ao5t2TsBxYT6KIJJ4Nnbg5_drJijuBxe7SIdBe31Fjs,34
|
1776
1776
|
esphome/components/mlx90393/sensor.py,sha256=s_Xjx1xzZC28YZaPwxzn2Z0VJr_ioMfZxRrS_QtrHw0,4966
|
1777
1777
|
esphome/components/mlx90393/sensor_mlx90393.cpp,sha256=2rhoxM7wx2pE_cYvjEzNJ0FYoFYpnYUSGWuaNnXRqhQ,2846
|
@@ -2355,7 +2355,7 @@ esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp,sha256=qU
|
|
2355
2355
|
esphome/components/resampler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2356
2356
|
esphome/components/resampler/speaker/__init__.py,sha256=qOJ7qHILE_zRH6ttxPg8eF318k8DZPTvnraz3RhBme4,3250
|
2357
2357
|
esphome/components/resampler/speaker/resampler_speaker.cpp,sha256=3eZWLASOLQmQkXYqj5XPtdBkyAlaQdiHRzq-_7Bxgi0,11187
|
2358
|
-
esphome/components/resampler/speaker/resampler_speaker.h,sha256=
|
2358
|
+
esphome/components/resampler/speaker/resampler_speaker.h,sha256=a1BFzJNc01-ke1Re9o6JoeYBEwlCFf43SrPrqsqq-HU,3696
|
2359
2359
|
esphome/components/resistance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2360
2360
|
esphome/components/resistance/resistance_sensor.cpp,sha256=rIrw4eeVqvWbNPawY6AukH2VAFxT0X_JYaAIPy9FB_w,1179
|
2361
2361
|
esphome/components/resistance/resistance_sensor.h,sha256=lOuc0sTlOs2fuw0CVOPCv5DHR5DrSeQDTjZU4sykeNA,1117
|
@@ -2685,7 +2685,7 @@ esphome/components/sonoff_d1/sonoff_d1.cpp,sha256=9xT42oxeLJ5CGrZ7wqIH5KVTkwW3XY
|
|
2685
2685
|
esphome/components/sonoff_d1/sonoff_d1.h,sha256=FNHcaqGktpV3S19A1LD2wtpRpEqA0h6g9GFb36pMy_E,3457
|
2686
2686
|
esphome/components/speaker/__init__.py,sha256=2juDem8QadLMwzFp8Rvl-KeIbE-iIEsCtDa9vyZcQVA,4373
|
2687
2687
|
esphome/components/speaker/automation.h,sha256=tVSTV49GvHk0bCEgLz3rNYFe8B1F0kXLgE-WihuRaV8,2320
|
2688
|
-
esphome/components/speaker/speaker.h,sha256=
|
2688
|
+
esphome/components/speaker/speaker.h,sha256=WHAQzuNxkaUxCfPySHUONoun0Uudw917KVlnI71_Mjo,4712
|
2689
2689
|
esphome/components/speaker/media_player/__init__.py,sha256=-bV3Fps2AGFUEW8C35py8ATO6bZhrWDGzW2YLM7kpnc,15436
|
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
|
@@ -3438,7 +3438,7 @@ esphome/core/entity_helpers.py,sha256=s5lYCG5hu_1SROtSWgzI0T6802l5-I8udGy1_6HNSd
|
|
3438
3438
|
esphome/core/gpio.h,sha256=kLkCnPxu4_1CsLR4BI_Baj1lDGoRIh8uubbwsIkJPIA,2575
|
3439
3439
|
esphome/core/hal.h,sha256=e3qFkax3jfncEusf3kwXCts0Ai7D4XspJgh-VqVDcK4,844
|
3440
3440
|
esphome/core/helpers.cpp,sha256=ao-3IMSjDWjdSxZw-oLVMhV2A-ltlKquFbGzzohaHB4,25024
|
3441
|
-
esphome/core/helpers.h,sha256=
|
3441
|
+
esphome/core/helpers.h,sha256=Glb9nMEmRl9rQElEy8sXkqNmUdwHdnGA4raehWkB8wI,30298
|
3442
3442
|
esphome/core/log.cpp,sha256=MDCx87ytW6Fz6basxYUpagkubFzUKO1ysvU5RXbXoII,1581
|
3443
3443
|
esphome/core/log.h,sha256=hnRVgv7LjfmCpFAFa5Trt_HmmChAm64j8a9c_N3GQXw,6493
|
3444
3444
|
esphome/core/macros.h,sha256=YRip3XYzXw2pg3AFpBFA0Js-Y5GMtPkuCp2km2g5uhc,196
|
@@ -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.0b3.dist-info/LICENSE,sha256=HzEjkBInJe44L4WvAOPfhPJJDNj6YbnqFyvGWRzArGM,36664
|
3478
|
+
esphome-2025.3.0b3.dist-info/METADATA,sha256=EpO47tRzjK6pyJGru626GK2LUW_a_Zd9ybDSWxX3xV0,3691
|
3479
|
+
esphome-2025.3.0b3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
3480
|
+
esphome-2025.3.0b3.dist-info/entry_points.txt,sha256=mIxVNuWtbYzeEcaWCl-AQ-97aBOWbnYBAK8nbF6P4M0,50
|
3481
|
+
esphome-2025.3.0b3.dist-info/top_level.txt,sha256=0GSXEW3cnITpgG3qnsSMz0qoqJHAFyfw7Y8MVtEf1Yk,8
|
3482
|
+
esphome-2025.3.0b3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|