diff --git a/include/serial_AT.hpp b/include/serial_AT.hpp index 9d3cd20..016f84a 100644 --- a/include/serial_AT.hpp +++ b/include/serial_AT.hpp @@ -2,6 +2,11 @@ #include "serial_port.h" +// 全局 IMEI(读取成功后写入) +extern std::string IMEI; + +// 初始化 AT 串口(启动线程) void init_serial_at(const std::string& device, int baudrate); -extern std::string IMEI; +// 停止 AT 串口(停止线程,join) +void stop_serial_at(); diff --git a/src/main.cpp b/src/main.cpp index 8ad97fc..5c3446c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -86,6 +86,8 @@ int main() // 停止 RecordManager 自动扫描线程 if (g_record_manager) g_record_manager->stopAutoScan(); + stop_serial_at(); + RTMPManager::stop_all(); if (mqtt_thread.joinable()) diff --git a/src/serial_AT.cpp b/src/serial_AT.cpp index 7213a84..8430a62 100644 --- a/src/serial_AT.cpp +++ b/src/serial_AT.cpp @@ -1,13 +1,20 @@ #include "serial_AT.hpp" #include +#include #include #include #include #include +#include "logger.hpp" +#include "serial_port.h" + // ================== 全局 IMEI ================== -std::string IMEI; // 一般 15 位 +std::string IMEI; + +// ================== 运行控制 ================== +static std::atomic serial_at_running{false}; // ================== AT 任务结构 ================== struct AtTask @@ -28,7 +35,9 @@ static std::vector at_tasks = {{"AT+GSN", 3, 0, {}}}; // ================== 发送线程 ================== static void serial_at_send_loop() { - while (true) + LOG_INFO("[serial_at] Sender thread started"); + + while (serial_at_running.load(std::memory_order_relaxed)) { if (!serial_at || !serial_at->is_open()) { @@ -37,32 +46,36 @@ static void serial_at_send_loop() } 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; + std::lock_guard lock(at_tasks_mutex); - if (task.sent_count >= task.max_retries) + for (auto it = at_tasks.begin(); it != at_tasks.end();) { - // 达到最大重试次数,直接移除 - it = at_tasks.erase(it); - continue; - } + auto& task = *it; - if (task.last_sent.time_since_epoch().count() == 0 || - std::chrono::duration_cast(now - task.last_sent).count() >= 5) - { - serial_at->send_data(task.cmd + "\r\n"); - task.sent_count++; - task.last_sent = now; - } + if (task.sent_count >= task.max_retries) + { + it = at_tasks.erase(it); + continue; + } - ++it; + if (task.last_sent.time_since_epoch().count() == 0 || + std::chrono::duration_cast(now - task.last_sent).count() >= 5) + { + 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)); } + + LOG_INFO("[serial_at] Sender thread exiting"); } // ================== 接收处理 ================== @@ -77,13 +90,13 @@ static void handle_serial_at_data(const std::string& data) line.erase(0, line.find_first_not_of(" \t\r\n")); line.erase(line.find_last_not_of(" \t\r\n") + 1); - // IMEI:14~17 位纯数字(不同模组略有差异) + // IMEI:14~17 位纯数字 if (line.size() >= 14 && line.size() <= 17 && std::all_of(line.begin(), line.end(), ::isdigit)) { IMEI = line; LOG_INFO("[serial_at] IMEI = " + IMEI); - // 成功后清空任务,不再发送 AT + // 成功后清空任务,不再发送 std::lock_guard lock(at_tasks_mutex); at_tasks.clear(); return; @@ -91,14 +104,44 @@ static void handle_serial_at_data(const std::string& data) } } -// ================== 初始化接口 ================== +// ================== 初始化 ================== void init_serial_at(const std::string& device, int baudrate) { - serial_at = std::make_unique("serial_at", device, baudrate, 5); + if (serial_at_running.load()) + { + LOG_WARN("[serial_at] Already running"); + return; + } + serial_at_running.store(true, std::memory_order_relaxed); + + 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(); +} + +// ================== 停止 ================== +void stop_serial_at() +{ + if (!serial_at_running.load()) return; + + LOG_INFO("[serial_at] Stopping..."); + + serial_at_running.store(false, std::memory_order_relaxed); + + if (serial_at) + { + serial_at->stop(); // 关闭串口,解除阻塞 + } + + if (serial_at_sender.joinable()) + { + serial_at_sender.join(); + } + + serial_at.reset(); + + LOG_INFO("[serial_at] Stopped cleanly"); }