Add V2 parition tables (#1137)

* v1.9.0: update font icons, add mqtt reconnect

* Add v2 parition tables
This commit is contained in:
Xiaoxia
2025-08-29 09:04:23 +08:00
committed by GitHub
parent 86921f4862
commit d09537ed5c
40 changed files with 185 additions and 103 deletions

View File

@@ -4,7 +4,7 @@
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
set(PROJECT_VER "1.8.9")
set(PROJECT_VER "1.9.0")
# Add this line to disable the specific warning
add_compile_options(-Wno-missing-field-initializers)

View File

@@ -5,7 +5,6 @@
#include "audio_codec.h"
#include "mqtt_protocol.h"
#include "websocket_protocol.h"
#include "font_awesome_symbols.h"
#include "assets/lang_config.h"
#include "mcp_server.h"
@@ -14,6 +13,7 @@
#include <cJSON.h>
#include <driver/gpio.h>
#include <arpa/inet.h>
#include <font_awesome.h>
#define TAG "Application"
@@ -87,7 +87,7 @@ void Application::CheckNewVersion(Ota& ota) {
char buffer[256];
snprintf(buffer, sizeof(buffer), Lang::Strings::CHECK_NEW_VERSION_FAILED, retry_delay, ota.GetCheckVersionUrl().c_str());
Alert(Lang::Strings::ERROR, buffer, "sad", Lang::Sounds::OGG_EXCLAMATION);
Alert(Lang::Strings::ERROR, buffer, "cloud_slash", Lang::Sounds::OGG_EXCLAMATION);
ESP_LOGW(TAG, "Check new version failed, retry in %d seconds (%d/%d)", retry_delay, retry_count, MAX_RETRY);
for (int i = 0; i < retry_delay; i++) {
@@ -103,13 +103,12 @@ void Application::CheckNewVersion(Ota& ota) {
retry_delay = 10; // 重置重试延迟时间
if (ota.HasNewVersion()) {
Alert(Lang::Strings::OTA_UPGRADE, Lang::Strings::UPGRADING, "happy", Lang::Sounds::OGG_UPGRADE);
Alert(Lang::Strings::OTA_UPGRADE, Lang::Strings::UPGRADING, "download", Lang::Sounds::OGG_UPGRADE);
vTaskDelay(pdMS_TO_TICKS(3000));
SetDeviceState(kDeviceStateUpgrading);
display->SetIcon(FONT_AWESOME_DOWNLOAD);
std::string message = std::string(Lang::Strings::NEW_VERSION) + ota.GetFirmwareVersion();
display->SetChatMessage("system", message.c_str());
@@ -130,7 +129,7 @@ void Application::CheckNewVersion(Ota& ota) {
ESP_LOGE(TAG, "Firmware upgrade failed, restarting audio service and continuing operation...");
audio_service_.Start(); // Restart audio service
board.SetPowerSaveMode(true); // Restore power save mode
Alert(Lang::Strings::ERROR, Lang::Strings::UPGRADE_FAILED, "sad", Lang::Sounds::OGG_EXCLAMATION);
Alert(Lang::Strings::ERROR, Lang::Strings::UPGRADE_FAILED, "circle_xmark", Lang::Sounds::OGG_EXCLAMATION);
vTaskDelay(pdMS_TO_TICKS(3000));
// Continue to normal operation (don't break, just fall through)
} else {
@@ -195,7 +194,7 @@ void Application::ShowActivationCode(const std::string& code, const std::string&
}};
// This sentence uses 9KB of SRAM, so we need to wait for it to finish
Alert(Lang::Strings::ACTIVATION, message.c_str(), "happy", Lang::Sounds::OGG_ACTIVATION);
Alert(Lang::Strings::ACTIVATION, message.c_str(), "link", Lang::Sounds::OGG_ACTIVATION);
for (const auto& digit : code) {
auto it = std::find_if(digit_sounds.begin(), digit_sounds.end(),
@@ -207,7 +206,7 @@ void Application::ShowActivationCode(const std::string& code, const std::string&
}
void Application::Alert(const char* status, const char* message, const char* emotion, const std::string_view& sound) {
ESP_LOGW(TAG, "Alert %s: %s [%s]", status, message, emotion);
ESP_LOGW(TAG, "Alert [%s] %s: %s", emotion, status, message);
auto display = Board::GetInstance().GetDisplay();
display->SetStatus(status);
display->SetEmotion(emotion);
@@ -378,6 +377,10 @@ void Application::Start() {
protocol_ = std::make_unique<MqttProtocol>();
}
protocol_->OnConnected([this]() {
DismissAlert();
});
protocol_->OnNetworkError([this](const std::string& message) {
last_error_message_ = message;
xEventGroupSetBits(event_group_, MAIN_EVENT_ERROR);
@@ -546,7 +549,7 @@ void Application::MainEventLoop() {
MAIN_EVENT_ERROR, pdTRUE, pdFALSE, portMAX_DELAY);
if (bits & MAIN_EVENT_ERROR) {
SetDeviceState(kDeviceStateIdle);
Alert(Lang::Strings::ERROR, last_error_message_.c_str(), "sad", Lang::Sounds::OGG_EXCLAMATION);
Alert(Lang::Strings::ERROR, last_error_message_.c_str(), "circle_xmark", Lang::Sounds::OGG_EXCLAMATION);
}
if (bits & MAIN_EVENT_SEND_AUDIO) {

View File

@@ -9,7 +9,6 @@
#include <string>
#include <mutex>
#include <deque>
#include <vector>
#include <memory>
#include "protocol.h"

View File

@@ -111,7 +111,7 @@ private:
InitializeButtons();
GetBacklight()->SetBrightness(100);
display_->SetStatus(Lang::Strings::ERROR);
display_->SetEmotion("sad");
display_->SetEmotion("triangle_exclamation");
display_->SetChatMessage("system", "Echo Base\nnot connected");
while (1) {

View File

@@ -177,7 +177,7 @@ private:
InitializeButtons();
GetBacklight()->SetBrightness(100);
display_->SetStatus(Lang::Strings::ERROR);
display_->SetEmotion("sad");
display_->SetEmotion("triangle_exclamation");
display_->SetChatMessage("system", "Echo Base\nnot connected");
while (1) {

View File

@@ -2,11 +2,11 @@
#include "application.h"
#include "display.h"
#include "font_awesome_symbols.h"
#include "assets/lang_config.h"
#include <esp_log.h>
#include <esp_timer.h>
#include <font_awesome.h>
#include <opus_encoder.h>
static const char *TAG = "Ml307Board";
@@ -50,9 +50,9 @@ void Ml307Board::StartNetwork() {
while (true) {
auto result = modem_->WaitForNetworkReady();
if (result == NetworkStatus::ErrorInsertPin) {
application.Alert(Lang::Strings::ERROR, Lang::Strings::PIN_ERROR, "sad", Lang::Sounds::OGG_ERR_PIN);
application.Alert(Lang::Strings::ERROR, Lang::Strings::PIN_ERROR, "triangle_exclamation", Lang::Sounds::OGG_ERR_PIN);
} else if (result == NetworkStatus::ErrorRegistrationDenied) {
application.Alert(Lang::Strings::ERROR, Lang::Strings::REG_ERROR, "sad", Lang::Sounds::OGG_ERR_REG);
application.Alert(Lang::Strings::ERROR, Lang::Strings::REG_ERROR, "triangle_exclamation", Lang::Sounds::OGG_ERR_REG);
} else {
break;
}
@@ -80,13 +80,13 @@ const char* Ml307Board::GetNetworkStateIcon() {
if (csq == -1) {
return FONT_AWESOME_SIGNAL_OFF;
} else if (csq >= 0 && csq <= 14) {
return FONT_AWESOME_SIGNAL_1;
return FONT_AWESOME_SIGNAL_WEAK;
} else if (csq >= 15 && csq <= 19) {
return FONT_AWESOME_SIGNAL_2;
return FONT_AWESOME_SIGNAL_FAIR;
} else if (csq >= 20 && csq <= 24) {
return FONT_AWESOME_SIGNAL_3;
return FONT_AWESOME_SIGNAL_GOOD;
} else if (csq >= 25 && csq <= 31) {
return FONT_AWESOME_SIGNAL_4;
return FONT_AWESOME_SIGNAL_STRONG;
}
ESP_LOGW(TAG, "Invalid CSQ: %d", csq);

View File

@@ -3,7 +3,6 @@
#include "display.h"
#include "application.h"
#include "system_info.h"
#include "font_awesome_symbols.h"
#include "settings.h"
#include "assets/lang_config.h"
@@ -12,6 +11,7 @@
#include <esp_network.h>
#include <esp_log.h>
#include <font_awesome.h>
#include <wifi_station.h>
#include <wifi_configuration_ap.h>
#include <ssid_manager.h>
@@ -49,7 +49,7 @@ void WifiBoard::EnterWifiConfigMode() {
hint += "\n\n";
// 播报配置 WiFi 的提示
application.Alert(Lang::Strings::WIFI_CONFIG_MODE, hint.c_str(), "", Lang::Sounds::OGG_WIFICONFIG);
application.Alert(Lang::Strings::WIFI_CONFIG_MODE, hint.c_str(), "gear", Lang::Sounds::OGG_WIFICONFIG);
#if CONFIG_USE_ACOUSTIC_WIFI_PROVISIONING
auto display = Board::GetInstance().GetDisplay();
@@ -124,7 +124,7 @@ const char* WifiBoard::GetNetworkStateIcon() {
}
auto& wifi_station = WifiStation::GetInstance();
if (!wifi_station.IsConnected()) {
return FONT_AWESOME_WIFI_OFF;
return FONT_AWESOME_WIFI_SLASH;
}
int8_t rssi = wifi_station.GetRssi();
if (rssi >= -60) {

View File

@@ -3,7 +3,6 @@
#include "display/lcd_display.h"
#include "esp_lcd_ili9341.h"
#include "led_control.h"
#include "font_awesome_symbols.h"
#include "application.h"
#include "button.h"
#include "config.h"

View File

@@ -1,12 +1,12 @@
#include "electron_emoji_display.h"
#include <esp_log.h>
#include <font_awesome.h>
#include <algorithm>
#include <cstring>
#include <string>
#include "font_awesome_symbols.h"
#define TAG "ElectronEmojiDisplay"

View File

@@ -2,7 +2,6 @@
#include "codecs/box_audio_codec.h"
#include "display/lcd_display.h"
#include "esp_lcd_ili9341.h"
#include "font_awesome_symbols.h"
#include "application.h"
#include "button.h"
#include "config.h"

View File

@@ -2,7 +2,6 @@
#include "box_audio_codec_lite.h"
#include "display/lcd_display.h"
#include "esp_lcd_ili9341.h"
#include "font_awesome_symbols.h"
#include "application.h"
#include "button.h"
#include "config.h"

View File

@@ -2,7 +2,6 @@
#include "codecs/box_audio_codec.h"
#include "display/lcd_display.h"
#include "esp_lcd_ili9341.h"
#include "font_awesome_symbols.h"
#include "application.h"
#include "button.h"
#include "config.h"

View File

@@ -1,7 +1,6 @@
#include "wifi_board.h"
#include "codecs/es8311_audio_codec.h"
#include "display/lcd_display.h"
#include "font_awesome_symbols.h"
#include "application.h"
#include "button.h"
#include "config.h"

View File

@@ -1,7 +1,6 @@
#include "wifi_board.h"
#include "display/lcd_display.h"
#include "esp_lcd_sh8601.h"
#include "font_awesome_symbols.h"
#include "codecs/es8311_audio_codec.h"
#include "application.h"

View File

@@ -2,7 +2,6 @@
#include "tab5_audio_codec.h"
#include "display/lcd_display.h"
#include "esp_lcd_ili9881c.h"
#include "font_awesome_symbols.h"
#include "font_emoji.h"
#include "application.h"
#include "button.h"

View File

@@ -5,7 +5,6 @@
#include "button.h"
#include "led/circular_strip.h"
#include "config.h"
#include "font_awesome_symbols.h"
#include "assets/lang_config.h"
#include <esp_lcd_panel_vendor.h>

View File

@@ -6,7 +6,6 @@
#include "led/circular_strip.h"
#include "config.h"
#include "assets/lang_config.h"
#include "font_awesome_symbols.h"
#include <esp_lcd_panel_vendor.h>
#include <wifi_station.h>

View File

@@ -6,7 +6,6 @@
#include "led/single_led.h"
#include "config.h"
#include "power_save_timer.h"
#include "font_awesome_symbols.h"
#include <wifi_station.h>
#include <esp_log.h>

View File

@@ -6,7 +6,6 @@
#include "led/single_led.h"
#include "config.h"
#include "power_save_timer.h"
#include "font_awesome_symbols.h"
#include <wifi_station.h>
#include <esp_log.h>

View File

@@ -1,13 +1,13 @@
#include "otto_emoji_display.h"
#include <esp_log.h>
#include <font_awesome.h>
#include <algorithm>
#include <cstring>
#include <string>
#include "display/lcd_display.h"
#include "font_awesome_symbols.h"
#define TAG "OttoEmojiDisplay"

View File

@@ -3,7 +3,6 @@
#include "wifi_board.h"
#include "sensecap_audio_codec.h"
#include "display/lcd_display.h"
#include "font_awesome_symbols.h"
#include "application.h"
#include "knob.h"
#include "config.h"

View File

@@ -8,7 +8,6 @@
#include "power_save_timer.h"
#include "axp2101.h"
#include "assets/lang_config.h"
#include "font_awesome_symbols.h"
#include <esp_log.h>
#include <driver/gpio.h>

View File

@@ -1,7 +1,6 @@
#include "wifi_board.h"
#include "display/lcd_display.h"
#include "esp_lcd_sh8601.h"
#include "font_awesome_symbols.h"
#include "codecs/box_audio_codec.h"
#include "application.h"

View File

@@ -1,7 +1,6 @@
#include "wifi_board.h"
#include "display/lcd_display.h"
#include "esp_lcd_sh8601.h"
#include "font_awesome_symbols.h"
#include "codecs/box_audio_codec.h"
#include "application.h"

View File

@@ -8,7 +8,6 @@
#include "settings.h"
#include "config.h"
#include "sleep_timer.h"
#include "font_awesome_symbols.h"
#include "adc_battery_monitor.h"
#include "press_to_talk_mcp_tool.h"

View File

@@ -8,7 +8,6 @@
#include "settings.h"
#include "config.h"
#include "power_save_timer.h"
#include "font_awesome_symbols.h"
#include "adc_battery_monitor.h"
#include "press_to_talk_mcp_tool.h"

View File

@@ -8,7 +8,6 @@
#include "settings.h"
#include "config.h"
#include "power_save_timer.h"
#include "font_awesome_symbols.h"
#include "press_to_talk_mcp_tool.h"
#include <wifi_station.h>

View File

@@ -3,11 +3,11 @@
#include <string>
#include <cstdlib>
#include <cstring>
#include <font_awesome.h>
#include "display.h"
#include "board.h"
#include "application.h"
#include "font_awesome_symbols.h"
#include "audio_codec.h"
#include "settings.h"
#include "assets/lang_config.h"
@@ -105,7 +105,7 @@ void Display::UpdateStatusBar(bool update_all) {
// 如果静音状态改变,则更新图标
if (codec->output_volume() == 0 && !muted_) {
muted_ = true;
lv_label_set_text(mute_label_, FONT_AWESOME_VOLUME_MUTE);
lv_label_set_text(mute_label_, FONT_AWESOME_VOLUME_XMARK);
} else if (codec->output_volume() > 0 && muted_) {
muted_ = false;
lv_label_set_text(mute_label_, "");
@@ -136,13 +136,13 @@ void Display::UpdateStatusBar(bool update_all) {
const char* icon = nullptr;
if (board.GetBatteryLevel(battery_level, charging, discharging)) {
if (charging) {
icon = FONT_AWESOME_BATTERY_CHARGING;
icon = FONT_AWESOME_BATTERY_BOLT;
} else {
const char* levels[] = {
FONT_AWESOME_BATTERY_EMPTY, // 0-19%
FONT_AWESOME_BATTERY_1, // 20-39%
FONT_AWESOME_BATTERY_2, // 40-59%
FONT_AWESOME_BATTERY_3, // 60-79%
FONT_AWESOME_BATTERY_QUARTER, // 20-39%
FONT_AWESOME_BATTERY_HALF, // 40-59%
FONT_AWESOME_BATTERY_THREE_QUARTERS, // 60-79%
FONT_AWESOME_BATTERY_FULL, // 80-99%
FONT_AWESOME_BATTERY_FULL, // 100%
};
@@ -196,50 +196,11 @@ void Display::UpdateStatusBar(bool update_all) {
void Display::SetEmotion(const char* emotion) {
struct Emotion {
const char* icon;
const char* text;
};
static const std::vector<Emotion> emotions = {
{FONT_AWESOME_EMOJI_NEUTRAL, "neutral"},
{FONT_AWESOME_EMOJI_HAPPY, "happy"},
{FONT_AWESOME_EMOJI_LAUGHING, "laughing"},
{FONT_AWESOME_EMOJI_FUNNY, "funny"},
{FONT_AWESOME_EMOJI_SAD, "sad"},
{FONT_AWESOME_EMOJI_ANGRY, "angry"},
{FONT_AWESOME_EMOJI_CRYING, "crying"},
{FONT_AWESOME_EMOJI_LOVING, "loving"},
{FONT_AWESOME_EMOJI_EMBARRASSED, "embarrassed"},
{FONT_AWESOME_EMOJI_SURPRISED, "surprised"},
{FONT_AWESOME_EMOJI_SHOCKED, "shocked"},
{FONT_AWESOME_EMOJI_THINKING, "thinking"},
{FONT_AWESOME_EMOJI_WINKING, "winking"},
{FONT_AWESOME_EMOJI_COOL, "cool"},
{FONT_AWESOME_EMOJI_RELAXED, "relaxed"},
{FONT_AWESOME_EMOJI_DELICIOUS, "delicious"},
{FONT_AWESOME_EMOJI_KISSY, "kissy"},
{FONT_AWESOME_EMOJI_CONFIDENT, "confident"},
{FONT_AWESOME_EMOJI_SLEEPY, "sleepy"},
{FONT_AWESOME_EMOJI_SILLY, "silly"},
{FONT_AWESOME_EMOJI_CONFUSED, "confused"}
};
// 查找匹配的表情
std::string_view emotion_view(emotion);
auto it = std::find_if(emotions.begin(), emotions.end(),
[&emotion_view](const Emotion& e) { return e.text == emotion_view; });
DisplayLockGuard lock(this);
if (emotion_label_ == nullptr) {
return;
}
// 如果找到匹配的表情就显示对应图标否则显示默认的neutral表情
if (it != emotions.end()) {
lv_label_set_text(emotion_label_, it->icon);
const char* utf8 = font_awesome_get_utf8(emotion);
if (utf8 != nullptr) {
SetIcon(utf8);
} else {
lv_label_set_text(emotion_label_, FONT_AWESOME_EMOJI_NEUTRAL);
SetIcon(FONT_AWESOME_NEUTRAL);
}
}

View File

@@ -2,7 +2,7 @@
#include <vector>
#include <algorithm>
#include <font_awesome_symbols.h>
#include <font_awesome.h>
#include <esp_log.h>
#include <esp_err.h>
#include <esp_lvgl_port.h>
@@ -367,7 +367,7 @@ void LcdDisplay::SetupUI() {
emotion_label_ = lv_label_create(status_bar_);
lv_obj_set_style_text_font(emotion_label_, &font_awesome_30_4, 0);
lv_obj_set_style_text_color(emotion_label_, current_theme_.text, 0);
lv_label_set_text(emotion_label_, FONT_AWESOME_AI_CHIP);
lv_label_set_text(emotion_label_, FONT_AWESOME_MICROCHIP_AI);
lv_obj_set_style_margin_right(emotion_label_, 5, 0); // 添加右边距,与后面的元素分隔
notification_label_ = lv_label_create(status_bar_);
@@ -744,7 +744,7 @@ void LcdDisplay::SetupUI() {
emotion_label_ = lv_label_create(content_);
lv_obj_set_style_text_font(emotion_label_, &font_awesome_30_4, 0);
lv_obj_set_style_text_color(emotion_label_, current_theme_.text, 0);
lv_label_set_text(emotion_label_, FONT_AWESOME_AI_CHIP);
lv_label_set_text(emotion_label_, FONT_AWESOME_MICROCHIP_AI);
preview_image_ = lv_image_create(content_);
lv_obj_set_size(preview_image_, width_ * 0.5, height_ * 0.5);
@@ -867,6 +867,13 @@ void LcdDisplay::SetEmotion(const char* emotion) {
std::string_view emotion_view(emotion);
auto it = std::find_if(emotions.begin(), emotions.end(),
[&emotion_view](const Emotion& e) { return e.text == emotion_view; });
if (fonts_.emoji_font == nullptr || it == emotions.end()) {
const char* utf8 = font_awesome_get_utf8(emotion);
if (utf8 != nullptr) {
SetIcon(utf8);
}
return;
}
DisplayLockGuard lock(this);
if (emotion_label_ == nullptr) {

View File

@@ -1,5 +1,4 @@
#include "oled_display.h"
#include "font_awesome_symbols.h"
#include "assets/lang_config.h"
#include <string>
@@ -8,6 +7,7 @@
#include <esp_log.h>
#include <esp_err.h>
#include <esp_lvgl_port.h>
#include <font_awesome.h>
#define TAG "OledDisplay"
@@ -157,7 +157,7 @@ void OledDisplay::SetupUI_128x64() {
emotion_label_ = lv_label_create(content_left_);
lv_obj_set_style_text_font(emotion_label_, &font_awesome_30_1, 0);
lv_label_set_text(emotion_label_, FONT_AWESOME_AI_CHIP);
lv_label_set_text(emotion_label_, FONT_AWESOME_MICROCHIP_AI);
lv_obj_center(emotion_label_);
lv_obj_set_style_pad_top(emotion_label_, 8, 0);
@@ -249,7 +249,7 @@ void OledDisplay::SetupUI_128x32() {
emotion_label_ = lv_label_create(content_);
lv_obj_set_style_text_font(emotion_label_, &font_awesome_30_1, 0);
lv_label_set_text(emotion_label_, FONT_AWESOME_AI_CHIP);
lv_label_set_text(emotion_label_, FONT_AWESOME_MICROCHIP_AI);
lv_obj_center(emotion_label_);
/* Right side */

View File

@@ -13,10 +13,10 @@ dependencies:
espressif/esp_io_expander_tca9554: ==2.0.0
espressif/esp_lcd_panel_io_additions: ^1.0.1
78/esp_lcd_nv3023: ~1.0.0
78/esp-wifi-connect: ~2.5.1
78/esp-wifi-connect: ~2.5.2
78/esp-opus-encoder: ~2.4.1
78/esp-ml307: ~3.2.8
78/xiaozhi-fonts: ~1.4.0
78/esp-ml307: ~3.3.0
78/xiaozhi-fonts: ~1.5.0
espressif/led_strip: ~3.0.1
espressif/esp_codec_dev: ~1.4.0
espressif/esp-sr: ~2.1.5

View File

@@ -12,12 +12,34 @@
MqttProtocol::MqttProtocol() {
event_group_handle_ = xEventGroupCreate();
// Initialize reconnect timer
esp_timer_create_args_t reconnect_timer_args = {
.callback = [](void* arg) {
MqttProtocol* protocol = (MqttProtocol*)arg;
auto& app = Application::GetInstance();
if (app.GetDeviceState() == kDeviceStateIdle) {
ESP_LOGI(TAG, "Reconnecting to MQTT server");
app.Schedule([protocol]() {
protocol->StartMqttClient(false);
});
}
},
.arg = this,
};
esp_timer_create(&reconnect_timer_args, &reconnect_timer_);
}
MqttProtocol::~MqttProtocol() {
ESP_LOGI(TAG, "MqttProtocol deinit");
if (reconnect_timer_ != nullptr) {
esp_timer_stop(reconnect_timer_);
esp_timer_delete(reconnect_timer_);
}
if (event_group_handle_ != nullptr) {
vEventGroupDelete(event_group_handle_);
}
}
bool MqttProtocol::Start() {
return StartMqttClient(false);
@@ -50,7 +72,18 @@ bool MqttProtocol::StartMqttClient(bool report_error) {
mqtt_->SetKeepAlive(keepalive_interval);
mqtt_->OnDisconnected([this]() {
ESP_LOGI(TAG, "Disconnected from endpoint");
if (on_disconnected_ != nullptr) {
on_disconnected_();
}
ESP_LOGI(TAG, "MQTT disconnected, schedule reconnect in %d seconds", MQTT_RECONNECT_INTERVAL_MS / 1000);
esp_timer_start_once(reconnect_timer_, MQTT_RECONNECT_INTERVAL_MS * 1000);
});
mqtt_->OnConnected([this]() {
if (on_connected_ != nullptr) {
on_connected_();
}
esp_timer_stop(reconnect_timer_);
});
mqtt_->OnMessage([this](const std::string& topic, const std::string& payload) {

View File

@@ -9,6 +9,7 @@
#include <mbedtls/aes.h>
#include <freertos/FreeRTOS.h>
#include <freertos/event_groups.h>
#include <esp_timer.h>
#include <functional>
#include <string>
@@ -16,7 +17,7 @@
#include <mutex>
#define MQTT_PING_INTERVAL_SECONDS 90
#define MQTT_RECONNECT_INTERVAL_MS 10000
#define MQTT_RECONNECT_INTERVAL_MS 60000
#define MQTT_PROTOCOL_SERVER_HELLO_EVENT (1 << 0)
@@ -45,6 +46,7 @@ private:
int udp_port_;
uint32_t local_sequence_;
uint32_t remote_sequence_;
esp_timer_handle_t reconnect_timer_;
bool StartMqttClient(bool report_error=false);
void ParseServerHello(const cJSON* root);

View File

@@ -24,6 +24,14 @@ void Protocol::OnNetworkError(std::function<void(const std::string& message)> ca
on_network_error_ = callback;
}
void Protocol::OnConnected(std::function<void()> callback) {
on_connected_ = callback;
}
void Protocol::OnDisconnected(std::function<void()> callback) {
on_disconnected_ = callback;
}
void Protocol::SetError(const std::string& message) {
error_occurred_ = true;
if (on_network_error_ != nullptr) {

View File

@@ -60,6 +60,8 @@ public:
void OnAudioChannelOpened(std::function<void()> callback);
void OnAudioChannelClosed(std::function<void()> callback);
void OnNetworkError(std::function<void(const std::string& message)> callback);
void OnConnected(std::function<void()> callback);
void OnDisconnected(std::function<void()> callback);
virtual bool Start() = 0;
virtual bool OpenAudioChannel() = 0;
@@ -78,6 +80,8 @@ protected:
std::function<void()> on_audio_channel_opened_;
std::function<void()> on_audio_channel_closed_;
std::function<void(const std::string& message)> on_network_error_;
std::function<void()> on_connected_;
std::function<void()> on_disconnected_;
int server_sample_rate_ = 24000;
int server_frame_duration_ = 60;

9
partitions/v2/16m.csv Normal file
View File

@@ -0,0 +1,9 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
model, data, spiffs, 0x10000, 0xF0000,
ota_0, app, ota_0, 0x100000, 4M,
ota_1, app, ota_1, 0x500000, 4M,
assets, data, spiffs, 0x900000, 7M
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x4000,
4 otadata, data, ota, 0xd000, 0x2000,
5 phy_init, data, phy, 0xf000, 0x1000,
6 model, data, spiffs, 0x10000, 0xF0000,
7 ota_0, app, ota_0, 0x100000, 4M,
8 ota_1, app, ota_1, 0x500000, 4M,
9 assets, data, spiffs, 0x900000, 7M

9
partitions/v2/16m_c3.csv Normal file
View File

@@ -0,0 +1,9 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
model, data, spiffs, 0x10000, 0xF0000,
ota_0, app, ota_0, 0x100000, 4M,
ota_1, app, ota_1, 0x500000, 4M,
assets, data, spiffs, 0x900000, 4000K
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x4000,
4 otadata, data, ota, 0xd000, 0x2000,
5 phy_init, data, phy, 0xf000, 0x1000,
6 model, data, spiffs, 0x10000, 0xF0000,
7 ota_0, app, ota_0, 0x100000, 4M,
8 ota_1, app, ota_1, 0x500000, 4M,
9 assets, data, spiffs, 0x900000, 4000K

10
partitions/v2/32m.csv Normal file
View File

@@ -0,0 +1,10 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvsfactory, data, nvs, , 200K,
nvs, data, nvs, , 840K,
otadata, data, ota, , 0x2000,
phy_init, data, phy, , 0x1000,
model, data, spiffs, , 0xF0000,
ota_0, app, ota_0, 0x200000, 4M,
ota_1, app, ota_1, 0x600000, 4M,
assets, data, spiffs, 0xA00000, 16M
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvsfactory, data, nvs, , 200K,
4 nvs, data, nvs, , 840K,
5 otadata, data, ota, , 0x2000,
6 phy_init, data, phy, , 0x1000,
7 model, data, spiffs, , 0xF0000,
8 ota_0, app, ota_0, 0x200000, 4M,
9 ota_1, app, ota_1, 0x600000, 4M,
10 assets, data, spiffs, 0xA00000, 16M

9
partitions/v2/8m.csv Normal file
View File

@@ -0,0 +1,9 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
model, data, spiffs, 0x10000, 0xF0000,
ota_0, app, ota_0, 0x100000, 3M,
ota_1, app, ota_1, 0x400000, 3M,
assets, data, spiffs, 0x700000, 1M
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x4000,
4 otadata, data, ota, 0xd000, 0x2000,
5 phy_init, data, phy, 0xf000, 0x1000,
6 model, data, spiffs, 0x10000, 0xF0000,
7 ota_0, app, ota_0, 0x100000, 3M,
8 ota_1, app, ota_1, 0x400000, 3M,
9 assets, data, spiffs, 0x700000, 1M

46
partitions/v2/README.md Normal file
View File

@@ -0,0 +1,46 @@
# Version 2 Partition Table
This version introduces significant improvements over v1 by adding an `assets` partition to support network-loadable content.
## Key Changes from v1
### Added Assets Partition
The v2 partition table includes a new `assets` partition that stores:
- **Wake word models**: Customizable wake word models that can be loaded from the network
- **Theme files**: Complete theming system including:
- Fonts
- Audio effects
- Background images
- Custom emoji packs
### Partition Layout Comparison
#### v1 Layout (16MB)
- `nvs`: 16KB (non-volatile storage)
- `otadata`: 8KB (OTA data)
- `phy_init`: 4KB (PHY initialization data)
- `model`: 960KB (model storage)
- `ota_0`: 6MB (application partition 0)
- `ota_1`: 6MB (application partition 1)
#### v2 Layout (16MB)
- `nvs`: 16KB (non-volatile storage)
- `otadata`: 8KB (OTA data)
- `phy_init`: 4KB (PHY initialization data)
- `model`: 960KB (model storage)
- `ota_0`: 4MB (application partition 0)
- `ota_1`: 4MB (application partition 1)
- `assets`: 7MB (network-loadable assets)
### Benefits
1. **Dynamic Content**: Users can download and update wake word models and themes without reflashing
2. **Reduced App Size**: Application partitions are smaller, allowing more space for assets
3. **Customization**: Support for custom themes and wake words enhances user experience
4. **Network Flexibility**: Assets can be updated independently of the main application
### Available Configurations
- `8m.csv`: For 8MB flash devices
- `16m.csv`: For 16MB flash devices (standard)
- `16m_c3.csv`: For 16MB flash devices with ESP32-C3 optimization