修改解析逻辑

This commit is contained in:
cxh 2026-01-22 15:47:17 +08:00
parent d1e9d2fe00
commit bf36b60d82

View File

@ -39,6 +39,122 @@ static std::mutex at_tasks_mutex;
static std::unique_ptr<httplib::Server> http_server; static std::unique_ptr<httplib::Server> http_server;
static std::thread http_thread; static std::thread http_thread;
// ---------- 安全 stoi ----------
static bool safe_stoi(const std::string& s, int& v)
{
try
{
size_t idx;
v = std::stoi(s, &idx);
return idx == s.size();
}
catch (...)
{
return false;
}
}
// ---------- split CSV ----------
static std::vector<std::string> split_csv(const std::string& line)
{
std::vector<std::string> out;
std::string cur;
std::stringstream ss(line);
while (std::getline(ss, cur, ','))
{
// 去引号和空白
cur.erase(std::remove(cur.begin(), cur.end(), '"'), cur.end());
while (!cur.empty() && isspace(cur.front())) cur.erase(cur.begin());
while (!cur.empty() && isspace(cur.back())) cur.pop_back();
out.push_back(cur);
}
return out;
}
// ---------- 解析入口 ----------
static void parse_qeng_servingcell(const std::string& line)
{
auto t = split_csv(line);
if (t.size() < 5) return;
// t[0] = +QENG:
// t[1] = servingcell
if (t[0].find("+QENG") != 0) return;
if (t[1] != "servingcell") return;
// t[2] = CONNECT/NOCONN
// t[3] = RAT: LTE / NR5G-SA / NR5G-NSA
std::string rat = t[3];
int pci = -1, rsrp = 0, rsrq = 0, sinr = 0, arfcn = 0;
// ------------------------------------------
// NR5G SA 模式字段表(你的情况)
// ------------------------------------------
// +QENG:"servingcell","CONNECT","NR5G-SA","TDD",
// 460,00, <NR CellID>, TAC, ARFCN, PCI,
// SSB, Beam, RSRP, RSRQ, SINR, ...
//
// 索引: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
//
if (rat == "NR5G-SA")
{
if (t.size() >= 15)
{
safe_stoi(t[9], pci);
safe_stoi(t[8], arfcn);
safe_stoi(t[12], rsrp);
safe_stoi(t[13], rsrq);
safe_stoi(t[14], sinr);
}
}
// ------------------------------------------
// LTE 模式字段表(兼容)
// ------------------------------------------
// LTE 一般字段:...,PCI= t[6], RSRP=t[11], RSRQ=t[12], SINR=t[14]
//
else if (rat == "LTE")
{
if (t.size() >= 15)
{
safe_stoi(t[6], pci);
safe_stoi(t[11], rsrp);
safe_stoi(t[12], rsrq);
safe_stoi(t[14], sinr);
}
}
// ------------------------------------------
// NSA 模式字段表(简单支持)
// ------------------------------------------
else if (rat == "NR5G-NSA")
{
// NSA 包含 LTE + NR 两部分字段,先取 LTE anchor
if (t.size() >= 15)
{
safe_stoi(t[6], pci);
safe_stoi(t[11], rsrp);
safe_stoi(t[12], rsrq);
safe_stoi(t[14], sinr);
}
}
{
std::lock_guard<std::mutex> lk(radio_mutex);
g_radio_info.pci = pci;
g_radio_info.rsrp = rsrp;
g_radio_info.rsrq = rsrq;
g_radio_info.sinr = sinr;
g_radio_info.arfcn = arfcn;
g_radio_info.raw = line;
}
LOG_INFO("[serial_at] QENG parsed: RAT=" + rat + " PCI=" + std::to_string(pci) + " RSRP=" + std::to_string(rsrp) +
" RSRQ=" + std::to_string(rsrq) + " SINR=" + std::to_string(sinr));
}
static bool is_imei_ready() static bool is_imei_ready()
{ {
std::lock_guard<std::mutex> lock(imei_mutex); std::lock_guard<std::mutex> lock(imei_mutex);
@ -203,50 +319,13 @@ static void handle_serial_at_data(const std::string& data)
// ======================= // =======================
// QENG="servingcell" 解析 // QENG="servingcell" 解析
// ======================= // =======================
if (line.rfind("+QENG:", 0) == 0 || line.find("servingcell") != std::string::npos) if (line.find("+QENG:") == 0)
{ {
std::vector<std::string> tokens; parse_qeng_servingcell(line);
std::string tmp;
std::stringstream ss(line);
while (std::getline(ss, tmp, ','))
{
// 去除双引号和空白
tmp.erase(std::remove(tmp.begin(), tmp.end(), '"'), tmp.end());
tmp.erase(0, tmp.find_first_not_of(" \t"));
tmp.erase(tmp.find_last_not_of(" \t") + 1);
tokens.push_back(tmp);
}
// LTE 格式固定至少 15~17 字段
if (tokens.size() >= 15)
{
// 对号入座
int pci = std::stoi(tokens[6]); // 物理小区编号
int band = std::stoi(tokens[8]); // LTE band
int rsrp = std::stoi(tokens[11]); // dBm
int rsrq = std::stoi(tokens[12]); // dB
int sinr = std::stoi(tokens[14]); // dB
{
std::lock_guard<std::mutex> lk(radio_mutex);
g_radio_info.pci = pci;
g_radio_info.band = band;
g_radio_info.rsrp = rsrp;
g_radio_info.rsrq = rsrq;
g_radio_info.sinr = sinr;
g_radio_info.raw = line; // 保留原始字符串用于调试
}
LOG_INFO("[serial_at] QENG parsed: RSRP=" + std::to_string(rsrp) + " RSRQ=" + std::to_string(rsrq) +
" SINR=" + std::to_string(sinr) + " PCI=" + std::to_string(pci) +
" BAND=" + std::to_string(band));
continue; continue;
} }
} }
} }
}
// ================== 初始化 ================== // ================== 初始化 ==================
void init_serial_at(const std::string& device, int baudrate) void init_serial_at(const std::string& device, int baudrate)