// // Created by misaki on 2025/9/24. // #pragma once #include #include #include #include #include #include "ThreadManager.h" class HttpOtaUpdater { public: // OTA状态枚举 enum class OtaState { IDLE, // 空闲状态 CONNECTING, // 连接中 DOWNLOADING, // 下载中 VERIFYING, // 验证中 SUCCESS, // 成功 FAILED // 失败 }; // 进度回调函数类型 using ProgressCallback = std::function; // 状态回调函数类型 using StateCallback = std::function; // 完成回调函数类型 using FinishCallback = std::function; /** * @brief 构造函数 */ HttpOtaUpdater(); /** * @brief 析构函数 */ ~HttpOtaUpdater(); /** * @brief 开始OTA升级 * @param url HTTP下载链接 * @return true-成功开始升级,false-失败 */ bool start(const std::string& url); /** * @brief 停止OTA升级 */ void stop(); /** * @brief 检查是否正在升级 * @return true-正在升级,false-空闲 */ [[nodiscard]] bool isUpdating() const; /** * @brief 设置进度回调 * @param callback 回调函数 */ void setProgressCallback(const ProgressCallback &callback); /** * @brief 设置状态回调 * @param callback 回调函数 */ void setStateCallback(const StateCallback &callback); /** * @brief 设置完成回调 * @param callback 回调函数 */ void setFinishCallback(const FinishCallback &callback); /** * @brief 设置CA证书(用于HTTPS,保留供后期使用) * @param cert_pem PEM格式的证书内容 */ void setCACert(const char* cert_pem); /** * @brief 跳过证书通用名检查(仅用于测试,保留供后期使用) * @param skip true-跳过检查,false-不跳过 */ void skipCertCommonNameCheck(bool skip); /** * @brief 获取当前状态 * @return 当前OTA状态 */ [[nodiscard]] OtaState getCurrentState() const; /** * @brief 获取错误信息 * @return 错误信息字符串 */ [[nodiscard]] std::string getErrorMessage() const; // 禁止拷贝和赋值 HttpOtaUpdater(const HttpOtaUpdater&) = delete; HttpOtaUpdater& operator=(const HttpOtaUpdater&) = delete; private: /** * @brief OTA任务主函数 */ void otaTask(); /** * @brief 执行OTA升级 * @param url 下载链接 */ void performOta(const std::string& url); /** * @brief 更新状态 * @param state 新状态 * @param message 状态信息 */ void updateState(OtaState state, const std::string& message = ""); /** * @brief HTTPS OTA事件处理函数 * @param event 事件 */ static esp_err_t httpEventHandle(esp_http_client_event_t* event); // 成员变量 std::string m_url; ///(state)], message.c_str()); }); // 设置完成回调 otaUpdater.setFinishCallback([](bool success, const std::string& message) { if (success) { ESP_LOGI("OTA", "Completed successfully: %s", message.c_str()); } else { ESP_LOGE("OTA", "Failed: %s", message.c_str()); } }); // 如果需要HTTPS,可以在这里设置证书(保留供后期使用) // otaUpdater.setCACert(my_ca_cert_pem); // otaUpdater.skipCertCommonNameCheck(true); // 仅用于测试 } // 在websocket消息处理函数中调用 void onOtaUrlReceived(const std::string& otaUrl) { ESP_LOGI("OTA", "Received OTA URL: %s", otaUrl.c_str()); if (otaUpdater.isUpdating()) { ESP_LOGW("OTA", "OTA update is already in progress"); return; } if (otaUpdater.start(otaUrl)) { ESP_LOGI("OTA", "OTA update started successfully"); } else { ESP_LOGE("OTA", "Failed to start OTA update"); } } // 检查OTA状态 void checkOtaStatus() { if (otaUpdater.isUpdating()) { ESP_LOGI("OTA", "OTA update in progress, state: %d", static_cast(otaUpdater.getCurrentState())); } else { ESP_LOGI("OTA", "No OTA update in progress"); } std::string error = otaUpdater.getErrorMessage(); if (!error.empty()) { ESP_LOGE("OTA", "Last error: %s", error.c_str()); } } */