1. 完成了ota功能的基本测试,测试通过
2. 封装了一个模板线程类,支持创建来自单例类的成员函数线程,普通类的线程,普通函数线程 3. 封装了一个Wifi模块类,支持Wifi的各种基本配置
This commit is contained in:
@@ -3,15 +3,3 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -6,5 +6,6 @@
|
|||||||
#include "OTAClass.h"
|
#include "OTAClass.h"
|
||||||
|
|
||||||
void Cpp_Hand() {
|
void Cpp_Hand() {
|
||||||
OTAClass::Init();
|
OTAClass oc;
|
||||||
}
|
oc.Init();
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,141 @@
|
|||||||
#include "OTAClass.h"
|
#include "OTAClass.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
#include <memory>
|
||||||
|
#include <sstream>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <esp_pthread.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
const auto sleep_time = seconds{
|
||||||
|
5
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下面的这个函数可以放在任何线程中,自动打印出对应线程的信息
|
||||||
|
void print_thread_info(const char *extra = nullptr)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
if (extra) {
|
||||||
|
ss << extra;
|
||||||
|
}
|
||||||
|
ss << "Core id: " << xPortGetCoreID()
|
||||||
|
<< ", prio: " << uxTaskPriorityGet(nullptr)
|
||||||
|
<< ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes.";
|
||||||
|
ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_func_inherited()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
print_thread_info("我是 普普通通的inherited 线程");
|
||||||
|
std::this_thread::sleep_for(sleep_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_func_any_core()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
print_thread_info("我是一个会跑在任意一个核的任务~");
|
||||||
|
std::this_thread::sleep_for(sleep_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_pthread_cfg_t create_config(const char *name, int core_id, int stack, int prio)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto cfg = esp_pthread_get_default_config();
|
||||||
|
cfg.thread_name = name;
|
||||||
|
cfg.pin_to_core = core_id;
|
||||||
|
cfg.stack_size = stack;
|
||||||
|
cfg.prio = prio;
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "ThreadManager.h"
|
||||||
|
#include "WifiConnectors.h"
|
||||||
|
#include <string>
|
||||||
void OTAClass::Init() {
|
void OTAClass::Init() {
|
||||||
ESP_LOGI("OTA", "Init");
|
ESP_LOGI("OTA", "Init");
|
||||||
|
|
||||||
|
ESP_LOGI("OTAClass::Init", "当前固件版本 1.0.1");
|
||||||
|
|
||||||
|
// 测试Wifi
|
||||||
|
// WifiConnectors::getInstance()->log();
|
||||||
|
//
|
||||||
|
// WifiConnectors::getInstance()->connectWifi("Misaki-2.4G", "88888888");
|
||||||
|
|
||||||
|
// 1. 创建普通函数一个可以运行在任意核上的线程
|
||||||
|
ThreadConfig config1;
|
||||||
|
config1.name = "NormalThread";
|
||||||
|
// config1.core_id = 0; // 不指定运行在哪个核,使其自动选择
|
||||||
|
config1.stack_size = 3072;
|
||||||
|
config1.priority = 5; // 优先级
|
||||||
|
std::thread normal_thread = ThreadManager::createThread(config1, thread_func_any_core);
|
||||||
|
|
||||||
|
ThreadConfig config2;
|
||||||
|
config2.name = "Thread2";
|
||||||
|
config2.core_id = 1; // 指定运行在核1
|
||||||
|
config2.stack_size = 3072;
|
||||||
|
config2.priority = 5;
|
||||||
|
std::thread thread2 = ThreadManager::createThread(config2, thread_func_inherited);
|
||||||
|
|
||||||
|
|
||||||
|
// 配置Wifi连接线程参数
|
||||||
|
ThreadConfig wifi_config;
|
||||||
|
wifi_config.name = "WifiConnector"; // 线程名称
|
||||||
|
wifi_config.core_id = 1; // 绑定到核心1(避免与主线程冲突)
|
||||||
|
wifi_config.stack_size = 4096; // 设置稍大的栈空间(Wifi连接可能需要)
|
||||||
|
wifi_config.priority = 6; // 设置较高优先级(确保连接及时)
|
||||||
|
// 使用单例方式创建线程,调用connectWifi成员函数
|
||||||
|
std::thread wifi_thread = ThreadManager::createSingletonThread<WifiConnectors>(
|
||||||
|
wifi_config,
|
||||||
|
&WifiConnectors::connectWifi,
|
||||||
|
"Misaki-2.4G", // SSID
|
||||||
|
"88888888", // 密码
|
||||||
|
5 // 最大重试次数
|
||||||
|
);
|
||||||
|
|
||||||
|
ThreadConfig ota_config;
|
||||||
|
ota_config.name = "OTA";
|
||||||
|
ota_config.stack_size = 4096;
|
||||||
|
ota_config.priority = 6;
|
||||||
|
ota_config.core_id = 0;
|
||||||
|
std::thread ota_thread = ThreadManager::createMemberThread<OTAClass>(
|
||||||
|
ota_config,
|
||||||
|
this,
|
||||||
|
&OTAClass::Update
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "core id: " << xPortGetCoreID()
|
||||||
|
<< ", prio: " << uxTaskPriorityGet(nullptr)
|
||||||
|
<< ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes.";
|
||||||
|
ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str());
|
||||||
|
std::this_thread::sleep_for(sleep_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "ota_ws.h"
|
||||||
|
// 启动OTA更新线程,前提是已经连接WiFi
|
||||||
|
void OTAClass::Update() {
|
||||||
|
// 测试OTA服务器192.168.1.11
|
||||||
|
while (true) {
|
||||||
|
if (WifiConnectors::getInstance()->isWifiConnect()) { // 如果Wifi已连接
|
||||||
|
ota_ws_start("192.168.1.11", 8080);
|
||||||
|
// 启动完就退出,删除自身
|
||||||
|
break;
|
||||||
|
}else {
|
||||||
|
std::this_thread::sleep_for(sleep_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelete(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,18 +4,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class OTAClass {
|
class OTAClass {
|
||||||
public:
|
public:
|
||||||
static void Init(void);
|
void Init(void);
|
||||||
void Update(void);
|
void Update(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -2,15 +2,3 @@
|
|||||||
// Created by misaki on 2025/9/2.
|
// Created by misaki on 2025/9/2.
|
||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
//
|
||||||
|
// Created by misaki on 2025/9/4.
|
||||||
|
//
|
||||||
|
#include "ThreadManager.h"
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
//
|
||||||
|
// Created by misaki on 2025/9/4.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <esp_pthread.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <sstream>
|
||||||
|
/**
|
||||||
|
* @brief 线程配置结构体
|
||||||
|
*
|
||||||
|
* 用于配置线程的各种属性,如名称、核心绑定、栈大小和优先级
|
||||||
|
*/
|
||||||
|
struct ThreadConfig {
|
||||||
|
std::string name = "thread"; // 线程名称
|
||||||
|
int core_id = -1; // 绑定核心ID (-1表示不绑定)
|
||||||
|
int stack_size = 3072; // 栈大小 (字节)
|
||||||
|
int priority = 5; // 优先级
|
||||||
|
bool inherit_cfg = false; // 是否允许子线程继承此配置
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 线程管理类
|
||||||
|
*
|
||||||
|
* 封装了ESP32上的线程创建和管理功能,支持普通函数、类成员函数和单例类成员函数
|
||||||
|
*/
|
||||||
|
class ThreadManager {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief 创建并启动一个线程
|
||||||
|
*
|
||||||
|
* @tparam Function 函数类型
|
||||||
|
* @tparam Args 参数类型
|
||||||
|
* @param config 线程配置
|
||||||
|
* @param func 要执行的函数
|
||||||
|
* @param args 函数参数
|
||||||
|
* @return std::thread 创建的线程对象
|
||||||
|
*/
|
||||||
|
template<typename Function, typename... Args>
|
||||||
|
static std::thread createThread(const ThreadConfig& config, Function&& func, Args&&... args) {
|
||||||
|
// 创建ESP32线程配置
|
||||||
|
auto esp_cfg = create_esp_config(config);
|
||||||
|
|
||||||
|
// 设置线程配置
|
||||||
|
esp_pthread_set_cfg(&esp_cfg);
|
||||||
|
|
||||||
|
// 创建并启动线程
|
||||||
|
return std::thread(std::forward<Function>(func), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建并启动一个执行类成员函数的线程
|
||||||
|
*
|
||||||
|
* @tparam T 类类型
|
||||||
|
* @tparam Method 成员函数类型
|
||||||
|
* @tparam Args 参数类型
|
||||||
|
* @param config 线程配置
|
||||||
|
* @param obj 类对象指针
|
||||||
|
* @param method 成员函数指针
|
||||||
|
* @param args 函数参数
|
||||||
|
* @return std::thread 创建的线程对象
|
||||||
|
*/
|
||||||
|
template<typename T, typename Method, typename... Args>
|
||||||
|
static std::thread createMemberThread(const ThreadConfig& config, T* obj, Method&& method, Args&&... args) {
|
||||||
|
// 使用lambda表达式包装成员函数调用
|
||||||
|
auto task = [obj, method, args...]() {
|
||||||
|
(obj->*method)(args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建ESP32线程配置
|
||||||
|
auto esp_cfg = create_esp_config(config);
|
||||||
|
|
||||||
|
// 设置线程配置
|
||||||
|
esp_pthread_set_cfg(&esp_cfg);
|
||||||
|
|
||||||
|
// 创建并启动线程
|
||||||
|
return std::thread(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建并启动一个执行单例类成员函数的线程
|
||||||
|
*
|
||||||
|
* @tparam T 单例类类型
|
||||||
|
* @tparam Method 成员函数类型
|
||||||
|
* @tparam Args 参数类型
|
||||||
|
* @param config 线程配置
|
||||||
|
* @param method 成员函数指针
|
||||||
|
* @param args 函数参数
|
||||||
|
* @return std::thread 创建的线程对象
|
||||||
|
*/
|
||||||
|
template<typename T, typename Method, typename... Args>
|
||||||
|
static std::thread createSingletonThread(const ThreadConfig& config, Method&& method, Args&&... args) {
|
||||||
|
// 获取单例实例
|
||||||
|
T* instance = T::getInstance(); // 获取单例实例,注意这里就要求每个单例都要实现这个同名的静态函数
|
||||||
|
|
||||||
|
// 使用lambda表达式包装成员函数调用
|
||||||
|
auto task = [instance, method, args...]() {
|
||||||
|
(instance->*method)(args...);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建ESP32线程配置
|
||||||
|
auto esp_cfg = create_esp_config(config);
|
||||||
|
|
||||||
|
// 设置线程配置
|
||||||
|
esp_pthread_set_cfg(&esp_cfg);
|
||||||
|
|
||||||
|
// 创建并启动线程
|
||||||
|
return std::thread(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 打印当前线程信息
|
||||||
|
*
|
||||||
|
* @param extra 额外信息
|
||||||
|
*/
|
||||||
|
static void printThreadInfo(const char *extra = nullptr) {
|
||||||
|
std::stringstream ss;
|
||||||
|
if (extra) {
|
||||||
|
ss << extra;
|
||||||
|
}
|
||||||
|
ss << "Core id: " << xPortGetCoreID()
|
||||||
|
<< ", prio: " << uxTaskPriorityGet(nullptr)
|
||||||
|
<< ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes.";
|
||||||
|
ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief 创建ESP32线程配置
|
||||||
|
*
|
||||||
|
* @param config 线程配置
|
||||||
|
* @return esp_pthread_cfg_t ESP32线程配置
|
||||||
|
*/
|
||||||
|
static esp_pthread_cfg_t create_esp_config(const ThreadConfig& config) {
|
||||||
|
auto cfg = esp_pthread_get_default_config();
|
||||||
|
cfg.thread_name = config.name.c_str();
|
||||||
|
cfg.pin_to_core = config.core_id;
|
||||||
|
cfg.stack_size = config.stack_size;
|
||||||
|
cfg.prio = config.priority;
|
||||||
|
cfg.inherit_cfg = config.inherit_cfg;
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -2,4 +2,3 @@
|
|||||||
// Created by misaki on 2025/9/2.
|
// Created by misaki on 2025/9/2.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "ToolsClass.h"
|
|
||||||
@@ -3,14 +3,10 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
/**
|
||||||
extern "C" {
|
* 本模块提供各种杂项工具类,基本都来源于对底层驱动的封装
|
||||||
#endif
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// Created by misaki on 2025/9/4.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include "WifiConnectors.h"
|
||||||
|
#include "Wireless.h"
|
||||||
|
|
||||||
|
WifiConnectors* WifiConnectors::WifiConnectorsInstance = nullptr; /// 单例实例
|
||||||
|
std::mutex WifiConnectors::m_mutex;
|
||||||
|
|
||||||
|
|
||||||
|
WifiConnectors *WifiConnectors::getInstance() {
|
||||||
|
// 双检锁(DCLP),C++11 起 atomic+mutex 组合保证线程安全
|
||||||
|
WifiConnectors* tmp = WifiConnectorsInstance;
|
||||||
|
if (tmp == nullptr) {
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
tmp = WifiConnectorsInstance;
|
||||||
|
if (tmp == nullptr) {
|
||||||
|
tmp = new WifiConnectors();
|
||||||
|
WifiConnectorsInstance = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
WifiConnectors::WifiConnectors() {
|
||||||
|
// 在此处调用底层的Wifi初始化驱动,这样Wifi就只会被初始化一次
|
||||||
|
Wireless_Init();
|
||||||
|
WIFI_Init(nullptr);
|
||||||
|
ESP_LOGI("WifiConnectors", "WifiConnectors getInstance");// 在此处调用底层的Wifi初始化驱动,这样Wifi就只会被初始化一次
|
||||||
|
}
|
||||||
|
|
||||||
|
// 析构函数
|
||||||
|
WifiConnectors::~WifiConnectors() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 连接Wifi
|
||||||
|
bool WifiConnectors::connectWifi(const std::string &ssid, const std::string &password, uint8_t max_retry) {
|
||||||
|
ESP_LOGI("WifiConnectors", "WifiConnectors connectWifi");
|
||||||
|
ESP_LOGI("WifiConnectors", "Now Try to connect %s", ssid.c_str());
|
||||||
|
if (WiFi_AutoConnect(ssid.c_str(), password.c_str(), max_retry)) {
|
||||||
|
ESP_LOGI("WifiConnectors", "WifiConnectors 连接WIFI %s 成功!!!", ssid.c_str());
|
||||||
|
this->isConnected = true; // 设置已连接
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ESP_LOGI("WifiConnectors", "WifiConnectors 连接Wifi失败!!!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 断开Wifi
|
||||||
|
bool WifiConnectors::disconnectWifi() {
|
||||||
|
if (WiFi_Disconnect() == ESP_OK) {
|
||||||
|
ESP_LOGI("WifiConnectors", "WifiConnectors disconnectWifi");
|
||||||
|
this->isConnected = false; // 设置未连接
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WifiConnectors::isWifiConnect() {
|
||||||
|
return this->isConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void WifiConnectors::log() {
|
||||||
|
ESP_LOGI("WifiConnectors", "WifiConnectors log");
|
||||||
|
|
||||||
|
WIFI_Scan();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// Created by misaki on 2025/9/4.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
class WifiConnectors{
|
||||||
|
// 显然,Wifi连接必须是单例的,否则必然出现冲突
|
||||||
|
|
||||||
|
public:
|
||||||
|
// 获取单例的静态方法
|
||||||
|
static WifiConnectors* getInstance();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void log();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接Wifi
|
||||||
|
* 注意:此处只是对连接wifi接口做了C++封装,实际调用的时候需要为连接Wifi创建一个线程,不要让其阻塞主线程
|
||||||
|
* @param ssid Wifi名称
|
||||||
|
* @param password Wifi密码
|
||||||
|
* @param max_retry 最大重连次数
|
||||||
|
* @return 最终是否连接成功
|
||||||
|
*/
|
||||||
|
bool connectWifi(const std::string& ssid, const std::string& password, uint8_t max_retry = 3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return 是否成功断开连接
|
||||||
|
*/
|
||||||
|
bool disconnectWifi();
|
||||||
|
|
||||||
|
bool isWifiConnect();
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit WifiConnectors(); // 构造函数私有化
|
||||||
|
~WifiConnectors(); // 析构函数私有化
|
||||||
|
|
||||||
|
WifiConnectors(const WifiConnectors&) = delete; // 禁止拷贝
|
||||||
|
WifiConnectors& operator=(const WifiConnectors&) = delete; // 禁止赋值
|
||||||
|
|
||||||
|
private:
|
||||||
|
static WifiConnectors *WifiConnectorsInstance; /// 单例实例指针
|
||||||
|
static std::mutex m_mutex; /// 互斥锁以确保线程安全
|
||||||
|
|
||||||
|
bool isConnected = false; /// 当前Wifi是否连接成功
|
||||||
|
};
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
//
|
||||||
|
// Created by misaki on 2025/9/4.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "app_ota.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#include "esp_http_client.h"
|
||||||
|
#include "esp_https_ota.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
static const char *TAG = "app_ota";
|
||||||
|
#define DEFAULT_VERSION "0.0.1"
|
||||||
|
|
||||||
|
/* 本地版本号,编译时可由构建系统注入 */
|
||||||
|
#ifndef APP_FW_VERSION
|
||||||
|
#define APP_FW_VERSION DEFAULT_VERSION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char s_version[] = APP_FW_VERSION;
|
||||||
|
|
||||||
|
const char *app_ota_current_version(void)
|
||||||
|
{
|
||||||
|
return s_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 简单版本号比较:a.b.c 字符串比较即可 */
|
||||||
|
static bool need_update(const char *server_ver)
|
||||||
|
{
|
||||||
|
if (!server_ver) return false;
|
||||||
|
return strcmp(server_ver, s_version) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HTTP 事件回调,仅打印进度 */
|
||||||
|
static esp_err_t http_evt(esp_http_client_event_t *evt)
|
||||||
|
{
|
||||||
|
switch (evt->event_id) {
|
||||||
|
case HTTP_EVENT_ON_DATA:
|
||||||
|
/* 数据流直接走 OTA,这里不打印 */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ota_task(void *pv)
|
||||||
|
{
|
||||||
|
char url[256];
|
||||||
|
strncpy(url, (const char *)pv, sizeof(url) - 1);
|
||||||
|
url[sizeof(url) - 1] = '\0';
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "开始 OTA,URL=%s", url);
|
||||||
|
|
||||||
|
esp_http_client_config_t http_cfg = {
|
||||||
|
.url = url,
|
||||||
|
.event_handler = http_evt,
|
||||||
|
.keep_alive_enable = true,
|
||||||
|
// 如用 https,把 cert_pem 打开即可
|
||||||
|
// .cert_pem = (const char *)server_cert_pem_start,
|
||||||
|
};
|
||||||
|
|
||||||
|
esp_https_ota_config_t ota_cfg = {
|
||||||
|
.http_config = &http_cfg,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 执行升级 */
|
||||||
|
esp_err_t ret = esp_https_ota(&ota_cfg);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ESP_LOGI(TAG, "OTA 完成,准备重启");
|
||||||
|
esp_restart();
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "OTA 失败,err=%s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t app_ota_start(const char *url)
|
||||||
|
{
|
||||||
|
if (!url) return ESP_ERR_INVALID_ARG;
|
||||||
|
/* 内部建 Task,栈 8 KB */
|
||||||
|
BaseType_t ok = xTaskCreate(ota_task, "ota_task", 8192, (void *)url, 5, NULL);
|
||||||
|
return ok == pdPASS ? ESP_OK : ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// Created by misaki on 2025/9/4.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
/* 一键启动 OTA(阻塞,内部建 Task) */
|
||||||
|
esp_err_t app_ota_start(const char *url);
|
||||||
|
|
||||||
|
/* 获取当前运行版本号(返回静态指针) */
|
||||||
|
const char *app_ota_current_version(void);
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// Created by misaki on 2025/9/4.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ota_ws.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_websocket_client.h"
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#include "esp_http_client.h"
|
||||||
|
#include "esp_https_ota.h"
|
||||||
|
#include "cJSON.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_mac.h"
|
||||||
|
|
||||||
|
static const char *TAG = "OTA_WS";
|
||||||
|
|
||||||
|
#define FW_VERSION "1.0.1" // ←每次发布修改这里
|
||||||
|
#define WS_URL_FMT "ws://%s:%d/ws?mac=%02X%02X%02X%02X%02X%02X"
|
||||||
|
|
||||||
|
static esp_websocket_client_handle_t ws = NULL;
|
||||||
|
|
||||||
|
static void ota_start(const char *url)
|
||||||
|
{
|
||||||
|
esp_http_client_config_t config = {
|
||||||
|
.url = url,
|
||||||
|
.keep_alive_enable = true,
|
||||||
|
};
|
||||||
|
esp_https_ota_config_t ota_cfg = { .http_config = &config };
|
||||||
|
ESP_LOGI(TAG, "开始下载固件...");
|
||||||
|
esp_err_t ret = esp_https_ota(&ota_cfg);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ESP_LOGI(TAG, "下载完成,重启");
|
||||||
|
esp_restart();
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "OTA 失败:%s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ws_event(void *arg, esp_event_base_t base, int32_t id, void *data)
|
||||||
|
{
|
||||||
|
esp_websocket_event_data_t *d = (esp_websocket_event_data_t *)data;
|
||||||
|
switch (id) {
|
||||||
|
case WEBSOCKET_EVENT_CONNECTED:
|
||||||
|
ESP_LOGI(TAG, "WebSocket 已连接");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WEBSOCKET_EVENT_DATA:
|
||||||
|
if (d->op_code == WS_TRANSPORT_OPCODES_TEXT) {
|
||||||
|
char *json = malloc(d->data_len + 1);
|
||||||
|
if (!json) break;
|
||||||
|
memcpy(json, d->data_ptr, d->data_len);
|
||||||
|
json[d->data_len] = 0;
|
||||||
|
|
||||||
|
cJSON *root = cJSON_Parse(json);
|
||||||
|
free(json);
|
||||||
|
if (root) {
|
||||||
|
cJSON *cmd = cJSON_GetObjectItem(root, "cmd");
|
||||||
|
if (cmd && strcmp(cmd->valuestring, "upgrade") == 0) {
|
||||||
|
const char *url = cJSON_GetObjectItem(root, "url")->valuestring;
|
||||||
|
ESP_LOGI(TAG, "收到升级指令,URL=%s", url);
|
||||||
|
ota_start(url);
|
||||||
|
}
|
||||||
|
cJSON_Delete(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WEBSOCKET_EVENT_DISCONNECTED:
|
||||||
|
ESP_LOGW(TAG, "WS 断开,5 秒后重连...");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||||
|
esp_websocket_client_start(ws);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t ota_ws_start(const char *server_ip, uint16_t port)
|
||||||
|
{
|
||||||
|
if (ws) return ESP_OK;
|
||||||
|
|
||||||
|
uint8_t mac[6];
|
||||||
|
esp_efuse_mac_get_default(mac);
|
||||||
|
char uri[128];
|
||||||
|
snprintf(uri, sizeof(uri), WS_URL_FMT,
|
||||||
|
server_ip, port, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
|
|
||||||
|
esp_websocket_client_config_t cfg = {
|
||||||
|
.uri = uri,
|
||||||
|
.ping_interval_sec = 30,
|
||||||
|
};
|
||||||
|
ws = esp_websocket_client_init(&cfg);
|
||||||
|
esp_websocket_register_events(ws, WEBSOCKET_EVENT_ANY, ws_event, NULL);
|
||||||
|
esp_websocket_client_start(ws);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// Created by misaki on 2025/9/4.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 启动 WebSocket 长连接,接收服务器推送的升级指令
|
||||||
|
* @param server_ip 服务器 IP 字符串,如 "192.168.1.100"
|
||||||
|
* @return esp_err_t
|
||||||
|
*/
|
||||||
|
esp_err_t ota_ws_start(const char *server_ip, uint16_t port);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+112
-35
@@ -14,46 +14,41 @@ ble_device_info_t *ble_device_list = NULL;
|
|||||||
void Wireless_Init(void)
|
void Wireless_Init(void)
|
||||||
{
|
{
|
||||||
// Initialize NVS.
|
// Initialize NVS.
|
||||||
esp_err_t ret = nvs_flash_init();
|
esp_err_t ret = nvs_flash_init(); // 初始化Flash
|
||||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { // 如果Flash有错误,则进行修复
|
||||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
ESP_ERROR_CHECK(nvs_flash_erase()); // 清空Flash
|
||||||
ret = nvs_flash_init();
|
ret = nvs_flash_init(); // 重新初始化Flash
|
||||||
}
|
}
|
||||||
ESP_ERROR_CHECK( ret );
|
ESP_ERROR_CHECK( ret ); // 检查错误
|
||||||
// WiFi
|
// WiFi 手动调用Wifi初始化
|
||||||
xTaskCreatePinnedToCore(
|
// xTaskCreatePinnedToCore(
|
||||||
WIFI_Init,
|
// WIFI_Init,
|
||||||
"WIFI task",
|
// "WIFI task",
|
||||||
4096,
|
// 4096,
|
||||||
NULL,
|
// NULL,
|
||||||
1,
|
// 1,
|
||||||
NULL,
|
// NULL,
|
||||||
0);
|
// 0);
|
||||||
// BLE
|
// BLE 当前工程不启用蓝牙
|
||||||
xTaskCreatePinnedToCore(
|
// xTaskCreatePinnedToCore(
|
||||||
BLE_Init,
|
// BLE_Init,
|
||||||
"BLE task",
|
// "BLE task",
|
||||||
4096,
|
// 4096,
|
||||||
NULL,
|
// NULL,
|
||||||
2,
|
// 2,
|
||||||
NULL,
|
// NULL,
|
||||||
0);
|
// 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIFI_Init(void *arg)
|
void WIFI_Init(void *arg)
|
||||||
{
|
{
|
||||||
esp_netif_init();
|
esp_netif_init(); // 初始化网络接口
|
||||||
esp_event_loop_create_default();
|
esp_event_loop_create_default(); // 创建事件循环
|
||||||
esp_netif_create_default_wifi_sta();
|
esp_netif_create_default_wifi_sta(); // 创建默认的WiFi Station
|
||||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); // 创建WiFi初始化配置(使用默认配置)
|
||||||
esp_wifi_init(&cfg);
|
esp_wifi_init(&cfg); // 初始化WiFi
|
||||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
esp_wifi_set_mode(WIFI_MODE_STA); // 设置WiFi模式为Station
|
||||||
esp_wifi_start();
|
esp_wifi_start(); // 启动WiFi
|
||||||
|
|
||||||
WIFI_NUM = WIFI_Scan();
|
|
||||||
printf("WIFI:%d\r\n",WIFI_NUM);
|
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -269,6 +264,88 @@ uint16_t BLE_Scan(void)
|
|||||||
return BLE_NUM;
|
return BLE_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 下面是新增的实现
|
||||||
|
static EventGroupHandle_t s_wifi_event_group;
|
||||||
|
#define WIFI_CONNECTED_BIT BIT0
|
||||||
|
#define WIFI_FAIL_BIT BIT1
|
||||||
|
|
||||||
|
static const char *TAG = "WiFi_UTIL";
|
||||||
|
|
||||||
|
/* --------------------------- 事件回调 --------------------------- */
|
||||||
|
static void event_handler(void *arg, esp_event_base_t event_base,
|
||||||
|
int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||||
|
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
|
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------- 自动连接 --------------------------- */
|
||||||
|
bool WiFi_AutoConnect(const char *ssid, const char *password, uint8_t max_retry)
|
||||||
|
{
|
||||||
|
if (s_wifi_event_group == NULL) {
|
||||||
|
s_wifi_event_group = xEventGroupCreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 注册一次性事件监听 */
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||||
|
WIFI_EVENT_STA_DISCONNECTED,
|
||||||
|
&event_handler,
|
||||||
|
NULL,
|
||||||
|
NULL));
|
||||||
|
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
|
||||||
|
IP_EVENT_STA_GOT_IP,
|
||||||
|
&event_handler,
|
||||||
|
NULL,
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
wifi_config_t wifi_config = { 0 };
|
||||||
|
strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
|
||||||
|
strncpy((char *)wifi_config.sta.password, password, sizeof(wifi_config.sta.password));
|
||||||
|
wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||||
|
|
||||||
|
uint8_t retry_cnt = 0;
|
||||||
|
while (retry_cnt <= max_retry) {
|
||||||
|
ESP_LOGI(TAG, "WiFi connect attempt %u/%u to \"%s\"", retry_cnt + 1, max_retry + 1, ssid);
|
||||||
|
|
||||||
|
xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT);
|
||||||
|
esp_wifi_connect();
|
||||||
|
|
||||||
|
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
||||||
|
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||||
|
pdFALSE, pdFALSE,
|
||||||
|
pdMS_TO_TICKS(6000)); /* 6 秒超时 */
|
||||||
|
|
||||||
|
if (bits & WIFI_CONNECTED_BIT) {
|
||||||
|
ESP_LOGI(TAG, "WiFi connected");
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 失败,准备重试 */
|
||||||
|
retry_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGE(TAG, "WiFi connect failed after %u retries", max_retry + 1);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
success:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------- 断开连接 --------------------------- */
|
||||||
|
esp_err_t WiFi_Disconnect(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Disconnecting WiFi...");
|
||||||
|
return esp_wifi_disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 获取WiFi AP列表
|
// 获取WiFi AP列表
|
||||||
uint16_t wireless_get_wifi_ap_list(wifi_ap_info_t *ap_list, uint16_t max_aps) {
|
uint16_t wireless_get_wifi_ap_list(wifi_ap_info_t *ap_list, uint16_t max_aps) {
|
||||||
if (!wifi_ap_list || wifi_ap_count == 0) {
|
if (!wifi_ap_list || wifi_ap_count == 0) {
|
||||||
|
|||||||
+19
-1
@@ -41,7 +41,25 @@ uint16_t WIFI_Scan(void);
|
|||||||
void BLE_Init(void *arg);
|
void BLE_Init(void *arg);
|
||||||
uint16_t BLE_Scan(void);
|
uint16_t BLE_Scan(void);
|
||||||
|
|
||||||
// 新增接口函数
|
// 下面的函数为新增的函数
|
||||||
|
// Code By Misaki
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 自动连接指定 Wi-Fi,带重试
|
||||||
|
* @param ssid 目标热点名称
|
||||||
|
* @param password 密码
|
||||||
|
* @param max_retry 最大重连次数(0 表示仅尝试一次)
|
||||||
|
* @return true 成功连接
|
||||||
|
* false 达到重试上限仍未连上
|
||||||
|
*/
|
||||||
|
bool WiFi_AutoConnect(const char *ssid, const char *password, uint8_t max_retry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 断开当前 STA 连接
|
||||||
|
*/
|
||||||
|
esp_err_t WiFi_Disconnect(void);
|
||||||
|
|
||||||
|
// 接口函数
|
||||||
uint16_t wireless_get_wifi_ap_list(wifi_ap_info_t *ap_list, uint16_t max_aps);
|
uint16_t wireless_get_wifi_ap_list(wifi_ap_info_t *ap_list, uint16_t max_aps);
|
||||||
uint16_t wireless_get_ble_device_list(ble_device_info_t *device_list, uint16_t max_devices);
|
uint16_t wireless_get_ble_device_list(ble_device_info_t *device_list, uint16_t max_devices);
|
||||||
void wireless_print_wifi_aps(void);
|
void wireless_print_wifi_aps(void);
|
||||||
|
|||||||
+12
-1
@@ -47,6 +47,16 @@ dependencies:
|
|||||||
registry_url: https://components.espressif.com/
|
registry_url: https://components.espressif.com/
|
||||||
type: service
|
type: service
|
||||||
version: 1.9.5
|
version: 1.9.5
|
||||||
|
espressif/esp_websocket_client:
|
||||||
|
component_hash: ac62982fcf9b266409c2299d2b6b1844122105b35163a3b7f8d0adaa9f7eb989
|
||||||
|
dependencies:
|
||||||
|
- name: idf
|
||||||
|
require: private
|
||||||
|
version: '>=5.0'
|
||||||
|
source:
|
||||||
|
registry_url: https://components.espressif.com/
|
||||||
|
type: service
|
||||||
|
version: 1.5.0
|
||||||
idf:
|
idf:
|
||||||
source:
|
source:
|
||||||
type: idf
|
type: idf
|
||||||
@@ -62,8 +72,9 @@ direct_dependencies:
|
|||||||
- chmorgan/esp-audio-player
|
- chmorgan/esp-audio-player
|
||||||
- chmorgan/esp-libhelix-mp3
|
- chmorgan/esp-libhelix-mp3
|
||||||
- espressif/esp-sr
|
- espressif/esp-sr
|
||||||
|
- espressif/esp_websocket_client
|
||||||
- idf
|
- idf
|
||||||
- lvgl/lvgl
|
- lvgl/lvgl
|
||||||
manifest_hash: 9bc1eee4314d6f75a0822d5e087c5603182eb609f99c1dd5726d7cea387e4d1d
|
manifest_hash: 2f09fb29ee9918e287005c3aa0d08252d2551c70eed608468245557ab01ac54b
|
||||||
target: esp32s3
|
target: esp32s3
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
|
|||||||
@@ -25,11 +25,15 @@ idf_component_register(SRCS "Bionic_sphere.c"
|
|||||||
"../Lib/Display/Touch_Driver/esp_lcd_touch/esp_lcd_touch.c" # 触摸屏驱动库
|
"../Lib/Display/Touch_Driver/esp_lcd_touch/esp_lcd_touch.c" # 触摸屏驱动库
|
||||||
"../Lib/PWR_Key/PWR_Key.c" # PWR按键驱动库
|
"../Lib/PWR_Key/PWR_Key.c" # PWR按键驱动库
|
||||||
"../Lib/MIC_Driver/MIC_Speech.c" # 录音驱动库
|
"../Lib/MIC_Driver/MIC_Speech.c" # 录音驱动库
|
||||||
|
"../Lib/OTA_Driver/app_ota.c" # OTA驱动库
|
||||||
|
"../Lib/OTA_Driver/ota_ws.c"
|
||||||
# 业务代码(使用Cpp编写)
|
# 业务代码(使用Cpp编写)
|
||||||
"../Bionic_Core/PetBaseClass/PetBaseClass.cpp" # 宠物基类库
|
"../Bionic_Core/PetBaseClass/PetBaseClass.cpp" # 宠物基类库
|
||||||
"../Bionic_Core/OTAClass/OTAClass.cpp" # OTA类库
|
"../Bionic_Core/OTAClass/OTAClass.cpp" # OTA类库
|
||||||
"../Bionic_Core/CommClass/CommClass.cpp" # 通信类库
|
"../Bionic_Core/CommClass/CommClass.cpp" # 通信类库
|
||||||
"../Bionic_Core/ToolsClass/ToolsClass.cpp" # 工具类库
|
"../Bionic_Core/ToolsClass/ToolsClass.cpp" # 工具类库
|
||||||
|
"../Bionic_Core/ToolsClass/WifiConnectors/WifiConnectors.cpp" # WIFI连接类库
|
||||||
|
"../Bionic_Core/ToolsClass/ThreadManager/ThreadManager.cpp" # 线程管理类库
|
||||||
"../Bionic_Core/CppHandle/CppHandle.cpp" # C++&C兼容库
|
"../Bionic_Core/CppHandle/CppHandle.cpp" # C++&C兼容库
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
"../test/driver_test"
|
"../test/driver_test"
|
||||||
@@ -55,10 +59,13 @@ idf_component_register(SRCS "Bionic_sphere.c"
|
|||||||
"../Lib/Display/Touch_Driver/esp_lcd_touch"
|
"../Lib/Display/Touch_Driver/esp_lcd_touch"
|
||||||
"../Lib/PWR_Key"
|
"../Lib/PWR_Key"
|
||||||
"../Lib/MIC_Driver"
|
"../Lib/MIC_Driver"
|
||||||
|
"../Lib/OTA_Driver"
|
||||||
"../Bionic_Core/PetBaseClass"
|
"../Bionic_Core/PetBaseClass"
|
||||||
"../Bionic_Core/OTAClass"
|
"../Bionic_Core/OTAClass"
|
||||||
"../Bionic_Core/CommClass"
|
"../Bionic_Core/CommClass"
|
||||||
"../Bionic_Core/ToolsClass"
|
"../Bionic_Core/ToolsClass"
|
||||||
|
"../Bionic_Core/ToolsClass/WifiConnectors"
|
||||||
|
"../Bionic_Core/ToolsClass/ThreadManager"
|
||||||
"../Bionic_Core/CppHandle"
|
"../Bionic_Core/CppHandle"
|
||||||
PRIV_REQUIRES # 私有依赖
|
PRIV_REQUIRES # 私有依赖
|
||||||
driver
|
driver
|
||||||
@@ -70,4 +77,12 @@ idf_component_register(SRCS "Bionic_sphere.c"
|
|||||||
esp_lcd
|
esp_lcd
|
||||||
lvgl__lvgl
|
lvgl__lvgl
|
||||||
fatfs
|
fatfs
|
||||||
|
pthread
|
||||||
|
app_update
|
||||||
|
esp_http_client
|
||||||
|
esp_websocket_client
|
||||||
|
esp_https_ota
|
||||||
|
json
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_compile_options(${COMPONENT_LIB} PUBLIC -std=gnu++17)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
idf: ">=4.4"
|
idf: '>=4.4'
|
||||||
lvgl/lvgl: "~8.3.0"
|
lvgl/lvgl: ~8.3.0
|
||||||
chmorgan/esp-audio-player: "==1.0.7"
|
chmorgan/esp-audio-player: ==1.0.7
|
||||||
chmorgan/esp-libhelix-mp3: "==1.0.3"
|
chmorgan/esp-libhelix-mp3: ==1.0.3
|
||||||
espressif/esp-sr: "~1.9.4"
|
espressif/esp-sr: ~1.9.4
|
||||||
|
espressif/esp_websocket_client: ^1.0.0
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
# Offset:起始地址(通常不写,让系统自动计算)。
|
# Offset:起始地址(通常不写,让系统自动计算)。
|
||||||
# Size:大小,比如 1M, 64K, 0x100000 等。
|
# Size:大小,比如 1M, 64K, 0x100000 等。
|
||||||
# Flags:可选标志,比如 encrypted(加密)。
|
# Flags:可选标志,比如 encrypted(加密)。
|
||||||
|
# 注意:因为没有设置工厂分区,那么每次烧录的时候程序会烧录在ota_0分区
|
||||||
|
# 根据官方文档OTA 数据分区的容量是 2 个 flash 扇区的大小(0x2000 字节)
|
||||||
|
# 那么可以计算出 OTA 数据分区大小最大为 64MB (2*16**3 *0x1000 / 1024 / 1024)MB
|
||||||
|
|
||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
nvs, data, nvs, , 0x6000,
|
nvs, data, nvs, , 0x6000,
|
||||||
|
|||||||
|
@@ -1413,7 +1413,7 @@ CONFIG_HTTPD_PURGE_BUF_LEN=32
|
|||||||
# ESP HTTPS OTA
|
# ESP HTTPS OTA
|
||||||
#
|
#
|
||||||
# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set
|
# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set
|
||||||
# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set
|
CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP=y
|
||||||
# end of ESP HTTPS OTA
|
# end of ESP HTTPS OTA
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -2635,6 +2635,13 @@ CONFIG_DSP_MAX_FFT_SIZE_4096=y
|
|||||||
CONFIG_DSP_MAX_FFT_SIZE=4096
|
CONFIG_DSP_MAX_FFT_SIZE=4096
|
||||||
# end of DSP Library
|
# end of DSP Library
|
||||||
|
|
||||||
|
#
|
||||||
|
# ESP WebSocket client
|
||||||
|
#
|
||||||
|
# CONFIG_ESP_WS_CLIENT_ENABLE_DYNAMIC_BUFFER is not set
|
||||||
|
# CONFIG_ESP_WS_CLIENT_SEPARATE_TX_LOCK is not set
|
||||||
|
# end of ESP WebSocket client
|
||||||
|
|
||||||
#
|
#
|
||||||
# LVGL configuration
|
# LVGL configuration
|
||||||
#
|
#
|
||||||
@@ -3184,7 +3191,7 @@ CONFIG_POST_EVENTS_FROM_ISR=y
|
|||||||
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
|
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
|
||||||
CONFIG_GDBSTUB_SUPPORT_TASKS=y
|
CONFIG_GDBSTUB_SUPPORT_TASKS=y
|
||||||
CONFIG_GDBSTUB_MAX_TASKS=32
|
CONFIG_GDBSTUB_MAX_TASKS=32
|
||||||
# CONFIG_OTA_ALLOW_HTTP is not set
|
CONFIG_OTA_ALLOW_HTTP=y
|
||||||
CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000
|
CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000
|
||||||
CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000
|
CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000
|
||||||
CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y
|
CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y
|
||||||
|
|||||||
+1
-1
@@ -778,7 +778,7 @@ CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2
|
|||||||
# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set
|
# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set
|
||||||
CONFIG_COMPILER_HIDE_PATHS_MACROS=y
|
CONFIG_COMPILER_HIDE_PATHS_MACROS=y
|
||||||
# CONFIG_COMPILER_CXX_EXCEPTIONS is not set
|
# CONFIG_COMPILER_CXX_EXCEPTIONS is not set
|
||||||
# CONFIG_COMPILER_CXX_RTTI is not set
|
CONFIG_COMPILER_CXX_RTTI=y
|
||||||
CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
|
CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
|
||||||
# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set
|
# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set
|
||||||
# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set
|
# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set
|
||||||
|
|||||||
@@ -187,4 +187,11 @@
|
|||||||
实际完成任务:
|
实际完成任务:
|
||||||
- [x] 1. 构建了业务层的基本框架(增加了底层驱动对于的C++兼容),业务代码采用C++编写,启用了RTTI(运行时类型识别)
|
- [x] 1. 构建了业务层的基本框架(增加了底层驱动对于的C++兼容),业务代码采用C++编写,启用了RTTI(运行时类型识别)
|
||||||
|
|
||||||
- [ ] 2.
|
#### Day11 2025.9.4
|
||||||
|
##### 主要目标:完成具体业务开发&各种优化
|
||||||
|
实际完成任务:
|
||||||
|
- [x] 1. 完成了ota功能的基本测试,测试通过
|
||||||
|
|
||||||
|
- [x] 2. 封装了一个模板线程类,支持创建来自单例类的成员函数线程,普通类的线程,普通函数线程
|
||||||
|
|
||||||
|
- [x] 3. 封装了一个Wifi模块类,支持Wifi的各种基本配置
|
||||||
|
|||||||
Reference in New Issue
Block a user