-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathModem.cpp
More file actions
170 lines (156 loc) · 4.87 KB
/
Copy pathModem.cpp
File metadata and controls
170 lines (156 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include "Modem.hpp"
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <ctime>
// 构造函数:打开串口和日志文件
Modem::Modem(const std::string &port) {
fd = open(port.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
std::cerr << "Error opening port " << port << ": " << strerror(errno) << std::endl;
std::exit(EXIT_FAILURE);
}
// 根据当前时间生成日志文件名,例如 "modem_log_YYYYMMDD_HHMMSS.txt"
time_t now = time(nullptr);
struct tm *local = localtime(&now);
char filename[128];
// 格式:modem_log_年年年年月月日日_时时分分秒秒.txt
strftime(filename, sizeof(filename), "modem_log_%Y%m%d_%H%M%S.txt", local);
logFile.open(filename);
if (!logFile.is_open()) {
std::cerr << "Error opening log file: " << filename << std::endl;
close(fd);
std::exit(EXIT_FAILURE);
}
}
// 析构函数:关闭日志文件和串口
Modem::~Modem() {
if (logFile.is_open()) {
logFile.close();
}
if (fd >= 0) {
close(fd);
}
}
// 配置串口
bool Modem::configure() {
struct termios tty;
if (tcgetattr(fd, &tty) != 0) {
std::cerr << "tcgetattr error: " << strerror(errno) << std::endl;
return false;
}
// 设置波特率
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
// 8 数据位、无校验、1 停止位、无硬件流控
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
tty.c_cflag |= CREAD | CLOCAL;
// 原始模式:禁用行缓冲、回显和信号
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_oflag &= ~OPOST;
// 设置读取条件
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
std::cerr << "tcsetattr error: " << strerror(errno) << std::endl;
return false;
}
return true;
}
// 设置 RTS 信号
bool Modem::setRTS(bool state) {
int status;
if (ioctl(fd, TIOCMGET, &status) != 0) {
std::cerr << "ioctl(TIOCMGET) error: " << strerror(errno) << std::endl;
return false;
}
if (state)
status |= TIOCM_RTS;
else
status &= ~TIOCM_RTS;
if (ioctl(fd, TIOCMSET, &status) != 0) {
std::cerr << "ioctl(TIOCMSET) error: " << strerror(errno) << std::endl;
return false;
}
return true;
}
// 发送 AT 命令并读取响应
int Modem::sendCommand(const std::string &cmd, std::string &response) {
int bytesWritten = write(fd, cmd.c_str(), cmd.size());
if (bytesWritten < 0) {
std::cerr << "write error: " << strerror(errno) << std::endl;
return -1;
}
// 读取响应数据
char buffer[256];
memset(buffer, 0, sizeof(buffer));
int bytesRead = read(fd, buffer, sizeof(buffer) - 1);
if (bytesRead < 0) {
std::cerr << "read error: " << strerror(errno) << std::endl;
return -1;
}
buffer[bytesRead] = '\0';
response = std::string(buffer);
return bytesRead;
}
// 输出当前时间戳(同时写入日志文件)
void Modem::logTimestamp() {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
std::ostringstream oss;
oss << "ts: " << ts.tv_sec << "." << ts.tv_nsec << " ";
std::string timestampStr = oss.str();
std::cout << timestampStr;
writeLog(timestampStr);
}
// 向日志文件写入消息
void Modem::writeLog(const std::string &msg) {
if (logFile.is_open()) {
logFile << msg;
logFile.flush();
}
}
// 解析函数:解析返回信息中以指定前缀开头的 4 个整数数据
bool parseSignalInfo(const std::string &response, const std::string &prefix, SignalInfo &info) {
std::istringstream iss(response);
std::string line;
while (std::getline(iss, line)) {
if (line.compare(0, prefix.size(), prefix) == 0) {
int prx, drx, rx2, rx3;
if (sscanf(line.c_str(), "%*[^:]: %d,%d,%d,%d", &prx, &drx, &rx2, &rx3) == 4) {
info.PRX = prx;
info.DRX = drx;
info.RX2 = rx2;
info.RX3 = rx3;
return true;
}
}
}
return false;
}
// 解析函数:解析 CSQ 返回数据(例如 "+CSQ: 17,0")
bool parseCSQInfo(const std::string &response, CSQ_Info &info) {
std::istringstream iss(response);
std::string line;
while (std::getline(iss, line)) {
if (line.compare(0, 5, "+CSQ:") == 0) {
int rssi, ber;
if (sscanf(line.c_str(), "+CSQ: %d,%d", &rssi, &ber) == 2) {
info.RSSI = rssi;
info.ber = ber;
return true;
}
}
}
return false;
}