1. 完成了ota功能的基本测试,测试通过
2. 封装了一个模板线程类,支持创建来自单例类的成员函数线程,普通类的线程,普通函数线程 3. 封装了一个Wifi模块类,支持Wifi的各种基本配置
This commit is contained in:
@@ -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.
|
||||
//
|
||||
|
||||
#include "ToolsClass.h"
|
||||
@@ -3,14 +3,10 @@
|
||||
//
|
||||
#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是否连接成功
|
||||
};
|
||||
Reference in New Issue
Block a user