1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-03 16:41:50 +00:00

Compare commits

..

24 Commits

Author SHA1 Message Date
Jesse Hills
1a9f66e630 Merge pull request #5787 from esphome/bump-2023.11.2
2023.11.2
2023-11-18 22:25:00 +13:00
Jesse Hills
8fb6b8f1a2 Bump version to 2023.11.2 2023-11-18 21:15:56 +13:00
Keith Burzinski
22eef036c7 Add 2MB option for partitions.csv generation and restore use of user-defined partitions (#5779) 2023-11-18 21:15:56 +13:00
Samuel Sieb
625ce2b8eb fix 32-bit arm (#5781) 2023-11-18 21:15:56 +13:00
dependabot[bot]
e5e3b253bc Bump aioesphomeapi from 18.4.1 to 18.5.2 (#5780)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-18 21:15:51 +13:00
dependabot[bot]
c369443263 Bump aioesphomeapi from 18.4.0 to 18.4.1 (#5767)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-18 21:14:50 +13:00
Jesse Hills
1e061582d3 Merge pull request #5776 from esphome/bump-2023.11.1
2023.11.1
2023-11-16 21:19:39 +13:00
Jesse Hills
445b13dbc6 Bump version to 2023.11.1 2023-11-16 20:55:28 +13:00
Mat931
255483de63 Fix MY9231 flicker (#5765) 2023-11-16 20:55:28 +13:00
Keith Burzinski
4ac49907ca Add more VA triggers (#5762) 2023-11-16 20:55:28 +13:00
Jesse Hills
c536c976b7 Merge pull request #5758 from esphome/bump-2023.11.0
2023.11.0
2023-11-15 16:11:18 +13:00
Jesse Hills
0c18872888 Bump version to 2023.11.0 2023-11-15 14:13:39 +13:00
Jesse Hills
197b6b4275 Merge pull request #5756 from esphome/bump-2023.11.0b7
2023.11.0b7
2023-11-15 13:19:48 +13:00
Jesse Hills
4e8bdc2155 Bump version to 2023.11.0b7 2023-11-15 12:45:03 +13:00
Jesse Hills
f1e8622187 Dont dump wifi info when disabled (#5755) 2023-11-15 12:45:02 +13:00
Jesse Hills
e0c7a02fbc Allow setup to continue past mqtt if network/wifi is disabled (#5754) 2023-11-15 12:45:02 +13:00
Jesse Hills
2a20a5fc11 Merge pull request #5750 from esphome/bump-2023.11.0b6
2023.11.0b6
2023-11-14 16:16:11 +13:00
Jesse Hills
7100d073f8 Bump version to 2023.11.0b6 2023-11-14 14:32:41 +13:00
Keith Burzinski
1ac6cf2ff9 Generate partitions.csv based on flash size (#5697) 2023-11-14 14:32:41 +13:00
J. Nick Koston
2ee089c9d5 dashboard: Run get_serial_ports in the executor (#5740) 2023-11-14 14:32:41 +13:00
J. Nick Koston
bd568eecf5 dashboard: remove usage of codecs module (#5741) 2023-11-14 14:32:40 +13:00
Jesse Hills
3e2b83acb0 Merge pull request #5742 from esphome/bump-2023.11.0b5
2023.11.0b5
2023-11-13 16:37:28 +13:00
Jesse Hills
c1eb5bd675 Bump version to 2023.11.0b5 2023-11-13 15:26:04 +13:00
Jesse Hills
a9772ebf3f Handle wake word not set up internally (#5738) 2023-11-13 15:26:04 +13:00
14 changed files with 248 additions and 66 deletions

View File

@@ -68,7 +68,7 @@ ENV \
# See: https://unix.stackexchange.com/questions/553743/correct-way-to-add-lib-ld-linux-so-3-in-debian
RUN \
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
ln -s /lib/arm-linux-gnueabihf/ld-linux.so.3 /lib/ld-linux.so.3; \
ln -s /lib/arm-linux-gnueabihf/ld-linux-armhf.so.3 /lib/ld-linux.so.3; \
fi
RUN \

View File

@@ -3,23 +3,26 @@ from typing import Union, Optional
from pathlib import Path
import logging
import os
import esphome.final_validate as fv
from esphome.helpers import copy_file_if_changed, write_file_if_changed, mkdir_p
from esphome.const import (
CONF_ADVANCED,
CONF_BOARD,
CONF_COMPONENTS,
CONF_ESPHOME,
CONF_FRAMEWORK,
CONF_IGNORE_EFUSE_MAC_CRC,
CONF_NAME,
CONF_PATH,
CONF_PLATFORMIO_OPTIONS,
CONF_REF,
CONF_REFRESH,
CONF_SOURCE,
CONF_TYPE,
CONF_URL,
CONF_VARIANT,
CONF_VERSION,
CONF_ADVANCED,
CONF_REFRESH,
CONF_PATH,
CONF_URL,
CONF_REF,
CONF_IGNORE_EFUSE_MAC_CRC,
KEY_CORE,
KEY_FRAMEWORK_VERSION,
KEY_NAME,
@@ -327,6 +330,32 @@ def _detect_variant(value):
return value
def final_validate(config):
if CONF_PLATFORMIO_OPTIONS not in fv.full_config.get()[CONF_ESPHOME]:
return config
pio_flash_size_key = "board_upload.flash_size"
pio_partitions_key = "board_build.partitions"
if (
CONF_PARTITIONS in config
and pio_partitions_key
in fv.full_config.get()[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS]
):
raise cv.Invalid(
f"Do not specify '{pio_partitions_key}' in '{CONF_PLATFORMIO_OPTIONS}' with '{CONF_PARTITIONS}' in esp32"
)
if (
pio_flash_size_key
in fv.full_config.get()[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS]
):
raise cv.Invalid(
f"Please specify {CONF_FLASH_SIZE} within esp32 configuration only"
)
return config
CONF_PLATFORM_VERSION = "platform_version"
ARDUINO_FRAMEWORK_SCHEMA = cv.All(
@@ -386,10 +415,24 @@ FRAMEWORK_SCHEMA = cv.typed_schema(
)
FLASH_SIZES = [
"2MB",
"4MB",
"8MB",
"16MB",
"32MB",
]
CONF_FLASH_SIZE = "flash_size"
CONF_PARTITIONS = "partitions"
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
cv.Required(CONF_BOARD): cv.string_strict,
cv.Optional(CONF_FLASH_SIZE, default="4MB"): cv.one_of(
*FLASH_SIZES, upper=True
),
cv.Optional(CONF_PARTITIONS): cv.file_,
cv.Optional(CONF_VARIANT): cv.one_of(*VARIANTS, upper=True),
cv.Optional(CONF_FRAMEWORK, default={}): FRAMEWORK_SCHEMA,
}
@@ -399,8 +442,12 @@ CONFIG_SCHEMA = cv.All(
)
FINAL_VALIDATE_SCHEMA = cv.Schema(final_validate)
async def to_code(config):
cg.add_platformio_option("board", config[CONF_BOARD])
cg.add_platformio_option("board_upload.flash_size", config[CONF_FLASH_SIZE])
cg.add_build_flag("-DUSE_ESP32")
cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
cg.add_build_flag(f"-DUSE_ESP32_VARIANT_{config[CONF_VARIANT]}")
@@ -450,7 +497,10 @@ async def to_code(config):
add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0", False)
add_idf_sdkconfig_option("CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1", False)
cg.add_platformio_option("board_build.partitions", "partitions.csv")
if CONF_PARTITIONS in config:
cg.add_platformio_option("board_build.partitions", config[CONF_PARTITIONS])
else:
cg.add_platformio_option("board_build.partitions", "partitions.csv")
for name, value in conf[CONF_SDKCONFIG_OPTIONS].items():
add_idf_sdkconfig_option(name, RawSdkconfigValue(value))
@@ -495,7 +545,10 @@ async def to_code(config):
[f"platformio/framework-arduinoespressif32@{conf[CONF_SOURCE]}"],
)
cg.add_platformio_option("board_build.partitions", "partitions.csv")
if CONF_PARTITIONS in config:
cg.add_platformio_option("board_build.partitions", config[CONF_PARTITIONS])
else:
cg.add_platformio_option("board_build.partitions", "partitions.csv")
cg.add_define(
"USE_ARDUINO_VERSION_CODE",
@@ -505,24 +558,47 @@ async def to_code(config):
)
ARDUINO_PARTITIONS_CSV = """\
nvs, data, nvs, 0x009000, 0x005000,
otadata, data, ota, 0x00e000, 0x002000,
app0, app, ota_0, 0x010000, 0x1C0000,
app1, app, ota_1, 0x1D0000, 0x1C0000,
eeprom, data, 0x99, 0x390000, 0x001000,
spiffs, data, spiffs, 0x391000, 0x00F000
APP_PARTITION_SIZES = {
"2MB": 0x0C0000, # 768 KB
"4MB": 0x1C0000, # 1792 KB
"8MB": 0x3C0000, # 3840 KB
"16MB": 0x7C0000, # 7936 KB
"32MB": 0xFC0000, # 16128 KB
}
def get_arduino_partition_csv(flash_size):
app_partition_size = APP_PARTITION_SIZES[flash_size]
eeprom_partition_size = 0x1000 # 4 KB
spiffs_partition_size = 0xF000 # 60 KB
app0_partition_start = 0x010000 # 64 KB
app1_partition_start = app0_partition_start + app_partition_size
eeprom_partition_start = app1_partition_start + app_partition_size
spiffs_partition_start = eeprom_partition_start + eeprom_partition_size
partition_csv = f"""\
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xE000, 0x2000,
app0, app, ota_0, 0x{app0_partition_start:X}, 0x{app_partition_size:X},
app1, app, ota_1, 0x{app1_partition_start:X}, 0x{app_partition_size:X},
eeprom, data, 0x99, 0x{eeprom_partition_start:X}, 0x{eeprom_partition_size:X},
spiffs, data, spiffs, 0x{spiffs_partition_start:X}, 0x{spiffs_partition_size:X}
"""
return partition_csv
IDF_PARTITIONS_CSV = """\
# Name, Type, SubType, Offset, Size, Flags
def get_idf_partition_csv(flash_size):
app_partition_size = APP_PARTITION_SIZES[flash_size]
partition_csv = f"""\
otadata, data, ota, , 0x2000,
phy_init, data, phy, , 0x1000,
app0, app, ota_0, , 0x1C0000,
app1, app, ota_1, , 0x1C0000,
nvs, data, nvs, , 0x6d000,
app0, app, ota_0, , 0x{app_partition_size:X},
app1, app, ota_1, , 0x{app_partition_size:X},
nvs, data, nvs, , 0x6D000,
"""
return partition_csv
def _format_sdkconfig_val(value: SdkconfigValueType) -> str:
@@ -565,13 +641,17 @@ def copy_files():
if CORE.using_arduino:
write_file_if_changed(
CORE.relative_build_path("partitions.csv"),
ARDUINO_PARTITIONS_CSV,
get_arduino_partition_csv(
CORE.platformio_options.get("board_upload.flash_size")
),
)
if CORE.using_esp_idf:
_write_sdkconfig()
write_file_if_changed(
CORE.relative_build_path("partitions.csv"),
IDF_PARTITIONS_CSV,
get_idf_partition_csv(
CORE.platformio_options.get("board_upload.flash_size")
),
)
# IDF build scripts look for version string to put in the build.
# However, if the build path does not have an initialized git repo,

View File

@@ -147,7 +147,7 @@ void MQTTClientComponent::dump_config() {
ESP_LOGCONFIG(TAG, " Availability: '%s'", this->availability_.topic.c_str());
}
}
bool MQTTClientComponent::can_proceed() { return this->is_connected(); }
bool MQTTClientComponent::can_proceed() { return network::is_disabled() || this->is_connected(); }
void MQTTClientComponent::start_dnslookup_() {
for (auto &subscription : this->subscriptions_) {

View File

@@ -1,5 +1,6 @@
#include "my9231.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace my9231 {
@@ -51,7 +52,11 @@ void MY9231OutputComponent::setup() {
MY9231_CMD_SCATTER_APDM | MY9231_CMD_FREQUENCY_DIVIDE_1 | MY9231_CMD_REACTION_FAST | MY9231_CMD_ONE_SHOT_DISABLE;
ESP_LOGV(TAG, " Command: 0x%02X", command);
this->init_chips_(command);
{
InterruptLock lock;
this->send_dcki_pulses_(32 * this->num_chips_);
this->init_chips_(command);
}
ESP_LOGV(TAG, " Chips initialized.");
}
void MY9231OutputComponent::dump_config() {
@@ -66,11 +71,14 @@ void MY9231OutputComponent::loop() {
if (!this->update_)
return;
for (auto pwm_amount : this->pwm_amounts_) {
this->write_word_(pwm_amount, this->bit_depth_);
{
InterruptLock lock;
for (auto pwm_amount : this->pwm_amounts_) {
this->write_word_(pwm_amount, this->bit_depth_);
}
// Send 8 DI pulses. After 8 falling edges, the duty data are store.
this->send_di_pulses_(8);
}
// Send 8 DI pulses. After 8 falling edges, the duty data are store.
this->send_di_pulses_(8);
this->update_ = false;
}
void MY9231OutputComponent::set_channel_value_(uint8_t channel, uint16_t value) {
@@ -92,6 +100,7 @@ void MY9231OutputComponent::init_chips_(uint8_t command) {
// Send 16 DI pulse. After 14 falling edges, the command data are
// stored and after 16 falling edges the duty mode is activated.
this->send_di_pulses_(16);
delayMicroseconds(12);
}
void MY9231OutputComponent::write_word_(uint16_t value, uint8_t bits) {
for (uint8_t i = bits; i > 0; i--) {
@@ -106,6 +115,13 @@ void MY9231OutputComponent::send_di_pulses_(uint8_t count) {
this->pin_di_->digital_write(false);
}
}
void MY9231OutputComponent::send_dcki_pulses_(uint8_t count) {
delayMicroseconds(12);
for (uint8_t i = 0; i < count; i++) {
this->pin_dcki_->digital_write(true);
this->pin_dcki_->digital_write(false);
}
}
} // namespace my9231
} // namespace esphome

View File

@@ -49,6 +49,7 @@ class MY9231OutputComponent : public Component {
void init_chips_(uint8_t command);
void write_word_(uint16_t value, uint8_t bits);
void send_di_pulses_(uint8_t count);
void send_dcki_pulses_(uint8_t count);
GPIOPin *pin_di_;
GPIOPin *pin_dcki_;

View File

@@ -29,6 +29,14 @@ bool is_connected() {
return false;
}
bool is_disabled() {
#ifdef USE_WIFI
if (wifi::global_wifi_component != nullptr)
return wifi::global_wifi_component->is_disabled();
#endif
return false;
}
network::IPAddress get_ip_address() {
#ifdef USE_ETHERNET
if (ethernet::global_eth_component != nullptr)

View File

@@ -8,6 +8,8 @@ namespace network {
/// Return whether the node is connected to the network (through wifi, eth, ...)
bool is_connected();
/// Return whether the network is disabled (only wifi for now)
bool is_disabled();
/// Get the active network hostname
std::string get_use_address();
IPAddress get_ip_address();

View File

@@ -18,20 +18,25 @@ DEPENDENCIES = ["api", "microphone"]
CODEOWNERS = ["@jesserockz"]
CONF_SILENCE_DETECTION = "silence_detection"
CONF_ON_LISTENING = "on_listening"
CONF_ON_START = "on_start"
CONF_ON_WAKE_WORD_DETECTED = "on_wake_word_detected"
CONF_ON_STT_END = "on_stt_end"
CONF_ON_TTS_START = "on_tts_start"
CONF_ON_TTS_END = "on_tts_end"
CONF_ON_END = "on_end"
CONF_ON_ERROR = "on_error"
CONF_ON_INTENT_END = "on_intent_end"
CONF_ON_INTENT_START = "on_intent_start"
CONF_ON_LISTENING = "on_listening"
CONF_ON_START = "on_start"
CONF_ON_STT_END = "on_stt_end"
CONF_ON_STT_VAD_END = "on_stt_vad_end"
CONF_ON_STT_VAD_START = "on_stt_vad_start"
CONF_ON_TTS_END = "on_tts_end"
CONF_ON_TTS_START = "on_tts_start"
CONF_ON_WAKE_WORD_DETECTED = "on_wake_word_detected"
CONF_SILENCE_DETECTION = "silence_detection"
CONF_USE_WAKE_WORD = "use_wake_word"
CONF_VAD_THRESHOLD = "vad_threshold"
CONF_NOISE_SUPPRESSION_LEVEL = "noise_suppression_level"
CONF_AUTO_GAIN = "auto_gain"
CONF_NOISE_SUPPRESSION_LEVEL = "noise_suppression_level"
CONF_VOLUME_MULTIPLIER = "volume_multiplier"
@@ -88,6 +93,18 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_ON_CLIENT_DISCONNECTED): automation.validate_automation(
single=True
),
cv.Optional(CONF_ON_INTENT_START): automation.validate_automation(
single=True
),
cv.Optional(CONF_ON_INTENT_END): automation.validate_automation(
single=True
),
cv.Optional(CONF_ON_STT_VAD_START): automation.validate_automation(
single=True
),
cv.Optional(CONF_ON_STT_VAD_END): automation.validate_automation(
single=True
),
}
).extend(cv.COMPONENT_SCHEMA),
)
@@ -177,6 +194,34 @@ async def to_code(config):
config[CONF_ON_CLIENT_DISCONNECTED],
)
if CONF_ON_INTENT_START in config:
await automation.build_automation(
var.get_intent_start_trigger(),
[],
config[CONF_ON_INTENT_START],
)
if CONF_ON_INTENT_END in config:
await automation.build_automation(
var.get_intent_end_trigger(),
[],
config[CONF_ON_INTENT_END],
)
if CONF_ON_STT_VAD_START in config:
await automation.build_automation(
var.get_stt_vad_start_trigger(),
[],
config[CONF_ON_STT_VAD_START],
)
if CONF_ON_STT_VAD_END in config:
await automation.build_automation(
var.get_stt_vad_end_trigger(),
[],
config[CONF_ON_STT_VAD_END],
)
cg.add_define("USE_VOICE_ASSISTANT")

View File

@@ -31,7 +31,7 @@ void VoiceAssistant::setup() {
this->socket_ = socket::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (socket_ == nullptr) {
ESP_LOGW(TAG, "Could not create socket.");
ESP_LOGW(TAG, "Could not create socket");
this->mark_failed();
return;
}
@@ -69,7 +69,7 @@ void VoiceAssistant::setup() {
ExternalRAMAllocator<uint8_t> speaker_allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
this->speaker_buffer_ = speaker_allocator.allocate(SPEAKER_BUFFER_SIZE);
if (this->speaker_buffer_ == nullptr) {
ESP_LOGW(TAG, "Could not allocate speaker buffer.");
ESP_LOGW(TAG, "Could not allocate speaker buffer");
this->mark_failed();
return;
}
@@ -79,7 +79,7 @@ void VoiceAssistant::setup() {
ExternalRAMAllocator<int16_t> allocator(ExternalRAMAllocator<int16_t>::ALLOW_FAILURE);
this->input_buffer_ = allocator.allocate(INPUT_BUFFER_SIZE);
if (this->input_buffer_ == nullptr) {
ESP_LOGW(TAG, "Could not allocate input buffer.");
ESP_LOGW(TAG, "Could not allocate input buffer");
this->mark_failed();
return;
}
@@ -89,7 +89,7 @@ void VoiceAssistant::setup() {
this->ring_buffer_ = rb_create(BUFFER_SIZE, sizeof(int16_t));
if (this->ring_buffer_ == nullptr) {
ESP_LOGW(TAG, "Could not allocate ring buffer.");
ESP_LOGW(TAG, "Could not allocate ring buffer");
this->mark_failed();
return;
}
@@ -98,7 +98,7 @@ void VoiceAssistant::setup() {
ExternalRAMAllocator<uint8_t> send_allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
this->send_buffer_ = send_allocator.allocate(SEND_BUFFER_SIZE);
if (send_buffer_ == nullptr) {
ESP_LOGW(TAG, "Could not allocate send buffer.");
ESP_LOGW(TAG, "Could not allocate send buffer");
this->mark_failed();
return;
}
@@ -221,8 +221,8 @@ void VoiceAssistant::loop() {
msg.audio_settings = audio_settings;
if (this->api_client_ == nullptr || !this->api_client_->send_voice_assistant_request(msg)) {
ESP_LOGW(TAG, "Could not request start.");
this->error_trigger_->trigger("not-connected", "Could not request start.");
ESP_LOGW(TAG, "Could not request start");
this->error_trigger_->trigger("not-connected", "Could not request start");
this->continuous_ = false;
this->set_state_(State::IDLE, State::IDLE);
break;
@@ -280,7 +280,7 @@ void VoiceAssistant::loop() {
this->speaker_buffer_size_ += len;
}
} else {
ESP_LOGW(TAG, "Receive buffer full.");
ESP_LOGW(TAG, "Receive buffer full");
}
if (this->speaker_buffer_size_ > 0) {
size_t written = this->speaker_->play(this->speaker_buffer_, this->speaker_buffer_size_);
@@ -290,7 +290,7 @@ void VoiceAssistant::loop() {
this->speaker_buffer_index_ -= written;
this->set_timeout("speaker-timeout", 2000, [this]() { this->speaker_->stop(); });
} else {
ESP_LOGW(TAG, "Speaker buffer full.");
ESP_LOGW(TAG, "Speaker buffer full");
}
}
if (this->wait_for_stream_end_) {
@@ -513,7 +513,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
break;
}
case api::enums::VOICE_ASSISTANT_STT_START:
ESP_LOGD(TAG, "STT Started");
ESP_LOGD(TAG, "STT started");
this->listening_trigger_->trigger();
break;
case api::enums::VOICE_ASSISTANT_STT_END: {
@@ -525,19 +525,24 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
}
if (text.empty()) {
ESP_LOGW(TAG, "No text in STT_END event.");
ESP_LOGW(TAG, "No text in STT_END event");
return;
}
ESP_LOGD(TAG, "Speech recognised as: \"%s\"", text.c_str());
this->stt_end_trigger_->trigger(text);
break;
}
case api::enums::VOICE_ASSISTANT_INTENT_START:
ESP_LOGD(TAG, "Intent started");
this->intent_start_trigger_->trigger();
break;
case api::enums::VOICE_ASSISTANT_INTENT_END: {
for (auto arg : msg.data) {
if (arg.name == "conversation_id") {
this->conversation_id_ = std::move(arg.value);
}
}
this->intent_end_trigger_->trigger();
break;
}
case api::enums::VOICE_ASSISTANT_TTS_START: {
@@ -548,7 +553,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
}
if (text.empty()) {
ESP_LOGW(TAG, "No text in TTS_START event.");
ESP_LOGW(TAG, "No text in TTS_START event");
return;
}
ESP_LOGD(TAG, "Response: \"%s\"", text.c_str());
@@ -566,7 +571,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
}
if (url.empty()) {
ESP_LOGW(TAG, "No url in TTS_END event.");
ESP_LOGW(TAG, "No url in TTS_END event");
return;
}
ESP_LOGD(TAG, "Response URL: \"%s\"", url.c_str());
@@ -610,6 +615,11 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
if (code == "wake-word-timeout" || code == "wake_word_detection_aborted") {
// Don't change state here since either the "tts-end" or "run-end" events will do it.
return;
} else if (code == "wake-provider-missing" || code == "wake-engine-missing") {
// Wake word is not set up or not ready on Home Assistant so stop and do not retry until user starts again.
this->request_stop();
this->error_trigger_->trigger(code, message);
return;
}
ESP_LOGE(TAG, "Error: %s - %s", code.c_str(), message.c_str());
if (this->state_ != State::IDLE) {
@@ -629,6 +639,14 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
this->set_state_(State::RESPONSE_FINISHED, State::IDLE);
break;
}
case api::enums::VOICE_ASSISTANT_STT_VAD_START:
ESP_LOGD(TAG, "Starting STT by VAD");
this->stt_vad_start_trigger_->trigger();
break;
case api::enums::VOICE_ASSISTANT_STT_VAD_END:
ESP_LOGD(TAG, "STT by VAD end");
this->stt_vad_end_trigger_->trigger();
break;
default:
ESP_LOGD(TAG, "Unhandled event type: %d", msg.event_type);
break;

View File

@@ -100,13 +100,17 @@ class VoiceAssistant : public Component {
void set_auto_gain(uint8_t auto_gain) { this->auto_gain_ = auto_gain; }
void set_volume_multiplier(float volume_multiplier) { this->volume_multiplier_ = volume_multiplier; }
Trigger<> *get_intent_end_trigger() const { return this->intent_end_trigger_; }
Trigger<> *get_intent_start_trigger() const { return this->intent_start_trigger_; }
Trigger<> *get_listening_trigger() const { return this->listening_trigger_; }
Trigger<> *get_end_trigger() const { return this->end_trigger_; }
Trigger<> *get_start_trigger() const { return this->start_trigger_; }
Trigger<> *get_stt_vad_end_trigger() const { return this->stt_vad_end_trigger_; }
Trigger<> *get_stt_vad_start_trigger() const { return this->stt_vad_start_trigger_; }
Trigger<> *get_wake_word_detected_trigger() const { return this->wake_word_detected_trigger_; }
Trigger<std::string> *get_stt_end_trigger() const { return this->stt_end_trigger_; }
Trigger<std::string> *get_tts_start_trigger() const { return this->tts_start_trigger_; }
Trigger<std::string> *get_tts_end_trigger() const { return this->tts_end_trigger_; }
Trigger<> *get_end_trigger() const { return this->end_trigger_; }
Trigger<std::string> *get_tts_start_trigger() const { return this->tts_start_trigger_; }
Trigger<std::string, std::string> *get_error_trigger() const { return this->error_trigger_; }
Trigger<> *get_client_connected_trigger() const { return this->client_connected_trigger_; }
@@ -124,13 +128,17 @@ class VoiceAssistant : public Component {
std::unique_ptr<socket::Socket> socket_ = nullptr;
struct sockaddr_storage dest_addr_;
Trigger<> *intent_end_trigger_ = new Trigger<>();
Trigger<> *intent_start_trigger_ = new Trigger<>();
Trigger<> *listening_trigger_ = new Trigger<>();
Trigger<> *end_trigger_ = new Trigger<>();
Trigger<> *start_trigger_ = new Trigger<>();
Trigger<> *stt_vad_start_trigger_ = new Trigger<>();
Trigger<> *stt_vad_end_trigger_ = new Trigger<>();
Trigger<> *wake_word_detected_trigger_ = new Trigger<>();
Trigger<std::string> *stt_end_trigger_ = new Trigger<std::string>();
Trigger<std::string> *tts_start_trigger_ = new Trigger<std::string>();
Trigger<std::string> *tts_end_trigger_ = new Trigger<std::string>();
Trigger<> *end_trigger_ = new Trigger<>();
Trigger<std::string> *tts_start_trigger_ = new Trigger<std::string>();
Trigger<std::string, std::string> *error_trigger_ = new Trigger<std::string, std::string>();
Trigger<> *client_connected_trigger_ = new Trigger<>();

View File

@@ -389,6 +389,10 @@ void WiFiComponent::print_connect_params_() {
bssid_t bssid = wifi_bssid();
ESP_LOGCONFIG(TAG, " Local MAC: %s", get_mac_address_pretty().c_str());
if (this->is_disabled()) {
ESP_LOGCONFIG(TAG, " WiFi is disabled!");
return;
}
ESP_LOGCONFIG(TAG, " SSID: " LOG_SECRET("'%s'"), wifi_ssid().c_str());
ESP_LOGCONFIG(TAG, " IP Address: %s", wifi_sta_ip().str().c_str());
ESP_LOGCONFIG(TAG, " BSSID: " LOG_SECRET("%02X:%02X:%02X:%02X:%02X:%02X"), bssid[0], bssid[1], bssid[2], bssid[3],

View File

@@ -1,6 +1,6 @@
"""Constants used by esphome."""
__version__ = "2023.11.0b4"
__version__ = "2023.11.2"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = (

View File

@@ -1,8 +1,8 @@
from __future__ import annotations
import asyncio
import base64
import binascii
import codecs
import collections
import datetime
import functools
@@ -339,8 +339,8 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
def handle_stdin(self, json_message):
if not self.is_process_active:
return
data = json_message["data"]
data = codecs.encode(data, "utf8", "replace")
text: str = json_message["data"]
data = text.encode("utf-8", "replace")
_LOGGER.debug("< stdin: %s", data)
self._proc.stdin.write(data)
@@ -351,18 +351,18 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
while True:
try:
if self._use_popen:
data = yield self._queue.get()
data: bytes = yield self._queue.get()
if data is None:
self._proc_on_exit(self._proc.poll())
break
else:
data = yield self._proc.stdout.read_until_regex(reg)
data: bytes = yield self._proc.stdout.read_until_regex(reg)
except tornado.iostream.StreamClosedError:
break
data = codecs.decode(data, "utf8", "replace")
_LOGGER.debug("> stdout: %s", data)
self.write_message({"event": "line", "data": data})
text = data.decode("utf-8", "replace")
_LOGGER.debug("> stdout: %s", text)
self.write_message({"event": "line", "data": text})
def _stdout_thread(self):
if not self._use_popen:
@@ -509,8 +509,8 @@ class EsphomeUpdateAllHandler(EsphomeCommandWebSocket):
class SerialPortRequestHandler(BaseHandler):
@authenticated
def get(self):
ports = get_serial_ports()
async def get(self):
ports = await asyncio.get_running_loop().run_in_executor(None, get_serial_ports)
data = []
for port in ports:
desc = port.description

View File

@@ -10,7 +10,7 @@ platformio==6.1.11 # When updating platformio, also update Dockerfile
esptool==4.6.2
click==8.1.7
esphome-dashboard==20231107.0
aioesphomeapi==18.4.0
aioesphomeapi==18.5.2
zeroconf==0.123.0
# esp-idf requires this, but doesn't bundle it by default