Switch to 2.0 branch (#1152)

* Adapt boards to v2 partition tables

* fix esp log error

* fix display style

* reset emotion after download assets

* fix compiling

* update assets default url

* Add user only tools

* Add image cache

* smaller cache and buffer, more heap

* use MAIN_EVENT_CLOCK_TICK to avoid audio glitches

* bump to 2.0.0

* fix compiling errors

---------

Co-authored-by: Xiaoxia <terrence.huang@tenclass.com>
This commit is contained in:
Xiaoxia
2025-09-04 15:41:28 +08:00
committed by GitHub
parent 3a3dfc003e
commit 83f6f8c703
196 changed files with 3918 additions and 4902 deletions

View File

@@ -66,7 +66,7 @@ Led* Board::GetLed() {
return &led;
}
std::string Board::GetJson() {
std::string Board::GetSystemInfoJson() {
/*
{
"version": 2,
@@ -159,4 +159,8 @@ std::string Board::GetJson() {
// Close the JSON object
json += R"(})";
return json;
}
Assets* Board::GetAssets() {
return nullptr;
}

View File

@@ -11,6 +11,8 @@
#include "led/led.h"
#include "backlight.h"
#include "camera.h"
#include "assets.h"
void* create_board();
class AudioCodec;
@@ -46,10 +48,11 @@ public:
virtual void StartNetwork() = 0;
virtual const char* GetNetworkStateIcon() = 0;
virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging);
virtual std::string GetJson();
virtual std::string GetSystemInfoJson();
virtual void SetPowerSaveMode(bool enabled) = 0;
virtual std::string GetBoardJson() = 0;
virtual std::string GetDeviceStatusJson() = 0;
virtual Assets* GetAssets();
};
#define DECLARE_BOARD(BOARD_CLASS_NAME) \

View File

@@ -23,48 +23,6 @@ Esp32Camera::Esp32Camera(const camera_config_t& config) {
if (s->id.PID == GC0308_PID) {
s->set_hmirror(s, 0); // 这里控制摄像头镜像 写1镜像 写0不镜像
}
// 初始化预览图片的内存
memset(&preview_image_, 0, sizeof(preview_image_));
preview_image_.header.magic = LV_IMAGE_HEADER_MAGIC;
preview_image_.header.cf = LV_COLOR_FORMAT_RGB565;
preview_image_.header.flags = 0;
switch (config.frame_size) {
case FRAMESIZE_SVGA:
preview_image_.header.w = 800;
preview_image_.header.h = 600;
break;
case FRAMESIZE_VGA:
preview_image_.header.w = 640;
preview_image_.header.h = 480;
break;
case FRAMESIZE_QVGA:
preview_image_.header.w = 320;
preview_image_.header.h = 240;
break;
case FRAMESIZE_128X128:
preview_image_.header.w = 128;
preview_image_.header.h = 128;
break;
case FRAMESIZE_240X240:
preview_image_.header.w = 240;
preview_image_.header.h = 240;
break;
default:
ESP_LOGE(TAG, "Unsupported frame size: %d, image preview will not be shown", config.frame_size);
preview_image_.data_size = 0;
preview_image_.data = nullptr;
return;
}
preview_image_.header.stride = preview_image_.header.w * 2;
preview_image_.data_size = preview_image_.header.w * preview_image_.header.h * 2;
preview_image_.data = (uint8_t*)heap_caps_malloc(preview_image_.data_size, MALLOC_CAP_SPIRAM);
if (preview_image_.data == nullptr) {
ESP_LOGE(TAG, "Failed to allocate memory for preview image");
return;
}
}
Esp32Camera::~Esp32Camera() {
@@ -72,10 +30,6 @@ Esp32Camera::~Esp32Camera() {
esp_camera_fb_return(fb_);
fb_ = nullptr;
}
if (preview_image_.data) {
heap_caps_free((void*)preview_image_.data);
preview_image_.data = nullptr;
}
esp_camera_deinit();
}
@@ -105,27 +59,33 @@ bool Esp32Camera::Capture() {
auto end_time = esp_timer_get_time();
ESP_LOGI(TAG, "Camera captured %d frames in %d ms", frames_to_get, int((end_time - start_time) / 1000));
// 如果预览图片 buffer 为空,则跳过预览
// 但仍返回 true因为此时图像可以上传至服务器
if (preview_image_.data_size == 0) {
ESP_LOGW(TAG, "Skip preview because of unsupported frame size");
return true;
}
if (preview_image_.data == nullptr) {
ESP_LOGE(TAG, "Preview image data is not initialized");
return true;
}
// 显示预览图片
auto display = Board::GetInstance().GetDisplay();
if (display != nullptr) {
// Create a new preview image
auto img_dsc = (lv_img_dsc_t*)heap_caps_calloc(1, sizeof(lv_img_dsc_t), MALLOC_CAP_8BIT);
img_dsc->header.magic = LV_IMAGE_HEADER_MAGIC;
img_dsc->header.cf = LV_COLOR_FORMAT_RGB565;
img_dsc->header.flags = 0;
img_dsc->header.w = fb_->width;
img_dsc->header.h = fb_->height;
img_dsc->header.stride = fb_->width * 2;
img_dsc->data_size = fb_->width * fb_->height * 2;
img_dsc->data = (uint8_t*)heap_caps_malloc(img_dsc->data_size, MALLOC_CAP_SPIRAM);
if (img_dsc->data == nullptr) {
ESP_LOGE(TAG, "Failed to allocate memory for preview image");
heap_caps_free(img_dsc);
return false;
}
auto src = (uint16_t*)fb_->buf;
auto dst = (uint16_t*)preview_image_.data;
auto dst = (uint16_t*)img_dsc->data;
size_t pixel_count = fb_->len / 2;
for (size_t i = 0; i < pixel_count; i++) {
// 交换每个16位字内的字节
dst[i] = __builtin_bswap16(src[i]);
}
display->SetPreviewImage(&preview_image_);
display->SetPreviewImage(img_dsc);
}
return true;
}
@@ -188,14 +148,14 @@ bool Esp32Camera::SetVFlip(bool enabled) {
*/
std::string Esp32Camera::Explain(const std::string& question) {
if (explain_url_.empty()) {
return "{\"success\": false, \"message\": \"Image explain URL or token is not set\"}";
throw std::runtime_error("Image explain URL or token is not set");
}
// 创建局部的 JPEG 队列, 40 entries is about to store 512 * 40 = 20480 bytes of JPEG data
QueueHandle_t jpeg_queue = xQueueCreate(40, sizeof(JpegChunk));
if (jpeg_queue == nullptr) {
ESP_LOGE(TAG, "Failed to create JPEG queue");
return "{\"success\": false, \"message\": \"Failed to create JPEG queue\"}";
throw std::runtime_error("Failed to create JPEG queue");
}
// We spawn a thread to encode the image to JPEG
@@ -238,7 +198,7 @@ std::string Esp32Camera::Explain(const std::string& question) {
}
}
vQueueDelete(jpeg_queue);
return "{\"success\": false, \"message\": \"Failed to connect to explain URL\"}";
throw std::runtime_error("Failed to connect to explain URL");
}
{
@@ -291,7 +251,7 @@ std::string Esp32Camera::Explain(const std::string& question) {
if (http->GetStatusCode() != 200) {
ESP_LOGE(TAG, "Failed to upload photo, status code: %d", http->GetStatusCode());
return "{\"success\": false, \"message\": \"Failed to upload photo\"}";
throw std::runtime_error("Failed to upload photo");
}
std::string result = http->ReadAll();

View File

@@ -19,7 +19,6 @@ struct JpegChunk {
class Esp32Camera : public Camera {
private:
camera_fb_t* fb_ = nullptr;
lv_img_dsc_t preview_image_;
std::string explain_url_;
std::string explain_token_;
std::thread encoder_thread_;