tx-nx设置wifi和接口
前言
针对嵌入式开发,有时候通过QT或PAD跨网络对设备设置WIFI,在此记录下,方便后续的查阅。
基础知识点
1.创建和删除一个wifi连接
创建WIFI 连接
nmcli device wifi connect "SSID" password "passwd"
每次创建在/etc/NetworkManager/system-connections/
目录下TR106-4文件多个,分别为"TR106" “TR106-4 1” TR106-4 2 …为什么有多个,笔者可能觉得是因为存在相同的SSID,不同的PASSWD的原因吧!
删除wifi连接
p.s:不允许手动rm删除,删除依然会保留到nmcli con show中
nmcli con del "SSID"
2. 启动连接和关闭连接
启动
nmcli connection up "TR106"或 nmcli device con wlan0
nmcli device con wlan0
关闭wifi连接
nmcli connection down "TR106"或nmcli device dis wlan0
- 创建热点 暂不描述,后续如增加再做记录。
代码和调试
1. 代码展示
#ifndef WIFI_MANAGE_H__
#define WIFI_MANAGE_H__
#include <vector>
#include <string>
#ifndef NMCCLI_CON_SHOW_ACTIVE
#define NMCCLI_CON_SHOW_ACTIVE "nmcli con show -active |grep wifi |grep wlan"
#endif
#define OUT //param out
#define IN //param in
#define MAX_STRING (1024)
#define MIN_STRING (128)
namespace NMV
{
};
class CWifiManage
{
public:
static CWifiManage *inst()
{
static CWifiManage wm;
return &wm;
}
/**获取设备WIFI扫描的列表*/
int getWifiSSIDScanf();
const std::vector<std::string> &getSsidList()const {return m_ssid_list;}
/**获取当前wlanx已连接的WIFI ssid和passwd,当前只有wlan0,如果有多个wlan,需要做修改*/
int getSystemWlanxInfo(std::string &rhs_ssid, std::string &rhs_passwd);
/**获取当前的SSID和PASSWD*/
int getWifiInfo(std::string &rhs_ssid, std::string &rhs_passwd)const {rhs_ssid = m_WifiSsid; rhs_passwd = m_WifiPasswd;}
/**设置一个wifi信息到系统,切换WIFI的操作*/
int setWifiInfo2SystemNetwork(const std::string &rhs_ssid, const std::string &rhs_passwd,
OUT char *sys_response);
/**外部接口,设置WIFI*/
int setWifiInfo(const std::string &rhs_ssid, const std::string &rhs_passwd);
private:
CWifiManage();
~CWifiManage();
std::string m_WifiSsid, m_WifiPasswd;
std::vector<std::string> m_ssid_list;
};
#endif
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <codecvt>
#include "wifi_manage.h"
CWifiManage::CWifiManage():m_WifiSsid(""), m_WifiPasswd("")
{
m_ssid_list.clear();
}
CWifiManage::~CWifiManage()
{}
int CWifiManage::getSystemWlanxInfo(OUT std::string &rhs_ssid, OUT std::string &rhs_passwd)
{
char pipeBuf[MAX_STRING] = {0};
char tssid[MIN_STRING] = {0};
FILE * pPipe = popen(NMCCLI_CON_SHOW_ACTIVE, "r");
if(!pPipe)
{
printf("PIPE ERROR\n");
return -1;
}
size_t pipeSiz = ftell(pPipe);
fseek(pPipe, 0, SEEK_SET);
fread(pipeBuf, 1, pipeSiz, pPipe);
if(pPipe){pclose(pPipe); pPipe = (FILE*)0;}
if(!strlen(pipeBuf))
{
printf("无连接上的WIFI!\n");
return -1;
}
sscanf(pipeBuf, "%s", tssid);
/*根据SSID查看Passwd*/
char ssidFileConfigure[MIN_STRING] = {0};
snprintf(ssidFileConfigure, MIN_STRING-1, "/etc/NetworkManager/system-connections/%s", tssid);
FILE *fp = fopen(ssidFileConfigure, "r");
if(!fp)
{
printf("打开%s失败!\n", ssidFileConfigure);
return -1;
}
char line_buf[MIN_STRING] = {0};
char tpasswd[MIN_STRING] = {0};
while(!feof(fp))
{
memset(line_buf, 0, MIN_STRING);
fgets(line_buf, MIN_STRING, fp);
if(strstr(line_buf, "psk="))
{
size_t line_siz = strlen(line_buf);
if(line_buf[line_siz-1] == '\n') line_buf[line_siz-1] = '\0';
memcpy(tpasswd, line_buf+strlen("psk="), strlen(line_buf+strlen("psk=")));
printf("passwd:%s, siz:%lu!\n" , tpasswd, strlen(tpasswd));
}
}
if(fp){fclose(fp); fp = (FILE*)0;}
if(strlen(tssid)&& strlen(tpasswd)){rhs_ssid = tssid; rhs_passwd = tpasswd;}
return 0;
}
int CWifiManage::setWifiInfo2SystemNetwork(const std::string &rhs_ssid, const std::string &rhs_passwd,char *sys_response)
{
char cmd_string[MIN_STRING] = {0};
memset(cmd_string, 0, MIN_STRING);
snprintf(cmd_string, MIN_STRING, "nmcli device wifi connect %s password %s", rhs_ssid.c_str(), rhs_passwd.c_str());
FILE *pPipe = popen(cmd_string, "r"); //阻塞
if(!pPipe)
{
printf("cmdString: %s, err:%s\n" , cmd_string, strerror(errno));
memcpy(sys_response, "pipe null", strlen("pipe null"));
return -1;
}
fread(sys_response, 1, MAX_STRING-1, pPipe);
pclose(pPipe); pPipe = (FILE*)0;
if(!strstr(sys_response, "successfully")) //如果设置失败
{
return -2;
}
printf("SSID:%s 设置成功!\n", rhs_ssid.c_str());
/*重置wifi为设置的ssid和信息,更新 "nmcli con show"*/
//1. 关闭之前的连接
pPipe = popen("nmcli device dis wlan0", "r");
if(pPipe){pclose(pPipe); pPipe = (FILE*)0;}
//2 开启设置的连接
memset(cmd_string, 0, MIN_STRING);
snprintf(cmd_string, MIN_STRING, "nmcli connection up %s", rhs_ssid.c_str());
pPipe = popen(cmd_string, "r");
if(pPipe){pclose(pPipe); pPipe = (FILE*)0;}
#if 0 //配置暂先不做处理
//3 删除(忘记)不需要的WIFI连接 cmd:nmcli con del "SSID",仅保留设置的wifi有效
pPipe = popen("ls /etc/NetworkManager/system-connections/ |grep -v 'Wire'", "r");
char ssid[MIN_STRING];
if(pPipe)
{
while(!feof(pPipe))
{
memset(ssid, 0, MIN_STRING);
fgets(ssid, MIN_STRING-1, pPipe);
if(ssid[strlen(ssid)-1] == '\n') ssid[strlen(ssid)-1] = '\0';
if(rhs_ssid == std::string(ssid))
{
continue;
}
comm_sys_cmd("nmcli con del %s", ssid);
}
}
#endif
return 0;
}
int CWifiManage::getWifiSSIDScanf()
{
//扫描WIFI ESSID
//do somethings
char cmd_string[MIN_STRING] = {0};
char sline[MIN_STRING], ssid[MIN_STRING];
memset(cmd_string, 0, MIN_STRING);
snprintf(cmd_string, MIN_STRING, "iw wlan0 scan |grep SSID");
FILE *pPipe = (FILE*)0;
pPipe = popen(cmd_string, "r");
if(!pPipe)
{
printf("cmdString: %s, err:%s\n" , cmd_string, strerror(errno));
return -1;
}
while(!feof(pPipe))
{
memset(sline, 0, MIN_STRING);memset(ssid, 0 , MIN_STRING);
fgets(sline, MIN_STRING, pPipe);
int j = 0;
for(int i = 0; i < strlen(sline); ++i)
{
if(sline[i] == '\t' || sline[i] == '\n' || sline[i] == ' ')
{
continue ;
}
ssid[j] = sline[i];
j++;
}
//printf("ssid:%s, siz:%lu\n", ssid, strlen(ssid));
if(0 == strlen(ssid) - strlen("SSID:") || strlen(sline) == 0 )
{
//printf("ssid为空\n");
continue;
}
if(strstr(ssid, "x00"))
{
printf("含有x00\n");
continue;
}
static std::wstring_convert<std::codecvt_utf8<wchar_t> > strCnv;
// std::wstring test = strCnv.from_bytes(ssid);
printf("%s\n", test.c_str());
m_ssid_list.push_back(ssid+strlen("SSID:"));
}
auto vit = m_ssid_list.begin();
for(; vit != m_ssid_list.end();++vit)
{
static int cnt = 0;
std::cout << "SSID_siz:" << (*vit).size() << " "<< *vit << std::endl;;
}
if(pPipe){pclose(pPipe); pPipe = (FILE*)0;}
return 0;
}
int CWifiManage::setWifiInfo(const std::string &rhs_ssid, const std::string &rhs_passwd)
{
char sys_resp[MAX_STRING] = {0};
if(setWifiInfo2SystemNetwork(rhs_ssid, rhs_passwd, sys_resp))
{
printf("设置wifi失败!");
}
std::cout << "设置wifi系统提示: " << sys_resp << std::endl;
m_WifiSsid = rhs_ssid;
m_WifiPasswd = rhs_passwd;
return 0;
}
int main(int argc, char *argv[])
{
int ret = 0;
#if 0
std::string str_ssid = "", str_passwd = "";
ret = CWifiManage::inst()->getSystemWlanxInfo(str_ssid, str_passwd);
if(ret == 0)
{
printf("当前wifi已连接成功, ssid:%s, passwd:%s\n", str_ssid.c_str(), str_passwd.c_str());
}
if(CWifiManage::inst()->setWifiInfo("HONOR-Hello-Ouyang_2.4", "woshisunouyangaaaa"))
{
printf("设置wifi失败!\n");
}
#else
CWifiManage::inst()->getWifiSSIDScanf();
#endif
}
2. 调试
扫描中踢出了空格,换行和制表符
获取WIFI扫描
{
"Jsonrpc": "1.0",
"Method": "GetWifiScan",
"Result": true,
"SsidList": [
"TR106-4",
"HONOR-Hello-Ouyang_2.4",
"HUAWEI-WANG",
"Maxvision-2.4G",
"HUAWEI-MV_SLAM_02",
"ymg",
"fanyiji-ceshi",
"Tenda_1D0130",
"cleanRobot",
"Xiaomi_DESKT",
"YUN",
"siweite7wifi",
"HUAWEI-MV_SLAM_00",
"HONOR-xunjian-Mast",
"HONOR-xunjian-Mast",
"jxkjc",
"Trans-4G-SanFanTest",
"TP-LINK_2.4G_D6D088",
"TR106-4",
"Maxvision-2.4G",
"ChinaNet-5pV3-5G",
"HUAWEI-MV_SLAM_00",
"HONOR-Hello-Ouyang_5G",
"HUAWEI-MV_SLAM_02",
"ROBOT_TEST",
"HONOR-0J14YA",
"xunjian"
]
}
设置wifi过程中遇到的问题:
1. SSID不存在,返回如下错误
{
"Jsonrpc": "1.0",
"Method": "SetWifiConnect",
"Params": null,
"ResponseMsg": "ERROR:未扫描到SSID:TR106-41",
"Result": false
}
之前使用PAD对设备设置,用的是android的API扫描WIFI SSID,可能设备和WIFI处的位置不同,以及无线网卡的差异性,导致PAD搜索的SSID可能设备网卡搜不到的情况。
2.输入的密码错误
{
"Jsonrpc": "1.0",
"Method": "SetWifiConnect",
"Params": null,
"ResponseMsg": "ERROR:Error: Connection activation failed: (7) Secrets were required, but not provided.\n",
"Result": false
}
写到最后
1. 每次设置一个新WIFI,将之前的配置都删除掉,让设备只连最近更新的WIFI,后面考虑合理性以及手机android等
都采用保存配置的情况, 该功能就删除了。
2. 还有比较多的功能可以实现,比如忘记WIFI名称等功能。
忘记WIFI名称
pPipe = popen("ls /etc/NetworkManager/system-connections/ |grep -v 'Wire'", "r");
char ssid[128];
if(pPipe)
{
while(!feof(pPipe))
{
memset(ssid, 0, MIN_STRING);
fgets(ssid, MIN_STRING-1, pPipe);
if(ssid[strlen(ssid)-1] == '\n') ssid[strlen(ssid)-1] = '\0';
if(rhs_ssid == std::string(ssid))
{
continue;
}
std::string str_cmd = "nmcli con del" + " " + ssid;
system(str_cmd.c_str());
}
}