kunlang_video/src/serial_AT.cpp
2026-01-04 17:18:24 +08:00

134 lines
4.3 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 <algorithm>
#include <chrono>
#include <mutex>
#include <thread>
#include "serail_AT.hpp"
// ================== 全局 IMEI ==================
std::string IMEI = ""; // 一般 15 位
// ================== AT 任务结构 ==================
struct AtTask
{
std::string cmd;
int interval; // 周期0 表示一次性任务
int max_retries; // -1 表示无限次
int sent_count;
std::chrono::steady_clock::time_point last_sent;
};
static std::unique_ptr<SerialPort> serial_at;
static std::thread serial_at_sender;
static std::mutex at_tasks_mutex;
// ================== AT 任务列表 ==================
static std::vector<AtTask> at_tasks = {
{"AT+GSN", 0, 3, 0, {}} // 查询 IMEI最多重试 3 次
};
// ================== 发送线程 ==================
static void serial_at_send_loop()
{
while (true)
{
if (serial_at && serial_at->is_open())
{
auto now = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> lock(at_tasks_mutex);
for (auto it = at_tasks.begin(); it != at_tasks.end();)
{
auto& task = *it;
bool should_send = false;
if (task.interval > 0)
{
if (task.last_sent.time_since_epoch().count() == 0 ||
std::chrono::duration_cast<std::chrono::seconds>(now - task.last_sent).count() >= task.interval)
{
should_send = true;
}
}
else
{
if ((task.max_retries < 0 || task.sent_count < task.max_retries) &&
(task.last_sent.time_since_epoch().count() == 0 ||
std::chrono::duration_cast<std::chrono::seconds>(now - task.last_sent).count() >= 5))
{
should_send = true;
}
else if (task.max_retries > 0 && task.sent_count >= task.max_retries)
{
LOG_ERROR("[serial_at] AT+GSN reached max retries");
// IMEI 获取失败,仍继续初始化
init_tcp_client_tbox_router(TboxConfigManager::instance().getPlatformIp(),
TboxConfigManager::instance().getPlatformPort());
it = at_tasks.erase(it);
continue;
}
}
if (should_send)
{
serial_at->send_data(task.cmd + "\r\n");
task.sent_count++;
task.last_sent = now;
}
++it;
}
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
// ================== 接收处理 ==================
static void handle_serial_at_data(const std::string& data)
{
// 拆行处理,避免粘包
std::istringstream iss(data);
std::string line;
while (std::getline(iss, line))
{
// 去空白
line.erase(0, line.find_first_not_of(" \t\r\n"));
line.erase(line.find_last_not_of(" \t\r\n") + 1);
// IMEI 通常是 15 位纯数字
if (line.size() >= 14 && line.size() <= 17 && std::all_of(line.begin(), line.end(), ::isdigit))
{
IMEI = line;
LOG_INFO("[serial_at] Extracted IMEI = " + IMEI);
init_tcp_client_tbox_router(TboxConfigManager::instance().getPlatformIp(),
TboxConfigManager::instance().getPlatformPort());
// 移除 AT+GSN 任务
std::lock_guard<std::mutex> lock(at_tasks_mutex);
at_tasks.erase(std::remove_if(at_tasks.begin(), at_tasks.end(),
[](const AtTask& task) { return task.cmd == "AT+GSN"; }),
at_tasks.end());
return;
}
}
}
// ================== 初始化接口 ==================
void init_serial_at(const std::string& device, int baudrate)
{
serial_at = std::make_unique<SerialPort>("serial_at", device, baudrate, 5);
serial_at->set_receive_callback(handle_serial_at_data);
serial_at->start();
serial_at_sender = std::thread(serial_at_send_loop);
serial_at_sender.detach();
}