Files
RkApp/DeviceActivate/src/main.cpp

241 lines
6.1 KiB
C++
Raw Normal View History

2025-10-24 16:56:35 +08:00
/*
,
,
*/
#include <iostream>
#include <mqtt/async_client.h> //和App进行MQTT数据交互
#include <boost/process.hpp>
#include <nlohmann/json.hpp> //用于操作JSON文件
#include "Netra.hpp"
using namespace std;
using namespace QCL;
using namespace chrono_literals;
// 配置相对路径
const string envPath = "/home/orangepi/RKApp/InitAuth/conf/.env";
// MQTT相关配置
const string mqtt_url = "tcp://192.168.12.1:1883";
const string clientId = "RK3588_SubTest";
2025-10-26 11:30:13 +08:00
const string TopicRecv = "/bsd_camera/cmd"; // 接收手机传来的信息
const string TopicSend = "/bsd_camera/init"; // 发送的话题
2025-10-24 16:56:35 +08:00
const int Qos = 1;
atomic<bool> isRunning(true);
2025-10-26 11:30:13 +08:00
atomic<bool> Deactivate(false); // 激活标志
2025-10-24 16:56:35 +08:00
mqtt::async_client client(mqtt_url, clientId);
// 获取SIM卡号
// 通过串口发送 AT+CCID 指令读取并解析返回的ICCID号
string GetSimICCID(const string &tty = "/dev/ttyUSB2");
// MQTT初始化
void mqttInit();
// 连接成功的回调
void connectCallback(const string &cause);
// 接受消息的回调
void messageCallback(mqtt::const_message_ptr msg);
// 检测设备是否已进行初始化
bool checkUUID();
2025-10-26 11:30:13 +08:00
// 退出程序,开始进行设备验证
void StartCheck();
2025-10-24 16:56:35 +08:00
int main()
{
2025-10-26 11:30:13 +08:00
Deactivate = checkUUID(); // 判断是否已被激活
if (Deactivate)
2025-10-24 16:56:35 +08:00
{
// 设备已被激活,调用验证程序,退出本程序
2025-10-26 11:30:13 +08:00
cout << "设备已激活,开始验证" << endl;
StartCheck();
2025-10-24 16:56:35 +08:00
return 0;
}
// 初始化MQTT
mqttInit();
while (isRunning)
{
this_thread::sleep_for(1s); // 防止系统占用过高
}
return 0;
}
2025-10-26 11:30:13 +08:00
// 退出程序,开始进行设备验证
void StartCheck()
{
isRunning = false; // 退出程序
string cmd = "../../softWareInit/bin/wifi ";
system(cmd.c_str());
}
2025-10-24 16:56:35 +08:00
// 检测设备是否已经激活
bool checkUUID()
{
bool flag = false;
// 读取文件
2025-10-24 17:25:57 +08:00
ReadFile rf(envPath);
if (rf.Open() == false)
2025-10-24 16:56:35 +08:00
{
cerr << "文件打开失败" << endl;
}
// 读取文本每一行
2025-10-24 17:25:57 +08:00
auto lines = rf.ReadLines();
2025-10-24 16:56:35 +08:00
for (auto &ii : lines)
{
if (ii.find("ServerPwd:null") != string::npos)
{
flag = false;
break;
}
else
flag = true;
}
2025-10-24 17:25:57 +08:00
rf.Close();
2025-10-24 16:56:35 +08:00
return flag;
}
// 接受消息的回调
void messageCallback(mqtt::const_message_ptr msg)
{
// 接受App传来的密文,并保存在配置文件中
auto buffer = msg->to_string();
2025-10-26 11:30:13 +08:00
// cout << "Topic:" << msg->get_topic() << ",msg:" << buffer << endl;
2025-10-24 16:56:35 +08:00
if (buffer.find("Activate") != string::npos)
{
// 接受请求,发送SIM卡号
string ICCID = GetSimICCID();
2025-10-26 11:30:13 +08:00
string deviceId = format("{\"deviceUid\":\"{}\"}", ICCID);
// cout << "ICCID:" << deviceId << endl;
client.publish(TopicSend, deviceId, Qos, false); // 不保存
2025-10-24 16:56:35 +08:00
}
else if (buffer.find("ServerPwd") != string::npos)
{
// 接受UUID,保存至配置文件中,退出程序,调用设备验证程序
auto res = nlohmann::json::parse(buffer); // 准备解析接受到的秘钥
2025-10-26 11:30:13 +08:00
auto pwd = res["Data"];
// cout << pwd << endl;
2025-10-24 17:25:57 +08:00
// 写入文件
ReadFile rf(envPath);
auto lines = rf.ReadLines();
for (auto &ii : lines)
{
if (ii.find("ServerPwd:null") != string::npos)
ii = format("ServerPwd:{}", pwd);
}
rf.Close();
thread([lines]()
{
WriteFile wf(envPath);
string out;
2025-10-26 11:30:13 +08:00
out.reserve(1024);
2025-10-24 17:25:57 +08:00
for (size_t i = 0; i < lines.size(); ++i)
{
out += lines[i];
if (i + 1 < lines.size())
out += "\n";
}
2025-10-26 11:30:13 +08:00
wf.overwriteText(out);
Deactivate =true; })
2025-10-24 17:25:57 +08:00
.detach();
2025-10-24 16:56:35 +08:00
}
2025-10-26 11:30:13 +08:00
if (Deactivate)
{ // 已激活
StartCheck();
}
2025-10-24 16:56:35 +08:00
}
// 连接成功的回调
void connectCallback(const string &cause)
{
cout << "连接成功" << endl;
}
void mqttInit()
{
client.set_message_callback(messageCallback);
client.set_connected_handler(connectCallback);
2025-10-26 11:30:13 +08:00
client.connect()->wait(); // 进行连接
client.subscribe(TopicRecv, Qos)->wait(); // 订阅话题
2025-10-24 16:56:35 +08:00
}
// 获取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 ""; // 多次重试失败,返回空
}