Files
xiaozhi-esp32/managed_components/78__esp-ml307/src/ec801e/ec801e_ssl.cc
2025-09-05 13:25:11 +08:00

161 lines
6.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "ec801e_ssl.h"
#include <esp_log.h>
#define TAG "Ec801ESsl"
Ec801ESsl::Ec801ESsl(std::shared_ptr<AtUart> at_uart, int ssl_id) : at_uart_(at_uart), ssl_id_(ssl_id) {
event_group_handle_ = xEventGroupCreate();
urc_callback_it_ = at_uart_->RegisterUrcCallback([this](const std::string& command, const std::vector<AtArgumentValue>& arguments) {
if (command == "QSSLOPEN" && arguments.size() == 2) {
if (arguments[0].int_value == ssl_id_ && !instance_active_) {
if (arguments[1].int_value == 0) {
connected_ = true;
instance_active_ = true;
xEventGroupClearBits(event_group_handle_, EC801E_SSL_DISCONNECTED | EC801E_SSL_ERROR);
xEventGroupSetBits(event_group_handle_, EC801E_SSL_CONNECTED);
} else {
connected_ = false;
xEventGroupSetBits(event_group_handle_, EC801E_SSL_ERROR);
}
}
} else if (command == "QSSLCLOSE" && arguments.size() == 1) {
if (arguments[0].int_value == ssl_id_) {
instance_active_ = false;
}
} else if (command == "QISEND" && arguments.size() == 3) {
if (arguments[0].int_value == ssl_id_) {
if (arguments[1].int_value == 0) {
xEventGroupSetBits(event_group_handle_, EC801E_SSL_SEND_COMPLETE);
} else {
xEventGroupSetBits(event_group_handle_, EC801E_SSL_ERROR);
}
}
} else if (command == "QSSLURC" && arguments.size() >= 2) {
if (arguments[1].int_value == ssl_id_) {
if (arguments[0].string_value == "recv" && arguments.size() >= 4) {
if (stream_callback_) {
stream_callback_(at_uart_->DecodeHex(arguments[3].string_value));
}
} else if (arguments[0].string_value == "closed") {
if (connected_) {
connected_ = false;
// instance_active_ 保持 true需要发送 QICLOSE 清理
if (disconnect_callback_) {
disconnect_callback_();
}
}
xEventGroupSetBits(event_group_handle_, EC801E_SSL_DISCONNECTED);
} else {
ESP_LOGE(TAG, "Unknown QIURC command: %s", arguments[0].string_value.c_str());
}
}
} else if (command == "QSSLSTATE" && arguments.size() > 5) {
if (arguments[0].int_value == ssl_id_) {
connected_ = arguments[5].int_value == 2;
instance_active_ = true;
xEventGroupSetBits(event_group_handle_, EC801E_SSL_INITIALIZED);
}
} else if (command == "FIFO_OVERFLOW") {
xEventGroupSetBits(event_group_handle_, EC801E_SSL_ERROR);
Disconnect();
}
});
}
Ec801ESsl::~Ec801ESsl() {
Disconnect();
at_uart_->UnregisterUrcCallback(urc_callback_it_);
}
bool Ec801ESsl::Connect(const std::string& host, int port) {
// Clear bits
xEventGroupClearBits(event_group_handle_, EC801E_SSL_CONNECTED | EC801E_SSL_DISCONNECTED | EC801E_SSL_ERROR);
// Keep data in one line; Use HEX encoding in response
at_uart_->SendCommand("AT+QICFG=\"close/mode\",1;+QICFG=\"viewmode\",1;+QICFG=\"sendinfo\",1;+QICFG=\"dataformat\",0,1");
// Config SSL Context
at_uart_->SendCommand("AT+QSSLCFG=\"sslversion\",1,4;+QSSLCFG=\"ciphersuite\",1,0xFFFF;+QSSLCFG=\"seclevel\",1,0");
// at_uart_->SendCommand("AT+QSSLCFG=\"cacert\",1,\"UFS:cacert.pem\"");
// 检查这个 id 是否已经连接
std::string command = "AT+QSSLSTATE=1," + std::to_string(ssl_id_);
at_uart_->SendCommand(command);
// 断开之前的连接(不触发回调事件)
if (instance_active_) {
at_uart_->SendCommand("AT+QSSLCLOSE=" + std::to_string(ssl_id_));
xEventGroupWaitBits(event_group_handle_, EC801E_SSL_DISCONNECTED, pdTRUE, pdFALSE, SSL_CONNECT_TIMEOUT_MS / portTICK_PERIOD_MS);
instance_active_ = false;
}
// 打开 TCP 连接
command = "AT+QSSLOPEN=1,1," + std::to_string(ssl_id_) + ",\"" + host + "\"," + std::to_string(port) + ",1";
if (!at_uart_->SendCommand(command)) {
ESP_LOGE(TAG, "Failed to open TCP connection");
return false;
}
// 等待连接完成
auto bits = xEventGroupWaitBits(event_group_handle_, EC801E_SSL_CONNECTED | EC801E_SSL_ERROR, pdTRUE, pdFALSE, SSL_CONNECT_TIMEOUT_MS / portTICK_PERIOD_MS);
if (bits & EC801E_SSL_ERROR) {
ESP_LOGE(TAG, "Failed to connect to %s:%d", host.c_str(), port);
return false;
}
return true;
}
void Ec801ESsl::Disconnect() {
if (!instance_active_) {
return;
}
at_uart_->SendCommand("AT+QSSLCLOSE=" + std::to_string(ssl_id_));
if (connected_) {
connected_ = false;
if (disconnect_callback_) {
disconnect_callback_();
}
}
}
int Ec801ESsl::Send(const std::string& data) {
const size_t MAX_PACKET_SIZE = 1460;
size_t total_sent = 0;
if (!connected_) {
ESP_LOGE(TAG, "Not connected");
return -1;
}
while (total_sent < data.size()) {
size_t chunk_size = std::min(data.size() - total_sent, MAX_PACKET_SIZE);
std::string command = "AT+QSSLSEND=" + std::to_string(ssl_id_) + "," + std::to_string(chunk_size);
if (!at_uart_->SendCommandWithData(command, 1000, true, data.data() + total_sent, chunk_size)) {
ESP_LOGE(TAG, "Send command failed");
Disconnect();
return -1;
}
auto bits = xEventGroupWaitBits(event_group_handle_, EC801E_SSL_SEND_COMPLETE | EC801E_SSL_SEND_FAILED, pdTRUE, pdFALSE, pdMS_TO_TICKS(SSL_CONNECT_TIMEOUT_MS));
if (bits & EC801E_SSL_SEND_FAILED) {
ESP_LOGE(TAG, "Send failed, retry later");
vTaskDelay(pdMS_TO_TICKS(100));
continue;
} else if (!(bits & EC801E_SSL_SEND_COMPLETE)) {
ESP_LOGE(TAG, "Send timeout");
return -1;
}
total_sent += chunk_size;
}
return data.size();
}