修复4G串口打不开,程序启动失败问题
This commit is contained in:
@@ -3,6 +3,10 @@ UUID:"mjb64bcdgdm7q"
|
|||||||
|
|
||||||
#以下配置用于获取云端发送秘钥
|
#以下配置用于获取云端发送秘钥
|
||||||
ServerPwd:"1905168ed33af18c0cd09d996e82e71d"
|
ServerPwd:"1905168ed33af18c0cd09d996e82e71d"
|
||||||
|
|
||||||
|
# 以下配置用于储存ICCID
|
||||||
|
ICCID:898604581824D0366321
|
||||||
|
|
||||||
#以下配置存储GPIO输出高低电平--状态机
|
#以下配置存储GPIO输出高低电平--状态机
|
||||||
outPutMode:false
|
outPutMode:false
|
||||||
|
|
||||||
|
|||||||
@@ -16864,3 +16864,13 @@
|
|||||||
2026-01-10 09:30:10 - 读取ICCID异常: (5, 'Input/output error')
|
2026-01-10 09:30:10 - 读取ICCID异常: (5, 'Input/output error')
|
||||||
2026-03-05 11:00:05 - ICCID刷新线程启动
|
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 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.
@@ -839,6 +839,7 @@ bool videoInit(VideoCapture &cap)
|
|||||||
cap.set(CAP_PROP_FRAME_HEIGHT, 480);
|
cap.set(CAP_PROP_FRAME_HEIGHT, 480);
|
||||||
cap.set(CAP_PROP_FPS, 30);
|
cap.set(CAP_PROP_FPS, 30);
|
||||||
cap.set(CAP_PROP_BUFFERSIZE, 1);
|
cap.set(CAP_PROP_BUFFERSIZE, 1);
|
||||||
|
|
||||||
// 尝试 MJPG,若不支持则忽略
|
// 尝试 MJPG,若不支持则忽略
|
||||||
cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G'));
|
cap.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G'));
|
||||||
double fccv = cap.get(CAP_PROP_FOURCC);
|
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);
|
this_thread::sleep_for(50ms);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFrame = frame;
|
handleFrame = frame;
|
||||||
|
|
||||||
vector<Dection> destCopy;
|
vector<Dection> destCopy;
|
||||||
|
|||||||
Binary file not shown.
@@ -267,14 +267,40 @@ void startCamera()
|
|||||||
// 初始化MQTT
|
// 初始化MQTT
|
||||||
void mqttInit()
|
void mqttInit()
|
||||||
{
|
{
|
||||||
|
|
||||||
client.set_connected_handler([](const string &cause)
|
client.set_connected_handler([](const string &cause)
|
||||||
{ cout << "Connected Successed!\n"; });
|
{ cout << "Connected Successed!\n"; });
|
||||||
client.set_message_callback(getMsgCallback);
|
client.set_message_callback(getMsgCallback);
|
||||||
|
|
||||||
// 连接服务器
|
// 连接服务器,增加重试与异常处理,避免崩溃
|
||||||
client.connect()->wait();
|
const int maxAttempts = 3;
|
||||||
client.subscribe(Topic, Qos)->wait();
|
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号
|
// 通过串口发送 AT+CCID 指令,读取并解析返回的ICCID号
|
||||||
string GetSimICCID(const string &tty)
|
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;
|
int retry = 0;
|
||||||
while (retry < 5)
|
while (retry < 5)
|
||||||
{
|
{
|
||||||
@@ -480,6 +602,13 @@ string GetSimICCID(const string &tty)
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
std::cerr << "无法打开串口: " << tty << std::endl;
|
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 "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,12 +627,10 @@ string GetSimICCID(const string &tty)
|
|||||||
|
|
||||||
auto send_and_read = [&](const char *cmd) -> std::string
|
auto send_and_read = [&](const char *cmd) -> std::string
|
||||||
{
|
{
|
||||||
// 清空缓冲并发送
|
|
||||||
tcflush(fd, TCIOFLUSH);
|
tcflush(fd, TCIOFLUSH);
|
||||||
write(fd, cmd, strlen(cmd));
|
write(fd, cmd, strlen(cmd));
|
||||||
std::string result;
|
std::string result;
|
||||||
char buf[256] = {0};
|
char buf[256] = {0};
|
||||||
// 轮询读取,累计约2秒
|
|
||||||
for (int i = 0; i < 20; ++i)
|
for (int i = 0; i < 20; ++i)
|
||||||
{
|
{
|
||||||
int n = read(fd, buf, sizeof(buf));
|
int n = read(fd, buf, sizeof(buf));
|
||||||
@@ -514,7 +641,6 @@ string GetSimICCID(const string &tty)
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 先试 AT+QCCID,失败再试 AT+CCID
|
|
||||||
std::string result = send_and_read("AT+QCCID\r\n");
|
std::string result = send_and_read("AT+QCCID\r\n");
|
||||||
if (result.find("+QCCID") == std::string::npos)
|
if (result.find("+QCCID") == std::string::npos)
|
||||||
{
|
{
|
||||||
@@ -524,16 +650,12 @@ string GetSimICCID(const string &tty)
|
|||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
// 打印原始回应便于调试
|
|
||||||
std::string debug = result;
|
std::string debug = result;
|
||||||
// 清理换行
|
|
||||||
debug.erase(std::remove_if(debug.begin(), debug.end(),
|
debug.erase(std::remove_if(debug.begin(), debug.end(),
|
||||||
[](unsigned char c)
|
[](unsigned char c)
|
||||||
{ return c == '\r' || c == '\n'; }),
|
{ return c == '\r' || c == '\n'; }),
|
||||||
debug.end());
|
debug.end());
|
||||||
// std::cout << "ICCID原始回应: " << debug << std::endl;
|
|
||||||
|
|
||||||
// 错误重试
|
|
||||||
if (result.find("ERROR") != std::string::npos)
|
if (result.find("ERROR") != std::string::npos)
|
||||||
{
|
{
|
||||||
retry++;
|
retry++;
|
||||||
@@ -541,22 +663,21 @@ string GetSimICCID(const string &tty)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析(支持字母数字)
|
|
||||||
std::smatch m;
|
std::smatch m;
|
||||||
// +QCCID 或 +CCID 后取字母数字
|
|
||||||
std::regex reg(R"(\+(?:Q)?CCID:\s*([0-9A-Za-z]+))");
|
std::regex reg(R"(\+(?:Q)?CCID:\s*([0-9A-Za-z]+))");
|
||||||
if (std::regex_search(debug, m, reg))
|
if (std::regex_search(debug, m, reg))
|
||||||
{
|
{
|
||||||
std::string iccid = m[1];
|
std::string iccid = m[1];
|
||||||
// 去掉尾部OK或非字母数字
|
|
||||||
while (!iccid.empty() && !std::isalnum(static_cast<unsigned char>(iccid.back())))
|
while (!iccid.empty() && !std::isalnum(static_cast<unsigned char>(iccid.back())))
|
||||||
iccid.pop_back();
|
iccid.pop_back();
|
||||||
if (iccid.size() >= 2 && iccid.substr(iccid.size() - 2) == "OK")
|
if (iccid.size() >= 2 && iccid.substr(iccid.size() - 2) == "OK")
|
||||||
iccid.erase(iccid.size() - 2);
|
iccid.erase(iccid.size() - 2);
|
||||||
|
|
||||||
|
// 2) 成功读到 ICCID -> 写入/更新文件
|
||||||
|
write_iccid_to_file(iccid);
|
||||||
return iccid;
|
return iccid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 兜底:19~22位的字母数字(如尾部含 D)
|
|
||||||
std::regex reg2(R"(([0-9A-Za-z]{19,22}))");
|
std::regex reg2(R"(([0-9A-Za-z]{19,22}))");
|
||||||
if (std::regex_search(debug, m, reg2))
|
if (std::regex_search(debug, m, reg2))
|
||||||
{
|
{
|
||||||
@@ -565,10 +686,11 @@ string GetSimICCID(const string &tty)
|
|||||||
iccid.pop_back();
|
iccid.pop_back();
|
||||||
if (iccid.size() >= 2 && iccid.substr(iccid.size() - 2) == "OK")
|
if (iccid.size() >= 2 && iccid.substr(iccid.size() - 2) == "OK")
|
||||||
iccid.erase(iccid.size() - 2);
|
iccid.erase(iccid.size() - 2);
|
||||||
|
|
||||||
|
write_iccid_to_file(iccid);
|
||||||
return iccid;
|
return iccid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 进一步兜底:手工截取 +QCCID: / +CCID: 后的连续字母数字
|
|
||||||
auto parse_after = [&](const std::string &s, const std::string &key) -> std::string
|
auto parse_after = [&](const std::string &s, const std::string &key) -> std::string
|
||||||
{
|
{
|
||||||
size_t pos = s.find(key);
|
size_t pos = s.find(key);
|
||||||
@@ -585,17 +707,32 @@ string GetSimICCID(const string &tty)
|
|||||||
iccid.erase(iccid.size() - 2);
|
iccid.erase(iccid.size() - 2);
|
||||||
return iccid;
|
return iccid;
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string iccid = parse_after(debug, "+QCCID:");
|
std::string iccid = parse_after(debug, "+QCCID:");
|
||||||
if (iccid.empty())
|
if (iccid.empty())
|
||||||
iccid = parse_after(debug, "+CCID:");
|
iccid = parse_after(debug, "+CCID:");
|
||||||
if (!iccid.empty())
|
if (!iccid.empty())
|
||||||
|
{
|
||||||
|
write_iccid_to_file(iccid);
|
||||||
return iccid;
|
return iccid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retry++;
|
retry++;
|
||||||
usleep(200000);
|
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 "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user