From 6f5f5a0642f97967cbc7aafb7996d8204667be95 Mon Sep 17 00:00:00 2001 From: Terrence Date: Wed, 30 Oct 2024 06:58:29 +0800 Subject: [PATCH] use protocol 3 --- CMakeLists.txt | 2 +- main/Application.cc | 94 ++++++++++++++---- main/Application.h | 17 ++-- main/Board.cc | 4 + main/Board.h | 1 + main/CMakeLists.txt | 1 + main/Display.cc | 11 +- main/Ml307Board.cc | 33 ++++-- main/Ml307Board.h | 1 + main/SystemReset.cc | 4 + main/WakeWordDetect.cc | 10 +- main/WifiBoard.cc | 14 ++- main/WifiBoard.h | 1 + main/assets/err_pin.p3 | Bin 0 -> 3128 bytes main/assets/err_reg.p3 | Bin 0 -> 6707 bytes main/assets/err_wificonfig.p3 | Bin 0 -> 3038 bytes .../bread-compact-ml307/CompactMl307Board.cc | 4 + .../bread-compact-wifi/CompactWifiBoard.cc | 5 +- main/boards/kevin-box-0/KevinBoxBoard.cc | 35 +++++++ main/idf_component.yml | 10 +- main/main.cc | 4 - versions.py | 8 +- 22 files changed, 191 insertions(+), 68 deletions(-) create mode 100644 main/assets/err_pin.p3 create mode 100644 main/assets/err_reg.p3 create mode 100644 main/assets/err_wificonfig.p3 diff --git a/CMakeLists.txt b/CMakeLists.txt index a8e1247a..32efa58d 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.5.0") +set(PROJECT_VER "0.6.0") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(xiaozhi) diff --git a/main/Application.cc b/main/Application.cc index 19f03ae9..e67e01fa 100644 --- a/main/Application.cc +++ b/main/Application.cc @@ -14,6 +14,13 @@ #define TAG "Application" +extern const char p3_err_reg_start[] asm("_binary_err_reg_p3_start"); +extern const char p3_err_reg_end[] asm("_binary_err_reg_p3_end"); +extern const char p3_err_pin_start[] asm("_binary_err_pin_p3_start"); +extern const char p3_err_pin_end[] asm("_binary_err_pin_p3_end"); +extern const char p3_err_wificonfig_start[] asm("_binary_err_wificonfig_p3_start"); +extern const char p3_err_wificonfig_end[] asm("_binary_err_wificonfig_p3_end"); + Application::Application() : boot_button_((gpio_num_t)BOOT_BUTTON_GPIO), @@ -80,6 +87,41 @@ void Application::CheckNewVersion() { } } +void Application::Alert(const std::string&& title, const std::string&& message) { + ESP_LOGE(TAG, "Alert: %s, %s", title.c_str(), message.c_str()); + display_.ShowNotification(std::string(title + "\n" + message)); + + if (message == "PIN is not ready") { + PlayLocalFile(p3_err_pin_start, p3_err_pin_end - p3_err_pin_start); + } else if (message == "Configuring WiFi") { + PlayLocalFile(p3_err_wificonfig_start, p3_err_wificonfig_end - p3_err_wificonfig_start); + } else if (message == "Registration denied") { + PlayLocalFile(p3_err_reg_start, p3_err_reg_end - p3_err_reg_start); + } +} + +void Application::PlayLocalFile(const char* data, size_t size) { + ESP_LOGI(TAG, "PlayLocalFile: %zu bytes", size); + SetDecodeSampleRate(16000); + + { + std::lock_guard lock(mutex_); + auto packet = new AudioPacket(); + packet->type = kAudioPacketTypeStart; + audio_decode_queue_.push_back(packet); + } + + ParseBinaryProtocol3(data, size); + + { + std::lock_guard lock(mutex_); + auto packet = new AudioPacket(); + packet->type = kAudioPacketTypeStop; + audio_decode_queue_.push_back(packet); + cv_.notify_all(); + } +} + void Application::Start() { auto& builtin_led = BuiltinLed::GetInstance(); builtin_led.SetBlue(); @@ -370,15 +412,12 @@ void Application::SetChatState(ChatState state) { } } -BinaryProtocol* Application::AllocateBinaryProtocol(const uint8_t* payload, size_t payload_size) { - auto last_timestamp = 0; - auto protocol = (BinaryProtocol*)heap_caps_malloc(sizeof(BinaryProtocol) + payload_size, MALLOC_CAP_SPIRAM); - protocol->version = htons(PROTOCOL_VERSION); - protocol->type = htons(0); +BinaryProtocol3* Application::AllocateBinaryProtocol3(const uint8_t* payload, size_t payload_size) { + auto protocol = (BinaryProtocol3*)heap_caps_malloc(sizeof(BinaryProtocol3) + payload_size, MALLOC_CAP_SPIRAM); + protocol->type = 0; protocol->reserved = 0; - protocol->timestamp = htonl(last_timestamp); - protocol->payload_size = htonl(payload_size); - assert(sizeof(BinaryProtocol) == 16); + protocol->payload_size = htons(payload_size); + assert(sizeof(BinaryProtocol3) == 4UL); memcpy(protocol->payload, payload, payload_size); return protocol; } @@ -400,10 +439,10 @@ void Application::AudioEncodeTask() { // Encode audio data opus_encoder_.Encode(pcm, [this](const uint8_t* opus, size_t opus_size) { - auto protocol = AllocateBinaryProtocol(opus, opus_size); + auto protocol = AllocateBinaryProtocol3(opus, opus_size); Schedule([this, protocol, opus_size]() { if (ws_client_ && ws_client_->IsConnected()) { - if (!ws_client_->Send(protocol, sizeof(BinaryProtocol) + opus_size, true)) { + if (!ws_client_->Send(protocol, sizeof(BinaryProtocol3) + opus_size, true)) { ESP_LOGE(TAG, "Failed to send audio data"); } } @@ -470,7 +509,11 @@ void Application::HandleAudioPacket(AudioPacket* packet) { break; case kAudioPacketTypeStop: Schedule([this]() { - SetChatState(kChatStateListening); + if (ws_client_ && ws_client_->IsConnected()) { + SetChatState(kChatStateListening); + } else { + SetChatState(kChatStateIdle); + } }); break; case kAudioPacketTypeSentenceStart: @@ -517,6 +560,23 @@ void Application::SetDecodeSampleRate(int sample_rate) { } } +void Application::ParseBinaryProtocol3(const char* data, size_t size) { + for (const char* p = data; p < data + size; ) { + auto protocol = (BinaryProtocol3*)p; + p += sizeof(BinaryProtocol3); + + auto packet = new AudioPacket(); + packet->type = kAudioPacketTypeData; + auto payload_size = ntohs(protocol->payload_size); + packet->opus.resize(payload_size); + memcpy(packet->opus.data(), protocol->payload, payload_size); + p += payload_size; + + std::lock_guard lock(mutex_); + audio_decode_queue_.push_back(packet); + } +} + void Application::StartWebSocketClient() { if (ws_client_ != nullptr) { ESP_LOGW(TAG, "WebSocket client already exists"); @@ -545,17 +605,7 @@ void Application::StartWebSocketClient() { ws_client_->OnData([this](const char* data, size_t len, bool binary) { if (binary) { - auto protocol = (BinaryProtocol*)data; - - auto packet = new AudioPacket(); - packet->type = kAudioPacketTypeData; - packet->timestamp = ntohl(protocol->timestamp); - auto payload_size = ntohl(protocol->payload_size); - packet->opus.resize(payload_size); - memcpy(packet->opus.data(), protocol->payload, payload_size); - - std::lock_guard lock(mutex_); - audio_decode_queue_.push_back(packet); + ParseBinaryProtocol3(data, len); cv_.notify_all(); } else { // Parse JSON data diff --git a/main/Application.h b/main/Application.h index b2e1bc2b..e0517c11 100644 --- a/main/Application.h +++ b/main/Application.h @@ -28,13 +28,11 @@ #define DETECTION_RUNNING 1 #define COMMUNICATION_RUNNING 2 -#define PROTOCOL_VERSION 2 -struct BinaryProtocol { - uint16_t version; - uint16_t type; - uint32_t reserved; - uint32_t timestamp; - uint32_t payload_size; +#define PROTOCOL_VERSION 3 +struct BinaryProtocol3 { + uint8_t type; + uint8_t reserved; + uint16_t payload_size; uint8_t payload[]; } __attribute__((packed)); @@ -78,6 +76,7 @@ public: Display& GetDisplay() { return display_; } void Schedule(std::function callback); void SetChatState(ChatState state); + void Alert(const std::string&& title, const std::string&& message); // 删除拷贝构造函数和赋值运算符 Application(const Application&) = delete; @@ -128,7 +127,8 @@ private: StackType_t* check_new_version_task_stack_ = nullptr; void MainLoop(); - BinaryProtocol* AllocateBinaryProtocol(const uint8_t* payload, size_t payload_size); + BinaryProtocol3* AllocateBinaryProtocol3(const uint8_t* payload, size_t payload_size); + void ParseBinaryProtocol3(const char* data, size_t size); void SetDecodeSampleRate(int sample_rate); void StartWebSocketClient(); void CheckNewVersion(); @@ -136,6 +136,7 @@ private: void AudioEncodeTask(); void AudioPlayTask(); void HandleAudioPacket(AudioPacket* packet); + void PlayLocalFile(const char* data, size_t size); }; #endif // _APPLICATION_H_ diff --git a/main/Board.cc b/main/Board.cc index 269f9d3c..099419c5 100644 --- a/main/Board.cc +++ b/main/Board.cc @@ -2,3 +2,7 @@ #include // static const char *TAG = "Board"; + +bool Board::GetBatteryVoltage(int &voltage) { + return false; +} diff --git a/main/Board.h b/main/Board.h index 5e958cab..97f2c307 100644 --- a/main/Board.h +++ b/main/Board.h @@ -25,6 +25,7 @@ public: virtual Http* CreateHttp() = 0; virtual WebSocket* CreateWebSocket() = 0; virtual bool GetNetworkState(std::string& network_name, int& signal_quality, std::string& signal_quality_text) = 0; + virtual bool GetBatteryVoltage(int &voltage); virtual std::string GetJson() = 0; protected: diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 4376166a..8254c67d 100755 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -45,6 +45,7 @@ if(CONFIG_USE_AFE_SR) endif() idf_component_register(SRCS ${SOURCES} + EMBED_FILES "assets/err_reg.p3" "assets/err_pin.p3" "assets/err_wificonfig.p3" INCLUDE_DIRS ${INCLUDE_DIRS} ) diff --git a/main/Display.cc b/main/Display.cc index dfaba1e0..0aedfcc3 100644 --- a/main/Display.cc +++ b/main/Display.cc @@ -220,8 +220,15 @@ void Display::UpdateDisplay() { if (!board.GetNetworkState(network_name, signal_quality, signal_quality_text)) { text = "No network"; } else { - ESP_LOGI(TAG, "%s CSQ: %d", network_name.c_str(), signal_quality); - text = network_name + "\n" + signal_quality_text + " (" + std::to_string(signal_quality) + ")"; + text = network_name + "\n" + signal_quality_text; + if (std::abs(signal_quality) != 99) { + text += " (" + std::to_string(signal_quality) + ")"; + } + } + + int battery_voltage; + if (board.GetBatteryVoltage(battery_voltage)) { + text += "\n" + std::to_string(battery_voltage) + "mV"; } SetText(text); } diff --git a/main/Ml307Board.cc b/main/Ml307Board.cc index b2294d81..2be817cd 100644 --- a/main/Ml307Board.cc +++ b/main/Ml307Board.cc @@ -30,28 +30,38 @@ static std::string csq_to_string(int csq) { Ml307Board::Ml307Board() : modem_(ML307_TX_PIN, ML307_RX_PIN, 4096) { } -void Ml307Board::StartModem() { +void Ml307Board::StartNetwork() { auto& application = Application::GetInstance(); auto& display = application.GetDisplay(); - modem_.SetDebug(false); - modem_.SetBaudRate(921600); + display.SetText(std::string("Wait for network\n")); + int result = modem_.WaitForNetworkReady(); + if (result == -1) { + application.Alert("Error", "PIN is not ready"); + } else if (result == -2) { + application.Alert("Error", "Registration denied"); + } + // Print the ML307 modem information std::string module_name = modem_.GetModuleName(); - ESP_LOGI(TAG, "ML307 Module: %s", module_name.c_str()); - display.SetText(std::string("Wait for network\n") + module_name); - modem_.ResetConnections(); - modem_.WaitForNetworkReady(); - std::string imei = modem_.GetImei(); std::string iccid = modem_.GetIccid(); + ESP_LOGI(TAG, "ML307 Module: %s", module_name.c_str()); ESP_LOGI(TAG, "ML307 IMEI: %s", imei.c_str()); ESP_LOGI(TAG, "ML307 ICCID: %s", iccid.c_str()); +} +void Ml307Board::StartModem() { + modem_.SetDebug(false); + modem_.SetBaudRate(921600); + StartNetwork(); + + auto& application = Application::GetInstance(); // If low power, the material ready event will be triggered by the modem because of a reset - modem_.OnMaterialReady([&application]() { + modem_.OnMaterialReady([this, &application]() { ESP_LOGI(TAG, "ML307 material ready"); - application.Schedule([&application]() { + application.Schedule([this, &application]() { application.SetChatState(kChatStateIdle); + StartNetwork(); }); }); } @@ -74,6 +84,9 @@ WebSocket* Ml307Board::CreateWebSocket() { } bool Ml307Board::GetNetworkState(std::string& network_name, int& signal_quality, std::string& signal_quality_text) { + if (!modem_.network_ready()) { + return false; + } network_name = modem_.GetCarrierName(); signal_quality = modem_.GetCsq(); signal_quality_text = csq_to_string(signal_quality); diff --git a/main/Ml307Board.h b/main/Ml307Board.h index 18cd572f..a069a0e5 100644 --- a/main/Ml307Board.h +++ b/main/Ml307Board.h @@ -9,6 +9,7 @@ protected: Ml307AtModem modem_; void StartModem(); + void StartNetwork(); public: Ml307Board(); diff --git a/main/SystemReset.cc b/main/SystemReset.cc index 94d2017a..bb206c8c 100644 --- a/main/SystemReset.cc +++ b/main/SystemReset.cc @@ -41,6 +41,10 @@ void SystemReset::ResetNvsFlash() { if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to erase NVS flash"); } + ret = nvs_flash_init(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize NVS flash"); + } } void SystemReset::ResetToFactory() { diff --git a/main/WakeWordDetect.cc b/main/WakeWordDetect.cc index 7dc147b0..582c02b4 100644 --- a/main/WakeWordDetect.cc +++ b/main/WakeWordDetect.cc @@ -180,14 +180,12 @@ void WakeWordDetect::EncodeWakeWordData() { for (auto& pcm: this_->wake_word_pcm_) { encoder->Encode(pcm, [this_, &offset](const uint8_t* opus, size_t opus_size) { - size_t protocol_size = sizeof(BinaryProtocol) + opus_size; + size_t protocol_size = sizeof(BinaryProtocol3) + opus_size; if (offset + protocol_size < this_->wake_word_opus_.size()) { - auto protocol = (BinaryProtocol*)(&this_->wake_word_opus_[offset]); - protocol->version = htons(PROTOCOL_VERSION); - protocol->type = htons(0); + auto protocol = (BinaryProtocol3*)(&this_->wake_word_opus_[offset]); + protocol->type = 0; protocol->reserved = 0; - protocol->timestamp = 0; - protocol->payload_size = htonl(opus_size); + protocol->payload_size = htons(opus_size); memcpy(protocol->payload, opus, opus_size); offset += protocol_size; } diff --git a/main/WifiBoard.cc b/main/WifiBoard.cc index fa657ba6..b3b6a7cf 100644 --- a/main/WifiBoard.cc +++ b/main/WifiBoard.cc @@ -39,16 +39,13 @@ void WifiBoard::StartWifi() { display.SetText(std::string("Connect to WiFi\n") + wifi_station.GetSsid()); wifi_station.Start(); if (!wifi_station.IsConnected()) { + application.Alert("Info", "Configuring WiFi"); builtin_led.SetBlue(); builtin_led.Blink(1000, 500); auto& wifi_ap = WifiConfigurationAp::GetInstance(); wifi_ap.SetSsidPrefix("Xiaozhi"); - display.SetText(wifi_ap.GetSsid() + "\n" + wifi_ap.GetWebServerUrl()); wifi_ap.Start(); - // Wait until the WiFi configuration is finished - while (true) { - vTaskDelay(pdMS_TO_TICKS(1000)); - } + wifi_config_mode_ = true; } } @@ -71,6 +68,13 @@ WebSocket* WifiBoard::CreateWebSocket() { } bool WifiBoard::GetNetworkState(std::string& network_name, int& signal_quality, std::string& signal_quality_text) { + if (wifi_config_mode_) { + auto& wifi_ap = WifiConfigurationAp::GetInstance(); + network_name = wifi_ap.GetSsid(); + signal_quality = -99; + signal_quality_text = wifi_ap.GetWebServerUrl(); + return true; + } auto& wifi_station = WifiStation::GetInstance(); if (!wifi_station.IsConnected()) { return false; diff --git a/main/WifiBoard.h b/main/WifiBoard.h index 4c8b2ced..9673de64 100644 --- a/main/WifiBoard.h +++ b/main/WifiBoard.h @@ -5,6 +5,7 @@ class WifiBoard : public Board { protected: + bool wifi_config_mode_ = false; virtual void StartWifi(); public: diff --git a/main/assets/err_pin.p3 b/main/assets/err_pin.p3 new file mode 100644 index 0000000000000000000000000000000000000000..f00ce48b544e6f4dd5e7af1502e600381efcb4db GIT binary patch literal 3128 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 literal 0 HcmV?d00001 diff --git a/main/assets/err_reg.p3 b/main/assets/err_reg.p3 new file mode 100644 index 0000000000000000000000000000000000000000..af60b6800f64a4aa8a5ff1699346c0e573fd30c6 GIT binary patch literal 6707 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 literal 0 HcmV?d00001 diff --git a/main/assets/err_wificonfig.p3 b/main/assets/err_wificonfig.p3 new file mode 100644 index 0000000000000000000000000000000000000000..54d0db58717a41eb538b5c0082a9e90fb0f17c60 GIT binary patch literal 3038 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 MIXaRP|NjsE1J<^`e*gdg literal 0 HcmV?d00001 diff --git a/main/boards/bread-compact-ml307/CompactMl307Board.cc b/main/boards/bread-compact-ml307/CompactMl307Board.cc index 50a9e778..4495b415 100644 --- a/main/boards/bread-compact-ml307/CompactMl307Board.cc +++ b/main/boards/bread-compact-ml307/CompactMl307Board.cc @@ -1,4 +1,5 @@ #include "Ml307Board.h" +#include "SystemReset.h" #include #define TAG "CompactMl307Board" @@ -7,6 +8,9 @@ class CompactMl307Board : public Ml307Board { public: virtual void Initialize() override { ESP_LOGI(TAG, "Initializing CompactMl307Board"); + // Check if the reset button is pressed + SystemReset::GetInstance().CheckButtons(); + Ml307Board::Initialize(); } diff --git a/main/boards/bread-compact-wifi/CompactWifiBoard.cc b/main/boards/bread-compact-wifi/CompactWifiBoard.cc index 44fce62e..5213e468 100644 --- a/main/boards/bread-compact-wifi/CompactWifiBoard.cc +++ b/main/boards/bread-compact-wifi/CompactWifiBoard.cc @@ -1,5 +1,5 @@ #include "WifiBoard.h" - +#include "SystemReset.h" #include #define TAG "CompactWifiBoard" @@ -8,6 +8,9 @@ class CompactWifiBoard : public WifiBoard { public: virtual void Initialize() override { ESP_LOGI(TAG, "Initializing CompactWifiBoard"); + // Check if the reset button is pressed + SystemReset::GetInstance().CheckButtons(); + WifiBoard::Initialize(); } diff --git a/main/boards/kevin-box-0/KevinBoxBoard.cc b/main/boards/kevin-box-0/KevinBoxBoard.cc index 7402e384..5f1f6c5b 100644 --- a/main/boards/kevin-box-0/KevinBoxBoard.cc +++ b/main/boards/kevin-box-0/KevinBoxBoard.cc @@ -4,11 +4,17 @@ #include #include #include +#include +#include +#include static const char *TAG = "KevinBoxBoard"; class KevinBoxBoard : public Ml307Board { private: + adc_oneshot_unit_handle_t adc1_handle_; + adc_cali_handle_t adc1_cali_handle_; + void MountStorage() { // Mount the storage partition esp_vfs_spiffs_conf_t conf = { @@ -32,9 +38,31 @@ private: gpio_config(&ml307_enable_config); gpio_set_level(GPIO_NUM_15, 1); } + + virtual void InitializeADC() { + adc_oneshot_unit_init_cfg_t init_config1 = {}; + init_config1.unit_id = ADC_UNIT_1; + ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle_)); + + //-------------ADC1 Config---------------// + adc_oneshot_chan_cfg_t config = { + .atten = ADC_ATTEN_DB_12, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle_, ADC_CHANNEL_0, &config)); + + adc_cali_curve_fitting_config_t cali_config = { + .unit_id = ADC_UNIT_1, + .chan = ADC_CHANNEL_0, + .atten = ADC_ATTEN_DB_12, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + ESP_ERROR_CHECK(adc_cali_create_scheme_curve_fitting(&cali_config, &adc1_cali_handle_)); + } public: virtual void Initialize() override { ESP_LOGI(TAG, "Initializing KevinBoxBoard"); + InitializeADC(); MountStorage(); Enable4GModule(); Ml307Board::Initialize(); @@ -43,6 +71,13 @@ public: virtual AudioDevice* CreateAudioDevice() override { return new BoxAudioDevice(); } + + virtual bool GetBatteryVoltage(int &voltage) override { + int adc_reading; + ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle_, ADC_CHANNEL_0, &adc_reading)); + ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle_, adc_reading, &voltage)); + return true; + } }; DECLARE_BOARD(KevinBoxBoard); diff --git a/main/idf_component.yml b/main/idf_component.yml index eec58b4e..2c08d9eb 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -1,14 +1,14 @@ ## IDF Component Manager Manifest File dependencies: - 78/esp-wifi-connect: "^1.2.0" - 78/esp-opus-encoder: "^1.0.2" - 78/esp-ml307: "^1.2.2" + 78/esp-wifi-connect: "~1.2.0" + 78/esp-opus-encoder: "~1.0.2" + 78/esp-ml307: "~1.3.0" espressif/led_strip: "^2.4.1" espressif/esp_codec_dev: "^1.3.1" espressif/esp-sr: "^1.9.0" espressif/button: "^3.3.1" - lvgl/lvgl: "^8.4.0" - esp_lvgl_port: "^2.4.1" + lvgl/lvgl: "~8.4.0" + esp_lvgl_port: "~2.4.1" ## Required IDF version idf: version: ">=5.3" diff --git a/main/main.cc b/main/main.cc index 020dc7d4..9ac9f70a 100755 --- a/main/main.cc +++ b/main/main.cc @@ -7,15 +7,11 @@ #include "Application.h" #include "SystemInfo.h" -#include "SystemReset.h" #define TAG "main" extern "C" void app_main(void) { - // Check if the reset button is pressed - SystemReset::GetInstance().CheckButtons(); - // Initialize the default event loop ESP_ERROR_CHECK(esp_event_loop_create_default()); diff --git a/versions.py b/versions.py index b68e11fa..e1a9eb00 100644 --- a/versions.py +++ b/versions.py @@ -56,12 +56,12 @@ def get_app_desc(data): def get_board_name(folder): basename = os.path.basename(folder) if basename.startswith("v0.2"): - return "simple" - if basename.startswith("v0.3") or basename.startswith("v0.4") or basename.startswith("v0.5"): + return "bread-simple" + if basename.startswith("v0.3") or basename.startswith("v0.4") or basename.startswith("v0.5") or basename.startswith("v0.6"): if "ML307" in basename: - return "compact.4g" + return "bread-compact-ml307" else: - return "compact.wifi" + return "bread-compact-wifi" raise Exception(f"Unknown board name: {basename}") def read_binary(dir_path):