From 58de3852c553f0674bffac9233735d5ab4c9ab74 Mon Sep 17 00:00:00 2001 From: Terrence Date: Fri, 15 Nov 2024 04:44:53 +0800 Subject: [PATCH] add settings --- CMakeLists.txt | 2 +- main/CMakeLists.txt | 1 + main/application.cc | 97 +++++++++++++++++---------------- main/application.h | 7 +-- main/audio_codec.cc | 7 +++ main/main.cc | 1 + main/ota.cc | 20 ++++--- main/ota.h | 5 +- main/protocol.h | 4 ++ main/protocols/mqtt_protocol.cc | 85 ++++++++++++++++++++++------- main/protocols/mqtt_protocol.h | 7 ++- main/settings.cc | 63 +++++++++++++++++++++ main/settings.h | 23 ++++++++ main/wake_word_detect.cc | 3 +- sdkconfig.defaults | 1 - 15 files changed, 237 insertions(+), 89 deletions(-) create mode 100644 main/settings.cc create mode 100644 main/settings.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 272a137b..8a028caa 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) -set(PROJECT_VER "0.8.0") +set(PROJECT_VER "0.8.1") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(xiaozhi) diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 3906cf29..b116ecf8 100755 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCES "audio_codec.cc" "button.cc" "led.cc" "ota.cc" + "settings.cc" "main.cc" ) set(INCLUDE_DIRS ".") diff --git a/main/application.cc b/main/application.cc index 41f3bd12..c2f59cf1 100644 --- a/main/application.cc +++ b/main/application.cc @@ -37,9 +37,6 @@ Application::~Application() { if (audio_encode_task_stack_ != nullptr) { heap_caps_free(audio_encode_task_stack_); } - if (main_loop_task_stack_ != nullptr) { - heap_caps_free(main_loop_task_stack_); - } vEventGroupDelete(event_group_); } @@ -47,20 +44,34 @@ Application::~Application() { void Application::CheckNewVersion() { // Check if there is a new firmware version available ota_.SetPostData(Board::GetInstance().GetJson()); - ota_.CheckVersion(); - if (ota_.HasNewVersion()) { - SetChatState(kChatStateUpgrading); - ota_.StartUpgrade([](int progress, size_t speed) { - char buffer[64]; - snprintf(buffer, sizeof(buffer), "Upgrading...\n %d%% %zuKB/s", progress, speed / 1024); - auto display = Board::GetInstance().GetDisplay(); - display->SetText(buffer); - }); - // If upgrade success, the device will reboot and never reach here - ESP_LOGI(TAG, "Firmware upgrade failed..."); - SetChatState(kChatStateIdle); - } else { - ota_.MarkCurrentVersionValid(); + + while (true) { + if (ota_.CheckVersion()) { + if (ota_.HasNewVersion()) { + // Wait for the chat state to be idle + while (chat_state_ != kChatStateIdle) { + vTaskDelay(100); + } + + SetChatState(kChatStateUpgrading); + ota_.StartUpgrade([](int progress, size_t speed) { + char buffer[64]; + snprintf(buffer, sizeof(buffer), "Upgrading...\n %d%% %zuKB/s", progress, speed / 1024); + auto display = Board::GetInstance().GetDisplay(); + display->SetText(buffer); + }); + + // If upgrade success, the device will reboot and never reach here + ESP_LOGI(TAG, "Firmware upgrade failed..."); + SetChatState(kChatStateIdle); + } else { + ota_.MarkCurrentVersionValid(); + } + return; + } + + // Check again in 60 seconds + vTaskDelay(pdMS_TO_TICKS(60000)); } } @@ -191,24 +202,18 @@ void Application::Start() { /* Wait for the network to be ready */ board.StartNetwork(); - const size_t main_loop_stack_size = 4096 * 8; - main_loop_task_stack_ = (StackType_t*)heap_caps_malloc(main_loop_stack_size, MALLOC_CAP_SPIRAM); - xTaskCreateStatic([](void* arg) { + xTaskCreate([](void* arg) { Application* app = (Application*)arg; app->MainLoop(); vTaskDelete(NULL); - }, "main_loop", main_loop_stack_size, this, 1, main_loop_task_stack_, &main_loop_task_buffer_); + }, "main_loop", 4096 * 2, this, 1, nullptr); // Check for new firmware version or get the MQTT broker address - while (true) { - CheckNewVersion(); - - if (ota_.HasMqttConfig()) { - break; - } - Alert("Error", "Missing MQTT config"); - vTaskDelay(pdMS_TO_TICKS(10000)); - } + xTaskCreate([](void* arg) { + Application* app = (Application*)arg; + app->CheckNewVersion(); + vTaskDelete(NULL); + }, "check_new_version", 4096 * 2, this, 1, nullptr); #ifdef CONFIG_USE_AFE_SR audio_processor_.Initialize(codec->input_channels(), codec->input_reference()); @@ -264,12 +269,19 @@ void Application::Start() { // Initialize the protocol display->SetText("Starting\nProtocol..."); - protocol_ = new MqttProtocol(ota_.GetMqttConfig()); + protocol_ = new MqttProtocol(); protocol_->OnIncomingAudio([this](const std::string& data) { std::lock_guard lock(mutex_); audio_decode_queue_.emplace_back(std::move(data)); cv_.notify_all(); }); + protocol_->OnAudioChannelOpened([this, codec]() { + if (protocol_->GetServerSampleRate() != codec->output_sample_rate()) { + ESP_LOGW(TAG, "服务器的音频采样率 %d 与设备输出的采样率 %d 不一致,重采样后可能会失真", + protocol_->GetServerSampleRate(), codec->output_sample_rate()); + } + SetDecodeSampleRate(protocol_->GetServerSampleRate()); + }); protocol_->OnAudioChannelClosed([this]() { Schedule([this]() { SetChatState(kChatStateIdle); @@ -289,7 +301,9 @@ void Application::Start() { Schedule([this]() { auto codec = Board::GetInstance().GetAudioCodec(); codec->WaitForOutputDone(); - SetChatState(kChatStateListening); + if (chat_state_ == kChatStateSpeaking) { + SetChatState(kChatStateListening); + } }); } else if (strcmp(state->valuestring, "sentence_start") == 0) { auto text = cJSON_GetObjectItem(root, "text"); @@ -307,15 +321,6 @@ void Application::Start() { if (emotion != NULL) { ESP_LOGD(TAG, "EMOTION: %s", emotion->valuestring); } - } else if (strcmp(type->valuestring, "hello") == 0) { - // Get sample rate from hello message - auto audio_params = cJSON_GetObjectItem(root, "audio_params"); - if (audio_params != NULL) { - auto sample_rate = cJSON_GetObjectItem(audio_params, "sample_rate"); - if (sample_rate != NULL) { - SetDecodeSampleRate(sample_rate->valueint); - } - } } }); @@ -351,8 +356,7 @@ void Application::MainLoop() { void Application::AbortSpeaking() { ESP_LOGI(TAG, "Abort speaking"); - std::string json = "{\"type\":\"abort\"}"; - protocol_->SendText(json); + protocol_->SendAbort(); skip_to_end_ = true; auto codec = Board::GetInstance().GetAudioCodec(); @@ -420,10 +424,7 @@ void Application::SetChatState(ChatState state) { break; } - std::string json = "{\"type\":\"state\",\"state\":\""; - json += state_str[chat_state_]; - json += "\"}"; - protocol_->SendText(json); + protocol_->SendState(state_str[chat_state_]); } void Application::AudioEncodeTask() { @@ -455,7 +456,7 @@ void Application::AudioEncodeTask() { continue; } - int frame_size = opus_decode_sample_rate_ * opus_duration_ms_ / 1000; + int frame_size = opus_decode_sample_rate_ * OPUS_FRAME_DURATION_MS / 1000; std::vector pcm(frame_size); int ret = opus_decode(opus_decoder_, (const unsigned char*)opus.data(), opus.size(), pcm.data(), frame_size, 0); diff --git a/main/application.h b/main/application.h index 305b78e8..f347d601 100644 --- a/main/application.h +++ b/main/application.h @@ -39,6 +39,8 @@ enum ChatState { kChatStateUpgrading }; +#define OPUS_FRAME_DURATION_MS 60 + class Application { public: static Application& GetInstance() { @@ -84,16 +86,11 @@ class Application { OpusEncoder opus_encoder_; OpusDecoder* opus_decoder_ = nullptr; - int opus_duration_ms_ = 60; int opus_decode_sample_rate_ = -1; OpusResampler input_resampler_; OpusResampler reference_resampler_; OpusResampler output_resampler_; - TaskHandle_t main_loop_task_ = nullptr; - StaticTask_t main_loop_task_buffer_; - StackType_t* main_loop_task_stack_ = nullptr; - void MainLoop(); void SetDecodeSampleRate(int sample_rate); void CheckNewVersion(); diff --git a/main/audio_codec.cc b/main/audio_codec.cc index b0ea4c10..cdfb568f 100644 --- a/main/audio_codec.cc +++ b/main/audio_codec.cc @@ -1,5 +1,6 @@ #include "audio_codec.h" #include "board.h" +#include "settings.h" #include #include @@ -40,6 +41,9 @@ IRAM_ATTR bool AudioCodec::on_sent(i2s_chan_handle_t handle, i2s_event_data_t *e } void AudioCodec::Start() { + Settings settings("audio", false); + output_volume_ = settings.GetInt("output_volume", output_volume_); + // 注册音频输出回调 i2s_event_callbacks_t callbacks = {}; callbacks.on_sent = on_sent; @@ -124,6 +128,9 @@ void AudioCodec::ClearOutputQueue() { void AudioCodec::SetOutputVolume(int volume) { output_volume_ = volume; ESP_LOGI(TAG, "Set output volume to %d", output_volume_); + + Settings settings("audio", true); + settings.SetInt("output_volume", output_volume_); } void AudioCodec::EnableInput(bool enable) { diff --git a/main/main.cc b/main/main.cc index d726c5d2..0faeb344 100755 --- a/main/main.cc +++ b/main/main.cc @@ -18,6 +18,7 @@ extern "C" void app_main(void) // Initialize NVS flash for WiFi configuration esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_LOGW(TAG, "Erasing NVS flash to fix corruption"); ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } diff --git a/main/ota.cc b/main/ota.cc index a4686eb5..d95ecc90 100644 --- a/main/ota.cc +++ b/main/ota.cc @@ -1,6 +1,7 @@ #include "ota.h" #include "system_info.h" #include "board.h" +#include "settings.h" #include #include @@ -34,13 +35,13 @@ void Ota::SetPostData(const std::string& post_data) { post_data_ = post_data; } -void Ota::CheckVersion() { +bool Ota::CheckVersion() { std::string current_version = esp_app_get_description()->version; ESP_LOGI(TAG, "Current version: %s", current_version.c_str()); if (check_version_url_.length() < 10) { ESP_LOGE(TAG, "Check version URL is not properly set"); - return; + return false; } auto http = Board::GetInstance().CreateHttp(); @@ -67,16 +68,18 @@ void Ota::CheckVersion() { cJSON *root = cJSON_Parse(response.c_str()); if (root == NULL) { ESP_LOGE(TAG, "Failed to parse JSON response"); - return; + return false; } cJSON *mqtt = cJSON_GetObjectItem(root, "mqtt"); if (mqtt != NULL) { + Settings settings("mqtt", true); cJSON *item = NULL; cJSON_ArrayForEach(item, mqtt) { if (item->type == cJSON_String) { - mqtt_config_[item->string] = item->valuestring; - ESP_LOGI(TAG, "MQTT config: %s = %s", item->string, item->valuestring); + if (settings.GetString(item->string) != item->valuestring) { + settings.SetString(item->string, item->valuestring); + } } } has_mqtt_config_ = true; @@ -86,19 +89,19 @@ void Ota::CheckVersion() { if (firmware == NULL) { ESP_LOGE(TAG, "Failed to get firmware object"); cJSON_Delete(root); - return; + return false; } cJSON *version = cJSON_GetObjectItem(firmware, "version"); if (version == NULL) { ESP_LOGE(TAG, "Failed to get version object"); cJSON_Delete(root); - return; + return false; } cJSON *url = cJSON_GetObjectItem(firmware, "url"); if (url == NULL) { ESP_LOGE(TAG, "Failed to get url object"); cJSON_Delete(root); - return; + return false; } firmware_version_ = version->valuestring; @@ -112,6 +115,7 @@ void Ota::CheckVersion() { } else { ESP_LOGI(TAG, "Current is the latest version"); } + return true; } void Ota::MarkCurrentVersionValid() { diff --git a/main/ota.h b/main/ota.h index a27cd277..de9e2da7 100644 --- a/main/ota.h +++ b/main/ota.h @@ -13,14 +13,12 @@ class Ota { void SetCheckVersionUrl(std::string check_version_url); void SetHeader(const std::string& key, const std::string& value); void SetPostData(const std::string& post_data); - void CheckVersion(); + bool CheckVersion(); bool HasNewVersion() { return has_new_version_; } bool HasMqttConfig() { return has_mqtt_config_; } void StartUpgrade(std::function callback); void MarkCurrentVersionValid(); - std::map& GetMqttConfig() { return mqtt_config_; } - private: std::string check_version_url_; bool has_new_version_ = false; @@ -29,7 +27,6 @@ class Ota { std::string firmware_url_; std::string post_data_; std::map headers_; - std::map mqtt_config_; void Upgrade(const std::string& firmware_url); std::function upgrade_callback_; diff --git a/main/protocol.h b/main/protocol.h index c64c925a..28b3b376 100644 --- a/main/protocol.h +++ b/main/protocol.h @@ -13,10 +13,14 @@ class Protocol { virtual void OnIncomingJson(std::function callback) = 0; virtual void SendAudio(const std::string& data) = 0; virtual void SendText(const std::string& text) = 0; + virtual void SendState(const std::string& state) = 0; + virtual void SendAbort() = 0; virtual bool OpenAudioChannel() = 0; virtual void CloseAudioChannel() = 0; virtual void OnAudioChannelOpened(std::function callback) = 0; virtual void OnAudioChannelClosed(std::function callback) = 0; + virtual bool IsAudioChannelOpened() const = 0; + virtual int GetServerSampleRate() const = 0; }; #endif // PROTOCOL_H diff --git a/main/protocols/mqtt_protocol.cc b/main/protocols/mqtt_protocol.cc index 2a41c932..22a92152 100644 --- a/main/protocols/mqtt_protocol.cc +++ b/main/protocols/mqtt_protocol.cc @@ -1,5 +1,7 @@ #include "mqtt_protocol.h" #include "board.h" +#include "application.h" +#include "settings.h" #include #include @@ -9,16 +11,9 @@ #define TAG "MQTT" -MqttProtocol::MqttProtocol(std::map& config) { +MqttProtocol::MqttProtocol() { event_group_handle_ = xEventGroupCreate(); - endpoint_ = config["endpoint"]; - client_id_ = config["client_id"]; - username_ = config["username"]; - password_ = config["password"]; - subscribe_topic_ = config["subscribe_topic"]; - publish_topic_ = config["publish_topic"]; - StartMqttClient(); } @@ -39,6 +34,19 @@ bool MqttProtocol::StartMqttClient() { delete mqtt_; } + Settings settings("mqtt", false); + endpoint_ = settings.GetString("endpoint"); + client_id_ = settings.GetString("client_id"); + username_ = settings.GetString("username"); + password_ = settings.GetString("password"); + subscribe_topic_ = settings.GetString("subscribe_topic"); + publish_topic_ = settings.GetString("publish_topic"); + + if (endpoint_.empty()) { + ESP_LOGE(TAG, "MQTT endpoint is not specified"); + return false; + } + mqtt_ = Board::GetInstance().CreateMqtt(); mqtt_->SetKeepAlive(90); @@ -58,9 +66,7 @@ bool MqttProtocol::StartMqttClient() { cJSON_Delete(root); return; } - if (on_incoming_json_ != nullptr) { - on_incoming_json_(root); - } + if (strcmp(type->valuestring, "hello") == 0) { ParseServerHello(root); } else if (strcmp(type->valuestring, "goodbye") == 0) { @@ -70,6 +76,8 @@ bool MqttProtocol::StartMqttClient() { on_audio_channel_closed_(); } } + } else if (on_incoming_json_ != nullptr) { + on_incoming_json_(root); } cJSON_Delete(root); }); @@ -89,13 +97,17 @@ bool MqttProtocol::StartMqttClient() { void MqttProtocol::SendText(const std::string& text) { if (publish_topic_.empty()) { - ESP_LOGE(TAG, "Publish topic is not specified"); return; } mqtt_->Publish(publish_topic_, text); } void MqttProtocol::SendAudio(const std::string& data) { + std::lock_guard lock(channel_mutex_); + if (udp_ == nullptr) { + return; + } + std::string nonce(aes_nonce_); *(uint16_t*)&nonce[2] = htons(data.size()); *(uint32_t*)&nonce[12] = htonl(++local_sequence_); @@ -111,14 +123,26 @@ void MqttProtocol::SendAudio(const std::string& data) { ESP_LOGE(TAG, "Failed to encrypt audio data"); return; } - - std::lock_guard lock(channel_mutex_); - if (udp_ == nullptr) { - return; - } udp_->Send(encrypted); } +void MqttProtocol::SendState(const std::string& state) { + std::string message = "{"; + message += "\"session_id\":\"" + session_id_ + "\","; + message += "\"type\":\"state\","; + message += "\"state\":\"" + state + "\""; + message += "}"; + SendText(message); +} + +void MqttProtocol::SendAbort() { + std::string message = "{"; + message += "\"session_id\":\"" + session_id_ + "\","; + message += "\"type\":\"abort\""; + message += "}"; + SendText(message); +} + void MqttProtocol::CloseAudioChannel() { { std::lock_guard lock(channel_mutex_); @@ -129,6 +153,7 @@ void MqttProtocol::CloseAudioChannel() { } std::string message = "{"; + message += "\"session_id\":\"" + session_id_ + "\","; message += "\"type\":\"goodbye\""; message += "}"; SendText(message); @@ -139,8 +164,8 @@ void MqttProtocol::CloseAudioChannel() { } bool MqttProtocol::OpenAudioChannel() { - if (!mqtt_->IsConnected()) { - ESP_LOGE(TAG, "MQTT is not connected, try to connect now"); + if (mqtt_ == nullptr || !mqtt_->IsConnected()) { + ESP_LOGI(TAG, "MQTT is not connected, try to connect now"); if (!StartMqttClient()) { ESP_LOGE(TAG, "Failed to connect to MQTT"); return false; @@ -155,7 +180,7 @@ bool MqttProtocol::OpenAudioChannel() { message += "\"version\": 3,"; message += "\"transport\":\"udp\","; message += "\"audio_params\":{"; - message += "\"format\":\"opus\", \"sample_rate\":16000, \"channels\":1, \"frame_duration\":60"; + message += "\"format\":\"opus\", \"sample_rate\":16000, \"channels\":1, \"frame_duration\":" + std::to_string(OPUS_FRAME_DURATION_MS); message += "}}"; SendText(message); @@ -185,6 +210,9 @@ bool MqttProtocol::OpenAudioChannel() { ESP_LOGW(TAG, "Received audio packet with old sequence: %lu, expected: %lu", sequence, remote_sequence_); return; } + if (sequence != remote_sequence_ + 1) { + ESP_LOGW(TAG, "Received audio packet with wrong sequence: %lu, expected: %lu", sequence, remote_sequence_ + 1); + } std::string decrypted; size_t decrypted_size = data.size() - aes_nonce_.size(); @@ -240,6 +268,15 @@ void MqttProtocol::ParseServerHello(const cJSON* root) { session_id_ = session_id->valuestring; } + // Get sample rate from hello message + auto audio_params = cJSON_GetObjectItem(root, "audio_params"); + if (audio_params != NULL) { + auto sample_rate = cJSON_GetObjectItem(audio_params, "sample_rate"); + if (sample_rate != NULL) { + server_sample_rate_ = sample_rate->valueint; + } + } + auto udp = cJSON_GetObjectItem(root, "udp"); if (udp == nullptr) { ESP_LOGE(TAG, "UDP is not specified"); @@ -260,6 +297,10 @@ void MqttProtocol::ParseServerHello(const cJSON* root) { xEventGroupSetBits(event_group_handle_, MQTT_PROTOCOL_SERVER_HELLO_EVENT); } +int MqttProtocol::GetServerSampleRate() const { + return server_sample_rate_; +} + static const char hex_chars[] = "0123456789ABCDEF"; // 辅助函数,将单个十六进制字符转换为对应的数值 @@ -279,3 +320,7 @@ std::string MqttProtocol::DecodeHexString(const std::string& hex_string) { } return decoded; } + +bool MqttProtocol::IsAudioChannelOpened() const { + return udp_ != nullptr; +} diff --git a/main/protocols/mqtt_protocol.h b/main/protocols/mqtt_protocol.h index a57cdc5b..a5de6251 100644 --- a/main/protocols/mqtt_protocol.h +++ b/main/protocols/mqtt_protocol.h @@ -21,17 +21,21 @@ class MqttProtocol : public Protocol { public: - MqttProtocol(std::map& config); + MqttProtocol(); ~MqttProtocol(); void OnIncomingAudio(std::function callback); void OnIncomingJson(std::function callback); void SendAudio(const std::string& data); void SendText(const std::string& text); + void SendState(const std::string& state); + void SendAbort(); bool OpenAudioChannel(); void CloseAudioChannel(); void OnAudioChannelOpened(std::function callback); void OnAudioChannelClosed(std::function callback); + bool IsAudioChannelOpened() const; + int GetServerSampleRate() const; private: EventGroupHandle_t event_group_handle_; @@ -58,6 +62,7 @@ class MqttProtocol : public Protocol { uint32_t local_sequence_; uint32_t remote_sequence_; std::string session_id_; + int server_sample_rate_ = 16000; bool StartMqttClient(); void ParseServerHello(const cJSON* root); diff --git a/main/settings.cc b/main/settings.cc new file mode 100644 index 00000000..70daf8ae --- /dev/null +++ b/main/settings.cc @@ -0,0 +1,63 @@ +#include "settings.h" + +#include +#include + +#define TAG "Settings" + +Settings::Settings(const std::string& ns, bool read_write) : ns_(ns), read_write_(read_write) { + nvs_open(ns.c_str(), read_write_ ? NVS_READWRITE : NVS_READONLY, &nvs_handle_); +} + +Settings::~Settings() { + if (nvs_handle_ != 0) { + if (read_write_) { + ESP_ERROR_CHECK(nvs_commit(nvs_handle_)); + } + nvs_close(nvs_handle_); + } +} + +std::string Settings::GetString(const std::string& key, const std::string& default_value) { + if (nvs_handle_ == 0) { + return default_value; + } + + size_t length = 0; + if (nvs_get_str(nvs_handle_, key.c_str(), nullptr, &length) != ESP_OK) { + return default_value; + } + + std::string value; + value.resize(length); + ESP_ERROR_CHECK(nvs_get_str(nvs_handle_, key.c_str(), value.data(), &length)); + return value; +} + +void Settings::SetString(const std::string& key, const std::string& value) { + if (read_write_) { + ESP_ERROR_CHECK(nvs_set_str(nvs_handle_, key.c_str(), value.c_str())); + } else { + ESP_LOGW(TAG, "Namespace %s is not open for writing", ns_.c_str()); + } +} + +int32_t Settings::GetInt(const std::string& key, int32_t default_value) { + if (nvs_handle_ == 0) { + return default_value; + } + + int32_t value; + if (nvs_get_i32(nvs_handle_, key.c_str(), &value) != ESP_OK) { + return default_value; + } + return value; +} + +void Settings::SetInt(const std::string& key, int32_t value) { + if (read_write_) { + ESP_ERROR_CHECK(nvs_set_i32(nvs_handle_, key.c_str(), value)); + } else { + ESP_LOGW(TAG, "Namespace %s is not open for writing", ns_.c_str()); + } +} diff --git a/main/settings.h b/main/settings.h new file mode 100644 index 00000000..bc4c4fe4 --- /dev/null +++ b/main/settings.h @@ -0,0 +1,23 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include +#include + +class Settings { +public: + Settings(const std::string& ns, bool read_write = false); + ~Settings(); + + std::string GetString(const std::string& key, const std::string& default_value = ""); + void SetString(const std::string& key, const std::string& value); + int32_t GetInt(const std::string& key, int32_t default_value = 0); + void SetInt(const std::string& key, int32_t value); + +private: + std::string ns_; + nvs_handle_t nvs_handle_ = 0; + bool read_write_ = false; +}; + +#endif diff --git a/main/wake_word_detect.cc b/main/wake_word_detect.cc index 261777d8..5fa8eee4 100644 --- a/main/wake_word_detect.cc +++ b/main/wake_word_detect.cc @@ -170,6 +170,7 @@ void WakeWordDetect::StoreWakeWordData(uint16_t* data, size_t samples) { } void WakeWordDetect::EncodeWakeWordData() { + xEventGroupClearBits(event_group_, WAKE_WORD_ENCODED_EVENT); wake_word_opus_.clear(); if (wake_word_encode_task_stack_ == nullptr) { wake_word_encode_task_stack_ = (StackType_t*)malloc(4096 * 8); @@ -192,7 +193,7 @@ void WakeWordDetect::EncodeWakeWordData() { this_->wake_word_pcm_.clear(); auto end_time = esp_timer_get_time(); - ESP_LOGI(TAG, "Encode wake word opus: %zu bytes in %lld ms", this_->wake_word_opus_.size(), (end_time - start_time) / 1000); + ESP_LOGI(TAG, "Encode wake word opus %zu packets in %lld ms", this_->wake_word_opus_.size(), (end_time - start_time) / 1000); xEventGroupSetBits(this_->event_group_, WAKE_WORD_ENCODED_EVENT); this_->wake_word_cv_.notify_one(); delete encoder; diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 23fe8055..d4889182 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -5,7 +5,6 @@ CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y CONFIG_HTTPD_MAX_REQ_HDR_LEN=2048 CONFIG_HTTPD_MAX_URI_LEN=2048 -CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"