#include #include #include #include #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 serial_at; static std::thread serial_at_sender; static std::mutex at_tasks_mutex; // ================== AT 任务列表 ================== static std::vector 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 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(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(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 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("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(); }