esphome 2025.6.1__py3-none-any.whl → 2025.6.2__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/audio/audio_reader.cpp +41 -21
- esphome/components/esp32/__init__.py +2 -2
- esphome/components/i2c/__init__.py +33 -0
- esphome/components/lvgl/widgets/qrcode.py +4 -6
- esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +5 -1
- esphome/components/speaker/media_player/audio_pipeline.cpp +12 -13
- esphome/components/voice_assistant/__init__.py +12 -1
- esphome/components/voice_assistant/voice_assistant.cpp +36 -2
- esphome/components/voice_assistant/voice_assistant.h +4 -0
- esphome/const.py +1 -1
- {esphome-2025.6.1.dist-info → esphome-2025.6.2.dist-info}/METADATA +1 -1
- {esphome-2025.6.1.dist-info → esphome-2025.6.2.dist-info}/RECORD +16 -16
- {esphome-2025.6.1.dist-info → esphome-2025.6.2.dist-info}/WHEEL +0 -0
- {esphome-2025.6.1.dist-info → esphome-2025.6.2.dist-info}/entry_points.txt +0 -0
- {esphome-2025.6.1.dist-info → esphome-2025.6.2.dist-info}/licenses/LICENSE +0 -0
- {esphome-2025.6.1.dist-info → esphome-2025.6.2.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@
|
|
5
5
|
#include "esphome/core/defines.h"
|
6
6
|
#include "esphome/core/hal.h"
|
7
7
|
#include "esphome/core/helpers.h"
|
8
|
+
#include "esphome/core/log.h"
|
8
9
|
|
9
10
|
#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
|
10
11
|
#include "esp_crt_bundle.h"
|
@@ -16,13 +17,13 @@ namespace audio {
|
|
16
17
|
static const uint32_t READ_WRITE_TIMEOUT_MS = 20;
|
17
18
|
|
18
19
|
static const uint32_t CONNECTION_TIMEOUT_MS = 5000;
|
19
|
-
|
20
|
-
// The number of times the http read times out with no data before throwing an error
|
21
|
-
static const uint32_t ERROR_COUNT_NO_DATA_READ_TIMEOUT = 100;
|
20
|
+
static const uint8_t MAX_FETCHING_HEADER_ATTEMPTS = 6;
|
22
21
|
|
23
22
|
static const size_t HTTP_STREAM_BUFFER_SIZE = 2048;
|
24
23
|
|
25
|
-
static const uint8_t
|
24
|
+
static const uint8_t MAX_REDIRECTIONS = 5;
|
25
|
+
|
26
|
+
static const char *const TAG = "audio_reader";
|
26
27
|
|
27
28
|
// Some common HTTP status codes - borrowed from http_request component accessed 20241224
|
28
29
|
enum HttpStatus {
|
@@ -94,7 +95,7 @@ esp_err_t AudioReader::start(const std::string &uri, AudioFileType &file_type) {
|
|
94
95
|
client_config.url = uri.c_str();
|
95
96
|
client_config.cert_pem = nullptr;
|
96
97
|
client_config.disable_auto_redirect = false;
|
97
|
-
client_config.max_redirection_count =
|
98
|
+
client_config.max_redirection_count = MAX_REDIRECTIONS;
|
98
99
|
client_config.event_handler = http_event_handler;
|
99
100
|
client_config.user_data = this;
|
100
101
|
client_config.buffer_size = HTTP_STREAM_BUFFER_SIZE;
|
@@ -116,12 +117,29 @@ esp_err_t AudioReader::start(const std::string &uri, AudioFileType &file_type) {
|
|
116
117
|
esp_err_t err = esp_http_client_open(this->client_, 0);
|
117
118
|
|
118
119
|
if (err != ESP_OK) {
|
120
|
+
ESP_LOGE(TAG, "Failed to open URL");
|
119
121
|
this->cleanup_connection_();
|
120
122
|
return err;
|
121
123
|
}
|
122
124
|
|
123
125
|
int64_t header_length = esp_http_client_fetch_headers(this->client_);
|
126
|
+
uint8_t reattempt_count = 0;
|
127
|
+
while ((header_length < 0) && (reattempt_count < MAX_FETCHING_HEADER_ATTEMPTS)) {
|
128
|
+
this->cleanup_connection_();
|
129
|
+
if (header_length != -ESP_ERR_HTTP_EAGAIN) {
|
130
|
+
// Serious error, no recovery
|
131
|
+
return ESP_FAIL;
|
132
|
+
} else {
|
133
|
+
// Reconnect from a fresh state to avoid a bug where it never reads the headers even if made available
|
134
|
+
this->client_ = esp_http_client_init(&client_config);
|
135
|
+
esp_http_client_open(this->client_, 0);
|
136
|
+
header_length = esp_http_client_fetch_headers(this->client_);
|
137
|
+
++reattempt_count;
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
124
141
|
if (header_length < 0) {
|
142
|
+
ESP_LOGE(TAG, "Failed to fetch headers");
|
125
143
|
this->cleanup_connection_();
|
126
144
|
return ESP_FAIL;
|
127
145
|
}
|
@@ -135,7 +153,7 @@ esp_err_t AudioReader::start(const std::string &uri, AudioFileType &file_type) {
|
|
135
153
|
|
136
154
|
ssize_t redirect_count = 0;
|
137
155
|
|
138
|
-
while ((esp_http_client_set_redirection(this->client_) == ESP_OK) && (redirect_count <
|
156
|
+
while ((esp_http_client_set_redirection(this->client_) == ESP_OK) && (redirect_count < MAX_REDIRECTIONS)) {
|
139
157
|
err = esp_http_client_open(this->client_, 0);
|
140
158
|
if (err != ESP_OK) {
|
141
159
|
this->cleanup_connection_();
|
@@ -267,27 +285,29 @@ AudioReaderState AudioReader::http_read_() {
|
|
267
285
|
return AudioReaderState::FINISHED;
|
268
286
|
}
|
269
287
|
} else if (this->output_transfer_buffer_->free() > 0) {
|
270
|
-
|
271
|
-
|
272
|
-
esp_http_client_read(this->client_, (char *) this->output_transfer_buffer_->get_buffer_end(), bytes_to_read);
|
288
|
+
int received_len = esp_http_client_read(this->client_, (char *) this->output_transfer_buffer_->get_buffer_end(),
|
289
|
+
this->output_transfer_buffer_->free());
|
273
290
|
|
274
291
|
if (received_len > 0) {
|
275
292
|
this->output_transfer_buffer_->increase_buffer_length(received_len);
|
276
293
|
this->last_data_read_ms_ = millis();
|
277
|
-
|
294
|
+
return AudioReaderState::READING;
|
295
|
+
} else if (received_len <= 0) {
|
278
296
|
// HTTP read error
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
// Read timed out
|
284
|
-
if ((millis() - this->last_data_read_ms_) > CONNECTION_TIMEOUT_MS) {
|
285
|
-
this->cleanup_connection_();
|
286
|
-
return AudioReaderState::FAILED;
|
287
|
-
}
|
288
|
-
|
289
|
-
delay(READ_WRITE_TIMEOUT_MS);
|
297
|
+
if (received_len == -1) {
|
298
|
+
// A true connection error occured, no chance at recovery
|
299
|
+
this->cleanup_connection_();
|
300
|
+
return AudioReaderState::FAILED;
|
290
301
|
}
|
302
|
+
|
303
|
+
// Read timed out, manually verify if it has been too long since the last successful read
|
304
|
+
if ((millis() - this->last_data_read_ms_) > MAX_FETCHING_HEADER_ATTEMPTS * CONNECTION_TIMEOUT_MS) {
|
305
|
+
ESP_LOGE(TAG, "Timed out");
|
306
|
+
this->cleanup_connection_();
|
307
|
+
return AudioReaderState::FAILED;
|
308
|
+
}
|
309
|
+
|
310
|
+
delay(READ_WRITE_TIMEOUT_MS);
|
291
311
|
}
|
292
312
|
}
|
293
313
|
|
@@ -605,7 +605,7 @@ ESP_IDF_FRAMEWORK_SCHEMA = cv.All(
|
|
605
605
|
CONF_ENABLE_LWIP_DHCP_SERVER, "wifi", default=False
|
606
606
|
): cv.boolean,
|
607
607
|
cv.Optional(
|
608
|
-
CONF_ENABLE_LWIP_MDNS_QUERIES, default=
|
608
|
+
CONF_ENABLE_LWIP_MDNS_QUERIES, default=True
|
609
609
|
): cv.boolean,
|
610
610
|
cv.Optional(
|
611
611
|
CONF_ENABLE_LWIP_BRIDGE_INTERFACE, default=False
|
@@ -760,7 +760,7 @@ async def to_code(config):
|
|
760
760
|
and not advanced[CONF_ENABLE_LWIP_DHCP_SERVER]
|
761
761
|
):
|
762
762
|
add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False)
|
763
|
-
if not advanced.get(CONF_ENABLE_LWIP_MDNS_QUERIES,
|
763
|
+
if not advanced.get(CONF_ENABLE_LWIP_MDNS_QUERIES, True):
|
764
764
|
add_idf_sdkconfig_option("CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES", False)
|
765
765
|
if not advanced.get(CONF_ENABLE_LWIP_BRIDGE_INTERFACE, False):
|
766
766
|
add_idf_sdkconfig_option("CONFIG_LWIP_BRIDGEIF_MAX_PORTS", 0)
|
@@ -1,5 +1,8 @@
|
|
1
|
+
import logging
|
2
|
+
|
1
3
|
from esphome import pins
|
2
4
|
import esphome.codegen as cg
|
5
|
+
from esphome.components import esp32
|
3
6
|
import esphome.config_validation as cv
|
4
7
|
from esphome.const import (
|
5
8
|
CONF_ADDRESS,
|
@@ -12,6 +15,8 @@ from esphome.const import (
|
|
12
15
|
CONF_SCL,
|
13
16
|
CONF_SDA,
|
14
17
|
CONF_TIMEOUT,
|
18
|
+
KEY_CORE,
|
19
|
+
KEY_FRAMEWORK_VERSION,
|
15
20
|
PLATFORM_ESP32,
|
16
21
|
PLATFORM_ESP8266,
|
17
22
|
PLATFORM_RP2040,
|
@@ -19,6 +24,7 @@ from esphome.const import (
|
|
19
24
|
from esphome.core import CORE, coroutine_with_priority
|
20
25
|
import esphome.final_validate as fv
|
21
26
|
|
27
|
+
LOGGER = logging.getLogger(__name__)
|
22
28
|
CODEOWNERS = ["@esphome/core"]
|
23
29
|
i2c_ns = cg.esphome_ns.namespace("i2c")
|
24
30
|
I2CBus = i2c_ns.class_("I2CBus")
|
@@ -40,6 +46,32 @@ def _bus_declare_type(value):
|
|
40
46
|
raise NotImplementedError
|
41
47
|
|
42
48
|
|
49
|
+
def validate_config(config):
|
50
|
+
if (
|
51
|
+
config[CONF_SCAN]
|
52
|
+
and CORE.is_esp32
|
53
|
+
and CORE.using_esp_idf
|
54
|
+
and esp32.get_esp32_variant()
|
55
|
+
in [
|
56
|
+
esp32.const.VARIANT_ESP32C5,
|
57
|
+
esp32.const.VARIANT_ESP32C6,
|
58
|
+
esp32.const.VARIANT_ESP32P4,
|
59
|
+
]
|
60
|
+
):
|
61
|
+
version: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]
|
62
|
+
if version.major == 5 and (
|
63
|
+
(version.minor == 3 and version.patch <= 3)
|
64
|
+
or (version.minor == 4 and version.patch <= 1)
|
65
|
+
):
|
66
|
+
LOGGER.warning(
|
67
|
+
"There is a bug in esp-idf version %s that breaks I2C scan, I2C scan "
|
68
|
+
"has been disabled, see https://github.com/esphome/issues/issues/7128",
|
69
|
+
str(version),
|
70
|
+
)
|
71
|
+
config[CONF_SCAN] = False
|
72
|
+
return config
|
73
|
+
|
74
|
+
|
43
75
|
pin_with_input_and_output_support = pins.internal_gpio_pin_number(
|
44
76
|
{CONF_OUTPUT: True, CONF_INPUT: True}
|
45
77
|
)
|
@@ -65,6 +97,7 @@ CONFIG_SCHEMA = cv.All(
|
|
65
97
|
}
|
66
98
|
).extend(cv.COMPONENT_SCHEMA),
|
67
99
|
cv.only_on([PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040]),
|
100
|
+
validate_config,
|
68
101
|
)
|
69
102
|
|
70
103
|
|
@@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
|
3
3
|
from esphome.const import CONF_SIZE, CONF_TEXT
|
4
4
|
from esphome.cpp_generator import MockObjClass
|
5
5
|
|
6
|
-
from ..defines import CONF_MAIN
|
6
|
+
from ..defines import CONF_MAIN
|
7
7
|
from ..lv_validation import color, color_retmapper, lv_text
|
8
8
|
from ..lvcode import LocalVariable, lv, lv_expr
|
9
9
|
from ..schemas import TEXT_SCHEMA
|
@@ -34,7 +34,7 @@ class QrCodeType(WidgetType):
|
|
34
34
|
)
|
35
35
|
|
36
36
|
def get_uses(self):
|
37
|
-
return ("canvas", "img")
|
37
|
+
return ("canvas", "img", "label")
|
38
38
|
|
39
39
|
def obj_creator(self, parent: MockObjClass, config: dict):
|
40
40
|
dark_color = color_retmapper(config[CONF_DARK_COLOR])
|
@@ -45,10 +45,8 @@ class QrCodeType(WidgetType):
|
|
45
45
|
async def to_code(self, w: Widget, config):
|
46
46
|
if (value := config.get(CONF_TEXT)) is not None:
|
47
47
|
value = await lv_text.process(value)
|
48
|
-
with LocalVariable(
|
49
|
-
|
50
|
-
) as str_obj:
|
51
|
-
lv.qrcode_update(w.obj, str_obj, literal(f"strlen({str_obj})"))
|
48
|
+
with LocalVariable("qr_text", cg.std_string, value, modifier="") as str_obj:
|
49
|
+
lv.qrcode_update(w.obj, str_obj.c_str(), str_obj.size())
|
52
50
|
|
53
51
|
|
54
52
|
qr_code_spec = QrCodeType()
|
@@ -6,7 +6,11 @@ namespace mcp23xxx_base {
|
|
6
6
|
|
7
7
|
float MCP23XXXBase::get_setup_priority() const { return setup_priority::IO; }
|
8
8
|
|
9
|
-
void MCP23XXXGPIOPin::setup() {
|
9
|
+
void MCP23XXXGPIOPin::setup() {
|
10
|
+
pin_mode(flags_);
|
11
|
+
this->parent_->pin_interrupt_mode(this->pin_, this->interrupt_mode_);
|
12
|
+
}
|
13
|
+
|
10
14
|
void MCP23XXXGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
|
11
15
|
bool MCP23XXXGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
|
12
16
|
void MCP23XXXGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
|
@@ -343,13 +343,12 @@ void AudioPipeline::read_task(void *params) {
|
|
343
343
|
xEventGroupSetBits(this_pipeline->event_group_, EventGroupBits::READER_MESSAGE_FINISHED);
|
344
344
|
|
345
345
|
// Wait until the pipeline notifies us the source of the media file
|
346
|
-
EventBits_t event_bits =
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
portMAX_DELAY); // Block indefinitely until bit is set
|
346
|
+
EventBits_t event_bits = xEventGroupWaitBits(
|
347
|
+
this_pipeline->event_group_,
|
348
|
+
EventGroupBits::READER_COMMAND_INIT_FILE | EventGroupBits::READER_COMMAND_INIT_HTTP, // Bit message to read
|
349
|
+
pdFALSE, // Clear the bit on exit
|
350
|
+
pdFALSE, // Wait for all the bits,
|
351
|
+
portMAX_DELAY); // Block indefinitely until bit is set
|
353
352
|
|
354
353
|
if (!(event_bits & EventGroupBits::PIPELINE_COMMAND_STOP)) {
|
355
354
|
xEventGroupClearBits(this_pipeline->event_group_, EventGroupBits::READER_MESSAGE_FINISHED |
|
@@ -434,12 +433,12 @@ void AudioPipeline::decode_task(void *params) {
|
|
434
433
|
xEventGroupSetBits(this_pipeline->event_group_, EventGroupBits::DECODER_MESSAGE_FINISHED);
|
435
434
|
|
436
435
|
// Wait until the reader notifies us that the media type is available
|
437
|
-
EventBits_t event_bits =
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
436
|
+
EventBits_t event_bits =
|
437
|
+
xEventGroupWaitBits(this_pipeline->event_group_,
|
438
|
+
EventGroupBits::READER_MESSAGE_LOADED_MEDIA_TYPE, // Bit message to read
|
439
|
+
pdFALSE, // Clear the bit on exit
|
440
|
+
pdFALSE, // Wait for all the bits,
|
441
|
+
portMAX_DELAY); // Block indefinitely until bit is set
|
443
442
|
|
444
443
|
xEventGroupClearBits(this_pipeline->event_group_,
|
445
444
|
EventGroupBits::DECODER_MESSAGE_FINISHED | EventGroupBits::READER_MESSAGE_LOADED_MEDIA_TYPE);
|
@@ -17,10 +17,11 @@ from esphome.const import (
|
|
17
17
|
AUTO_LOAD = ["socket"]
|
18
18
|
DEPENDENCIES = ["api", "microphone"]
|
19
19
|
|
20
|
-
CODEOWNERS = ["@jesserockz"]
|
20
|
+
CODEOWNERS = ["@jesserockz", "@kahrendt"]
|
21
21
|
|
22
22
|
CONF_ON_END = "on_end"
|
23
23
|
CONF_ON_INTENT_END = "on_intent_end"
|
24
|
+
CONF_ON_INTENT_PROGRESS = "on_intent_progress"
|
24
25
|
CONF_ON_INTENT_START = "on_intent_start"
|
25
26
|
CONF_ON_LISTENING = "on_listening"
|
26
27
|
CONF_ON_START = "on_start"
|
@@ -136,6 +137,9 @@ CONFIG_SCHEMA = cv.All(
|
|
136
137
|
cv.Optional(CONF_ON_INTENT_START): automation.validate_automation(
|
137
138
|
single=True
|
138
139
|
),
|
140
|
+
cv.Optional(CONF_ON_INTENT_PROGRESS): automation.validate_automation(
|
141
|
+
single=True
|
142
|
+
),
|
139
143
|
cv.Optional(CONF_ON_INTENT_END): automation.validate_automation(
|
140
144
|
single=True
|
141
145
|
),
|
@@ -282,6 +286,13 @@ async def to_code(config):
|
|
282
286
|
config[CONF_ON_INTENT_START],
|
283
287
|
)
|
284
288
|
|
289
|
+
if CONF_ON_INTENT_PROGRESS in config:
|
290
|
+
await automation.build_automation(
|
291
|
+
var.get_intent_progress_trigger(),
|
292
|
+
[(cg.std_string, "x")],
|
293
|
+
config[CONF_ON_INTENT_PROGRESS],
|
294
|
+
)
|
295
|
+
|
285
296
|
if CONF_ON_INTENT_END in config:
|
286
297
|
await automation.build_automation(
|
287
298
|
var.get_intent_end_trigger(),
|
@@ -555,7 +555,7 @@ void VoiceAssistant::request_stop() {
|
|
555
555
|
break;
|
556
556
|
case State::AWAITING_RESPONSE:
|
557
557
|
this->signal_stop_();
|
558
|
-
|
558
|
+
// Fallthrough intended to stop a streaming TTS announcement that has potentially started
|
559
559
|
case State::STREAMING_RESPONSE:
|
560
560
|
#ifdef USE_MEDIA_PLAYER
|
561
561
|
// Stop any ongoing media player announcement
|
@@ -599,6 +599,14 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|
599
599
|
switch (msg.event_type) {
|
600
600
|
case api::enums::VOICE_ASSISTANT_RUN_START:
|
601
601
|
ESP_LOGD(TAG, "Assist Pipeline running");
|
602
|
+
#ifdef USE_MEDIA_PLAYER
|
603
|
+
this->started_streaming_tts_ = false;
|
604
|
+
for (auto arg : msg.data) {
|
605
|
+
if (arg.name == "url") {
|
606
|
+
this->tts_response_url_ = std::move(arg.value);
|
607
|
+
}
|
608
|
+
}
|
609
|
+
#endif
|
602
610
|
this->defer([this]() { this->start_trigger_->trigger(); });
|
603
611
|
break;
|
604
612
|
case api::enums::VOICE_ASSISTANT_WAKE_WORD_START:
|
@@ -622,6 +630,8 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|
622
630
|
if (text.empty()) {
|
623
631
|
ESP_LOGW(TAG, "No text in STT_END event");
|
624
632
|
return;
|
633
|
+
} else if (text.length() > 500) {
|
634
|
+
text = text.substr(0, 497) + "...";
|
625
635
|
}
|
626
636
|
ESP_LOGD(TAG, "Speech recognised as: \"%s\"", text.c_str());
|
627
637
|
this->defer([this, text]() { this->stt_end_trigger_->trigger(text); });
|
@@ -631,6 +641,27 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|
631
641
|
ESP_LOGD(TAG, "Intent started");
|
632
642
|
this->defer([this]() { this->intent_start_trigger_->trigger(); });
|
633
643
|
break;
|
644
|
+
case api::enums::VOICE_ASSISTANT_INTENT_PROGRESS: {
|
645
|
+
ESP_LOGD(TAG, "Intent progress");
|
646
|
+
std::string tts_url_for_trigger = "";
|
647
|
+
#ifdef USE_MEDIA_PLAYER
|
648
|
+
if (this->media_player_ != nullptr) {
|
649
|
+
for (const auto &arg : msg.data) {
|
650
|
+
if ((arg.name == "tts_start_streaming") && (arg.value == "1") && !this->tts_response_url_.empty()) {
|
651
|
+
this->media_player_->make_call().set_media_url(this->tts_response_url_).set_announcement(true).perform();
|
652
|
+
|
653
|
+
this->media_player_wait_for_announcement_start_ = true;
|
654
|
+
this->media_player_wait_for_announcement_end_ = false;
|
655
|
+
this->started_streaming_tts_ = true;
|
656
|
+
tts_url_for_trigger = this->tts_response_url_;
|
657
|
+
this->tts_response_url_.clear(); // Reset streaming URL
|
658
|
+
}
|
659
|
+
}
|
660
|
+
}
|
661
|
+
#endif
|
662
|
+
this->defer([this, tts_url_for_trigger]() { this->intent_progress_trigger_->trigger(tts_url_for_trigger); });
|
663
|
+
break;
|
664
|
+
}
|
634
665
|
case api::enums::VOICE_ASSISTANT_INTENT_END: {
|
635
666
|
for (auto arg : msg.data) {
|
636
667
|
if (arg.name == "conversation_id") {
|
@@ -653,6 +684,9 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|
653
684
|
ESP_LOGW(TAG, "No text in TTS_START event");
|
654
685
|
return;
|
655
686
|
}
|
687
|
+
if (text.length() > 500) {
|
688
|
+
text = text.substr(0, 497) + "...";
|
689
|
+
}
|
656
690
|
ESP_LOGD(TAG, "Response: \"%s\"", text.c_str());
|
657
691
|
this->defer([this, text]() {
|
658
692
|
this->tts_start_trigger_->trigger(text);
|
@@ -678,7 +712,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|
678
712
|
ESP_LOGD(TAG, "Response URL: \"%s\"", url.c_str());
|
679
713
|
this->defer([this, url]() {
|
680
714
|
#ifdef USE_MEDIA_PLAYER
|
681
|
-
if (this->media_player_ != nullptr) {
|
715
|
+
if ((this->media_player_ != nullptr) && (!this->started_streaming_tts_)) {
|
682
716
|
this->media_player_->make_call().set_media_url(url).set_announcement(true).perform();
|
683
717
|
|
684
718
|
this->media_player_wait_for_announcement_start_ = true;
|
@@ -177,6 +177,7 @@ class VoiceAssistant : public Component {
|
|
177
177
|
|
178
178
|
Trigger<> *get_intent_end_trigger() const { return this->intent_end_trigger_; }
|
179
179
|
Trigger<> *get_intent_start_trigger() const { return this->intent_start_trigger_; }
|
180
|
+
Trigger<std::string> *get_intent_progress_trigger() const { return this->intent_progress_trigger_; }
|
180
181
|
Trigger<> *get_listening_trigger() const { return this->listening_trigger_; }
|
181
182
|
Trigger<> *get_end_trigger() const { return this->end_trigger_; }
|
182
183
|
Trigger<> *get_start_trigger() const { return this->start_trigger_; }
|
@@ -233,6 +234,7 @@ class VoiceAssistant : public Component {
|
|
233
234
|
Trigger<> *tts_stream_start_trigger_ = new Trigger<>();
|
234
235
|
Trigger<> *tts_stream_end_trigger_ = new Trigger<>();
|
235
236
|
#endif
|
237
|
+
Trigger<std::string> *intent_progress_trigger_ = new Trigger<std::string>();
|
236
238
|
Trigger<> *wake_word_detected_trigger_ = new Trigger<>();
|
237
239
|
Trigger<std::string> *stt_end_trigger_ = new Trigger<std::string>();
|
238
240
|
Trigger<std::string> *tts_end_trigger_ = new Trigger<std::string>();
|
@@ -268,6 +270,8 @@ class VoiceAssistant : public Component {
|
|
268
270
|
#endif
|
269
271
|
#ifdef USE_MEDIA_PLAYER
|
270
272
|
media_player::MediaPlayer *media_player_{nullptr};
|
273
|
+
std::string tts_response_url_{""};
|
274
|
+
bool started_streaming_tts_{false};
|
271
275
|
bool media_player_wait_for_announcement_start_{false};
|
272
276
|
bool media_player_wait_for_announcement_end_{false};
|
273
277
|
#endif
|
esphome/const.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: esphome
|
3
|
-
Version: 2025.6.
|
3
|
+
Version: 2025.6.2
|
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=Nt8rQegT0VRAcWumtI0rJ92kW0milKMv3b443ZUzcfY,63437
|
8
|
-
esphome/const.py,sha256=
|
8
|
+
esphome/const.py,sha256=591hDg5BeLmGO3rB4VTv6lc7Ii7_PthanUG1rGI0Vbw,41815
|
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
|
@@ -259,7 +259,7 @@ esphome/components/audio/audio.cpp,sha256=McWhPhfL41LchHiFqS_96W_cmL5zgs4KrDN3u5
|
|
259
259
|
esphome/components/audio/audio.h,sha256=Wmwz_JfJyEZJmeK9SopPZysq10TJGwlcg55EcMcLtRw,8038
|
260
260
|
esphome/components/audio/audio_decoder.cpp,sha256=PtSWlj4zdoDCfMUedHuTTrKMiRESLjhh-C1-LDgjfbo,14921
|
261
261
|
esphome/components/audio/audio_decoder.h,sha256=hpPJjrHsK_N2crCVvsrlu7zivx4oQHQz5hr-mlW6fl0,5351
|
262
|
-
esphome/components/audio/audio_reader.cpp,sha256=
|
262
|
+
esphome/components/audio/audio_reader.cpp,sha256=gOYuGJaE2snMr7HDWa4STEyrb00-fVyNlD8-4fPTjm8,9734
|
263
263
|
esphome/components/audio/audio_reader.h,sha256=1FwkJAunr3OOy2DGOmlKHfD3cwOrmBVPQvDj7Z0DTuk,3188
|
264
264
|
esphome/components/audio/audio_resampler.cpp,sha256=3lLPf7r360hVQpDh6CTM9ZkadGWpqQDumTCzjLif-_A,6916
|
265
265
|
esphome/components/audio/audio_resampler.h,sha256=9sHV-YhT7PhipYQUQLCVxttI7qIYqnoFhkmKLMqYQKM,4322
|
@@ -819,7 +819,7 @@ esphome/components/es8388/select/adc_input_mic_select.cpp,sha256=xBlweJHP_BHSvwP
|
|
819
819
|
esphome/components/es8388/select/adc_input_mic_select.h,sha256=1Wf54OGjnrj9vFe7WuIU10qraRAJX7HM1qEcCTTSlvc,336
|
820
820
|
esphome/components/es8388/select/dac_output_select.cpp,sha256=FDOC7NHBaR34BqzzsPrmzBIzY_4o_YkF3_wSs_A9LC8,302
|
821
821
|
esphome/components/es8388/select/dac_output_select.h,sha256=u00z0jHqKmqsaKht3b3k7aGtYudU0cCJRTOw1Zh-mbw,334
|
822
|
-
esphome/components/esp32/__init__.py,sha256=
|
822
|
+
esphome/components/esp32/__init__.py,sha256=R1MHqoCZ42cZlhRbiHYQ0vbJQ_VrN6yzZCLy0BUO88g,37262
|
823
823
|
esphome/components/esp32/boards.py,sha256=RHJK4x6dEz4v3CuFHIPp0gvJmCWAl7hH3Xoy8-pq6wY,55161
|
824
824
|
esphome/components/esp32/const.py,sha256=3sPibOKzbGgtSUIn7PfTQJRyob6x1vUtxagKCGS9CyY,1130
|
825
825
|
esphome/components/esp32/core.cpp,sha256=7O7S5bJPNUeX8ge1mxpyZ1WzxTf1fFDCRK3P5UxZvq8,2865
|
@@ -1250,7 +1250,7 @@ esphome/components/hyt271/__init__.py,sha256=P5EsUvp7gs6CYTt46VpaCuiQhMVvmmC27SU
|
|
1250
1250
|
esphome/components/hyt271/hyt271.cpp,sha256=fJkV2QowprzkUwhsJDWiIFpEVGDW1HRcQalwR9yM9jo,1610
|
1251
1251
|
esphome/components/hyt271/hyt271.h,sha256=AqCCr54XGNQubwC6RbZTNjNfloS8rNbFLyFo2DpNKxg,717
|
1252
1252
|
esphome/components/hyt271/sensor.py,sha256=MuCcT_FO0WiAaM7Czd53oV0PNzstrwLEc09nKPosu7U,1687
|
1253
|
-
esphome/components/i2c/__init__.py,sha256=
|
1253
|
+
esphome/components/i2c/__init__.py,sha256=S9mx_bxaUzLrAYfsinVYGpY9uz9IuyFTQKv8YC_Cj0U,7339
|
1254
1254
|
esphome/components/i2c/i2c.cpp,sha256=7Myvw1pXTmYtlAF6FWuf2CvjPM2lUjm-J5A-syOdEKE,3221
|
1255
1255
|
esphome/components/i2c/i2c.h,sha256=dL6zWtZom38BSj4VitlC8tAMe0YpX1f1NLVzn-9VF00,12235
|
1256
1256
|
esphome/components/i2c/i2c_bus.h,sha256=rse0RqXoP9JBcMk82vrlYNtrc4dsF9U8_9vH74NGImw,5191
|
@@ -1610,7 +1610,7 @@ esphome/components/lvgl/widgets/meter.py,sha256=I_BSID9CNbHSX1xhQJVtvjHSu3oLn1ft
|
|
1610
1610
|
esphome/components/lvgl/widgets/msgbox.py,sha256=i98hz6RKJRMWQ4wz9T1qOHzmdmZ6yHDvHDeJ1T9_Gt0,5335
|
1611
1611
|
esphome/components/lvgl/widgets/obj.py,sha256=6lKIfsdKLWIE8u_Lw0X0ChMCKcV8EZYF8WQKQEBCKYU,439
|
1612
1612
|
esphome/components/lvgl/widgets/page.py,sha256=W7kQ1xfJLRMdy6wFKoA6tZxUXNKGBZWrjMw9OZRfLqA,5870
|
1613
|
-
esphome/components/lvgl/widgets/qrcode.py,sha256=
|
1613
|
+
esphome/components/lvgl/widgets/qrcode.py,sha256=IuSlVDlQ0Y_Bt3lytoNx6fYYFpWrfrPG2bzk9T8z8Nc,1656
|
1614
1614
|
esphome/components/lvgl/widgets/roller.py,sha256=oYoIvTuOL_Tynn4BsFQ25G0M2mEwypxf49KKZXde-o8,2461
|
1615
1615
|
esphome/components/lvgl/widgets/slider.py,sha256=JlRVXxiRdQK1m4Iz7K8O8tlBXMYhzvdLqstBaWLCEdI,1793
|
1616
1616
|
esphome/components/lvgl/widgets/spinbox.py,sha256=Qq44UxpDZ06uh3TDdrYznAEiioemLcl7HS7f0R5R9QY,5080
|
@@ -1705,7 +1705,7 @@ esphome/components/mcp23x17_base/__init__.py,sha256=QbwBlubiQUzBHGLyksUp0o4AagpH
|
|
1705
1705
|
esphome/components/mcp23x17_base/mcp23x17_base.cpp,sha256=RVDrXonaV6PM_ziamv_eq6hO-Dv0EXXJYFcVEdMaQgs,2975
|
1706
1706
|
esphome/components/mcp23x17_base/mcp23x17_base.h,sha256=sveF5Wsc3godQeFh-3Y5h1DLAeeAgSgBUNuRnISZdH8,1337
|
1707
1707
|
esphome/components/mcp23xxx_base/__init__.py,sha256=Xh3XRtpaQvwwb6kEEE-kqaTuNGvXVSiM5XcE9u7h8WQ,2607
|
1708
|
-
esphome/components/mcp23xxx_base/mcp23xxx_base.cpp,sha256=
|
1708
|
+
esphome/components/mcp23xxx_base/mcp23xxx_base.cpp,sha256=6rmTZO_9snQJ43A-FWUKKKyZq6eIuAwwye2xCVbp2iU,843
|
1709
1709
|
esphome/components/mcp23xxx_base/mcp23xxx_base.h,sha256=1-zERN4VLGDc_Rvx_AMD5Lo9XBbMjX_9zcU-xmbkLU4,1823
|
1710
1710
|
esphome/components/mcp2515/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1711
1711
|
esphome/components/mcp2515/canbus.py,sha256=dhmF5h6br1nhegixla8hJ1nyy3P06AxO_aJA1KBlwFw,1547
|
@@ -2786,7 +2786,7 @@ esphome/components/speaker/__init__.py,sha256=2juDem8QadLMwzFp8Rvl-KeIbE-iIEsCtD
|
|
2786
2786
|
esphome/components/speaker/automation.h,sha256=tVSTV49GvHk0bCEgLz3rNYFe8B1F0kXLgE-WihuRaV8,2320
|
2787
2787
|
esphome/components/speaker/speaker.h,sha256=Y6EuDzsIx8GDcFeWnYXg4cXiBU-6CkmrRCaMpXQYiWo,4355
|
2788
2788
|
esphome/components/speaker/media_player/__init__.py,sha256=QfJfrfwYuTEWJ_P3mVACjiATFPHSfDK-eJ0YOiSgatE,15441
|
2789
|
-
esphome/components/speaker/media_player/audio_pipeline.cpp,sha256=
|
2789
|
+
esphome/components/speaker/media_player/audio_pipeline.cpp,sha256=VjodnH-hIPRtulk4iPt_oaym3qr_O2-fK3dyufenPnQ,22147
|
2790
2790
|
esphome/components/speaker/media_player/audio_pipeline.h,sha256=MYt7_kp4IJDSTnXWqLaXIkbbNkGx6F_imSryFo2UUkc,5000
|
2791
2791
|
esphome/components/speaker/media_player/automation.h,sha256=I8psUHnJ8T3fkM05h1yEYDxb0yWe6Vjz7i30OSVA3Is,683
|
2792
2792
|
esphome/components/speaker/media_player/speaker_media_player.cpp,sha256=M_eFKuivv__swCA8xhWd4-cfNdrY2h8Vm8VfG8DUDZ8,22610
|
@@ -3323,9 +3323,9 @@ esphome/components/vl53l0x/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
3323
3323
|
esphome/components/vl53l0x/sensor.py,sha256=qQVBjhMl_nGbzuAHY0Fz2GnG5TkNJLuyFRYmQaVeTWI,2851
|
3324
3324
|
esphome/components/vl53l0x/vl53l0x_sensor.cpp,sha256=mBGggbztlCSvjPDA6IY3p1uBnziXdkaMKLCLWcZL0ok,15170
|
3325
3325
|
esphome/components/vl53l0x/vl53l0x_sensor.h,sha256=F29WiWgbLxjZxxy8JWdrpoD4lDGdB9dVUbRqbv-11sA,2670
|
3326
|
-
esphome/components/voice_assistant/__init__.py,sha256=
|
3327
|
-
esphome/components/voice_assistant/voice_assistant.cpp,sha256=
|
3328
|
-
esphome/components/voice_assistant/voice_assistant.h,sha256=
|
3326
|
+
esphome/components/voice_assistant/__init__.py,sha256=cYEmZoI6w05kMF_ZrFHgsvKOLGO1GIT-a3aUWqepNt4,15264
|
3327
|
+
esphome/components/voice_assistant/voice_assistant.cpp,sha256=heQWZVPKl5yNpHHpdM7Ae8gcLv4TAGFaE5zFrnfDUKo,33212
|
3328
|
+
esphome/components/voice_assistant/voice_assistant.h,sha256=M42wYACkOB90iIeejCXaFnqRZkETsEjjJSi7j_YZxg8,12381
|
3329
3329
|
esphome/components/voltage_sampler/__init__.py,sha256=IU5YrROZSNyuAP1d6M_V3ZGAwNjXCHPcVy5nMjZ953Y,155
|
3330
3330
|
esphome/components/voltage_sampler/voltage_sampler.h,sha256=Y67FLOpOzW29v29BRRyYgEmGZ_B8QnUUaqJMH6FA3jM,337
|
3331
3331
|
esphome/components/wake_on_lan/__init__.py,sha256=-RYpXD02o3dlFnKzOCYk58bUbxfD2v-wj1ECywj-cgI,50
|
@@ -3596,9 +3596,9 @@ esphome/dashboard/util/itertools.py,sha256=8eLrWEWmICLtXNxkKdYPQV0c_N4GEz8m9Npnb
|
|
3596
3596
|
esphome/dashboard/util/password.py,sha256=cQz3b9B-ijTe7zS6BeCW0hc3pWv6JjC78jmnycYYAh8,321
|
3597
3597
|
esphome/dashboard/util/subprocess.py,sha256=T8EW6dbU4LPd2DG1dRrdh8li71tt6J1isn411poMhkk,1022
|
3598
3598
|
esphome/dashboard/util/text.py,sha256=ENDnfN4O0NdA3CKVJjQYabFbwbrsIhVKrAMQe53qYu4,534
|
3599
|
-
esphome-2025.6.
|
3600
|
-
esphome-2025.6.
|
3601
|
-
esphome-2025.6.
|
3602
|
-
esphome-2025.6.
|
3603
|
-
esphome-2025.6.
|
3604
|
-
esphome-2025.6.
|
3599
|
+
esphome-2025.6.2.dist-info/licenses/LICENSE,sha256=HzEjkBInJe44L4WvAOPfhPJJDNj6YbnqFyvGWRzArGM,36664
|
3600
|
+
esphome-2025.6.2.dist-info/METADATA,sha256=iVaivl7IcZGOyoHhVWYTLTPoN818SPv0BO_nInQymVA,3678
|
3601
|
+
esphome-2025.6.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
3602
|
+
esphome-2025.6.2.dist-info/entry_points.txt,sha256=mIxVNuWtbYzeEcaWCl-AQ-97aBOWbnYBAK8nbF6P4M0,50
|
3603
|
+
esphome-2025.6.2.dist-info/top_level.txt,sha256=0GSXEW3cnITpgG3qnsSMz0qoqJHAFyfw7Y8MVtEf1Yk,8
|
3604
|
+
esphome-2025.6.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|