diff --git a/CMakeLists.txt b/CMakeLists.txt index a748bedb..e4321830 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.4.0") +set(PROJECT_VER "0.4.1") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(xiaozhi) diff --git a/main/Application.cc b/main/Application.cc index 89dc597b..b20494cc 100644 --- a/main/Application.cc +++ b/main/Application.cc @@ -44,7 +44,6 @@ Application::Application() firmware_upgrade_.SetCheckVersionUrl(CONFIG_OTA_VERSION_URL); firmware_upgrade_.SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str()); - firmware_upgrade_.SetPostData(SystemInfo::GetJsonString()); } Application::~Application() { @@ -156,8 +155,10 @@ void Application::Start() { ml307_at_modem_.ResetConnections(); ml307_at_modem_.WaitForNetworkReady(); - ESP_LOGI(TAG, "ML307 IMEI: %s", ml307_at_modem_.GetImei().c_str()); - ESP_LOGI(TAG, "ML307 ICCID: %s", ml307_at_modem_.GetIccid().c_str()); + std::string imei = ml307_at_modem_.GetImei(); + std::string iccid = ml307_at_modem_.GetIccid(); + ESP_LOGI(TAG, "ML307 IMEI: %s", imei.c_str()); + ESP_LOGI(TAG, "ML307 ICCID: %s", iccid.c_str()); // If low power, the material ready event will be triggered by the modem because of a reset ml307_at_modem_.OnMaterialReady([this]() { @@ -166,6 +167,17 @@ void Application::Start() { SetChatState(kChatStateIdle); }); }); + + // Set the board type for OTA + std::string carrier_name = ml307_at_modem_.GetCarrierName(); + int csq = ml307_at_modem_.GetCsq(); + std::string board_json = std::string("{\"type\":\"compact.4g\","); + board_json += "\"revision\":\"" + module_name + "\","; + board_json += "\"carrier\":\"" + carrier_name + "\","; + board_json += "\"csq\":\"" + std::to_string(csq) + "\","; + board_json += "\"imei\":\"" + imei + "\","; + board_json += "\"iccid\":\"" + iccid + "\"}"; + firmware_upgrade_.SetBoardJson(board_json); #else // Try to connect to WiFi, if failed, launch the WiFi configuration AP auto& wifi_station = WifiStation::GetInstance(); @@ -186,6 +198,15 @@ void Application::Start() { wifi_ap.Start(); return; } + + // Set the board type for OTA + std::string board_json = std::string("{\"type\":\"compact.wifi\","); + board_json += "\"ssid\":\"" + wifi_station.GetSsid() + "\","; + board_json += "\"rssi\":" + std::to_string(wifi_station.GetRssi()) + ","; + board_json += "\"channel\":" + std::to_string(wifi_station.GetChannel()) + ","; + board_json += "\"ip\":\"" + wifi_station.GetIpAddress() + "\","; + board_json += "\"mac\":\"" + SystemInfo::GetMacAddress() + "\"}"; + firmware_upgrade_.SetBoardJson(board_json); #endif audio_device_.Initialize(); @@ -646,8 +667,8 @@ void Application::StartWebSocketClient() { } #endif ws_client_->SetHeader("Authorization", token.c_str()); - ws_client_->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str()); ws_client_->SetHeader("Protocol-Version", std::to_string(PROTOCOL_VERSION).c_str()); + ws_client_->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str()); ws_client_->OnConnected([this]() { ESP_LOGI(TAG, "Websocket connected"); diff --git a/main/FirmwareUpgrade.cc b/main/FirmwareUpgrade.cc index 56f67aba..3fd8a40c 100644 --- a/main/FirmwareUpgrade.cc +++ b/main/FirmwareUpgrade.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -24,10 +25,6 @@ void FirmwareUpgrade::SetCheckVersionUrl(std::string check_version_url) { check_version_url_ = check_version_url; } -void FirmwareUpgrade::SetPostData(const std::string& post_data) { - post_data_ = post_data; -} - void FirmwareUpgrade::SetHeader(const std::string& key, const std::string& value) { headers_[key] = value; } @@ -45,13 +42,9 @@ void FirmwareUpgrade::CheckVersion() { http_.SetHeader(header.first, header.second); } - if (post_data_.empty()) { - http_.Open("GET", check_version_url_); - } else { - http_.SetHeader("Content-Type", "application/json"); - http_.SetContent(post_data_); - http_.Open("POST", check_version_url_); - } + http_.SetHeader("Content-Type", "application/json"); + http_.SetContent(GetPostData()); + http_.Open("POST", check_version_url_); auto response = http_.GetBody(); http_.Close(); @@ -257,3 +250,99 @@ bool FirmwareUpgrade::IsNewVersionAvailable(const std::string& currentVersion, c return newer.size() > current.size(); } + +void FirmwareUpgrade::SetBoardJson(const std::string& board_json) { + board_json_ = board_json; +} + +std::string FirmwareUpgrade::GetPostData() { + /* + { + "flash_size": 4194304, + "psram_size": 0, + "minimum_free_heap_size": 123456, + "mac_address": "00:00:00:00:00:00", + "chip_model_name": "esp32s3", + "chip_info": { + "model": 1, + "cores": 2, + "revision": 0, + "features": 0 + }, + "application": { + "name": "my-app", + "version": "1.0.0", + "compile_time": "2021-01-01T00:00:00Z" + "idf_version": "4.2-dev" + "elf_sha256": "" + }, + "partition_table": [ + "app": { + "label": "app", + "type": 1, + "subtype": 2, + "address": 0x10000, + "size": 0x100000 + } + ], + "ota": { + "label": "ota_0" + } + } + */ + std::string json = "{"; + json += "\"flash_size\":" + std::to_string(SystemInfo::GetFlashSize()) + ","; + json += "\"minimum_free_heap_size\":" + std::to_string(SystemInfo::GetMinimumFreeHeapSize()) + ","; + json += "\"mac_address\":\"" + SystemInfo::GetMacAddress() + "\","; + json += "\"chip_model_name\":\"" + SystemInfo::GetChipModelName() + "\","; + json += "\"chip_info\":{"; + + esp_chip_info_t chip_info; + esp_chip_info(&chip_info); + json += "\"model\":" + std::to_string(chip_info.model) + ","; + json += "\"cores\":" + std::to_string(chip_info.cores) + ","; + json += "\"revision\":" + std::to_string(chip_info.revision) + ","; + json += "\"features\":" + std::to_string(chip_info.features); + json += "},"; + + json += "\"application\":{"; + auto app_desc = esp_app_get_description(); + json += "\"name\":\"" + std::string(app_desc->project_name) + "\","; + json += "\"version\":\"" + std::string(app_desc->version) + "\","; + json += "\"compile_time\":\"" + std::string(app_desc->date) + "T" + std::string(app_desc->time) + "Z\","; + json += "\"idf_version\":\"" + std::string(app_desc->idf_ver) + "\","; + + char sha256_str[65]; + for (int i = 0; i < 32; i++) { + snprintf(sha256_str + i * 2, sizeof(sha256_str) - i * 2, "%02x", app_desc->app_elf_sha256[i]); + } + json += "\"elf_sha256\":\"" + std::string(sha256_str) + "\""; + json += "},"; + + json += "\"partition_table\": ["; + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL); + while (it) { + const esp_partition_t *partition = esp_partition_get(it); + json += "{"; + json += "\"label\":\"" + std::string(partition->label) + "\","; + json += "\"type\":" + std::to_string(partition->type) + ","; + json += "\"subtype\":" + std::to_string(partition->subtype) + ","; + json += "\"address\":" + std::to_string(partition->address) + ","; + json += "\"size\":" + std::to_string(partition->size); + json += "},"; + it = esp_partition_next(it); + } + json.pop_back(); // Remove the last comma + json += "],"; + + json += "\"ota\":{"; + auto ota_partition = esp_ota_get_running_partition(); + json += "\"label\":\"" + std::string(ota_partition->label) + "\""; + json += "},"; + + json += "\"board\":" + board_json_; + + // Close the JSON object + json += "}"; + return json; +} diff --git a/main/FirmwareUpgrade.h b/main/FirmwareUpgrade.h index 1fe86c80..a7f282f6 100644 --- a/main/FirmwareUpgrade.h +++ b/main/FirmwareUpgrade.h @@ -12,8 +12,8 @@ public: FirmwareUpgrade(Http& http); ~FirmwareUpgrade(); + void SetBoardJson(const std::string& board_json); void SetCheckVersionUrl(std::string check_version_url); - void SetPostData(const std::string& post_data); void SetHeader(const std::string& key, const std::string& value); void CheckVersion(); bool HasNewVersion() { return has_new_version_; } @@ -26,13 +26,14 @@ private: bool has_new_version_ = false; std::string firmware_version_; std::string firmware_url_; - std::string post_data_; + std::string board_json_; std::map headers_; void Upgrade(const std::string& firmware_url); std::function upgrade_callback_; std::vector ParseVersion(const std::string& version); bool IsNewVersionAvailable(const std::string& currentVersion, const std::string& newVersion); + std::string GetPostData(); }; #endif // _FIRMWARE_UPGRADE_H diff --git a/main/SystemInfo.cc b/main/SystemInfo.cc index f62393fc..c2462590 100644 --- a/main/SystemInfo.cc +++ b/main/SystemInfo.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -41,96 +40,6 @@ std::string SystemInfo::GetChipModelName() { return std::string(CONFIG_IDF_TARGET); } -std::string SystemInfo::GetJsonString() { - /* - { - "flash_size": 4194304, - "psram_size": 0, - "minimum_free_heap_size": 123456, - "mac_address": "00:00:00:00:00:00", - "chip_model_name": "esp32s3", - "chip_info": { - "model": 1, - "cores": 2, - "revision": 0, - "features": 0 - }, - "application": { - "name": "my-app", - "version": "1.0.0", - "compile_time": "2021-01-01T00:00:00Z" - "idf_version": "4.2-dev" - "elf_sha256": "" - }, - "partition_table": [ - "app": { - "label": "app", - "type": 1, - "subtype": 2, - "address": 0x10000, - "size": 0x100000 - } - ], - "ota": { - "label": "ota_0" - } - } - */ - std::string json = "{"; - json += "\"flash_size\":" + std::to_string(GetFlashSize()) + ","; - json += "\"minimum_free_heap_size\":" + std::to_string(GetMinimumFreeHeapSize()) + ","; - json += "\"mac_address\":\"" + GetMacAddress() + "\","; - json += "\"chip_model_name\":\"" + GetChipModelName() + "\","; - json += "\"chip_info\":{"; - - esp_chip_info_t chip_info; - esp_chip_info(&chip_info); - json += "\"model\":" + std::to_string(chip_info.model) + ","; - json += "\"cores\":" + std::to_string(chip_info.cores) + ","; - json += "\"revision\":" + std::to_string(chip_info.revision) + ","; - json += "\"features\":" + std::to_string(chip_info.features); - json += "},"; - - json += "\"application\":{"; - auto app_desc = esp_app_get_description(); - json += "\"name\":\"" + std::string(app_desc->project_name) + "\","; - json += "\"version\":\"" + std::string(app_desc->version) + "\","; - json += "\"compile_time\":\"" + std::string(app_desc->date) + "T" + std::string(app_desc->time) + "Z\","; - json += "\"idf_version\":\"" + std::string(app_desc->idf_ver) + "\","; - - char sha256_str[65]; - for (int i = 0; i < 32; i++) { - snprintf(sha256_str + i * 2, sizeof(sha256_str) - i * 2, "%02x", app_desc->app_elf_sha256[i]); - } - json += "\"elf_sha256\":\"" + std::string(sha256_str) + "\""; - json += "},"; - - json += "\"partition_table\": ["; - esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL); - while (it) { - const esp_partition_t *partition = esp_partition_get(it); - json += "{"; - json += "\"label\":\"" + std::string(partition->label) + "\","; - json += "\"type\":" + std::to_string(partition->type) + ","; - json += "\"subtype\":" + std::to_string(partition->subtype) + ","; - json += "\"address\":" + std::to_string(partition->address) + ","; - json += "\"size\":" + std::to_string(partition->size); - json += "},"; - it = esp_partition_next(it); - } - json.pop_back(); // Remove the last comma - json += "],"; - - json += "\"ota\":{"; - auto ota_partition = esp_ota_get_running_partition(); - json += "\"label\":\"" + std::string(ota_partition->label) + "\""; - json += "}"; - - // Close the JSON object - json += "}"; - return json; -} - esp_err_t SystemInfo::PrintRealTimeStats(TickType_t xTicksToWait) { #define ARRAY_SIZE_OFFSET 5 TaskStatus_t *start_array = NULL, *end_array = NULL; diff --git a/main/SystemInfo.h b/main/SystemInfo.h index a750bcf6..54d2c3e4 100644 --- a/main/SystemInfo.h +++ b/main/SystemInfo.h @@ -13,7 +13,6 @@ public: static size_t GetFreeHeapSize(); static std::string GetMacAddress(); static std::string GetChipModelName(); - static std::string GetJsonString(); static esp_err_t PrintRealTimeStats(TickType_t xTicksToWait); }; diff --git a/pack.py b/pack.py deleted file mode 100644 index 00194a78..00000000 --- a/pack.py +++ /dev/null @@ -1,68 +0,0 @@ -#! /usr/bin/env python3 - -import csv -import os - -# 例如:1000, 0x1000, 1M -def read_value(text): - text = text.strip() - if text.endswith('K'): - return int(text[:-1]) * 1024 - elif text.endswith('M'): - return int(text[:-1]) * 1024 * 1024 - else: - if text.startswith('0x'): - return int(text, 16) - else: - return int(text) - - -def write_bin(image_data, offset, file_path, max_size=None): - # Read file_path and write to image_data - with open(file_path, 'rb') as f: - data = f.read() - if max_size is not None: - assert len(data) <= max_size, f"Data from {file_path} is too large" - image_data[offset:offset+len(data)] = data - print(f"Write {os.path.basename(file_path)} to 0x{offset:08X} with size 0x{len(data):08X}") - - -''' -根据 partitions.csv 文件,把 bin 文件打包成一个 4MB 的 image 文件,方便烧录 -''' -def pack_firmware_image(): - # Create a 4MB image filled with 0xFF - image_size = 4 * 1024 * 1024 - image_data = bytearray([0xFF] * image_size) - - build_dir = os.path.join(os.path.dirname(__file__), 'build') - write_bin(image_data, 0, os.path.join(build_dir, 'bootloader', 'bootloader.bin')) - write_bin(image_data, 0x8000, os.path.join(build_dir, 'partition_table', 'partition-table.bin')) - - # 读取 partitions.csv 文件 - with open('partitions.csv', 'r') as f: - reader = csv.reader(f) - for row in reader: - if row[0] == 'model': - file_path = os.path.join(build_dir, 'srmodels', 'srmodels.bin') - elif row[0] == 'factory': - file_path = os.path.join(build_dir, 'xiaozhi.bin') - else: - continue - - offset = read_value(row[3]) - size = read_value(row[4]) - write_bin(image_data, offset, file_path, size) - - # 写入 image 文件 - output_path = os.path.join(build_dir, 'xiaozhi.img') - with open(output_path, 'wb') as f: - f.write(image_data) - print(f"Image file {output_path} created with size 0x{len(image_data):08X}") - - # Compress image with zip without directory - os.system(f"zip -j {output_path}.zip {output_path}") - - -if __name__ == '__main__': - pack_firmware_image()