finnal
This commit is contained in:
BIN
GetNet/bin/setNet
Executable file
BIN
GetNet/bin/setNet
Executable file
Binary file not shown.
229
GetNet/src/GetNet.cpp
Normal file
229
GetNet/src/GetNet.cpp
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
本程序主要用于初始化网络配置,使4g模块可以正常上网
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <poll.h>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// 串口设备
|
||||
string Serious = "/dev/ttyUSB2";
|
||||
|
||||
// 设置网络
|
||||
void SetNet();
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
this_thread::sleep_for(chrono::seconds(3));
|
||||
|
||||
SetNet();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 设置网络
|
||||
void SetNet()
|
||||
{
|
||||
auto configure_serial = [](int fd) -> bool
|
||||
{
|
||||
struct termios options;
|
||||
if (tcgetattr(fd, &options) != 0)
|
||||
return false;
|
||||
|
||||
cfsetispeed(&options, B115200);
|
||||
cfsetospeed(&options, B115200);
|
||||
|
||||
options.c_cflag |= (CLOCAL | CREAD);
|
||||
options.c_cflag &= ~PARENB; // 无校验
|
||||
options.c_cflag &= ~CSTOPB; // 1 位停止位
|
||||
options.c_cflag &= ~CSIZE;
|
||||
options.c_cflag |= CS8; // 8 位数据位
|
||||
options.c_cflag &= ~CRTSCTS; // 关闭硬件流控
|
||||
|
||||
options.c_iflag &= ~(IXON | IXOFF | IXANY); // 关闭软件流控
|
||||
options.c_iflag &= ~(INLCR | ICRNL);
|
||||
|
||||
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始模式
|
||||
options.c_oflag &= ~OPOST; // 原始输出
|
||||
|
||||
options.c_cc[VMIN] = 0; // 非阻塞读取
|
||||
options.c_cc[VTIME] = 10; // 1.0s 读超时
|
||||
|
||||
if (tcsetattr(fd, TCSANOW, &options) != 0)
|
||||
return false;
|
||||
tcflush(fd, TCIOFLUSH);
|
||||
return true;
|
||||
};
|
||||
|
||||
auto write_all = [](int fd, const std::string &data) -> bool
|
||||
{
|
||||
const char *p = data.c_str();
|
||||
size_t left = data.size();
|
||||
while (left > 0)
|
||||
{
|
||||
ssize_t n = write(fd, p, left);
|
||||
if (n < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
left -= static_cast<size_t>(n);
|
||||
p += n;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
auto send_at = [&](int fd, const std::string &cmd, std::string &resp, int timeout_ms = 3000) -> bool
|
||||
{
|
||||
std::string line = cmd + "\r\n";
|
||||
if (!write_all(fd, line))
|
||||
return false;
|
||||
|
||||
resp.clear();
|
||||
char buf[256];
|
||||
int elapsed = 0;
|
||||
while (elapsed < timeout_ms)
|
||||
{
|
||||
struct pollfd pfd{fd, POLLIN, 0};
|
||||
int pr = poll(&pfd, 1, 200);
|
||||
if (pr > 0 && (pfd.revents & POLLIN))
|
||||
{
|
||||
ssize_t n = read(fd, buf, sizeof(buf));
|
||||
if (n > 0)
|
||||
{
|
||||
resp.append(buf, buf + n);
|
||||
if (resp.find("\r\nOK\r\n") != std::string::npos ||
|
||||
resp.find("\nOK\n") != std::string::npos ||
|
||||
resp.find("OK") != std::string::npos)
|
||||
return true;
|
||||
if (resp.find("ERROR") != std::string::npos)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elapsed += 200;
|
||||
}
|
||||
return false; // 超时
|
||||
};
|
||||
|
||||
int fd = open(Serious.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
{
|
||||
std::cerr << "无法打开串口: " << Serious << "\n";
|
||||
return;
|
||||
}
|
||||
// 设为阻塞
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
|
||||
if (!configure_serial(fd))
|
||||
{
|
||||
std::cerr << "串口参数配置失败\n";
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string resp;
|
||||
// 0) 连续握手,确保 AT 可用(最多 10 次)
|
||||
{
|
||||
bool ok = false;
|
||||
for (int i = 1; i <= 10; ++i)
|
||||
{
|
||||
if (send_at(fd, "AT", resp, 500))
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
usleep(500 * 1000);
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
std::cerr << "AT 握手失败,模块未响应\n";
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 1) 打开功能
|
||||
if (!send_at(fd, "AT+CFUN=1", resp))
|
||||
{
|
||||
std::cerr << "AT+CFUN=1 失败: " << resp << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "AT+CFUN=1 OK\n";
|
||||
}
|
||||
|
||||
// 1.1) 等 SIM 就绪(AT+CPIN? 返回 READY,最多 30 秒)
|
||||
{
|
||||
bool ready = false;
|
||||
for (int i = 0; i < 60; ++i)
|
||||
{
|
||||
if (send_at(fd, "AT+CPIN?", resp, 500) && resp.find("READY") != std::string::npos)
|
||||
{
|
||||
ready = true;
|
||||
break;
|
||||
}
|
||||
usleep(500 * 1000);
|
||||
}
|
||||
if (!ready)
|
||||
std::cerr << "SIM 未就绪,后续可能失败\n";
|
||||
}
|
||||
|
||||
// 2) 设置 PDP 上下文:APN = ipn(请按运营商实际 APN 调整)
|
||||
if (!send_at(fd, "AT+CGDCONT=1,\"IP\",\"ipn\"", resp))
|
||||
{
|
||||
std::cerr << "AT+CGDCONT 设置失败: " << resp << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "AT+CGDCONT OK\n";
|
||||
}
|
||||
|
||||
// 2.1) 等驻网(AT+CEREG? 返回 ,1 或 ,5,最多 60 秒)
|
||||
{
|
||||
auto registered = [](const std::string &s)
|
||||
{ return s.find(",1") != std::string::npos || s.find(",5") != std::string::npos; };
|
||||
bool ok = false;
|
||||
for (int i = 0; i < 60; ++i)
|
||||
{
|
||||
if (send_at(fd, "AT+CEREG?", resp, 500) && registered(resp))
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
usleep(1000 * 1000);
|
||||
}
|
||||
if (!ok)
|
||||
std::cerr << "未驻网,继续尝试拨号但成功率较低\n";
|
||||
}
|
||||
|
||||
// 3) 打开网卡/拨号(Quectel 私有指令示例)- 失败重试 5 次
|
||||
{
|
||||
bool ok = false;
|
||||
for (int attempt = 1; attempt <= 5; ++attempt)
|
||||
{
|
||||
resp.clear();
|
||||
if (send_at(fd, "AT+QNETDEVCTL=1,1,1", resp))
|
||||
{
|
||||
std::cout << "AT+QNETDEVCTL OK (attempt " << attempt << ")\n";
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
std::cerr << "AT+QNETDEVCTL 失败 (attempt " << attempt << "/5): " << resp << "\n";
|
||||
usleep(1000 * 1000); // 1s 间隔
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
std::cerr << "AT+QNETDEVCTL 连续 5 次失败,退出本步骤\n";
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
8
GetNet/src/makefile
Normal file
8
GetNet/src/makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
all:SetNet
|
||||
|
||||
SetNet:GetNet.cpp
|
||||
g++ -g -o setNet GetNet.cpp
|
||||
mv ./setNet ../bin/
|
||||
|
||||
clean:
|
||||
rm -rf ../bin/*
|
Reference in New Issue
Block a user