修复4G串口打不开,程序启动失败问题

This commit is contained in:
2026-03-05 13:40:03 +08:00
parent 0448084da5
commit 99ad0a33df
6 changed files with 169 additions and 16 deletions

View File

@@ -3,6 +3,10 @@ UUID:"mjb64bcdgdm7q"
#以下配置用于获取云端发送秘钥
ServerPwd:"1905168ed33af18c0cd09d996e82e71d"
# 以下配置用于储存ICCID
ICCID:898604581824D0366321
#以下配置存储GPIO输出高低电平--状态机
outPutMode:false

View File

@@ -16864,3 +16864,13 @@
2026-01-10 09:30:10 - 读取ICCID异常: (5, 'Input/output error')
2026-03-05 11:00:05 - ICCID刷新线程启动
2026-03-05 11:00:05 - 主程序异常: [Errno 2] No such file or directory: '/mnt/save/warning'
2026-03-05 12:38:03 - ICCID刷新线程启动
2026-03-05 12:38:03 - 主程序异常: [Errno 2] No such file or directory: '/mnt/save/warning'
2026-03-05 12:46:00 - ICCID刷新线程启动
2026-03-05 12:46:00 - 主程序异常: [Errno 2] No such file or directory: '/mnt/save/warning'
2026-03-05 12:51:05 - ICCID刷新线程启动
2026-03-05 12:51:05 - 主程序异常: [Errno 2] No such file or directory: '/mnt/save/warning'
2026-03-05 13:27:21 - ICCID刷新线程启动
2026-03-05 13:27:21 - 主程序异常: [Errno 2] No such file or directory: '/mnt/save/warning'
2026-03-05 13:36:37 - ICCID刷新线程启动
2026-03-05 13:36:37 - 主程序异常: [Errno 2] No such file or directory: '/mnt/save/warning'

Binary file not shown.

View File

@@ -839,6 +839,7 @@ bool videoInit(VideoCapture &cap)
cap.set(CAP_PROP_FRAME_HEIGHT, 480);
cap.set(CAP_PROP_FPS, 30);
cap.set(CAP_PROP_BUFFERSIZE, 1);
// 尝试 MJPG若不支持则忽略
cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G'));
double fccv = cap.get(CAP_PROP_FOURCC);
@@ -887,6 +888,7 @@ bool processFrame(VideoCapture &cap, FILE *pipe, Mat &frame, int64 &count, chron
this_thread::sleep_for(50ms);
return true;
}
handleFrame = frame;
vector<Dection> destCopy;

Binary file not shown.

View File

@@ -267,14 +267,40 @@ void startCamera()
// 初始化MQTT
void mqttInit()
{
client.set_connected_handler([](const string &cause)
{ cout << "Connected Successed!\n"; });
client.set_message_callback(getMsgCallback);
// 连接服务器
// 连接服务器,增加重试与异常处理,避免崩溃
const int maxAttempts = 3;
int attempt = 0;
while (attempt < maxAttempts)
{
try
{
client.connect()->wait();
client.subscribe(Topic, Qos)->wait();
cout << "MQTT 已连接并订阅主题\n";
return;
}
catch (const mqtt::exception &e)
{
cerr << "MQTT 连接失败: " << e.what() << " (尝试 " << (attempt + 1) << "/" << maxAttempts << ")\n";
}
catch (const std::exception &e)
{
cerr << "MQTT 连接异常: " << e.what() << " (尝试 " << (attempt + 1) << "/" << maxAttempts << ")\n";
}
catch (...)
{
cerr << "MQTT 连接发生未知异常 (尝试 " << (attempt + 1) << "/" << maxAttempts << ")\n";
}
attempt++;
std::this_thread::sleep_for(2s);
}
cerr << "MQTT 初始化失败,程序将继续运行但不使用 MQTT\n";
}
// 接收消息回调
@@ -472,6 +498,102 @@ void Exit(int sig)
// 通过串口发送 AT+CCID 指令读取并解析返回的ICCID号
string GetSimICCID(const string &tty)
{
auto trim = [](std::string s) -> std::string
{
auto is_ws = [](unsigned char c)
{ return std::isspace(c) != 0; };
while (!s.empty() && (is_ws((unsigned char)s.front()) || s.front() == '\"'))
s.erase(s.begin());
while (!s.empty() && (is_ws((unsigned char)s.back()) || s.back() == '\r' || s.back() == '\n' || s.back() == '\"'))
s.pop_back();
return s;
};
// 从配置文件读取 ICCID支持 ICCID:null / ICCID:xxxxx / ICCID=xxxxx
auto read_iccid_from_file = [&]() -> std::string
{
std::lock_guard<std::mutex> lk(envMutex);
ReadFile rf(filepath);
if (!rf.Open())
return "";
auto lines = rf.ReadLines();
rf.Close();
for (auto &line : lines)
{
// 允许空格: "ICCID: 8986..." 或 "ICCID=null"
auto posColon = line.find("ICCID:");
auto posEq = line.find("ICCID=");
size_t pos = std::string::npos;
size_t keyLen = 0;
if (posColon != std::string::npos)
{
pos = posColon;
keyLen = sizeof("ICCID:") - 1;
}
else if (posEq != std::string::npos)
{
pos = posEq;
keyLen = sizeof("ICCID=") - 1;
}
if (pos != std::string::npos)
{
std::string v = trim(line.substr(pos + keyLen));
if (v == "null" || v.empty())
return "";
return v;
}
}
return "";
};
// 写回 ICCID优先替换已有 ICCID 行;没有则追加一行 "ICCID:xxxx"
auto write_iccid_to_file = [&](const std::string &iccid) -> void
{
if (iccid.empty())
return;
std::lock_guard<std::mutex> lk(envMutex);
ReadFile rf(filepath);
if (!rf.Open())
{
std::cerr << "ICCID 写入失败,无法打开文件: " << filepath << std::endl;
return;
}
auto lines = rf.ReadLines();
rf.Close();
bool replaced = false;
for (auto &line : lines)
{
// 覆盖这几类ICCID:null / ICCID:old / ICCID=old
if (line.rfind("ICCID:", 0) == 0 || line.rfind("ICCID=", 0) == 0)
{
line = std::string("ICCID:") + iccid;
replaced = true;
break;
}
}
if (!replaced)
lines.push_back(std::string("ICCID:") + iccid);
std::string out;
out.reserve(4096);
for (size_t i = 0; i < lines.size(); ++i)
{
out += lines[i];
if (i + 1 < lines.size())
out += "\n";
}
WriteFile wf(filepath);
wf.overwriteText(out);
};
int retry = 0;
while (retry < 5)
{
@@ -480,6 +602,13 @@ string GetSimICCID(const string &tty)
if (fd < 0)
{
std::cerr << "无法打开串口: " << tty << std::endl;
// 1) 无法打开串口 -> 读取文件上次写入的 ICCID 返回
std::string cached = read_iccid_from_file();
if (!cached.empty())
return cached;
std::cerr << "未找到可用的缓存 ICCID文件无 ICCID 或为 null" << std::endl;
return "";
}
@@ -498,12 +627,10 @@ string GetSimICCID(const string &tty)
auto send_and_read = [&](const char *cmd) -> std::string
{
// 清空缓冲并发送
tcflush(fd, TCIOFLUSH);
write(fd, cmd, strlen(cmd));
std::string result;
char buf[256] = {0};
// 轮询读取累计约2秒
for (int i = 0; i < 20; ++i)
{
int n = read(fd, buf, sizeof(buf));
@@ -514,7 +641,6 @@ string GetSimICCID(const string &tty)
return result;
};
// 先试 AT+QCCID失败再试 AT+CCID
std::string result = send_and_read("AT+QCCID\r\n");
if (result.find("+QCCID") == std::string::npos)
{
@@ -524,16 +650,12 @@ string GetSimICCID(const string &tty)
}
close(fd);
// 打印原始回应便于调试
std::string debug = result;
// 清理换行
debug.erase(std::remove_if(debug.begin(), debug.end(),
[](unsigned char c)
{ return c == '\r' || c == '\n'; }),
debug.end());
// std::cout << "ICCID原始回应: " << debug << std::endl;
// 错误重试
if (result.find("ERROR") != std::string::npos)
{
retry++;
@@ -541,22 +663,21 @@ string GetSimICCID(const string &tty)
continue;
}
// 解析(支持字母数字)
std::smatch m;
// +QCCID 或 +CCID 后取字母数字
std::regex reg(R"(\+(?:Q)?CCID:\s*([0-9A-Za-z]+))");
if (std::regex_search(debug, m, reg))
{
std::string iccid = m[1];
// 去掉尾部OK或非字母数字
while (!iccid.empty() && !std::isalnum(static_cast<unsigned char>(iccid.back())))
iccid.pop_back();
if (iccid.size() >= 2 && iccid.substr(iccid.size() - 2) == "OK")
iccid.erase(iccid.size() - 2);
// 2) 成功读到 ICCID -> 写入/更新文件
write_iccid_to_file(iccid);
return iccid;
}
// 兜底19~22位的字母数字如尾部含 D
std::regex reg2(R"(([0-9A-Za-z]{19,22}))");
if (std::regex_search(debug, m, reg2))
{
@@ -565,10 +686,11 @@ string GetSimICCID(const string &tty)
iccid.pop_back();
if (iccid.size() >= 2 && iccid.substr(iccid.size() - 2) == "OK")
iccid.erase(iccid.size() - 2);
write_iccid_to_file(iccid);
return iccid;
}
// 进一步兜底:手工截取 +QCCID: / +CCID: 后的连续字母数字
auto parse_after = [&](const std::string &s, const std::string &key) -> std::string
{
size_t pos = s.find(key);
@@ -585,17 +707,32 @@ string GetSimICCID(const string &tty)
iccid.erase(iccid.size() - 2);
return iccid;
};
{
std::string iccid = parse_after(debug, "+QCCID:");
if (iccid.empty())
iccid = parse_after(debug, "+CCID:");
if (!iccid.empty())
{
write_iccid_to_file(iccid);
return iccid;
}
}
retry++;
usleep(200000);
}
// 多次重试失败:最后再尝试用缓存兜底(可选,但更符合“尽量别失败”)
std::string cached = read_iccid_from_file();
if (!cached.empty())
{
std::cerr << "多次尝试失败,使用缓存的 ICCID 作为兜底: " << cached << std::endl;
return cached;
}
std::cerr << "未找到可用的缓存 ICCID文件无 ICCID 或为 null" << std::endl;
return "";
}