update to 0.4.1

This commit is contained in:
Terrence
2024-10-25 12:29:23 +08:00
parent 357cd95693
commit 32a5977fcc
7 changed files with 129 additions and 178 deletions

View File

@@ -4,7 +4,7 @@
# CMakeLists in this exact order for cmake to work correctly # CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16) 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) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(xiaozhi) project(xiaozhi)

View File

@@ -44,7 +44,6 @@ Application::Application()
firmware_upgrade_.SetCheckVersionUrl(CONFIG_OTA_VERSION_URL); firmware_upgrade_.SetCheckVersionUrl(CONFIG_OTA_VERSION_URL);
firmware_upgrade_.SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str()); firmware_upgrade_.SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str());
firmware_upgrade_.SetPostData(SystemInfo::GetJsonString());
} }
Application::~Application() { Application::~Application() {
@@ -156,8 +155,10 @@ void Application::Start() {
ml307_at_modem_.ResetConnections(); ml307_at_modem_.ResetConnections();
ml307_at_modem_.WaitForNetworkReady(); ml307_at_modem_.WaitForNetworkReady();
ESP_LOGI(TAG, "ML307 IMEI: %s", ml307_at_modem_.GetImei().c_str()); std::string imei = ml307_at_modem_.GetImei();
ESP_LOGI(TAG, "ML307 ICCID: %s", ml307_at_modem_.GetIccid().c_str()); 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 // If low power, the material ready event will be triggered by the modem because of a reset
ml307_at_modem_.OnMaterialReady([this]() { ml307_at_modem_.OnMaterialReady([this]() {
@@ -166,6 +167,17 @@ void Application::Start() {
SetChatState(kChatStateIdle); 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 #else
// Try to connect to WiFi, if failed, launch the WiFi configuration AP // Try to connect to WiFi, if failed, launch the WiFi configuration AP
auto& wifi_station = WifiStation::GetInstance(); auto& wifi_station = WifiStation::GetInstance();
@@ -186,6 +198,15 @@ void Application::Start() {
wifi_ap.Start(); wifi_ap.Start();
return; 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 #endif
audio_device_.Initialize(); audio_device_.Initialize();
@@ -646,8 +667,8 @@ void Application::StartWebSocketClient() {
} }
#endif #endif
ws_client_->SetHeader("Authorization", token.c_str()); 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("Protocol-Version", std::to_string(PROTOCOL_VERSION).c_str());
ws_client_->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str());
ws_client_->OnConnected([this]() { ws_client_->OnConnected([this]() {
ESP_LOGI(TAG, "Websocket connected"); ESP_LOGI(TAG, "Websocket connected");

View File

@@ -6,6 +6,7 @@
#include <esp_http_client.h> #include <esp_http_client.h>
#include <esp_ota_ops.h> #include <esp_ota_ops.h>
#include <esp_app_format.h> #include <esp_app_format.h>
#include <esp_chip_info.h>
#include <vector> #include <vector>
#include <sstream> #include <sstream>
@@ -24,10 +25,6 @@ void FirmwareUpgrade::SetCheckVersionUrl(std::string check_version_url) {
check_version_url_ = 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) { void FirmwareUpgrade::SetHeader(const std::string& key, const std::string& value) {
headers_[key] = value; headers_[key] = value;
} }
@@ -45,13 +42,9 @@ void FirmwareUpgrade::CheckVersion() {
http_.SetHeader(header.first, header.second); http_.SetHeader(header.first, header.second);
} }
if (post_data_.empty()) { http_.SetHeader("Content-Type", "application/json");
http_.Open("GET", check_version_url_); http_.SetContent(GetPostData());
} else { http_.Open("POST", check_version_url_);
http_.SetHeader("Content-Type", "application/json");
http_.SetContent(post_data_);
http_.Open("POST", check_version_url_);
}
auto response = http_.GetBody(); auto response = http_.GetBody();
http_.Close(); http_.Close();
@@ -257,3 +250,99 @@ bool FirmwareUpgrade::IsNewVersionAvailable(const std::string& currentVersion, c
return newer.size() > current.size(); 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;
}

View File

@@ -12,8 +12,8 @@ public:
FirmwareUpgrade(Http& http); FirmwareUpgrade(Http& http);
~FirmwareUpgrade(); ~FirmwareUpgrade();
void SetBoardJson(const std::string& board_json);
void SetCheckVersionUrl(std::string check_version_url); 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 SetHeader(const std::string& key, const std::string& value);
void CheckVersion(); void CheckVersion();
bool HasNewVersion() { return has_new_version_; } bool HasNewVersion() { return has_new_version_; }
@@ -26,13 +26,14 @@ private:
bool has_new_version_ = false; bool has_new_version_ = false;
std::string firmware_version_; std::string firmware_version_;
std::string firmware_url_; std::string firmware_url_;
std::string post_data_; std::string board_json_;
std::map<std::string, std::string> headers_; std::map<std::string, std::string> headers_;
void Upgrade(const std::string& firmware_url); void Upgrade(const std::string& firmware_url);
std::function<void(int progress, size_t speed)> upgrade_callback_; std::function<void(int progress, size_t speed)> upgrade_callback_;
std::vector<int> ParseVersion(const std::string& version); std::vector<int> ParseVersion(const std::string& version);
bool IsNewVersionAvailable(const std::string& currentVersion, const std::string& newVersion); bool IsNewVersionAvailable(const std::string& currentVersion, const std::string& newVersion);
std::string GetPostData();
}; };
#endif // _FIRMWARE_UPGRADE_H #endif // _FIRMWARE_UPGRADE_H

View File

@@ -3,7 +3,6 @@
#include <esp_log.h> #include <esp_log.h>
#include <esp_flash.h> #include <esp_flash.h>
#include <esp_mac.h> #include <esp_mac.h>
#include <esp_chip_info.h>
#include <esp_system.h> #include <esp_system.h>
#include <esp_partition.h> #include <esp_partition.h>
#include <esp_app_desc.h> #include <esp_app_desc.h>
@@ -41,96 +40,6 @@ std::string SystemInfo::GetChipModelName() {
return std::string(CONFIG_IDF_TARGET); 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) { esp_err_t SystemInfo::PrintRealTimeStats(TickType_t xTicksToWait) {
#define ARRAY_SIZE_OFFSET 5 #define ARRAY_SIZE_OFFSET 5
TaskStatus_t *start_array = NULL, *end_array = NULL; TaskStatus_t *start_array = NULL, *end_array = NULL;

View File

@@ -13,7 +13,6 @@ public:
static size_t GetFreeHeapSize(); static size_t GetFreeHeapSize();
static std::string GetMacAddress(); static std::string GetMacAddress();
static std::string GetChipModelName(); static std::string GetChipModelName();
static std::string GetJsonString();
static esp_err_t PrintRealTimeStats(TickType_t xTicksToWait); static esp_err_t PrintRealTimeStats(TickType_t xTicksToWait);
}; };

68
pack.py
View File

@@ -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()