通过发送AT+CWLAP
,可捕获周围的AP信息,下面是查看官方AT文档后得到的信息:
在超级终端中尝试,其中新刷入的固件要启动WIFI模式,启动指令:AT+CWMODE_DEF=3
由于我用的是改造过的固件,波特率和官方的不一样,所以在使用的时候请改一下波特率,在代码的宏定义部分。
int main(int argc, char *argv[])
{
int fd, res;
struct termios oldtio, newtio;
char ch;
char buf[256] = {0};
printf("Start...\n");
//-----------打开uart设备文件------------------
fd = open(UART_DEVICE, O_RDWR|O_NOCTTY);//没有设置O_NONBLOCK,所以这里read和write是阻塞操作
if (fd < 0) {
perror(UART_DEVICE);
exit(1);
}
else
printf("Open %s successfully\n", UART_DEVICE);
//-----------设置操作参数-----------------------
tcgetattr(fd, &oldtio);//获取当前操作模式参数
memset(&newtio, 0, sizeof(newtio));
//波特率 数据位=8 使能数据接收
newtio.c_cflag = BAUDRATE|CS8|CLOCAL|CREAD;
newtio.c_iflag = IGNPAR;
//newtio.c_oflag = OPOST | OLCUC; //
/* 设定为正规模式 */
//newtio.c_lflag = ICANON;
tcflush(fd, TCIFLUSH);//清空输入缓冲区和输出缓冲区
tcsetattr(fd, TCSANOW, &newtio);//设置新的操作参数
//------------向urat发送数据-------------------
char writeBuf[32] = "AT+CWLAP\r\n";
res = write(fd, writeBuf, 32);
printf("Writing: %s\n", writeBuf);
//-------------从uart接收数据-------------------
string allReturnBuf = "";
string s_buf;
printf("Reading...\n");
while(1) {
res = read(fd, buf, 64);//程序将在这里挂起,直到从uart接收到数据(阻塞操作)
if (res == 0)
continue;
buf[res] = '\0';
// printf("res = %d, buf = %s\n", res, buf);//将uart接收到的字符打印出来
// 由于每次最多只能拿32位数据,所以要一直获取直到指令返回信息全部取回
s_buf = buf;
allReturnBuf += s_buf;
// 判断AT返回命令是否到头
if (isEnd(allReturnBuf)) {
// for (int i = 0; i < allReturnBuf.size(); i++) {
// if ('\n' == allReturnBuf[i]) cout << "\\n";
// else if ('\0' == allReturnBuf[i]) cout << "\\0";
// else if ('\r' == allReturnBuf[i]) cout << "\\r";
// else cout << allReturnBuf[i];
// }
cout << "response:\n" << allReturnBuf;
cout << endl;
displayRes(selectWifiInfo(allReturnBuf));
break;
}
}
//------------关闭uart设备文件,恢复原先参数--------
close(fd);
printf("Close %s\n", UART_DEVICE);
tcsetattr(fd, TCSANOW, &oldtio); //恢复原先的设置
return 0;
}
由于每次通过UART收到的信息是固定位数的,例如在我的是每次接受32位,所以要不断收集返回信息并判断,直到判断出是指令返回结尾。
// 通过判断字符串的最后是否为 ERROR\r\n 或 OK\r\n 来判断命令输出是否结束
bool isEnd(string &str) {
if (str.size() < 4) return false;
string last4(str, str.size() - 4, 4);
if ("OK\r\n" == last4) {
cout << "AT response OK!" << endl;
return true;
}
if (str.size() >= 7) {
string last7(str, str.size() - 7, 7);
if ("ERROR\r\n" == last7) {
cout << "AT response ERROR!" << endl;
return true;
}
}
}
下面函数用于分隔字符串
//split a string by a pattern
vector<string> split(string str, string pattern) {
vector<string> ret;
if(pattern.empty()) return ret;
size_t start=0,index=str.find_first_of(pattern,0);
while(index!=str.npos) {
if(start!=index)
ret.push_back(str.substr(start,index-start));
start=index+1;
index=str.find_first_of(pattern,start);
}
if(!str.substr(start).empty())
ret.push_back(str.substr(start));
return ret;
}
// 用于筛选通过 AT+CWLAP 取回的信息
vector< vector<string> > selectWifiInfo(string &str) {
/* AT+CWLAP 命令获取格式
+CWLAP:,,,,,,
,,,,
AT+CWLAP 获取样例
+CWLAP:(4,"MastarB",-74,"30:fc:68:bf:c5:cd",1,9,0,4,4,7,1)
AT+CWLAP 参数说明
:加密方式
:字符串参数,AP 的 SSID
:信号强度
:字符串参数,AP 的 MAC 地址
:信道号
:AP 频偏,单位:kHz。此数值除以 2.4,可得到 ppm 值
:频偏校准值
*/
vector<string> lines = split(str, "\n"); //lines of response
// 通过长度将有用信息筛选
vector<string>::iterator iter = lines.begin();
while(iter != lines.end()) {
if ((*iter).size() <= 15) {
lines.erase(iter);
} else {
iter++;
}
}
vector< vector<string> > result;
// 裁剪有用信息
for (int i = 0; i < lines.size(); i++) {
string info = string(lines[i].begin(), lines[i].end() - 1);
result.push_back(split(info, ","));
}
return result;
}
参考http://blog.csdn.net/cherish_x/article/details/79362532,利用esp8266wifi信号强度测距,d = 10^((abs(rssi) - A) / (10 * n))。
// 将RSSI转换成距离
float rssiTodis(int RSSI) {
float iu, distance;
iu = (float)(RSSI - A) / (float)N;
distance = pow(10, iu);
return distance;
}
/*
Author: [email protected]
Date: 2018.03.24
Used for getting the rssi of the wifi nearby from 8266.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BAUDRATE B38400
#define UART_DEVICE "/dev/ttyS3"
#define FALSE -1
#define TRUE 0
#define N 40 //N = 10 * n ,其中n为环境衰减因子,3.25-4.5
#define A 51 //接收机和发射机间隔1m时的信号强度
using namespace std;
// my functions
vector<string> split(string str, string pattern);
bool isEnd(string &str);
vector< vector<string> > selectWifiInfo(string &str);
float rssiTodis(int RSSI);
void displayRes(vector< vector<string> > result);
int main(int argc, char *argv[])
{
int fd, res;
struct termios oldtio, newtio;
char ch;
char buf[256] = {0};
printf("Start...\n");
//-----------打开uart设备文件------------------
fd = open(UART_DEVICE, O_RDWR|O_NOCTTY);//没有设置O_NONBLOCK,所以这里read和write是阻塞操作
if (fd < 0) {
perror(UART_DEVICE);
exit(1);
}
else
printf("Open %s successfully\n", UART_DEVICE);
//-----------设置操作参数-----------------------
tcgetattr(fd, &oldtio);//获取当前操作模式参数
memset(&newtio, 0, sizeof(newtio));
//波特率 数据位=8 使能数据接收
newtio.c_cflag = BAUDRATE|CS8|CLOCAL|CREAD;
newtio.c_iflag = IGNPAR;
//newtio.c_oflag = OPOST | OLCUC; //
/* 设定为正规模式 */
//newtio.c_lflag = ICANON;
tcflush(fd, TCIFLUSH);//清空输入缓冲区和输出缓冲区
tcsetattr(fd, TCSANOW, &newtio);//设置新的操作参数
//------------向urat发送数据-------------------
char writeBuf[32] = "AT+CWLAP\r\n";
res = write(fd, writeBuf, 32);
printf("Writing: %s\n", writeBuf);
//-------------从uart接收数据-------------------
string allReturnBuf = "";
string s_buf;
printf("Reading...\n");
while(1) {
res = read(fd, buf, 64);//程序将在这里挂起,直到从uart接收到数据(阻塞操作)
if (res == 0)
continue;
buf[res] = '\0';
// printf("res = %d, buf = %s\n", res, buf);//将uart接收到的字符打印出来
// 由于每次最多只能拿32位数据,所以要一直获取直到指令返回信息全部取回
s_buf = buf;
allReturnBuf += s_buf;
// 判断AT返回命令是否到头
if (isEnd(allReturnBuf)) {
// for (int i = 0; i < allReturnBuf.size(); i++) {
// if ('\n' == allReturnBuf[i]) cout << "\\n";
// else if ('\0' == allReturnBuf[i]) cout << "\\0";
// else if ('\r' == allReturnBuf[i]) cout << "\\r";
// else cout << allReturnBuf[i];
// }
cout << "response:\n" << allReturnBuf;
cout << endl;
displayRes(selectWifiInfo(allReturnBuf));
break;
}
}
//------------关闭uart设备文件,恢复原先参数--------
close(fd);
printf("Close %s\n", UART_DEVICE);
tcsetattr(fd, TCSANOW, &oldtio); //恢复原先的设置
return 0;
}
// 通过判断字符串的最后是否为 ERROR\r\n 或 OK\r\n 来判断命令输出是否结束
bool isEnd(string &str) {
if (str.size() < 4) return false;
string last4(str, str.size() - 4, 4);
if ("OK\r\n" == last4) {
cout << "AT response OK!" << endl;
return true;
}
if (str.size() >= 7) {
string last7(str, str.size() - 7, 7);
if ("ERROR\r\n" == last7) {
cout << "AT response ERROR!" << endl;
return true;
}
}
}
//split a string by a pattern
vector<string> split(string str, string pattern) {
vector<string> ret;
if(pattern.empty()) return ret;
size_t start=0,index=str.find_first_of(pattern,0);
while(index!=str.npos) {
if(start!=index)
ret.push_back(str.substr(start,index-start));
start=index+1;
index=str.find_first_of(pattern,start);
}
if(!str.substr(start).empty())
ret.push_back(str.substr(start));
return ret;
}
// 用于筛选通过 AT+CWLAP 取回的信息
vector< vector<string> > selectWifiInfo(string &str) {
/* AT+CWLAP 命令获取格式
+CWLAP:,,,,,,
,,,,
AT+CWLAP 获取样例
+CWLAP:(4,"MastarB",-74,"30:fc:68:bf:c5:cd",1,9,0,4,4,7,1)
AT+CWLAP 参数说明
:加密方式
:字符串参数,AP 的 SSID
:信号强度
:字符串参数,AP 的 MAC 地址
:信道号
:AP 频偏,单位:kHz。此数值除以 2.4,可得到 ppm 值
:频偏校准值
*/
vector<string> lines = split(str, "\n"); //lines of response
// 通过长度将有用信息筛选
vector<string>::iterator iter = lines.begin();
while(iter != lines.end()) {
if ((*iter).size() <= 15) {
lines.erase(iter);
} else {
iter++;
}
}
vector< vector<string> > result;
// 裁剪有用信息
for (int i = 0; i < lines.size(); i++) {
string info = string(lines[i].begin(), lines[i].end() - 1);
result.push_back(split(info, ","));
}
return result;
}
// 将RSSI转换成距离
float rssiTodis(int RSSI) {
float iu, distance;
iu = (float)(RSSI - A) / (float)N;
distance = pow(10, iu);
return distance;
}
// 用于命令行展示结果
void displayRes(vector< vector<string> > result) {
if (result.size() == 0) cout << "NO WIFI INFO!" << endl;
cout << std::left << setw(40) << setfill(' ') << "| NAME";
cout << setw(10) << setfill(' ') << "| CHANNEL";
cout << setw(10) << setfill(' ') << "| RSSI";
cout << setw(10) << setfill(' ') << "| DIS(m)";
cout << setw(30) << setfill(' ') << "| MAC" << endl;
int temp;
for (int i = 0; i < result.size(); i++) {
cout <<" " << setw(40) << setfill(' ') << result[i][1];
cout << setw(10) << setfill(' ') << result[i][4];
cout << setw(10) << setfill(' ') << result[i][2];
temp = (result[i][2][1] - '0') * 10 + (result[i][2][2] - '0');
cout << setw(10) << setiosflags(ios::fixed) << setprecision(2)
<< setfill(' ') << rssiTodis(temp);
cout << setw(30) << setfill(' ') << result[i][3];
cout << endl;
}
cout << endl;
}