finanl
This commit is contained in:
@@ -535,7 +535,7 @@ namespace QCL
|
|||||||
// }
|
// }
|
||||||
// return lines;
|
// return lines;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mtx_);
|
// std::lock_guard<std::mutex> lock(mtx_);
|
||||||
if (!file_.is_open()) {
|
if (!file_.is_open()) {
|
||||||
file_.open(filename_, std::ios::in | std::ios::binary);
|
file_.open(filename_, std::ios::in | std::ios::binary);
|
||||||
if (!file_.is_open()) return {};
|
if (!file_.is_open()) return {};
|
||||||
|
|||||||
BIN
ApCreate/bin/ap
Executable file
BIN
ApCreate/bin/ap
Executable file
Binary file not shown.
Binary file not shown.
10
ApCreate/src/createAp.cpp
Normal file
10
ApCreate/src/createAp.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
string cmd = "echo 'orangepi' | sudo -S create_ap wlan0 enP4p65s0 orangepi 12345678";
|
||||||
|
thread([cmd](){ system(cmd.c_str()); }).detach();
|
||||||
|
}
|
||||||
@@ -24,11 +24,11 @@ using namespace std;
|
|||||||
using namespace QCL;
|
using namespace QCL;
|
||||||
using namespace ntq;
|
using namespace ntq;
|
||||||
using namespace encrypt;
|
using namespace encrypt;
|
||||||
|
using namespace chrono_literals;
|
||||||
namespace bp = boost::process;
|
namespace bp = boost::process;
|
||||||
|
|
||||||
bp::child rtsp_proc; // 服务器进程
|
bp::child rtsp_proc; // 服务器进程
|
||||||
bp::child video_proc; // 视频推流进程
|
bp::child video_proc; // 视频推流进程
|
||||||
bp::child ap_proc; // 创建热点进程
|
|
||||||
bp::child net_proc; // 开启网络进程
|
bp::child net_proc; // 开启网络进程
|
||||||
|
|
||||||
// 文件设置路径
|
// 文件设置路径
|
||||||
@@ -40,7 +40,7 @@ string passwd = "/home/orangepi/InitAuth/pwd/.env";
|
|||||||
const string url = "http://116.147.36.110:8095/device/validateDevice";
|
const string url = "http://116.147.36.110:8095/device/validateDevice";
|
||||||
const string mqtt_url = "tcp://192.168.12.1:1883";
|
const string mqtt_url = "tcp://192.168.12.1:1883";
|
||||||
const string clientId = "RK3588_SubTest";
|
const string clientId = "RK3588_SubTest";
|
||||||
const string Topic = "/Test";
|
const string Topic = "/bsd_camera/cmd";
|
||||||
const int Qos = 1;
|
const int Qos = 1;
|
||||||
|
|
||||||
std::atomic<bool> isRunning(true); // 全局运行标志
|
std::atomic<bool> isRunning(true); // 全局运行标志
|
||||||
@@ -61,8 +61,6 @@ struct OutSignal
|
|||||||
bool inPutMode; // 触发输入模式 true--高电平,false -- 低电平
|
bool inPutMode; // 触发输入模式 true--高电平,false -- 低电平
|
||||||
} algor{};
|
} algor{};
|
||||||
|
|
||||||
mqtt::async_client client(mqtt_url, clientId);
|
|
||||||
|
|
||||||
// 确认是否已经进行过认证
|
// 确认是否已经进行过认证
|
||||||
bool ConfirmInit();
|
bool ConfirmInit();
|
||||||
|
|
||||||
@@ -73,7 +71,7 @@ string GetCardInfo();
|
|||||||
string GetSimICCID(const string &tty = "/dev/ttyUSB2");
|
string GetSimICCID(const string &tty = "/dev/ttyUSB2");
|
||||||
|
|
||||||
// 发送cpu序列号和SIM卡号
|
// 发送cpu序列号和SIM卡号
|
||||||
void SendCardInfo(TcpServer *MyServer);
|
void SendCardInfo(mqtt::async_client &client);
|
||||||
|
|
||||||
// 进行验证
|
// 进行验证
|
||||||
bool verification();
|
bool verification();
|
||||||
@@ -83,7 +81,9 @@ template <class T>
|
|||||||
void CalculateInfo(T &conf, const string &json);
|
void CalculateInfo(T &conf, const string &json);
|
||||||
|
|
||||||
// 创建服务器
|
// 创建服务器
|
||||||
TcpServer *MyServer;
|
// TcpServer *MyServer;
|
||||||
|
// mqtt client
|
||||||
|
mqtt::async_client client(mqtt_url, clientId);
|
||||||
|
|
||||||
// 打开RSTP服务器
|
// 打开RSTP服务器
|
||||||
void OpenRTSP();
|
void OpenRTSP();
|
||||||
@@ -91,9 +91,6 @@ void OpenRTSP();
|
|||||||
// 视频推流
|
// 视频推流
|
||||||
void VideoStream();
|
void VideoStream();
|
||||||
|
|
||||||
// 接收数据
|
|
||||||
void ReceiveData();
|
|
||||||
|
|
||||||
// 退出信号捕捉
|
// 退出信号捕捉
|
||||||
void Exit(int sig);
|
void Exit(int sig);
|
||||||
|
|
||||||
@@ -128,20 +125,11 @@ int main(int argc, char *argv[])
|
|||||||
// 初始化mqtt服务器
|
// 初始化mqtt服务器
|
||||||
mqttInit();
|
mqttInit();
|
||||||
|
|
||||||
while (1)
|
// // 开启服务器
|
||||||
{
|
|
||||||
this_thread::sleep_for(chrono::seconds(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开启服务器
|
|
||||||
MyServer = new TcpServer(8848);
|
|
||||||
|
|
||||||
MyServer->start(); // 不会阻塞
|
|
||||||
|
|
||||||
// 如果没有进行过初始化,发送物联网卡信息进行认证
|
// 如果没有进行过初始化,发送物联网卡信息进行认证
|
||||||
if (ConfirmInit() == false)
|
if (ConfirmInit() == false)
|
||||||
{
|
{
|
||||||
SendCardInfo(MyServer);
|
SendCardInfo(client);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -156,29 +144,30 @@ int main(int argc, char *argv[])
|
|||||||
thread(StartService).detach();
|
thread(StartService).detach();
|
||||||
|
|
||||||
thread Rtsp(OpenRTSP);
|
thread Rtsp(OpenRTSP);
|
||||||
|
// OpenRTSP();
|
||||||
std::this_thread::sleep_for(chrono::seconds(2)); // 等待RTSP服务器启动
|
std::this_thread::sleep_for(chrono::seconds(2)); // 等待RTSP服务器启动
|
||||||
|
|
||||||
// 进行RTSP视频推流
|
// 进行RTSP视频推流
|
||||||
thread video(VideoStream);
|
thread video(VideoStream);
|
||||||
|
|
||||||
// 作为服务端进行数据的收发
|
while (isRunning)
|
||||||
thread Processing(ReceiveData);
|
{
|
||||||
|
this_thread::sleep_for(1s);
|
||||||
|
}
|
||||||
|
|
||||||
// 等待热点创建线程结束
|
// Processing.join();
|
||||||
Processing.join();
|
|
||||||
video.join();
|
video.join();
|
||||||
Rtsp.join();
|
Rtsp.join();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化MQTT
|
||||||
void mqttInit()
|
void mqttInit()
|
||||||
{
|
{
|
||||||
|
|
||||||
client.set_connected_handler([](const string &cause)
|
client.set_connected_handler([](const string &cause)
|
||||||
{
|
{ cout << "Connected Successed!\n"; });
|
||||||
cout << cause << endl;
|
|
||||||
cout << "Connected Successed!\n"; });
|
|
||||||
client.set_message_callback(getMsgCallback);
|
client.set_message_callback(getMsgCallback);
|
||||||
|
|
||||||
// 连接服务器
|
// 连接服务器
|
||||||
@@ -189,17 +178,144 @@ void mqttInit()
|
|||||||
// 接收消息回调
|
// 接收消息回调
|
||||||
void getMsgCallback(mqtt::const_message_ptr msg)
|
void getMsgCallback(mqtt::const_message_ptr msg)
|
||||||
{
|
{
|
||||||
cout << "收到消息" << endl;
|
// 立即拷贝负载,避免在回调里做大量工作
|
||||||
cout << "recv:" << msg->to_string() << endl;
|
std::string payload = msg->to_string();
|
||||||
|
|
||||||
|
cout << "Recv:" << payload << endl;
|
||||||
|
|
||||||
|
std::thread([payload]()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string buffer = payload;
|
||||||
|
if (buffer.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Pass: 更新 Init 标志并写入密码文件
|
||||||
|
if (buffer.find("Pass:") != string::npos)
|
||||||
|
{
|
||||||
|
WriteFile wf(filepath);
|
||||||
|
string str = "yse\n";
|
||||||
|
wf.overwriteAtPos(str, wf.countBytesPattern("InitOrNot:", true), str.size());
|
||||||
|
|
||||||
|
WriteFile wf2(passwd);
|
||||||
|
wf2.overwriteText(buffer.substr(5));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SET_DISTANCES: 解析 JSON 并更新 cameraPath 文件
|
||||||
|
if (buffer.find("SET_DISTANCES") != string::npos)
|
||||||
|
{
|
||||||
|
auto res = nlohmann::json::parse(buffer);
|
||||||
|
auto &danger_json = res["params"]["danger_distance"];
|
||||||
|
auto &warning_json = res["params"]["warning_distance"];
|
||||||
|
auto &safe_json = res["params"]["safe_distance"];
|
||||||
|
|
||||||
|
auto toDouble = [](const nlohmann::json &jv) -> double {
|
||||||
|
if (jv.is_number()) return jv.get<double>();
|
||||||
|
if (jv.is_string()) {
|
||||||
|
try { return std::stod(jv.get<string>()); }
|
||||||
|
catch (...) { return 0.0; }
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
double danger = toDouble(danger_json);
|
||||||
|
double warn = toDouble(warning_json);
|
||||||
|
double safe = toDouble(safe_json);
|
||||||
|
|
||||||
|
ReadFile rf(cameraPath);
|
||||||
|
if (!rf.Open()) {
|
||||||
|
cerr << "文件打开失败: " << cameraPath << "\n";
|
||||||
|
} else {
|
||||||
|
auto lines = rf.ReadLines();
|
||||||
|
for (auto &line : lines) {
|
||||||
|
if (line.rfind("NEAR_THRESHOLD=", 0) == 0) line = format("NEAR_THRESHOLD={}", danger);
|
||||||
|
else if (line.rfind("MID_THRESHOLD=", 0) == 0) line = format("MID_THRESHOLD={}", warn);
|
||||||
|
else if (line.rfind("MAX_DISTANCE=", 0) == 0) line = format("MAX_DISTANCE={}", safe);
|
||||||
|
}
|
||||||
|
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(cameraPath);
|
||||||
|
wf.overwriteText(out);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// media: 更新 cameraPath 的 MEDIA_* 设置
|
||||||
|
if (buffer.find("media") != string::npos)
|
||||||
|
{
|
||||||
|
CalculateInfo(media, buffer);
|
||||||
|
ReadFile rf(cameraPath);
|
||||||
|
if (!rf.Open()) {
|
||||||
|
cerr << "文件打开失败: " << cameraPath << "\n";
|
||||||
|
} else {
|
||||||
|
auto lines = rf.ReadLines();
|
||||||
|
for (auto &line : lines) {
|
||||||
|
if (line.rfind("MEDIA_MIRROR=", 0) == 0) line = format("MEDIA_MIRROR={}", media.mirror ? "true" : "false");
|
||||||
|
else if (line.rfind("MEDIA_FLIP=", 0) == 0) line = format("MEDIA_FLIP={}", media.flip ? "true" : "false");
|
||||||
|
else if (line.rfind("MEDIA_OCCLUSION=", 0) == 0) line = format("MEDIA_OCCLUSION={}", media.occlusion ? "true" : "false");
|
||||||
|
}
|
||||||
|
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(cameraPath);
|
||||||
|
wf.overwriteText(out);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// algorithm: 更新 filepath 中的 outPutMode/inPutMode
|
||||||
|
if (buffer.find("algorithm") != string::npos)
|
||||||
|
{
|
||||||
|
CalculateInfo(algor, buffer);
|
||||||
|
ReadFile rf2(filepath);
|
||||||
|
if (!rf2.Open()) {
|
||||||
|
cerr << "文件打开失败: " << filepath << "\n";
|
||||||
|
} else {
|
||||||
|
auto lines = rf2.ReadLines();
|
||||||
|
for (auto &line : lines) {
|
||||||
|
if (line.rfind("outPutMode:", 0) == 0) line = format("outPutMode:{}", algor.outPutMode ? "true" : "false");
|
||||||
|
else if (line.rfind("inPutMode:", 0) == 0) line = format("inPutMode:{}", algor.inPutMode ? "true" : "false");
|
||||||
|
}
|
||||||
|
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 wf2(filepath);
|
||||||
|
wf2.overwriteText(out);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "处理 MQTT 消息异常: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cerr << "处理 MQTT 消息时发生未知错误\n";
|
||||||
|
} })
|
||||||
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开启服务
|
// 开启服务:fastApi,pub
|
||||||
void StartService()
|
void StartService()
|
||||||
{
|
{
|
||||||
string commnd = "echo 'orangepi' | sudo -S ../../StartService/bin/start start";
|
string commnd = "echo 'orangepi' | sudo -S ../../StartService/bin/start start";
|
||||||
system(commnd.c_str());
|
system(commnd.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 开启网络
|
||||||
void StartNet()
|
void StartNet()
|
||||||
{
|
{
|
||||||
string commd = "../../GetNet/bin/setNet";
|
string commd = "../../GetNet/bin/setNet";
|
||||||
@@ -279,210 +395,19 @@ void Exit(int sig)
|
|||||||
{
|
{
|
||||||
cout << "Exiting..." << endl;
|
cout << "Exiting..." << endl;
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
confirm = false;
|
// confirm = false;
|
||||||
MyServer->stop();
|
// MyServer->stop();
|
||||||
|
|
||||||
system("sudo killall create_ap");
|
cout << "System Quit" << endl;
|
||||||
|
|
||||||
|
// system("sudo killall create_ap");
|
||||||
// 杀死后台 RTSP 和 ffmpeg 进程
|
// 杀死后台 RTSP 和 ffmpeg 进程
|
||||||
if (rtsp_proc.running())
|
// if (rtsp_proc.running())
|
||||||
rtsp_proc.terminate();
|
// rtsp_proc.terminate();
|
||||||
if (video_proc.running())
|
// if (video_proc.running())
|
||||||
video_proc.terminate();
|
// video_proc.terminate();
|
||||||
if (ap_proc.running())
|
// if (net_proc.running())
|
||||||
ap_proc.terminate();
|
// net_proc.terminate();
|
||||||
if (net_proc.running())
|
|
||||||
net_proc.terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 接收数据
|
|
||||||
void ReceiveData()
|
|
||||||
{
|
|
||||||
string buffer = "";
|
|
||||||
while (isRunning)
|
|
||||||
{
|
|
||||||
std::vector<int> client = MyServer->getClientSockets();
|
|
||||||
if (client.empty())
|
|
||||||
{
|
|
||||||
this_thread::sleep_for(chrono::milliseconds(100));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int index = client.size();
|
|
||||||
// cout << "index: " << index << endl;
|
|
||||||
for (int ii = 0; ii < index; ++ii) // 从新到旧,优先处理新连接
|
|
||||||
{
|
|
||||||
buffer = MyServer->receiveFromClient(client[ii], false); // 非阻塞模式接受数据
|
|
||||||
// cout << buffer << endl;
|
|
||||||
if (buffer.empty() == false)
|
|
||||||
{
|
|
||||||
cout << "已收到" << buffer << endl;
|
|
||||||
// 处理数据
|
|
||||||
if (buffer.find("Pass:") != string::npos)
|
|
||||||
{
|
|
||||||
cout << "已收到" << buffer << endl;
|
|
||||||
// 验证秘钥
|
|
||||||
WriteFile wf(filepath);
|
|
||||||
string str = "yse\n";
|
|
||||||
wf.overwriteAtPos(str, wf.countBytesPattern("InitOrNot:", true), str.size());
|
|
||||||
cout << "已更新" << endl;
|
|
||||||
// 将秘钥写入配置文件:
|
|
||||||
WriteFile wf2(passwd);
|
|
||||||
wf2.overwriteText(buffer.substr(5));
|
|
||||||
}
|
|
||||||
else if (buffer.find("SET_DISTANCES") != string::npos)
|
|
||||||
{ // 接收距离参数
|
|
||||||
auto res = nlohmann::json::parse(buffer);
|
|
||||||
// 读取值并兼容 number/string
|
|
||||||
auto &danger_json = res["params"]["danger_distance"];
|
|
||||||
auto &warning_json = res["params"]["warning_distance"];
|
|
||||||
auto &safe_json = res["params"]["safe_distance"];
|
|
||||||
|
|
||||||
auto toDouble = [](const nlohmann::json &jv) -> double
|
|
||||||
{
|
|
||||||
if (jv.is_number())
|
|
||||||
return jv.get<double>();
|
|
||||||
if (jv.is_string())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return std::stod(jv.get<string>());
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0.0;
|
|
||||||
};
|
|
||||||
|
|
||||||
double danger = toDouble(danger_json);
|
|
||||||
double warn = toDouble(warning_json);
|
|
||||||
double safe = toDouble(safe_json);
|
|
||||||
|
|
||||||
// 整文件读取,逐行替换,保持注释不变
|
|
||||||
ReadFile *rf = new ReadFile(cameraPath);
|
|
||||||
if (!rf->Open())
|
|
||||||
{
|
|
||||||
cerr << "文件打开失败: " << cameraPath << "\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto lines = rf->ReadLines();
|
|
||||||
delete rf;
|
|
||||||
for (auto &line : lines)
|
|
||||||
{
|
|
||||||
if (line.rfind("NEAR_THRESHOLD=", 0) == 0)
|
|
||||||
{
|
|
||||||
line = format("NEAR_THRESHOLD={}", danger);
|
|
||||||
}
|
|
||||||
else if (line.rfind("MID_THRESHOLD=", 0) == 0)
|
|
||||||
{
|
|
||||||
line = format("MID_THRESHOLD={}", warn);
|
|
||||||
}
|
|
||||||
else if (line.rfind("MAX_DISTANCE=", 0) == 0)
|
|
||||||
{
|
|
||||||
line = format("MAX_DISTANCE={}", safe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新拼接并整体写回
|
|
||||||
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 = new WriteFile(cameraPath);
|
|
||||||
wf->overwriteText(out);
|
|
||||||
delete wf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (buffer.find("media") != string::npos)
|
|
||||||
{
|
|
||||||
// 写摄像头参数(与距离相同方式: 整体读取-逐行替换-整体写回)
|
|
||||||
cout << buffer << endl;
|
|
||||||
CalculateInfo(media, buffer);
|
|
||||||
ReadFile *rf = new ReadFile(cameraPath);
|
|
||||||
if (!rf->Open())
|
|
||||||
{
|
|
||||||
cerr << "文件打开失败: " << cameraPath << "\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto lines = rf->ReadLines();
|
|
||||||
delete rf;
|
|
||||||
for (auto &line : lines)
|
|
||||||
{
|
|
||||||
if (line.rfind("MEDIA_MIRROR=", 0) == 0)
|
|
||||||
{
|
|
||||||
line = format("MEDIA_MIRROR={}", media.mirror ? "true" : "false");
|
|
||||||
}
|
|
||||||
else if (line.rfind("MEDIA_FLIP=", 0) == 0)
|
|
||||||
{
|
|
||||||
line = format("MEDIA_FLIP={}", media.flip ? "true" : "false");
|
|
||||||
}
|
|
||||||
else if (line.rfind("MEDIA_OCCLUSION=", 0) == 0)
|
|
||||||
{
|
|
||||||
line = format("MEDIA_OCCLUSION={}", media.occlusion ? "true" : "false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = new WriteFile(cameraPath);
|
|
||||||
wf->overwriteText(out);
|
|
||||||
delete wf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (buffer.find("algorithm") != string::npos)
|
|
||||||
{
|
|
||||||
// 写输入输出参数(与距离相同方式: 整体读取-逐行替换-整体写回)
|
|
||||||
CalculateInfo(algor, buffer);
|
|
||||||
ReadFile *rf2 = new ReadFile(filepath);
|
|
||||||
if (!rf2->Open())
|
|
||||||
{
|
|
||||||
cerr << "文件打开失败: " << filepath << "\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto lines = rf2->ReadLines();
|
|
||||||
delete rf2;
|
|
||||||
for (auto &line : lines)
|
|
||||||
{
|
|
||||||
if (line.rfind("outPutMode:", 0) == 0)
|
|
||||||
{
|
|
||||||
line = format("outPutMode:{}", algor.outPutMode ? "true" : "false");
|
|
||||||
}
|
|
||||||
else if (line.rfind("inPutMode:", 0) == 0)
|
|
||||||
{
|
|
||||||
line = format("inPutMode:{}", algor.inPutMode ? "true" : "false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 *wf2 = new WriteFile(filepath);
|
|
||||||
wf2->overwriteText(out);
|
|
||||||
delete wf2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this_thread::sleep_for(chrono::milliseconds(100)); // 避免过于频繁的循环
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打开RSTP服务器
|
// 打开RSTP服务器
|
||||||
@@ -610,30 +535,14 @@ string GetSimICCID(const string &tty)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 发送cpu序列号和SIM卡号
|
// 发送cpu序列号和SIM卡号
|
||||||
void SendCardInfo(TcpServer *MyServer)
|
void SendCardInfo(mqtt::async_client &client)
|
||||||
{
|
{
|
||||||
string CardID = GetCardInfo();
|
string CardID = GetCardInfo();
|
||||||
string SIMID = GetSimICCID();
|
string SIMID = GetSimICCID();
|
||||||
string info = CardID + SIMID;
|
string info = CardID + SIMID;
|
||||||
|
|
||||||
while (confirm)
|
// 发送信息
|
||||||
{
|
client.publish(Topic, info, Qos, false);
|
||||||
std::vector<int> client = MyServer->getClientSockets();
|
|
||||||
if (client.empty())
|
|
||||||
continue;
|
|
||||||
cout << "有了客户端连接" << endl;
|
|
||||||
size_t index = client.size();
|
|
||||||
|
|
||||||
for (int ii = 0; ii < index; ii++)
|
|
||||||
{
|
|
||||||
if (MyServer->receiveFromClient(client[ii]) == "GET_ID")
|
|
||||||
{
|
|
||||||
cout << info << endl;
|
|
||||||
MyServer->sendToClient(client[ii], info + " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析接收的数据
|
// 解析接收的数据
|
||||||
|
|||||||
577
ApCreate/src/main.cpp.bak
Normal file
577
ApCreate/src/main.cpp.bak
Normal file
@@ -0,0 +1,577 @@
|
|||||||
|
/*
|
||||||
|
本程序提供以下功能:
|
||||||
|
1.开启4G模块,允许上网
|
||||||
|
2.进行RTSP推流
|
||||||
|
3.初始化验证->启动系统服务
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <mqtt/async_client.h>
|
||||||
|
|
||||||
|
#include <boost/process.hpp>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include "Netra.hpp"
|
||||||
|
#include "NetRequest.hpp"
|
||||||
|
#include "encrypt.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace QCL;
|
||||||
|
using namespace ntq;
|
||||||
|
using namespace encrypt;
|
||||||
|
using namespace chrono_literals;
|
||||||
|
namespace bp = boost::process;
|
||||||
|
|
||||||
|
bp::child rtsp_proc; // 服务器进程
|
||||||
|
bp::child video_proc; // 视频推流进程
|
||||||
|
bp::child net_proc; // 开启网络进程
|
||||||
|
|
||||||
|
// 文件设置路径
|
||||||
|
string filepath = "/home/orangepi/InitAuth/conf/.env";
|
||||||
|
string cameraPath = "/opt/rknn-yolov11/.env";
|
||||||
|
string passwd = "/home/orangepi/InitAuth/pwd/.env";
|
||||||
|
|
||||||
|
// 云端Web认证接口
|
||||||
|
const string url = "http://116.147.36.110:8095/device/validateDevice";
|
||||||
|
const string mqtt_url = "tcp://192.168.12.1:1883";
|
||||||
|
const string clientId = "RK3588_SubTest";
|
||||||
|
const string Topic = "/bsd_camera/cmd";
|
||||||
|
const int Qos = 1;
|
||||||
|
|
||||||
|
std::atomic<bool> isRunning(true); // 全局运行标志
|
||||||
|
std::atomic<bool> confirm(true); // 发送卡和ID
|
||||||
|
|
||||||
|
// 媒体对象
|
||||||
|
struct Media
|
||||||
|
{
|
||||||
|
bool mirror; // 镜像
|
||||||
|
bool flip; // 翻转
|
||||||
|
bool occlusion; // 遮挡
|
||||||
|
} media{};
|
||||||
|
|
||||||
|
// 输入输出对象
|
||||||
|
struct OutSignal
|
||||||
|
{
|
||||||
|
bool outPutMode; // 警报输出电平 true--高电平,false -- 低电平
|
||||||
|
bool inPutMode; // 触发输入模式 true--高电平,false -- 低电平
|
||||||
|
} algor{};
|
||||||
|
|
||||||
|
// 确认是否已经进行过认证
|
||||||
|
bool ConfirmInit();
|
||||||
|
|
||||||
|
// 获取cpu序列号和SIM卡号
|
||||||
|
string GetCardInfo();
|
||||||
|
|
||||||
|
// 获取SIM卡号
|
||||||
|
string GetSimICCID(const string &tty = "/dev/ttyUSB2");
|
||||||
|
|
||||||
|
// 发送cpu序列号和SIM卡号
|
||||||
|
void SendCardInfo(mqtt::async_client &client);
|
||||||
|
|
||||||
|
// 进行验证
|
||||||
|
bool verification();
|
||||||
|
|
||||||
|
// 解析接收的数据
|
||||||
|
template <class T>
|
||||||
|
void CalculateInfo(T &conf, const string &json);
|
||||||
|
|
||||||
|
// 创建服务器
|
||||||
|
// TcpServer *MyServer;
|
||||||
|
// mqtt client
|
||||||
|
mqtt::async_client client(mqtt_url, clientId);
|
||||||
|
|
||||||
|
// 打开RSTP服务器
|
||||||
|
void OpenRTSP();
|
||||||
|
|
||||||
|
// 视频推流
|
||||||
|
void VideoStream();
|
||||||
|
|
||||||
|
// 退出信号捕捉
|
||||||
|
void Exit(int sig);
|
||||||
|
|
||||||
|
// 开启网络(4G模块)
|
||||||
|
void StartNet();
|
||||||
|
|
||||||
|
// 开启服务
|
||||||
|
void StartService();
|
||||||
|
|
||||||
|
// mqtt初始化
|
||||||
|
void mqttInit();
|
||||||
|
|
||||||
|
// 接收消息回调
|
||||||
|
void getMsgCallback(mqtt::const_message_ptr msg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
parames:
|
||||||
|
argv[1] - SSID of the WiFi network to connect to
|
||||||
|
argv[2] - Password for the WiFi network (if applicable)
|
||||||
|
*/
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
// 开启4G模块
|
||||||
|
StartNet();
|
||||||
|
|
||||||
|
this_thread::sleep_for(chrono::seconds(2));
|
||||||
|
|
||||||
|
// 关闭全部信号
|
||||||
|
blockAllSignals();
|
||||||
|
signal(SIGINT, Exit); // 捕获Ctrl+C信号
|
||||||
|
|
||||||
|
// 初始化mqtt服务器
|
||||||
|
mqttInit();
|
||||||
|
|
||||||
|
// // 开启服务器
|
||||||
|
// 如果没有进行过初始化,发送物联网卡信息进行认证
|
||||||
|
if (ConfirmInit() == false)
|
||||||
|
{
|
||||||
|
SendCardInfo(client);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (verification() == false)
|
||||||
|
{
|
||||||
|
cerr << "验证失败" << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启服务
|
||||||
|
thread(StartService).detach();
|
||||||
|
|
||||||
|
thread Rtsp(OpenRTSP);
|
||||||
|
std::this_thread::sleep_for(chrono::seconds(2)); // 等待RTSP服务器启动
|
||||||
|
|
||||||
|
// 进行RTSP视频推流
|
||||||
|
thread video(VideoStream);
|
||||||
|
|
||||||
|
while (isRunning)
|
||||||
|
{
|
||||||
|
this_thread::sleep_for(1s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processing.join();
|
||||||
|
video.join();
|
||||||
|
Rtsp.join();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化MQTT
|
||||||
|
void mqttInit()
|
||||||
|
{
|
||||||
|
|
||||||
|
client.set_connected_handler([](const string &cause)
|
||||||
|
{ cout << "Connected Successed!\n"; });
|
||||||
|
client.set_message_callback(getMsgCallback);
|
||||||
|
|
||||||
|
// 连接服务器
|
||||||
|
client.connect()->wait();
|
||||||
|
client.subscribe(Topic, Qos)->wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接收消息回调
|
||||||
|
void getMsgCallback(mqtt::const_message_ptr msg)
|
||||||
|
{
|
||||||
|
// 立即拷贝负载,避免在回调里做大量工作
|
||||||
|
std::string payload = msg->to_string();
|
||||||
|
|
||||||
|
cout << "Recv:" << payload << endl;
|
||||||
|
|
||||||
|
std::thread([payload]()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string buffer = payload;
|
||||||
|
if (buffer.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Pass: 更新 Init 标志并写入密码文件
|
||||||
|
if (buffer.find("Pass:") != string::npos)
|
||||||
|
{
|
||||||
|
WriteFile wf(filepath);
|
||||||
|
string str = "yse\n";
|
||||||
|
wf.overwriteAtPos(str, wf.countBytesPattern("InitOrNot:", true), str.size());
|
||||||
|
|
||||||
|
WriteFile wf2(passwd);
|
||||||
|
wf2.overwriteText(buffer.substr(5));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SET_DISTANCES: 解析 JSON 并更新 cameraPath 文件
|
||||||
|
if (buffer.find("SET_DISTANCES") != string::npos)
|
||||||
|
{
|
||||||
|
auto res = nlohmann::json::parse(buffer);
|
||||||
|
auto &danger_json = res["params"]["danger_distance"];
|
||||||
|
auto &warning_json = res["params"]["warning_distance"];
|
||||||
|
auto &safe_json = res["params"]["safe_distance"];
|
||||||
|
|
||||||
|
auto toDouble = [](const nlohmann::json &jv) -> double {
|
||||||
|
if (jv.is_number()) return jv.get<double>();
|
||||||
|
if (jv.is_string()) {
|
||||||
|
try { return std::stod(jv.get<string>()); }
|
||||||
|
catch (...) { return 0.0; }
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
};
|
||||||
|
|
||||||
|
double danger = toDouble(danger_json);
|
||||||
|
double warn = toDouble(warning_json);
|
||||||
|
double safe = toDouble(safe_json);
|
||||||
|
|
||||||
|
ReadFile rf(cameraPath);
|
||||||
|
if (!rf.Open()) {
|
||||||
|
cerr << "文件打开失败: " << cameraPath << "\n";
|
||||||
|
} else {
|
||||||
|
auto lines = rf.ReadLines();
|
||||||
|
for (auto &line : lines) {
|
||||||
|
if (line.rfind("NEAR_THRESHOLD=", 0) == 0) line = format("NEAR_THRESHOLD={}", danger);
|
||||||
|
else if (line.rfind("MID_THRESHOLD=", 0) == 0) line = format("MID_THRESHOLD={}", warn);
|
||||||
|
else if (line.rfind("MAX_DISTANCE=", 0) == 0) line = format("MAX_DISTANCE={}", safe);
|
||||||
|
}
|
||||||
|
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(cameraPath);
|
||||||
|
wf.overwriteText(out);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// media: 更新 cameraPath 的 MEDIA_* 设置
|
||||||
|
if (buffer.find("media") != string::npos)
|
||||||
|
{
|
||||||
|
CalculateInfo(media, buffer);
|
||||||
|
ReadFile rf(cameraPath);
|
||||||
|
if (!rf.Open()) {
|
||||||
|
cerr << "文件打开失败: " << cameraPath << "\n";
|
||||||
|
} else {
|
||||||
|
auto lines = rf.ReadLines();
|
||||||
|
for (auto &line : lines) {
|
||||||
|
if (line.rfind("MEDIA_MIRROR=", 0) == 0) line = format("MEDIA_MIRROR={}", media.mirror ? "true" : "false");
|
||||||
|
else if (line.rfind("MEDIA_FLIP=", 0) == 0) line = format("MEDIA_FLIP={}", media.flip ? "true" : "false");
|
||||||
|
else if (line.rfind("MEDIA_OCCLUSION=", 0) == 0) line = format("MEDIA_OCCLUSION={}", media.occlusion ? "true" : "false");
|
||||||
|
}
|
||||||
|
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(cameraPath);
|
||||||
|
wf.overwriteText(out);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// algorithm: 更新 filepath 中的 outPutMode/inPutMode
|
||||||
|
if (buffer.find("algorithm") != string::npos)
|
||||||
|
{
|
||||||
|
CalculateInfo(algor, buffer);
|
||||||
|
ReadFile rf2(filepath);
|
||||||
|
if (!rf2.Open()) {
|
||||||
|
cerr << "文件打开失败: " << filepath << "\n";
|
||||||
|
} else {
|
||||||
|
auto lines = rf2.ReadLines();
|
||||||
|
for (auto &line : lines) {
|
||||||
|
if (line.rfind("outPutMode:", 0) == 0) line = format("outPutMode:{}", algor.outPutMode ? "true" : "false");
|
||||||
|
else if (line.rfind("inPutMode:", 0) == 0) line = format("inPutMode:{}", algor.inPutMode ? "true" : "false");
|
||||||
|
}
|
||||||
|
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 wf2(filepath);
|
||||||
|
wf2.overwriteText(out);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "处理 MQTT 消息异常: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cerr << "处理 MQTT 消息时发生未知错误\n";
|
||||||
|
} })
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启服务:fastApi,pub
|
||||||
|
void StartService()
|
||||||
|
{
|
||||||
|
string commnd = "echo 'orangepi' | sudo -S ../../StartService/bin/start start";
|
||||||
|
system(commnd.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启网络
|
||||||
|
void StartNet()
|
||||||
|
{
|
||||||
|
string commd = "../../GetNet/bin/setNet";
|
||||||
|
net_proc = bp::child("/bin/bash", bp::args = {"-c", commd});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进行验证
|
||||||
|
bool verification()
|
||||||
|
{
|
||||||
|
// 读取文件密文
|
||||||
|
ReadFile *rf = new ReadFile(passwd);
|
||||||
|
bool flag = false;
|
||||||
|
auto pass = rf->ReadLines();
|
||||||
|
// 若为空:改写初始化标志位false,重认证
|
||||||
|
if (pass.empty())
|
||||||
|
{
|
||||||
|
WriteFile *wf = new WriteFile(filepath);
|
||||||
|
wf->overwriteAtPos("no", wf->countBytesPattern("InitOrNot:", true), 3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &ii : pass)
|
||||||
|
{
|
||||||
|
// 不为空,线上发送密文开始认证
|
||||||
|
auto pos = format(R"({{"cardNo":"{}"}})", ii);
|
||||||
|
|
||||||
|
auto res = NetRequest::QuickPostJson(url, pos);
|
||||||
|
|
||||||
|
int code = -1;
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
code = nlohmann::json::parse(res->body).value("code", -1);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "JSON解析失败: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res && code == 200)
|
||||||
|
{
|
||||||
|
cout << "线上:认证成功" << endl;
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 进行线下认证
|
||||||
|
// 获取cpu序列号和SIM卡号
|
||||||
|
string CardID = GetCardInfo();
|
||||||
|
string SIMID = GetSimICCID();
|
||||||
|
string info = CardID + SIMID;
|
||||||
|
// 进行MD5加密
|
||||||
|
string md5 = MD5(info);
|
||||||
|
cout << md5 << endl;
|
||||||
|
if (md5.compare(ii) == 0)
|
||||||
|
{
|
||||||
|
cout << "线下:认证成功" << endl;
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cout << "结束" << endl;
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 退出信号
|
||||||
|
void Exit(int sig)
|
||||||
|
{
|
||||||
|
cout << "Exiting..." << endl;
|
||||||
|
isRunning = false;
|
||||||
|
confirm = false;
|
||||||
|
// MyServer->stop();
|
||||||
|
|
||||||
|
system("sudo killall create_ap");
|
||||||
|
// 杀死后台 RTSP 和 ffmpeg 进程
|
||||||
|
if (rtsp_proc.running())
|
||||||
|
rtsp_proc.terminate();
|
||||||
|
if (video_proc.running())
|
||||||
|
video_proc.terminate();
|
||||||
|
if (net_proc.running())
|
||||||
|
net_proc.terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开RSTP服务器
|
||||||
|
void OpenRTSP()
|
||||||
|
{
|
||||||
|
string commnd = "../RTSPServer/mediamtx ../RTSPServer/mediamtx.yml";
|
||||||
|
rtsp_proc = bp::child("/bin/bash", bp::args = {"-c", commnd});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 视频推流
|
||||||
|
void VideoStream()
|
||||||
|
{
|
||||||
|
// 静音ffmpeg的统计输出,保留错误;避免污染日志
|
||||||
|
string commnd = "ffmpeg -nostats -hide_banner -loglevel error -f v4l2 -i /dev/video0 -c:v h264_rkmpp -rtsp_transport tcp -f rtsp rtsp://192.168.12.1:8554/stream 2>/dev/null";
|
||||||
|
video_proc = bp::child("/bin/bash", bp::args = {"-c", commnd});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认是否已经进行过认证
|
||||||
|
bool ConfirmInit()
|
||||||
|
{
|
||||||
|
ReadFile *rf = new ReadFile(filepath);
|
||||||
|
if (rf->Open() == false)
|
||||||
|
{
|
||||||
|
cerr << "文件打开失败\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto vct = rf->ReadLines();
|
||||||
|
for (auto &ii : vct)
|
||||||
|
{
|
||||||
|
if (ii.find("InitOrNot:no") != string::npos)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取cpu序列号和SIM卡号
|
||||||
|
string GetCardInfo()
|
||||||
|
{
|
||||||
|
ReadFile *rf = new ReadFile("/proc/cpuinfo");
|
||||||
|
if (rf->Open() == false)
|
||||||
|
{
|
||||||
|
cerr << "文件打开失败\n";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lines = rf->ReadLines();
|
||||||
|
string res = "";
|
||||||
|
for (auto &ii : lines)
|
||||||
|
{
|
||||||
|
if (ii.find("Serial") != string::npos)
|
||||||
|
{
|
||||||
|
auto pos = ii.find(":");
|
||||||
|
if (pos != string::npos)
|
||||||
|
{
|
||||||
|
res = ii.substr(pos + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LRtrim(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取SIM卡号
|
||||||
|
// 通过串口发送 AT+CCID 指令,读取并解析返回的ICCID号
|
||||||
|
string GetSimICCID(const string &tty)
|
||||||
|
{
|
||||||
|
int retry = 0; // 重试次数
|
||||||
|
while (retry < 5) // 最多重试5次
|
||||||
|
{
|
||||||
|
int fd = open(tty.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); // 打开串口
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
std::cerr << "无法打开串口: " << tty << std::endl;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置串口参数
|
||||||
|
struct termios options;
|
||||||
|
tcgetattr(fd, &options);
|
||||||
|
cfsetispeed(&options, B115200);
|
||||||
|
cfsetospeed(&options, B115200);
|
||||||
|
options.c_cflag |= (CLOCAL | CREAD);
|
||||||
|
tcsetattr(fd, TCSANOW, &options);
|
||||||
|
|
||||||
|
// 发送 AT+CCID 指令
|
||||||
|
write(fd, "AT+CCID\r\n", 9);
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
char buf[256] = {0};
|
||||||
|
// 循环多次读取,拼接内容,防止数据分包
|
||||||
|
for (int i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
usleep(100000); // 每次等待100ms
|
||||||
|
int n = read(fd, buf, sizeof(buf) - 1);
|
||||||
|
if (n > 0)
|
||||||
|
result.append(buf, n);
|
||||||
|
}
|
||||||
|
close(fd); // 关闭串口
|
||||||
|
|
||||||
|
// 检查是否有ERROR,若有则重试
|
||||||
|
if (result.find("ERROR") != std::string::npos)
|
||||||
|
{
|
||||||
|
retry++;
|
||||||
|
usleep(200000); // 等待200ms再重试
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用正则提取ICCID(+CCID: 后面的数字)
|
||||||
|
std::smatch m;
|
||||||
|
std::regex reg(R"(\+CCID:\s*([0-9]+))");
|
||||||
|
if (std::regex_search(result, m, reg))
|
||||||
|
return m[1];
|
||||||
|
|
||||||
|
// 兜底:直接找19~22位数字(兼容不同长度的ICCID)
|
||||||
|
std::regex reg2(R"((\d{19,22}))");
|
||||||
|
if (std::regex_search(result, m, reg2))
|
||||||
|
return m[1];
|
||||||
|
|
||||||
|
// 没有ERROR但也没读到ICCID,直接退出循环
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ""; // 多次重试失败,返回空
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送cpu序列号和SIM卡号
|
||||||
|
void SendCardInfo(mqtt::async_client &client)
|
||||||
|
{
|
||||||
|
string CardID = GetCardInfo();
|
||||||
|
string SIMID = GetSimICCID();
|
||||||
|
string info = CardID + SIMID;
|
||||||
|
|
||||||
|
// 发送信息
|
||||||
|
client.publish(Topic, info, Qos, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析接收的数据
|
||||||
|
template <class T>
|
||||||
|
void CalculateInfo(T &conf, const string &json)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
/* code */
|
||||||
|
auto j = nlohmann::json::parse(json);
|
||||||
|
if (j.contains("params") && j["params"].contains("media"))
|
||||||
|
{
|
||||||
|
auto conf = j["params"]["media"];
|
||||||
|
if (conf.contains("mirror"))
|
||||||
|
media.mirror = conf["mirror"].get<bool>();
|
||||||
|
if (conf.contains("flip"))
|
||||||
|
media.flip = conf["mirror"].get<bool>();
|
||||||
|
if (conf.contains("occlusion"))
|
||||||
|
media.occlusion = conf["occlusion"].get<bool>();
|
||||||
|
}
|
||||||
|
else if (j.contains("params") && j["params"].contains("algorithm"))
|
||||||
|
{
|
||||||
|
auto conf = j["params"]["algorithm"];
|
||||||
|
if (conf.contains("alarm_output_mode"))
|
||||||
|
algor.outPutMode = (conf["alarm_output_mode"].get<string>().find("高电平") != string::npos) ? true : false;
|
||||||
|
|
||||||
|
if (conf.contains("trigger_input_mode"))
|
||||||
|
algor.inPutMode = (conf["trigger_input_mode"].get<string>().find("高电平") != string::npos) ? true : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1479,3 +1479,5 @@
|
|||||||
2025-10-13 10:28:15 - 使用经纬度上传: lon=1201, lat=3129
|
2025-10-13 10:28:15 - 使用经纬度上传: lon=1201, lat=3129
|
||||||
2025-10-13 10:28:16 - 数据库插入成功
|
2025-10-13 10:28:16 - 数据库插入成功
|
||||||
2025-10-13 10:28:16 - 上传线程结束: /mnt/save/warning/warning_20251013_102811.jpg: 成功!
|
2025-10-13 10:28:16 - 上传线程结束: /mnt/save/warning/warning_20251013_102811.jpg: 成功!
|
||||||
|
2025-10-21 12:02:47 - 开始上传图片: /mnt/save/warning/warning_20251021_120245.jpg
|
||||||
|
2025-10-21 12:02:48 - 使用经纬度上传: lon=1201, lat=3129
|
||||||
|
|||||||
Reference in New Issue
Block a user