diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3904834dc9..7ebd04e793 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -117,7 +117,7 @@ jobs: --suffix "${{ matrix.image.suffix }}" - name: Build and push - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . file: ./docker/Dockerfile diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 671fe1f21a..396dd64165 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -48,7 +48,7 @@ jobs: echo "$delimiter" >> $GITHUB_OUTPUT - name: Commit changes - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v5 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot diff --git a/esphome/components/debug/__init__.py b/esphome/components/debug/__init__.py index 223c3c8df1..c18baa1cca 100644 --- a/esphome/components/debug/__init__.py +++ b/esphome/components/debug/__init__.py @@ -1,15 +1,11 @@ import esphome.codegen as cg import esphome.config_validation as cv -import esphome.final_validate as fv -from esphome.components import logger from esphome.const import ( CONF_BLOCK, CONF_DEVICE, CONF_FRAGMENTATION, CONF_FREE, CONF_ID, - CONF_LEVEL, - CONF_LOGGER, CONF_LOOP_TIME, ) @@ -43,18 +39,6 @@ CONFIG_SCHEMA = cv.Schema( ).extend(cv.polling_component_schema("60s")) -def _final_validate(_): - logger_conf = fv.full_config.get()[CONF_LOGGER] - severity = logger.LOG_LEVEL_SEVERITY.index(logger_conf[CONF_LEVEL]) - if severity < logger.LOG_LEVEL_SEVERITY.index("DEBUG"): - raise cv.Invalid( - "The debug component requires the logger to be at least at DEBUG level" - ) - - -FINAL_VALIDATE_SCHEMA = _final_validate - - async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index c1ede684e6..9843fa1c99 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -37,6 +37,10 @@ static uint32_t get_free_heap() { } void DebugComponent::dump_config() { +#ifndef ESPHOME_LOG_HAS_DEBUG + return; // Can't log below if debug logging is disabled +#endif + std::string device_info; std::string reset_reason; device_info.reserve(256); diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 8eb4718f49..447c5b8075 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -276,7 +276,7 @@ void EthernetComponent::start_connect_() { #endif dns_setserver(0, &d); } - if (uint32_t(this->manual_ip_->dns1) != 0) { + if (uint32_t(this->manual_ip_->dns2) != 0) { ip_addr_t d; #if LWIP_IPV6 d.type = IPADDR_TYPE_V4; diff --git a/esphome/components/i2c/i2c_bus_arduino.cpp b/esphome/components/i2c/i2c_bus_arduino.cpp index 16d89c3450..e08622a3ae 100644 --- a/esphome/components/i2c/i2c_bus_arduino.cpp +++ b/esphome/components/i2c/i2c_bus_arduino.cpp @@ -154,18 +154,25 @@ ErrorCode ArduinoI2CBus::writev(uint8_t address, WriteBuffer *buffers, size_t cn } } uint8_t status = wire_->endTransmission(stop); - if (status == 0) { - return ERROR_OK; - } else if (status == 1) { - // transmit buffer not large enough - ESP_LOGVV(TAG, "TX failed: buffer not large enough"); - return ERROR_UNKNOWN; - } else if (status == 2 || status == 3) { - ESP_LOGVV(TAG, "TX failed: not acknowledged"); - return ERROR_NOT_ACKNOWLEDGED; + switch (status) { + case 0: + return ERROR_OK; + case 1: + // transmit buffer not large enough + ESP_LOGVV(TAG, "TX failed: buffer not large enough"); + return ERROR_UNKNOWN; + case 2: + case 3: + ESP_LOGVV(TAG, "TX failed: not acknowledged"); + return ERROR_NOT_ACKNOWLEDGED; + case 5: + ESP_LOGVV(TAG, "TX failed: timeout"); + return ERROR_UNKNOWN; + case 4: + default: + ESP_LOGVV(TAG, "TX failed: unknown error %u", status); + return ERROR_UNKNOWN; } - ESP_LOGVV(TAG, "TX failed: unknown error %u", status); - return ERROR_UNKNOWN; } /// Perform I2C bus recovery, see: diff --git a/esphome/components/voice_assistant/__init__.py b/esphome/components/voice_assistant/__init__.py index c90fd554ae..20698a1b82 100644 --- a/esphome/components/voice_assistant/__init__.py +++ b/esphome/components/voice_assistant/__init__.py @@ -11,6 +11,14 @@ DEPENDENCIES = ["api", "microphone"] CODEOWNERS = ["@jesserockz"] +CONF_ON_START = "on_start" +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" + + voice_assistant_ns = cg.esphome_ns.namespace("voice_assistant") VoiceAssistant = voice_assistant_ns.class_("VoiceAssistant", cg.Component) @@ -26,6 +34,12 @@ CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(VoiceAssistant), cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone), + cv.Optional(CONF_ON_START): automation.validate_automation(single=True), + cv.Optional(CONF_ON_STT_END): automation.validate_automation(single=True), + cv.Optional(CONF_ON_TTS_START): automation.validate_automation(single=True), + cv.Optional(CONF_ON_TTS_END): automation.validate_automation(single=True), + cv.Optional(CONF_ON_END): automation.validate_automation(single=True), + cv.Optional(CONF_ON_ERROR): automation.validate_automation(single=True), } ).extend(cv.COMPONENT_SCHEMA) @@ -37,6 +51,40 @@ async def to_code(config): mic = await cg.get_variable(config[CONF_MICROPHONE]) cg.add(var.set_microphone(mic)) + if CONF_ON_START in config: + await automation.build_automation( + var.get_start_trigger(), [], config[CONF_ON_START] + ) + + if CONF_ON_STT_END in config: + await automation.build_automation( + var.get_stt_end_trigger(), [(cg.std_string, "x")], config[CONF_ON_STT_END] + ) + + if CONF_ON_TTS_START in config: + await automation.build_automation( + var.get_tts_start_trigger(), + [(cg.std_string, "x")], + config[CONF_ON_TTS_START], + ) + + if CONF_ON_TTS_END in config: + await automation.build_automation( + var.get_tts_end_trigger(), [(cg.std_string, "x")], config[CONF_ON_TTS_END] + ) + + if CONF_ON_END in config: + await automation.build_automation( + var.get_end_trigger(), [], config[CONF_ON_END] + ) + + if CONF_ON_ERROR in config: + await automation.build_automation( + var.get_error_trigger(), + [(cg.std_string, "code"), (cg.std_string, "message")], + config[CONF_ON_ERROR], + ) + cg.add_define("USE_VOICE_ASSISTANT") diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 7f4bbf9934..777bef4edb 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -76,8 +76,9 @@ void VoiceAssistant::signal_stop() { void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { switch (msg.event_type) { - case api::enums::VOICE_ASSISTANT_RUN_END: - ESP_LOGD(TAG, "Voice Assistant ended."); + case api::enums::VOICE_ASSISTANT_RUN_START: + ESP_LOGD(TAG, "Assist Pipeline running"); + this->start_trigger_->trigger(); break; case api::enums::VOICE_ASSISTANT_STT_END: { std::string text; @@ -91,7 +92,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { return; } ESP_LOGD(TAG, "Speech recognised as: \"%s\"", text.c_str()); - // TODO `on_stt_end` trigger + this->stt_end_trigger_->trigger(text); break; } case api::enums::VOICE_ASSISTANT_TTS_START: { @@ -106,7 +107,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { return; } ESP_LOGD(TAG, "Response: \"%s\"", text.c_str()); - // TODO `on_tts_start` trigger + this->tts_start_trigger_->trigger(text); break; } case api::enums::VOICE_ASSISTANT_TTS_END: { @@ -121,9 +122,13 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { return; } ESP_LOGD(TAG, "Response URL: \"%s\"", url.c_str()); - // TODO `on_tts_end` trigger + this->tts_end_trigger_->trigger(url); break; } + case api::enums::VOICE_ASSISTANT_RUN_END: + ESP_LOGD(TAG, "Assist Pipeline ended"); + this->end_trigger_->trigger(); + break; case api::enums::VOICE_ASSISTANT_ERROR: { std::string code = ""; std::string message = ""; @@ -135,7 +140,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } } ESP_LOGE(TAG, "Error: %s - %s", code.c_str(), message.c_str()); - // TODO `on_error` trigger + this->error_trigger_->trigger(code, message); } default: break; diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 8cc20c31ad..813c006e98 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -25,10 +25,24 @@ class VoiceAssistant : public Component { void on_event(const api::VoiceAssistantEventResponse &msg); + Trigger<> *get_start_trigger() const { return this->start_trigger_; } + Trigger *get_stt_end_trigger() const { return this->stt_end_trigger_; } + Trigger *get_tts_start_trigger() const { return this->tts_start_trigger_; } + Trigger *get_tts_end_trigger() const { return this->tts_end_trigger_; } + Trigger<> *get_end_trigger() const { return this->end_trigger_; } + Trigger *get_error_trigger() const { return this->error_trigger_; } + protected: std::unique_ptr socket_ = nullptr; struct sockaddr_storage dest_addr_; + Trigger<> *start_trigger_ = new Trigger<>(); + Trigger *stt_end_trigger_ = new Trigger(); + Trigger *tts_start_trigger_ = new Trigger(); + Trigger *tts_end_trigger_ = new Trigger(); + Trigger<> *end_trigger_ = new Trigger<>(); + Trigger *error_trigger_ = new Trigger(); + microphone::Microphone *mic_{nullptr}; bool running_{false}; diff --git a/tests/test4.yaml b/tests/test4.yaml index c21e71be00..7b8f139a43 100644 --- a/tests/test4.yaml +++ b/tests/test4.yaml @@ -696,3 +696,23 @@ microphone: voice_assistant: microphone: mic_id + on_start: + - logger.log: "Voice assistant started" + on_stt_end: + - logger.log: + format: "Voice assistant STT ended with result %s" + args: [x.c_str()] + on_tts_start: + - logger.log: + format: "Voice assistant TTS started with text %s" + args: [x.c_str()] + on_tts_end: + - logger.log: + format: "Voice assistant TTS ended with url %s" + args: [x.c_str()] + on_end: + - logger.log: "Voice assistant ended" + on_error: + - logger.log: + format: "Voice assistant error - code %s, message: %s" + args: [code.c_str(), message.c_str()]