From 656bf3c7fa5cfc63626fc5ad9d20aef8cd1877d2 Mon Sep 17 00:00:00 2001 From: Ky1eYang Date: Wed, 23 Jul 2025 22:59:07 +0800 Subject: [PATCH] =?UTF-8?q?FIX:=20=E4=BF=AE=E5=A4=8D=E5=8F=8C=E5=A3=B0?= =?UTF-8?q?=E9=81=93=E5=A3=B0=E6=B3=A2=E9=85=8D=E7=BD=91=E5=A4=B1=E6=95=88?= =?UTF-8?q?,=20=E6=B7=BB=E5=8A=A0=E5=B1=8F=E5=B9=95=E6=89=93=E5=8D=B0SSID/?= =?UTF-8?q?=E5=AF=86=E7=A0=81=20(#971)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * debug: 添加声波配网的log打印点display * fix: 修复双声道下声波配网失效的问题 * fix: codec可能为nullptr的问题(需要从单例board获取) * Update afsk_demod.cc fix coding style --------- Co-authored-by: yangkaiyue Co-authored-by: Xiaoxia --- main/boards/common/afsk_demod.cc | 164 ++++++++++++------------------- main/boards/common/afsk_demod.h | 3 +- main/boards/common/wifi_board.cc | 9 +- 3 files changed, 72 insertions(+), 104 deletions(-) diff --git a/main/boards/common/afsk_demod.cc b/main/boards/common/afsk_demod.cc index ac2df808..9e040de0 100644 --- a/main/boards/common/afsk_demod.cc +++ b/main/boards/common/afsk_demod.cc @@ -2,6 +2,7 @@ #include #include #include "esp_log.h" +#include "display.h" #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -12,7 +13,10 @@ namespace audio_wifi_config static const char *kLogTag = "AUDIO_WIFI_CONFIG"; void ReceiveWifiCredentialsFromAudio(Application *app, - WifiConfigurationAp *wifi_ap) + WifiConfigurationAp *wifi_ap, + Display *display, + size_t input_channels + ) { const int kInputSampleRate = 16000; // Input sampling rate const float kDownsampleStep = static_cast(kInputSampleRate) / static_cast(kAudioSampleRate); // Downsampling step @@ -35,29 +39,31 @@ namespace audio_wifi_config vTaskDelay(pdMS_TO_TICKS(10)); continue; } + + if (input_channels == 2) { // 如果是双声道输入,转换为单声道 + auto mono_data = std::vector(audio_data.size() / 2); + for (size_t i = 0, j = 0; i < mono_data.size(); ++i, j += 2) { + mono_data[i] = audio_data[j]; + } + audio_data = std::move(mono_data); + } // Downsample the audio data std::vector downsampled_data; size_t last_index = 0; - if (kDownsampleStep > 1.0f) - { + if (kDownsampleStep > 1.0f) { downsampled_data.reserve(audio_data.size() / static_cast(kDownsampleStep)); - for (size_t i = 0; i < audio_data.size(); ++i) - { + for (size_t i = 0; i < audio_data.size(); ++i) { size_t sample_index = static_cast(i / kDownsampleStep); - if ((sample_index + 1) > last_index) - { + if ((sample_index + 1) > last_index) { downsampled_data.push_back(static_cast(audio_data[i])); last_index = sample_index + 1; } } - } - else - { + } else { downsampled_data.reserve(audio_data.size()); - for (int16_t sample : audio_data) - { + for (int16_t sample : audio_data) { downsampled_data.push_back(static_cast(sample)); } } @@ -66,35 +72,28 @@ namespace audio_wifi_config auto probabilities = signal_processor.ProcessAudioSamples(downsampled_data); // Feed probability data to the data buffer - if (data_buffer.ProcessProbabilityData(probabilities, 0.5f)) - { + if (data_buffer.ProcessProbabilityData(probabilities, 0.5f)) { // If complete data was received, extract WiFi credentials - if (data_buffer.decoded_text.has_value()) - { + if (data_buffer.decoded_text.has_value()) { ESP_LOGI(kLogTag, "Received text data: %s", data_buffer.decoded_text->c_str()); + display->SetChatMessage("system", data_buffer.decoded_text->c_str()); // Split SSID and password by newline character std::string wifi_ssid, wifi_password; size_t newline_position = data_buffer.decoded_text->find('\n'); - if (newline_position != std::string::npos) - { + if (newline_position != std::string::npos) { wifi_ssid = data_buffer.decoded_text->substr(0, newline_position); wifi_password = data_buffer.decoded_text->substr(newline_position + 1); ESP_LOGI(kLogTag, "WiFi SSID: %s, Password: %s", wifi_ssid.c_str(), wifi_password.c_str()); - } - else - { + } else { ESP_LOGE(kLogTag, "Invalid data format, no newline character found"); continue; } - if (wifi_ap->ConnectToWifi(wifi_ssid, wifi_password)) - { + if (wifi_ap->ConnectToWifi(wifi_ssid, wifi_password)) { wifi_ap->Save(wifi_ssid, wifi_password); // Save WiFi credentials esp_restart(); // Restart device to apply new WiFi configuration - } - else - { + } else { ESP_LOGE(kLogTag, "Failed to connect to WiFi with received credentials"); } data_buffer.decoded_text.reset(); // Clear processed data @@ -115,8 +114,7 @@ namespace audio_wifi_config // FrequencyDetector implementation FrequencyDetector::FrequencyDetector(float frequency, size_t window_size) - : frequency_(frequency), window_size_(window_size) - { + : frequency_(frequency), window_size_(window_size) { frequency_bin_ = std::floor(frequency_ * static_cast(window_size_)); angular_frequency_ = 2.0f * M_PI * frequency_; cos_coefficient_ = std::cos(angular_frequency_); @@ -128,17 +126,14 @@ namespace audio_wifi_config state_buffer_.push_back(0.0f); } - void FrequencyDetector::Reset() - { + void FrequencyDetector::Reset() { state_buffer_.clear(); state_buffer_.push_back(0.0f); state_buffer_.push_back(0.0f); } - void FrequencyDetector::ProcessSample(float sample) - { - if (state_buffer_.size() < 2) - { + void FrequencyDetector::ProcessSample(float sample) { + if (state_buffer_.size() < 2) { return; } @@ -153,10 +148,8 @@ namespace audio_wifi_config state_buffer_.push_back(s_current); // Add new S[0] } - float FrequencyDetector::GetAmplitude() const - { - if (state_buffer_.size() < 2) - { + float FrequencyDetector::GetAmplitude() const { + if (state_buffer_.size() < 2) { return 0.0f; } @@ -172,10 +165,8 @@ namespace audio_wifi_config // AudioSignalProcessor implementation AudioSignalProcessor::AudioSignalProcessor(size_t sample_rate, size_t mark_frequency, size_t space_frequency, size_t bit_rate, size_t window_size) - : input_buffer_size_(window_size), output_sample_count_(0) - { - if (sample_rate % bit_rate != 0) - { + : input_buffer_size_(window_size), output_sample_count_(0) { + if (sample_rate % bit_rate != 0) { // On ESP32 we can continue execution, but log the error ESP_LOGW(kLogTag, "Sample rate %zu is not divisible by bit rate %zu", sample_rate, bit_rate); } @@ -189,28 +180,21 @@ namespace audio_wifi_config samples_per_bit_ = sample_rate / bit_rate; // Number of samples per bit } - std::vector AudioSignalProcessor::ProcessAudioSamples(const std::vector &samples) - { + std::vector AudioSignalProcessor::ProcessAudioSamples(const std::vector &samples) { std::vector result; - for (float sample : samples) - { - if (input_buffer_.size() < input_buffer_size_) - { + for (float sample : samples) { + if (input_buffer_.size() < input_buffer_size_) { input_buffer_.push_back(sample); // Just add, don't process yet - } - else - { + } else { // Input buffer is full, process the data input_buffer_.pop_front(); // Remove oldest sample input_buffer_.push_back(sample); // Add new sample output_sample_count_++; - if (output_sample_count_ >= samples_per_bit_) - { + if (output_sample_count_ >= samples_per_bit_) { // Process all samples in the window using Goertzel algorithm - for (float window_sample : input_buffer_) - { + for (float window_sample : input_buffer_) { mark_detector_->ProcessSample(window_sample); space_detector_->ProcessSample(window_sample); } @@ -239,8 +223,7 @@ namespace audio_wifi_config : current_state_(DataReceptionState::kInactive), start_of_transmission_(kDefaultStartTransmissionPattern), end_of_transmission_(kDefaultEndTransmissionPattern), - enable_checksum_validation_(true) - { + enable_checksum_validation_(true) { identifier_buffer_size_ = std::max(start_of_transmission_.size(), end_of_transmission_.size()); max_bit_buffer_size_ = 776; // Preset bit buffer size, 776 bits = (32 + 1 + 63 + 1) * 8 = 776 @@ -252,48 +235,39 @@ namespace audio_wifi_config : current_state_(DataReceptionState::kInactive), start_of_transmission_(start_identifier), end_of_transmission_(end_identifier), - enable_checksum_validation_(enable_checksum) - { + enable_checksum_validation_(enable_checksum) { identifier_buffer_size_ = std::max(start_of_transmission_.size(), end_of_transmission_.size()); max_bit_buffer_size_ = max_byte_size * 8; // Bit buffer size in bytes bit_buffer_.reserve(max_bit_buffer_size_); } - uint8_t AudioDataBuffer::CalculateChecksum(const std::string &text) - { + uint8_t AudioDataBuffer::CalculateChecksum(const std::string &text) { uint8_t checksum = 0; - for (char character : text) - { + for (char character : text) { checksum += static_cast(character); } return checksum; } - void AudioDataBuffer::ClearBuffers() - { + void AudioDataBuffer::ClearBuffers() { identifier_buffer_.clear(); bit_buffer_.clear(); } - bool AudioDataBuffer::ProcessProbabilityData(const std::vector &probabilities, float threshold) - { - for (float probability : probabilities) - { + bool AudioDataBuffer::ProcessProbabilityData(const std::vector &probabilities, float threshold) { + for (float probability : probabilities) { uint8_t bit = (probability > threshold) ? 1 : 0; - if (identifier_buffer_.size() >= identifier_buffer_size_) - { + if (identifier_buffer_.size() >= identifier_buffer_size_) { identifier_buffer_.pop_front(); // Maintain buffer size } identifier_buffer_.push_back(bit); // Process received bit based on state machine - switch (current_state_) - { + switch (current_state_) { case DataReceptionState::kInactive: - if (identifier_buffer_.size() >= start_of_transmission_.size()) - { + if (identifier_buffer_.size() >= start_of_transmission_.size()) { current_state_ = DataReceptionState::kWaiting; // Enter waiting state ESP_LOGI(kLogTag, "Entering Waiting state"); } @@ -301,8 +275,7 @@ namespace audio_wifi_config case DataReceptionState::kWaiting: // Waiting state, possibly waiting for transmission end - if (identifier_buffer_.size() >= start_of_transmission_.size()) - { + if (identifier_buffer_.size() >= start_of_transmission_.size()) { std::vector identifier_snapshot(identifier_buffer_.begin(), identifier_buffer_.end()); if (identifier_snapshot == start_of_transmission_) { @@ -315,11 +288,9 @@ namespace audio_wifi_config case DataReceptionState::kReceiving: bit_buffer_.push_back(bit); - if (identifier_buffer_.size() >= end_of_transmission_.size()) - { + if (identifier_buffer_.size() >= end_of_transmission_.size()) { std::vector identifier_snapshot(identifier_buffer_.begin(), identifier_buffer_.end()); - if (identifier_snapshot == end_of_transmission_) - { + if (identifier_snapshot == end_of_transmission_) { current_state_ = DataReceptionState::kInactive; // Enter inactive state // Convert bits to bytes @@ -328,22 +299,18 @@ namespace audio_wifi_config uint8_t received_checksum = 0; size_t minimum_length = 0; - if (enable_checksum_validation_) - { + if (enable_checksum_validation_) { // If checksum is required, last byte is checksum minimum_length = 1 + start_of_transmission_.size() / 8; if (bytes.size() >= minimum_length) { received_checksum = bytes[bytes.size() - start_of_transmission_.size() / 8 - 1]; } - } - else - { + } else { minimum_length = start_of_transmission_.size() / 8; } - if (bytes.size() < minimum_length) - { + if (bytes.size() < minimum_length) { ClearBuffers(); ESP_LOGW(kLogTag, "Data too short, clearing buffer"); return false; // Data too short, return failure @@ -356,11 +323,9 @@ namespace audio_wifi_config std::string result(text_bytes.begin(), text_bytes.end()); // Validate checksum if required - if (enable_checksum_validation_) - { + if (enable_checksum_validation_) { uint8_t calculated_checksum = CalculateChecksum(result); - if (calculated_checksum != received_checksum) - { + if (calculated_checksum != received_checksum) { // Checksum mismatch ESP_LOGW(kLogTag, "Checksum mismatch: expected %d, got %d", received_checksum, calculated_checksum); @@ -372,9 +337,7 @@ namespace audio_wifi_config ClearBuffers(); decoded_text = result; return true; // Return success - } - else if (bit_buffer_.size() >= max_bit_buffer_size_) - { + } else if (bit_buffer_.size() >= max_bit_buffer_size_) { // If not end identifier and bit buffer is full, reset ClearBuffers(); ESP_LOGW(kLogTag, "Buffer overflow, clearing buffer"); @@ -388,19 +351,16 @@ namespace audio_wifi_config return false; } - std::vector AudioDataBuffer::ConvertBitsToBytes(const std::vector &bits) const - { + std::vector AudioDataBuffer::ConvertBitsToBytes(const std::vector &bits) const { std::vector bytes; // Ensure number of bits is a multiple of 8 size_t complete_bytes_count = bits.size() / 8; bytes.reserve(complete_bytes_count); - for (size_t i = 0; i < complete_bytes_count; ++i) - { + for (size_t i = 0; i < complete_bytes_count; ++i) { uint8_t byte_value = 0; - for (size_t j = 0; j < 8; ++j) - { + for (size_t j = 0; j < 8; ++j) { byte_value |= bits[i * 8 + j] << (7 - j); } bytes.push_back(byte_value); @@ -408,4 +368,4 @@ namespace audio_wifi_config return bytes; } -} \ No newline at end of file +} diff --git a/main/boards/common/afsk_demod.h b/main/boards/common/afsk_demod.h index 13b5bb9e..87b3805d 100644 --- a/main/boards/common/afsk_demod.h +++ b/main/boards/common/afsk_demod.h @@ -19,7 +19,8 @@ const size_t kWindowSize = 64; namespace audio_wifi_config { // Main function to receive WiFi credentials through audio signal - void ReceiveWifiCredentialsFromAudio(Application *app, WifiConfigurationAp *wifi_ap); + void ReceiveWifiCredentialsFromAudio(Application *app, WifiConfigurationAp *wifi_ap, Display *display, + size_t input_channels = 1); /** * Goertzel algorithm implementation for single frequency detection diff --git a/main/boards/common/wifi_board.cc b/main/boards/common/wifi_board.cc index 92ce68a9..a944b0f8 100644 --- a/main/boards/common/wifi_board.cc +++ b/main/boards/common/wifi_board.cc @@ -52,7 +52,14 @@ void WifiBoard::EnterWifiConfigMode() { application.Alert(Lang::Strings::WIFI_CONFIG_MODE, hint.c_str(), "", Lang::Sounds::P3_WIFICONFIG); #if CONFIG_USE_ACOUSTIC_WIFI_PROVISIONING - audio_wifi_config::ReceiveWifiCredentialsFromAudio(&application, &wifi_ap); + auto display = Board::GetInstance().GetDisplay(); + auto codec = Board::GetInstance().GetAudioCodec(); + int channel = 1; + if (codec) { + channel = codec->input_channels(); + } + ESP_LOGI(TAG, "Start receiving WiFi credentials from audio, input channels: %d", channel); + audio_wifi_config::ReceiveWifiCredentialsFromAudio(&application, &wifi_ap, display, channel); #endif // Wait forever until reset after configuration