forked from xiaozhi/xiaozhi-esp32
Enhance device activation and OTA update process
- Add support for device activation with audio feedback - Refactor OTA update flow to include activation code handling - Update asset management for localized sound resources - Improve error handling and device state management - Reorganize binary asset includes and CMake configuration
This commit is contained in:
@@ -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 "1.1.2")
|
set(PROJECT_VER "1.1.9")
|
||||||
|
|
||||||
# Add this line to disable the specific warning
|
# Add this line to disable the specific warning
|
||||||
add_compile_options(-Wno-missing-field-initializers)
|
add_compile_options(-Wno-missing-field-initializers)
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ set(SOURCES "audio_codecs/audio_codec.cc"
|
|||||||
"display/ssd1306_display.cc"
|
"display/ssd1306_display.cc"
|
||||||
"boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.c"
|
"boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.c"
|
||||||
"protocols/protocol.cc"
|
"protocols/protocol.cc"
|
||||||
"protocols/mqtt_protocol.cc"
|
|
||||||
"protocols/websocket_protocol.cc"
|
|
||||||
"iot/thing.cc"
|
"iot/thing.cc"
|
||||||
"iot/thing_manager.cc"
|
"iot/thing_manager.cc"
|
||||||
"system_info.cc"
|
"system_info.cc"
|
||||||
@@ -107,6 +105,12 @@ endif()
|
|||||||
file(GLOB BOARD_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.cc)
|
file(GLOB BOARD_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.cc)
|
||||||
list(APPEND SOURCES ${BOARD_SOURCES})
|
list(APPEND SOURCES ${BOARD_SOURCES})
|
||||||
|
|
||||||
|
if(CONFIG_CONNECTION_TYPE_MQTT_UDP)
|
||||||
|
list(APPEND SOURCES "protocols/mqtt_protocol.cc")
|
||||||
|
elseif(CONFIG_CONNECTION_TYPE_WEBSOCKET)
|
||||||
|
list(APPEND SOURCES "protocols/websocket_protocol.cc")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_USE_AUDIO_PROCESSING)
|
if(CONFIG_USE_AUDIO_PROCESSING)
|
||||||
list(APPEND SOURCES "audio_processing/audio_processor.cc" "audio_processing/wake_word_detect.cc")
|
list(APPEND SOURCES "audio_processing/audio_processor.cc" "audio_processing/wake_word_detect.cc")
|
||||||
endif()
|
endif()
|
||||||
@@ -119,8 +123,10 @@ if(CONFIG_IDF_TARGET_ESP32)
|
|||||||
"audio_codecs/es8388_audio_codec.cc")
|
"audio_codecs/es8388_audio_codec.cc")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
file(GLOB ASSETS ${CMAKE_CURRENT_SOURCE_DIR}/assets/zh/*.p3)
|
||||||
|
|
||||||
idf_component_register(SRCS ${SOURCES}
|
idf_component_register(SRCS ${SOURCES}
|
||||||
EMBED_FILES "assets/err_reg.p3" "assets/err_pin.p3" "assets/wificonfig.p3" "assets/upgrade.p3"
|
EMBED_FILES ${ASSETS}
|
||||||
INCLUDE_DIRS ${INCLUDE_DIRS}
|
INCLUDE_DIRS ${INCLUDE_DIRS}
|
||||||
WHOLE_ARCHIVE
|
WHOLE_ARCHIVE
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "websocket_protocol.h"
|
#include "websocket_protocol.h"
|
||||||
#include "font_awesome_symbols.h"
|
#include "font_awesome_symbols.h"
|
||||||
#include "iot/thing_manager.h"
|
#include "iot/thing_manager.h"
|
||||||
|
#include "assets/zh/binary.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
@@ -17,14 +18,6 @@
|
|||||||
|
|
||||||
#define TAG "Application"
|
#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_wificonfig_start[] asm("_binary_wificonfig_p3_start");
|
|
||||||
extern const char p3_wificonfig_end[] asm("_binary_wificonfig_p3_end");
|
|
||||||
extern const char p3_upgrade_start[] asm("_binary_upgrade_p3_start");
|
|
||||||
extern const char p3_upgrade_end[] asm("_binary_upgrade_p3_end");
|
|
||||||
|
|
||||||
static const char* const STATE_STRINGS[] = {
|
static const char* const STATE_STRINGS[] = {
|
||||||
"unknown",
|
"unknown",
|
||||||
@@ -35,6 +28,7 @@ static const char* const STATE_STRINGS[] = {
|
|||||||
"listening",
|
"listening",
|
||||||
"speaking",
|
"speaking",
|
||||||
"upgrading",
|
"upgrading",
|
||||||
|
"activating",
|
||||||
"fatal_error",
|
"fatal_error",
|
||||||
"invalid_state"
|
"invalid_state"
|
||||||
};
|
};
|
||||||
@@ -42,9 +36,6 @@ static const char* const STATE_STRINGS[] = {
|
|||||||
Application::Application() {
|
Application::Application() {
|
||||||
event_group_ = xEventGroupCreate();
|
event_group_ = xEventGroupCreate();
|
||||||
background_task_ = new BackgroundTask(4096 * 8);
|
background_task_ = new BackgroundTask(4096 * 8);
|
||||||
|
|
||||||
ota_.SetCheckVersionUrl(CONFIG_OTA_VERSION_URL);
|
|
||||||
ota_.SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
@@ -61,13 +52,9 @@ void Application::CheckNewVersion() {
|
|||||||
ota_.SetPostData(board.GetJson());
|
ota_.SetPostData(board.GetJson());
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
bool success = ota_.CheckVersion();
|
if (ota_.CheckVersion()) {
|
||||||
if (ota_.HasActivationCode()) {
|
|
||||||
DisplayActivationCode();
|
|
||||||
}
|
|
||||||
if (success) {
|
|
||||||
if (ota_.HasNewVersion()) {
|
if (ota_.HasNewVersion()) {
|
||||||
Alert("Info", "正在升级固件");
|
Alert("OTA 升级", "正在升级系统", "happy", std::string(p3_upgrade_start, p3_upgrade_end - p3_upgrade_start));
|
||||||
// Wait for the chat state to be idle
|
// Wait for the chat state to be idle
|
||||||
do {
|
do {
|
||||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||||
@@ -78,7 +65,7 @@ void Application::CheckNewVersion() {
|
|||||||
SetDeviceState(kDeviceStateUpgrading);
|
SetDeviceState(kDeviceStateUpgrading);
|
||||||
|
|
||||||
display->SetIcon(FONT_AWESOME_DOWNLOAD);
|
display->SetIcon(FONT_AWESOME_DOWNLOAD);
|
||||||
display->SetStatus("新版本 " + ota_.GetFirmwareVersion());
|
display->SetChatMessage("system", "新版本 " + ota_.GetFirmwareVersion());
|
||||||
|
|
||||||
board.SetPowerSaveMode(false);
|
board.SetPowerSaveMode(false);
|
||||||
#if CONFIG_USE_AUDIO_PROCESSING
|
#if CONFIG_USE_AUDIO_PROCESSING
|
||||||
@@ -100,52 +87,83 @@ void Application::CheckNewVersion() {
|
|||||||
ota_.StartUpgrade([display](int progress, size_t speed) {
|
ota_.StartUpgrade([display](int progress, size_t speed) {
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
snprintf(buffer, sizeof(buffer), "%d%% %zuKB/s", progress, speed / 1024);
|
snprintf(buffer, sizeof(buffer), "%d%% %zuKB/s", progress, speed / 1024);
|
||||||
display->SetStatus(buffer);
|
display->SetChatMessage("system", buffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
// If upgrade success, the device will reboot and never reach here
|
// If upgrade success, the device will reboot and never reach here
|
||||||
display->SetStatus("更新失败");
|
display->SetStatus("更新失败");
|
||||||
ESP_LOGI(TAG, "Firmware upgrade failed...");
|
ESP_LOGI(TAG, "Firmware upgrade failed...");
|
||||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||||
esp_restart();
|
Reboot();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
ota_.MarkCurrentVersionValid();
|
ota_.MarkCurrentVersionValid();
|
||||||
display->ShowNotification("版本 " + ota_.GetCurrentVersion());
|
display->ShowNotification("版本 " + ota_.GetCurrentVersion());
|
||||||
}
|
|
||||||
|
// Check if the activation code is valid
|
||||||
|
if (ota_.HasActivationCode()) {
|
||||||
|
SetDeviceState(kDeviceStateActivating);
|
||||||
|
ShowActivationCode();
|
||||||
|
} else {
|
||||||
|
SetDeviceState(kDeviceStateIdle);
|
||||||
|
display->SetChatMessage("system", "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check again in 60 seconds
|
// Check again in 60 seconds
|
||||||
vTaskDelay(pdMS_TO_TICKS(60000));
|
vTaskDelay(pdMS_TO_TICKS(60000));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::DisplayActivationCode() {
|
void Application::ShowActivationCode() {
|
||||||
ESP_LOGW(TAG, "Activation Message: %s", ota_.GetActivationMessage().c_str());
|
auto& message = ota_.GetActivationMessage();
|
||||||
ESP_LOGW(TAG, "Activation Code: %s", ota_.GetActivationCode().c_str());
|
auto& code = ota_.GetActivationCode();
|
||||||
auto display = Board::GetInstance().GetDisplay();
|
|
||||||
display->ShowNotification(ota_.GetActivationMessage(), 30000);
|
struct digit_sound {
|
||||||
|
char digit;
|
||||||
|
const char* sound_data_start;
|
||||||
|
const char* sound_data_end;
|
||||||
|
};
|
||||||
|
digit_sound digit_sounds[] = {
|
||||||
|
{'0', p3_0_start, p3_0_end},
|
||||||
|
{'1', p3_1_start, p3_1_end},
|
||||||
|
{'2', p3_2_start, p3_2_end},
|
||||||
|
{'3', p3_3_start, p3_3_end},
|
||||||
|
{'4', p3_4_start, p3_4_end},
|
||||||
|
{'5', p3_5_start, p3_5_end},
|
||||||
|
{'6', p3_6_start, p3_6_end},
|
||||||
|
{'7', p3_7_start, p3_7_end},
|
||||||
|
{'8', p3_8_start, p3_8_end},
|
||||||
|
{'9', p3_9_start, p3_9_end},
|
||||||
|
};
|
||||||
|
std::string sound = std::string(p3_activation_start, p3_activation_end - p3_activation_start);
|
||||||
|
for (const auto& digit : code) {
|
||||||
|
auto it = std::find_if(digit_sounds, digit_sounds + sizeof(digit_sounds) / sizeof(digit_sound),
|
||||||
|
[digit](const digit_sound& ds) { return ds.digit == digit; });
|
||||||
|
if (it != digit_sounds + sizeof(digit_sounds) / sizeof(digit_sound)) {
|
||||||
|
sound += std::string(it->sound_data_start, it->sound_data_end - it->sound_data_start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Alert("激活设备", message, "happy", sound);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::Alert(const std::string& title, const std::string& message) {
|
void Application::Alert(const std::string& status, const std::string& message, const std::string& emotion, const std::string& sound) {
|
||||||
ESP_LOGW(TAG, "Alert: %s, %s", title.c_str(), message.c_str());
|
ESP_LOGW(TAG, "Alert %s: %s [%s]", status.c_str(), message.c_str(), emotion.c_str());
|
||||||
auto display = Board::GetInstance().GetDisplay();
|
auto display = Board::GetInstance().GetDisplay();
|
||||||
display->ShowNotification(message);
|
display->SetStatus(status);
|
||||||
|
display->SetEmotion(emotion);
|
||||||
if (message == "进入配网模式") {
|
display->SetChatMessage("system", message);
|
||||||
PlayLocalFile(p3_wificonfig_start, p3_wificonfig_end - p3_wificonfig_start);
|
if (!sound.empty()) {
|
||||||
} else if (message == "正在升级固件") {
|
PlayLocalFile(sound.data(), sound.size());
|
||||||
PlayLocalFile(p3_upgrade_start, p3_upgrade_end - p3_upgrade_start);
|
|
||||||
} else if (message == "请插入SIM卡") {
|
|
||||||
PlayLocalFile(p3_err_pin_start, p3_err_pin_end - p3_err_pin_start);
|
|
||||||
} else if (message == "无法接入网络,请检查流量卡状态") {
|
|
||||||
PlayLocalFile(p3_err_reg_start, p3_err_reg_end - p3_err_reg_start);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::PlayLocalFile(const char* data, size_t size) {
|
void Application::PlayLocalFile(const char* data, size_t size) {
|
||||||
ESP_LOGI(TAG, "PlayLocalFile: %zu bytes", size);
|
ESP_LOGI(TAG, "PlayLocalFile: %zu bytes", size);
|
||||||
|
auto codec = Board::GetInstance().GetAudioCodec();
|
||||||
|
codec->EnableOutput(true);
|
||||||
SetDecodeSampleRate(16000);
|
SetDecodeSampleRate(16000);
|
||||||
for (const char* p = data; p < data + size; ) {
|
for (const char* p = data; p < data + size; ) {
|
||||||
auto p3 = (BinaryProtocol3*)p;
|
auto p3 = (BinaryProtocol3*)p;
|
||||||
@@ -164,6 +182,11 @@ void Application::PlayLocalFile(const char* data, size_t size) {
|
|||||||
|
|
||||||
void Application::ToggleChatState() {
|
void Application::ToggleChatState() {
|
||||||
Schedule([this]() {
|
Schedule([this]() {
|
||||||
|
if (device_state_ == kDeviceStateActivating) {
|
||||||
|
Reboot();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!protocol_) {
|
if (!protocol_) {
|
||||||
ESP_LOGE(TAG, "Protocol not initialized");
|
ESP_LOGE(TAG, "Protocol not initialized");
|
||||||
return;
|
return;
|
||||||
@@ -172,7 +195,7 @@ void Application::ToggleChatState() {
|
|||||||
if (device_state_ == kDeviceStateIdle) {
|
if (device_state_ == kDeviceStateIdle) {
|
||||||
SetDeviceState(kDeviceStateConnecting);
|
SetDeviceState(kDeviceStateConnecting);
|
||||||
if (!protocol_->OpenAudioChannel()) {
|
if (!protocol_->OpenAudioChannel()) {
|
||||||
Alert("Error", "Failed to open audio channel");
|
Alert("ERROR", "无法建立音频通道");
|
||||||
SetDeviceState(kDeviceStateIdle);
|
SetDeviceState(kDeviceStateIdle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -190,6 +213,11 @@ void Application::ToggleChatState() {
|
|||||||
|
|
||||||
void Application::StartListening() {
|
void Application::StartListening() {
|
||||||
Schedule([this]() {
|
Schedule([this]() {
|
||||||
|
if (device_state_ == kDeviceStateActivating) {
|
||||||
|
Reboot();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!protocol_) {
|
if (!protocol_) {
|
||||||
ESP_LOGE(TAG, "Protocol not initialized");
|
ESP_LOGE(TAG, "Protocol not initialized");
|
||||||
return;
|
return;
|
||||||
@@ -201,7 +229,7 @@ void Application::StartListening() {
|
|||||||
SetDeviceState(kDeviceStateConnecting);
|
SetDeviceState(kDeviceStateConnecting);
|
||||||
if (!protocol_->OpenAudioChannel()) {
|
if (!protocol_->OpenAudioChannel()) {
|
||||||
SetDeviceState(kDeviceStateIdle);
|
SetDeviceState(kDeviceStateIdle);
|
||||||
Alert("Error", "Failed to open audio channel");
|
Alert("ERROR", "无法建立音频通道");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,14 +303,14 @@ void Application::Start() {
|
|||||||
board.StartNetwork();
|
board.StartNetwork();
|
||||||
|
|
||||||
// Initialize the protocol
|
// Initialize the protocol
|
||||||
display->SetStatus("初始化协议");
|
display->SetStatus("加载协议...");
|
||||||
#ifdef CONFIG_CONNECTION_TYPE_WEBSOCKET
|
#ifdef CONFIG_CONNECTION_TYPE_WEBSOCKET
|
||||||
protocol_ = std::make_unique<WebsocketProtocol>();
|
protocol_ = std::make_unique<WebsocketProtocol>();
|
||||||
#else
|
#else
|
||||||
protocol_ = std::make_unique<MqttProtocol>();
|
protocol_ = std::make_unique<MqttProtocol>();
|
||||||
#endif
|
#endif
|
||||||
protocol_->OnNetworkError([this](const std::string& message) {
|
protocol_->OnNetworkError([this](const std::string& message) {
|
||||||
Alert("Error", std::move(message));
|
Alert("ERROR", message);
|
||||||
});
|
});
|
||||||
protocol_->OnIncomingAudio([this](std::vector<uint8_t>&& data) {
|
protocol_->OnIncomingAudio([this](std::vector<uint8_t>&& data) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
@@ -371,6 +399,9 @@ void Application::Start() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check for new firmware version or get the MQTT broker address
|
// Check for new firmware version or get the MQTT broker address
|
||||||
|
ota_.SetCheckVersionUrl(CONFIG_OTA_VERSION_URL);
|
||||||
|
ota_.SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str());
|
||||||
|
ota_.SetHeader("Client-Id", board.GetUuid());
|
||||||
xTaskCreate([](void* arg) {
|
xTaskCreate([](void* arg) {
|
||||||
Application* app = (Application*)arg;
|
Application* app = (Application*)arg;
|
||||||
app->CheckNewVersion();
|
app->CheckNewVersion();
|
||||||
@@ -664,3 +695,8 @@ void Application::UpdateIotStates() {
|
|||||||
protocol_->SendIotStates(states);
|
protocol_->SendIotStates(states);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::Reboot() {
|
||||||
|
ESP_LOGI(TAG, "Rebooting...");
|
||||||
|
esp_restart();
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ enum DeviceState {
|
|||||||
kDeviceStateListening,
|
kDeviceStateListening,
|
||||||
kDeviceStateSpeaking,
|
kDeviceStateSpeaking,
|
||||||
kDeviceStateUpgrading,
|
kDeviceStateUpgrading,
|
||||||
|
kDeviceStateActivating,
|
||||||
kDeviceStateFatalError
|
kDeviceStateFatalError
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,12 +56,13 @@ public:
|
|||||||
bool IsVoiceDetected() const { return voice_detected_; }
|
bool IsVoiceDetected() const { return voice_detected_; }
|
||||||
void Schedule(std::function<void()> callback);
|
void Schedule(std::function<void()> callback);
|
||||||
void SetDeviceState(DeviceState state);
|
void SetDeviceState(DeviceState state);
|
||||||
void Alert(const std::string& title, const std::string& message);
|
void Alert(const std::string& status, const std::string& message, const std::string& emotion = "", const std::string& sound = "");
|
||||||
void AbortSpeaking(AbortReason reason);
|
void AbortSpeaking(AbortReason reason);
|
||||||
void ToggleChatState();
|
void ToggleChatState();
|
||||||
void StartListening();
|
void StartListening();
|
||||||
void StopListening();
|
void StopListening();
|
||||||
void UpdateIotStates();
|
void UpdateIotStates();
|
||||||
|
void Reboot();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Application();
|
Application();
|
||||||
@@ -100,7 +102,7 @@ private:
|
|||||||
void ResetDecoder();
|
void ResetDecoder();
|
||||||
void SetDecodeSampleRate(int sample_rate);
|
void SetDecodeSampleRate(int sample_rate);
|
||||||
void CheckNewVersion();
|
void CheckNewVersion();
|
||||||
void DisplayActivationCode();
|
void ShowActivationCode();
|
||||||
|
|
||||||
void PlayLocalFile(const char* data, size_t size);
|
void PlayLocalFile(const char* data, size_t size);
|
||||||
};
|
};
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
main/assets/zh/0.p3
Normal file
BIN
main/assets/zh/0.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/1.p3
Normal file
BIN
main/assets/zh/1.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/2.p3
Normal file
BIN
main/assets/zh/2.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/3.p3
Normal file
BIN
main/assets/zh/3.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/4.p3
Normal file
BIN
main/assets/zh/4.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/5.p3
Normal file
BIN
main/assets/zh/5.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/6.p3
Normal file
BIN
main/assets/zh/6.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/7.p3
Normal file
BIN
main/assets/zh/7.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/8.p3
Normal file
BIN
main/assets/zh/8.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/9.p3
Normal file
BIN
main/assets/zh/9.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/activation.p3
Normal file
BIN
main/assets/zh/activation.p3
Normal file
Binary file not shown.
39
main/assets/zh/binary.h
Normal file
39
main/assets/zh/binary.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef BINARY_H
|
||||||
|
#define BINARY_H
|
||||||
|
|
||||||
|
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_wificonfig_start[] asm("_binary_wificonfig_p3_start");
|
||||||
|
extern const char p3_wificonfig_end[] asm("_binary_wificonfig_p3_end");
|
||||||
|
extern const char p3_upgrade_start[] asm("_binary_upgrade_p3_start");
|
||||||
|
extern const char p3_upgrade_end[] asm("_binary_upgrade_p3_end");
|
||||||
|
extern const char p3_activation_start[] asm("_binary_activation_p3_start");
|
||||||
|
extern const char p3_activation_end[] asm("_binary_activation_p3_end");
|
||||||
|
extern const char p3_welcome_start[] asm("_binary_welcome_p3_start");
|
||||||
|
extern const char p3_welcome_end[] asm("_binary_welcome_p3_end");
|
||||||
|
|
||||||
|
extern const char p3_0_start[] asm("_binary_0_p3_start");
|
||||||
|
extern const char p3_0_end[] asm("_binary_0_p3_end");
|
||||||
|
extern const char p3_1_start[] asm("_binary_1_p3_start");
|
||||||
|
extern const char p3_1_end[] asm("_binary_1_p3_end");
|
||||||
|
extern const char p3_2_start[] asm("_binary_2_p3_start");
|
||||||
|
extern const char p3_2_end[] asm("_binary_2_p3_end");
|
||||||
|
extern const char p3_3_start[] asm("_binary_3_p3_start");
|
||||||
|
extern const char p3_3_end[] asm("_binary_3_p3_end");
|
||||||
|
extern const char p3_4_start[] asm("_binary_4_p3_start");
|
||||||
|
extern const char p3_4_end[] asm("_binary_4_p3_end");
|
||||||
|
extern const char p3_5_start[] asm("_binary_5_p3_start");
|
||||||
|
extern const char p3_5_end[] asm("_binary_5_p3_end");
|
||||||
|
extern const char p3_6_start[] asm("_binary_6_p3_start");
|
||||||
|
extern const char p3_6_end[] asm("_binary_6_p3_end");
|
||||||
|
extern const char p3_7_start[] asm("_binary_7_p3_start");
|
||||||
|
extern const char p3_7_end[] asm("_binary_7_p3_end");
|
||||||
|
extern const char p3_8_start[] asm("_binary_8_p3_start");
|
||||||
|
extern const char p3_8_end[] asm("_binary_8_p3_end");
|
||||||
|
extern const char p3_9_start[] asm("_binary_9_p3_start");
|
||||||
|
extern const char p3_9_end[] asm("_binary_9_p3_end");
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
BIN
main/assets/zh/err_pin.p3
Normal file
BIN
main/assets/zh/err_pin.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/err_reg.p3
Normal file
BIN
main/assets/zh/err_reg.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/sounds.tar.gz
Normal file
BIN
main/assets/zh/sounds.tar.gz
Normal file
Binary file not shown.
BIN
main/assets/zh/upgrade.p3
Normal file
BIN
main/assets/zh/upgrade.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/welcome.p3
Normal file
BIN
main/assets/zh/welcome.p3
Normal file
Binary file not shown.
BIN
main/assets/zh/wificonfig.p3
Normal file
BIN
main/assets/zh/wificonfig.p3
Normal file
Binary file not shown.
@@ -20,7 +20,10 @@ BackgroundTask::~BackgroundTask() {
|
|||||||
void BackgroundTask::Schedule(std::function<void()> callback) {
|
void BackgroundTask::Schedule(std::function<void()> callback) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
if (active_tasks_ >= 30) {
|
if (active_tasks_ >= 30) {
|
||||||
ESP_LOGW(TAG, "active_tasks_ == %u", active_tasks_.load());
|
int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||||
|
if (free_sram < 10000) {
|
||||||
|
ESP_LOGW(TAG, "active_tasks_ == %u, free_sram == %u", active_tasks_.load(), free_sram);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
active_tasks_++;
|
active_tasks_++;
|
||||||
main_tasks_.emplace_back([this, cb = std::move(callback)]() {
|
main_tasks_.emplace_back([this, cb = std::move(callback)]() {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "font_awesome_symbols.h"
|
#include "font_awesome_symbols.h"
|
||||||
|
#include "assets/zh/binary.h"
|
||||||
|
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include <esp_timer.h>
|
#include <esp_timer.h>
|
||||||
@@ -24,7 +25,7 @@ std::string Ml307Board::GetBoardType() {
|
|||||||
|
|
||||||
void Ml307Board::StartNetwork() {
|
void Ml307Board::StartNetwork() {
|
||||||
auto display = Board::GetInstance().GetDisplay();
|
auto display = Board::GetInstance().GetDisplay();
|
||||||
display->SetStatus("初始化模块");
|
display->SetStatus("检测模组...");
|
||||||
modem_.SetDebug(false);
|
modem_.SetDebug(false);
|
||||||
modem_.SetBaudRate(921600);
|
modem_.SetBaudRate(921600);
|
||||||
|
|
||||||
@@ -47,10 +48,10 @@ void Ml307Board::WaitForNetworkReady() {
|
|||||||
display->SetStatus("等待网络...");
|
display->SetStatus("等待网络...");
|
||||||
int result = modem_.WaitForNetworkReady();
|
int result = modem_.WaitForNetworkReady();
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
application.Alert("Error", "请插入SIM卡");
|
application.Alert("PIN_ERROR", "请插入SIM卡", "sad", std::string(p3_err_pin_start, p3_err_pin_end - p3_err_pin_start));
|
||||||
return;
|
return;
|
||||||
} else if (result == -2) {
|
} else if (result == -2) {
|
||||||
application.Alert("Error", "无法接入网络,请检查流量卡状态");
|
application.Alert("REG_ERROR", "无法接入网络,请检查流量卡状态", "sad", std::string(p3_err_reg_start, p3_err_reg_end - p3_err_reg_start));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "system_info.h"
|
#include "system_info.h"
|
||||||
#include "font_awesome_symbols.h"
|
#include "font_awesome_symbols.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "assets/zh/binary.h"
|
||||||
|
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
@@ -37,7 +38,6 @@ std::string WifiBoard::GetBoardType() {
|
|||||||
|
|
||||||
void WifiBoard::EnterWifiConfigMode() {
|
void WifiBoard::EnterWifiConfigMode() {
|
||||||
auto& application = Application::GetInstance();
|
auto& application = Application::GetInstance();
|
||||||
auto display = Board::GetInstance().GetDisplay();
|
|
||||||
application.SetDeviceState(kDeviceStateWifiConfiguring);
|
application.SetDeviceState(kDeviceStateWifiConfiguring);
|
||||||
|
|
||||||
auto& wifi_ap = WifiConfigurationAp::GetInstance();
|
auto& wifi_ap = WifiConfigurationAp::GetInstance();
|
||||||
@@ -50,10 +50,8 @@ void WifiBoard::EnterWifiConfigMode() {
|
|||||||
hint += ",然后打开浏览器访问 ";
|
hint += ",然后打开浏览器访问 ";
|
||||||
hint += wifi_ap.GetWebServerUrl();
|
hint += wifi_ap.GetWebServerUrl();
|
||||||
|
|
||||||
display->SetStatus(hint);
|
|
||||||
|
|
||||||
// 播报配置 WiFi 的提示
|
// 播报配置 WiFi 的提示
|
||||||
application.Alert("Info", "进入配网模式");
|
application.Alert("配网模式", hint, "", std::string(p3_wificonfig_start, p3_wificonfig_end - p3_wificonfig_start));
|
||||||
|
|
||||||
// Wait forever until reset after configuration
|
// Wait forever until reset after configuration
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -83,11 +81,11 @@ void WifiBoard::StartNetwork() {
|
|||||||
auto& wifi_station = WifiStation::GetInstance();
|
auto& wifi_station = WifiStation::GetInstance();
|
||||||
wifi_station.OnScanBegin([this]() {
|
wifi_station.OnScanBegin([this]() {
|
||||||
auto display = Board::GetInstance().GetDisplay();
|
auto display = Board::GetInstance().GetDisplay();
|
||||||
display->ShowNotification("正在扫描 WiFi 网络", 30000);
|
display->ShowNotification("扫描 WiFi...", 30000);
|
||||||
});
|
});
|
||||||
wifi_station.OnConnect([this](const std::string& ssid) {
|
wifi_station.OnConnect([this](const std::string& ssid) {
|
||||||
auto display = Board::GetInstance().GetDisplay();
|
auto display = Board::GetInstance().GetDisplay();
|
||||||
display->ShowNotification(std::string("正在连接 ") + ssid, 30000);
|
display->ShowNotification(std::string("连接 ") + ssid + "...", 30000);
|
||||||
});
|
});
|
||||||
wifi_station.OnConnected([this](const std::string& ssid) {
|
wifi_station.OnConnected([this](const std::string& ssid) {
|
||||||
auto display = Board::GetInstance().GetDisplay();
|
auto display = Board::GetInstance().GetDisplay();
|
||||||
|
|||||||
@@ -210,6 +210,11 @@ void Display::SetIcon(const char* icon) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Display::SetChatMessage(const std::string &role, const std::string &content) {
|
void Display::SetChatMessage(const std::string &role, const std::string &content) {
|
||||||
|
DisplayLockGuard lock(this);
|
||||||
|
if (chat_message_label_ == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lv_label_set_text(chat_message_label_, content.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::SetBacklight(uint8_t brightness) {
|
void Display::SetBacklight(uint8_t brightness) {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ protected:
|
|||||||
lv_obj_t *notification_label_ = nullptr;
|
lv_obj_t *notification_label_ = nullptr;
|
||||||
lv_obj_t *mute_label_ = nullptr;
|
lv_obj_t *mute_label_ = nullptr;
|
||||||
lv_obj_t *battery_label_ = nullptr;
|
lv_obj_t *battery_label_ = nullptr;
|
||||||
|
lv_obj_t* chat_message_label_ = nullptr;
|
||||||
const char* battery_icon_ = nullptr;
|
const char* battery_icon_ = nullptr;
|
||||||
const char* network_icon_ = nullptr;
|
const char* network_icon_ = nullptr;
|
||||||
bool muted_ = false;
|
bool muted_ = false;
|
||||||
|
|||||||
@@ -274,14 +274,6 @@ void LcdDisplay::SetupUI() {
|
|||||||
lv_obj_set_style_text_font(battery_label_, fonts_.icon_font, 0);
|
lv_obj_set_style_text_font(battery_label_, fonts_.icon_font, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LcdDisplay::SetChatMessage(const std::string &role, const std::string &content) {
|
|
||||||
DisplayLockGuard lock(this);
|
|
||||||
if (chat_message_label_ == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
lv_label_set_text(chat_message_label_, content.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LcdDisplay::SetEmotion(const std::string &emotion) {
|
void LcdDisplay::SetEmotion(const std::string &emotion) {
|
||||||
struct Emotion {
|
struct Emotion {
|
||||||
const char* icon;
|
const char* icon;
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ protected:
|
|||||||
lv_obj_t* content_ = nullptr;
|
lv_obj_t* content_ = nullptr;
|
||||||
lv_obj_t* container_ = nullptr;
|
lv_obj_t* container_ = nullptr;
|
||||||
lv_obj_t* side_bar_ = nullptr;
|
lv_obj_t* side_bar_ = nullptr;
|
||||||
lv_obj_t* chat_message_label_ = nullptr;
|
|
||||||
|
|
||||||
DisplayFonts fonts_;
|
DisplayFonts fonts_;
|
||||||
|
|
||||||
@@ -46,7 +45,6 @@ public:
|
|||||||
DisplayFonts fonts);
|
DisplayFonts fonts);
|
||||||
~LcdDisplay();
|
~LcdDisplay();
|
||||||
|
|
||||||
virtual void SetChatMessage(const std::string &role, const std::string &content) override;
|
|
||||||
virtual void SetEmotion(const std::string &emotion) override;
|
virtual void SetEmotion(const std::string &emotion) override;
|
||||||
virtual void SetIcon(const char* icon) override;
|
virtual void SetIcon(const char* icon) override;
|
||||||
virtual void SetBacklight(uint8_t brightness) override;
|
virtual void SetBacklight(uint8_t brightness) override;
|
||||||
|
|||||||
@@ -132,6 +132,20 @@ void Ssd1306Display::Unlock() {
|
|||||||
lvgl_port_unlock();
|
lvgl_port_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ssd1306Display::SetChatMessage(const std::string &role, const std::string &content) {
|
||||||
|
DisplayLockGuard lock(this);
|
||||||
|
if (content_right_ == nullptr) {
|
||||||
|
lv_label_set_text(chat_message_label_, content.c_str());
|
||||||
|
} else {
|
||||||
|
if (content.empty()) {
|
||||||
|
lv_obj_add_flag(content_right_, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
} else {
|
||||||
|
lv_label_set_text(chat_message_label_, content.c_str());
|
||||||
|
lv_obj_clear_flag(content_right_, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Ssd1306Display::SetupUI_128x64() {
|
void Ssd1306Display::SetupUI_128x64() {
|
||||||
DisplayLockGuard lock(this);
|
DisplayLockGuard lock(this);
|
||||||
|
|
||||||
@@ -149,20 +163,46 @@ void Ssd1306Display::SetupUI_128x64() {
|
|||||||
|
|
||||||
/* Status bar */
|
/* Status bar */
|
||||||
status_bar_ = lv_obj_create(container_);
|
status_bar_ = lv_obj_create(container_);
|
||||||
lv_obj_set_size(status_bar_, LV_HOR_RES, 18);
|
lv_obj_set_size(status_bar_, LV_HOR_RES, 16);
|
||||||
|
lv_obj_set_style_border_width(status_bar_, 0, 0);
|
||||||
|
lv_obj_set_style_pad_all(status_bar_, 0, 0);
|
||||||
lv_obj_set_style_radius(status_bar_, 0, 0);
|
lv_obj_set_style_radius(status_bar_, 0, 0);
|
||||||
|
|
||||||
/* Content */
|
/* Content */
|
||||||
content_ = lv_obj_create(container_);
|
content_ = lv_obj_create(container_);
|
||||||
lv_obj_set_scrollbar_mode(content_, LV_SCROLLBAR_MODE_OFF);
|
lv_obj_set_scrollbar_mode(content_, LV_SCROLLBAR_MODE_OFF);
|
||||||
lv_obj_set_style_radius(status_bar_, 0, 0);
|
lv_obj_set_style_radius(content_, 0, 0);
|
||||||
|
lv_obj_set_style_pad_all(content_, 0, 0);
|
||||||
lv_obj_set_width(content_, LV_HOR_RES);
|
lv_obj_set_width(content_, LV_HOR_RES);
|
||||||
lv_obj_set_flex_grow(content_, 1);
|
lv_obj_set_flex_grow(content_, 1);
|
||||||
|
lv_obj_set_flex_flow(content_, LV_FLEX_FLOW_ROW);
|
||||||
|
lv_obj_set_style_flex_main_place(content_, LV_FLEX_ALIGN_CENTER, 0);
|
||||||
|
|
||||||
emotion_label_ = lv_label_create(content_);
|
// 创建左侧固定宽度的容器
|
||||||
|
content_left_ = lv_obj_create(content_);
|
||||||
|
lv_obj_set_size(content_left_, 32, LV_SIZE_CONTENT); // 固定宽度32像素
|
||||||
|
lv_obj_set_style_pad_all(content_left_, 0, 0);
|
||||||
|
lv_obj_set_style_border_width(content_left_, 0, 0);
|
||||||
|
|
||||||
|
emotion_label_ = lv_label_create(content_left_);
|
||||||
lv_obj_set_style_text_font(emotion_label_, &font_awesome_30_1, 0);
|
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_AI_CHIP);
|
||||||
lv_obj_center(emotion_label_);
|
lv_obj_center(emotion_label_);
|
||||||
|
lv_obj_set_style_pad_top(emotion_label_, 8, 0);
|
||||||
|
|
||||||
|
// 创建右侧可扩展的容器
|
||||||
|
content_right_ = lv_obj_create(content_);
|
||||||
|
lv_obj_set_size(content_right_, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||||
|
lv_obj_set_style_pad_all(content_right_, 0, 0);
|
||||||
|
lv_obj_set_style_border_width(content_right_, 0, 0);
|
||||||
|
lv_obj_set_flex_grow(content_right_, 1);
|
||||||
|
lv_obj_add_flag(content_right_, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
chat_message_label_ = lv_label_create(content_right_);
|
||||||
|
lv_label_set_text(chat_message_label_, "");
|
||||||
|
lv_label_set_long_mode(chat_message_label_, LV_LABEL_LONG_WRAP);
|
||||||
|
lv_obj_set_width(chat_message_label_, lv_pct(100));
|
||||||
|
lv_obj_set_style_text_align(chat_message_label_, LV_TEXT_ALIGN_LEFT, 0);
|
||||||
|
|
||||||
/* Status bar */
|
/* Status bar */
|
||||||
lv_obj_set_flex_flow(status_bar_, LV_FLEX_FLOW_ROW);
|
lv_obj_set_flex_flow(status_bar_, LV_FLEX_FLOW_ROW);
|
||||||
@@ -250,17 +290,19 @@ void Ssd1306Display::SetupUI_128x32() {
|
|||||||
lv_label_set_text(battery_label_, "");
|
lv_label_set_text(battery_label_, "");
|
||||||
lv_obj_set_style_text_font(battery_label_, icon_font_, 0);
|
lv_obj_set_style_text_font(battery_label_, icon_font_, 0);
|
||||||
|
|
||||||
status_label_ = lv_label_create(side_bar_);
|
status_label_ = lv_label_create(status_bar_);
|
||||||
lv_obj_set_flex_grow(status_label_, 1);
|
lv_obj_set_style_pad_left(status_label_, 2, 0);
|
||||||
lv_obj_set_width(status_label_, width_ - 32);
|
|
||||||
lv_label_set_long_mode(status_label_, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
|
||||||
lv_label_set_text(status_label_, "正在初始化");
|
lv_label_set_text(status_label_, "正在初始化");
|
||||||
|
|
||||||
notification_label_ = lv_label_create(side_bar_);
|
notification_label_ = lv_label_create(status_bar_);
|
||||||
lv_obj_set_flex_grow(notification_label_, 1);
|
|
||||||
lv_obj_set_width(notification_label_, width_ - 32);
|
|
||||||
lv_label_set_long_mode(notification_label_, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
|
||||||
lv_label_set_text(notification_label_, "通知");
|
lv_label_set_text(notification_label_, "通知");
|
||||||
|
lv_obj_set_style_pad_left(notification_label_, 2, 0);
|
||||||
lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
chat_message_label_ = lv_label_create(side_bar_);
|
||||||
|
lv_obj_set_flex_grow(chat_message_label_, 1);
|
||||||
|
lv_obj_set_width(chat_message_label_, width_ - 32);
|
||||||
|
lv_label_set_long_mode(chat_message_label_, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
||||||
|
lv_label_set_text(chat_message_label_, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ private:
|
|||||||
|
|
||||||
lv_obj_t* status_bar_ = nullptr;
|
lv_obj_t* status_bar_ = nullptr;
|
||||||
lv_obj_t* content_ = nullptr;
|
lv_obj_t* content_ = nullptr;
|
||||||
|
lv_obj_t* content_left_ = nullptr;
|
||||||
|
lv_obj_t* content_right_ = nullptr;
|
||||||
lv_obj_t* container_ = nullptr;
|
lv_obj_t* container_ = nullptr;
|
||||||
lv_obj_t* side_bar_ = nullptr;
|
lv_obj_t* side_bar_ = nullptr;
|
||||||
|
|
||||||
@@ -29,6 +31,8 @@ public:
|
|||||||
Ssd1306Display(void* i2c_master_handle, int width, int height, bool mirror_x, bool mirror_y,
|
Ssd1306Display(void* i2c_master_handle, int width, int height, bool mirror_x, bool mirror_y,
|
||||||
const lv_font_t* text_font, const lv_font_t* icon_font);
|
const lv_font_t* text_font, const lv_font_t* icon_font);
|
||||||
~Ssd1306Display();
|
~Ssd1306Display();
|
||||||
|
|
||||||
|
virtual void SetChatMessage(const std::string &role, const std::string &content);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SSD1306_DISPLAY_H
|
#endif // SSD1306_DISPLAY_H
|
||||||
|
|||||||
@@ -211,8 +211,13 @@ void CircularStrip::OnStateChanged() {
|
|||||||
Blink(color, 100);
|
Blink(color, 100);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kDeviceStateActivating: {
|
||||||
|
StripColor color = { LOW_BRIGHTNESS, DEFAULT_BRIGHTNESS, LOW_BRIGHTNESS };
|
||||||
|
Blink(color, 500);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ESP_LOGE(TAG, "Invalid led strip event: %d", device_state);
|
ESP_LOGW(TAG, "Unknown led strip event: %d", device_state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,8 +151,12 @@ void SingleLed::OnStateChanged() {
|
|||||||
SetColor(0, DEFAULT_BRIGHTNESS, 0);
|
SetColor(0, DEFAULT_BRIGHTNESS, 0);
|
||||||
StartContinuousBlink(100);
|
StartContinuousBlink(100);
|
||||||
break;
|
break;
|
||||||
|
case kDeviceStateActivating:
|
||||||
|
SetColor(0, DEFAULT_BRIGHTNESS, 0);
|
||||||
|
StartContinuousBlink(500);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ESP_LOGE(TAG, "Invalid led strip event: %d", device_state);
|
ESP_LOGW(TAG, "Unknown led strip event: %d", device_state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ bool Ota::CheckVersion() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has_activation_code_ = false;
|
||||||
cJSON *activation = cJSON_GetObjectItem(root, "activation");
|
cJSON *activation = cJSON_GetObjectItem(root, "activation");
|
||||||
if (activation != NULL) {
|
if (activation != NULL) {
|
||||||
cJSON* message = cJSON_GetObjectItem(activation, "message");
|
cJSON* message = cJSON_GetObjectItem(activation, "message");
|
||||||
@@ -84,6 +85,7 @@ bool Ota::CheckVersion() {
|
|||||||
has_activation_code_ = true;
|
has_activation_code_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has_mqtt_config_ = false;
|
||||||
cJSON *mqtt = cJSON_GetObjectItem(root, "mqtt");
|
cJSON *mqtt = cJSON_GetObjectItem(root, "mqtt");
|
||||||
if (mqtt != NULL) {
|
if (mqtt != NULL) {
|
||||||
Settings settings("mqtt", true);
|
Settings settings("mqtt", true);
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
#define TAG "WS"
|
#define TAG "WS"
|
||||||
|
|
||||||
#ifdef CONFIG_CONNECTION_TYPE_WEBSOCKET
|
|
||||||
|
|
||||||
WebsocketProtocol::WebsocketProtocol() {
|
WebsocketProtocol::WebsocketProtocol() {
|
||||||
event_group_handle_ = xEventGroupCreate();
|
event_group_handle_ = xEventGroupCreate();
|
||||||
}
|
}
|
||||||
@@ -61,7 +59,7 @@ bool WebsocketProtocol::OpenAudioChannel() {
|
|||||||
websocket_->SetHeader("Authorization", token.c_str());
|
websocket_->SetHeader("Authorization", token.c_str());
|
||||||
websocket_->SetHeader("Protocol-Version", "1");
|
websocket_->SetHeader("Protocol-Version", "1");
|
||||||
websocket_->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str());
|
websocket_->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str());
|
||||||
websocket_->SetHeader("X-Uuid", Board::GetInstance().GetUuid().c_str());
|
websocket_->SetHeader("Client-Id", Board::GetInstance().GetUuid().c_str());
|
||||||
|
|
||||||
websocket_->OnData([this](const char* data, size_t len, bool binary) {
|
websocket_->OnData([this](const char* data, size_t len, bool binary) {
|
||||||
if (binary) {
|
if (binary) {
|
||||||
@@ -147,5 +145,3 @@ void WebsocketProtocol::ParseServerHello(const cJSON* root) {
|
|||||||
|
|
||||||
xEventGroupSetBits(event_group_handle_, WEBSOCKET_PROTOCOL_SERVER_HELLO_EVENT);
|
xEventGroupSetBits(event_group_handle_, WEBSOCKET_PROTOCOL_SERVER_HELLO_EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
Reference in New Issue
Block a user