1*4882a593Smuzhiyun #include "hostapdcli.h"
2*4882a593Smuzhiyun #include "terminal.h"
3*4882a593Smuzhiyun #include <QTimer>
4*4882a593Smuzhiyun #include <QDebug>
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #define AP_INTERFACE "interface=%1\n"
7*4882a593Smuzhiyun #define AP_DRIVER "driver=%1\n"
8*4882a593Smuzhiyun #define AP_SSID "ssid=%1\n"
9*4882a593Smuzhiyun #define AP_CHANNEL "channel=%1\n"
10*4882a593Smuzhiyun #define AP_HW_MODE "hw_mode=%1\n"
11*4882a593Smuzhiyun #define AP_MACADDR_ACL "macaddr_acl="
12*4882a593Smuzhiyun #define AP_IGNORE_BROADCAST_SSID "ignore_broadcast_ssid=%1\n"
13*4882a593Smuzhiyun #define AP_AUTH_ALGS "auth_algs=%1\n"
14*4882a593Smuzhiyun #define AP_WPA "wpa=%1\n"
15*4882a593Smuzhiyun #define AP_WPA_PASSPHRASE "wpa_passphrase=%1\n"
16*4882a593Smuzhiyun #define AP_WPA_KEY_MGMT "wpa_key_mgmt=%1\n"
17*4882a593Smuzhiyun #define AP_WPA_PAIRWISE "wpa_pairwise=%1\n"
18*4882a593Smuzhiyun #define AP_RSN_PAIRWISE "rsn_pairwise=%1\n"
19*4882a593Smuzhiyun #define AP_CTR_INTERFACE "ctrl_interface=%1\n"
20*4882a593Smuzhiyun #define AP_RELOAD "reload\n"
21*4882a593Smuzhiyun #define AP_ALL_STA "all_sta\n"
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun class HostapdcliPrivate
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun public:
HostapdcliPrivate(Hostapdcli * _q)26*4882a593Smuzhiyun HostapdcliPrivate(Hostapdcli *_q):q(_q){}
27*4882a593Smuzhiyun void handAutoMessage(const QByteArray &a);
28*4882a593Smuzhiyun void handCmdMessage(const QByteArray &d);
29*4882a593Smuzhiyun QString get(const QByteArray &a, const QByteArray &start, const QByteArray &end);
30*4882a593Smuzhiyun void pharsAllStaInfo(const QByteArray &a, QList<ScanInfoAp> &infos);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun QString message;
33*4882a593Smuzhiyun QString ssid;
34*4882a593Smuzhiyun QString passphrase;
35*4882a593Smuzhiyun QString driver;
36*4882a593Smuzhiyun QString interface;
37*4882a593Smuzhiyun QString ip;
38*4882a593Smuzhiyun QTimer *timer;
39*4882a593Smuzhiyun Hostapdcli *q;
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun
Hostapdcli(QObject * parent)42*4882a593Smuzhiyun Hostapdcli::Hostapdcli(QObject *parent):QObject(parent),
43*4882a593Smuzhiyun m_d(new HostapdcliPrivate(this))
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun m_d->timer =new QTimer(this);
46*4882a593Smuzhiyun connect(m_d->timer, &QTimer::timeout, this, [=](){
47*4882a593Smuzhiyun allsta();
48*4882a593Smuzhiyun });
49*4882a593Smuzhiyun m_d->timer->setInterval(2000);
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun
~Hostapdcli()52*4882a593Smuzhiyun Hostapdcli::~Hostapdcli()
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun delete m_d;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
start_hostapd(const QString & ko,const QString & ModuleName,const QString & driverName,const QString & cardName,const QString & ip)57*4882a593Smuzhiyun void Hostapdcli::start_hostapd(const QString &ko, const QString &ModuleName, const QString &driverName, const QString &cardName, const QString &ip)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun qDebug()<<"start_hostapd";
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun m_d->driver = driverName;
62*4882a593Smuzhiyun m_d->interface = cardName;
63*4882a593Smuzhiyun m_d->ip = ip;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun QString moudleIsExit =QString("lsmod | grep %1 | grep -v grep").arg(ModuleName);
66*4882a593Smuzhiyun if(!Terminal::execCmd(moudleIsExit).contains(ModuleName))
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun qDebug() << Terminal::execCmd("insmod " + ko);
69*4882a593Smuzhiyun qDebug() << QString("insmod %1").arg(ko);
70*4882a593Smuzhiyun }else{
71*4882a593Smuzhiyun qDebug() << QString("driver: %1 already install").arg(ModuleName);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun QString defaultConfig = QString(
75*4882a593Smuzhiyun "ctrl_interface=/var/run/hostapd\n"
76*4882a593Smuzhiyun "interface=wlan0\n"
77*4882a593Smuzhiyun "driver=%1\n"
78*4882a593Smuzhiyun "ssid=wifi_test\n"
79*4882a593Smuzhiyun "channel=9\n"
80*4882a593Smuzhiyun "hw_mode=g\n"
81*4882a593Smuzhiyun "macaddr_acl=0\n"
82*4882a593Smuzhiyun "ignore_broadcast_ssid=0\n"
83*4882a593Smuzhiyun "auth_algs=1\n"
84*4882a593Smuzhiyun "wpa=3\n"
85*4882a593Smuzhiyun "wpa_passphrase=12345678\n"
86*4882a593Smuzhiyun "wpa_key_mgmt=WPA-PSK\n"
87*4882a593Smuzhiyun "wpa_pairwise=TKIP\n"
88*4882a593Smuzhiyun "rsn_pairwise=CCMP\n").arg(driverName) ;
89*4882a593Smuzhiyun QString hostapdConf = QString("echo \"%1\" > /etc/hostapd.conf").arg(defaultConfig);
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun Terminal::execCmd(hostapdConf);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun auto driveInstallFinish = [=](){
94*4882a593Smuzhiyun Terminal::execCmd("echo 1 > /proc/sys/net/ipv4/ip_forward");
95*4882a593Smuzhiyun Terminal::execCmd("iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE");
96*4882a593Smuzhiyun Terminal::execCmd(QString("ifconfig %1 up").arg(cardName));
97*4882a593Smuzhiyun Terminal::execCmd(QString("ifconfig %1 %2").arg(cardName).arg(ip));
98*4882a593Smuzhiyun QString startSevrverCmd =QString("hostapd /etc/hostapd.conf &");
99*4882a593Smuzhiyun if(!Terminal::execCmd("ps -ef | grep -v grep | grep \"hostapd /etc/hostapd.conf\"").contains("hostapd"))
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun system(startSevrverCmd.toLatin1().data());
102*4882a593Smuzhiyun qDebug()<<"start :"<< startSevrverCmd;
103*4882a593Smuzhiyun }else{
104*4882a593Smuzhiyun qDebug() <<"hostapd already start!";
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun if(!Terminal::execCmd("ps -ef | grep -v grep | grep dnsmasq").contains("dnsmasq"))
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun Terminal::execCmd("/etc/init.d/dnsmasq start");
110*4882a593Smuzhiyun }else{
111*4882a593Smuzhiyun qDebug() <<"dnsmasq already start!";
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun ///一秒后在启动服务,应为wifi网卡驱动可能没有安转好.
117*4882a593Smuzhiyun QTimer::singleShot(1000, this, [=](){
118*4882a593Smuzhiyun driveInstallFinish();
119*4882a593Smuzhiyun emit hospapdStartFinish();
120*4882a593Smuzhiyun });
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
setStart(bool bStart)123*4882a593Smuzhiyun void Hostapdcli::setStart(bool bStart)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun if(bStart)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun this->start("hostapd_cli");
128*4882a593Smuzhiyun m_d->timer->start();
129*4882a593Smuzhiyun }else{
130*4882a593Smuzhiyun m_d->timer->stop();
131*4882a593Smuzhiyun this->stop();
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
stop_hostapd()135*4882a593Smuzhiyun void Hostapdcli::stop_hostapd()
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun qDebug()<<"stop_hostapd ";
138*4882a593Smuzhiyun Terminal::killProcess("dnsmasq");
139*4882a593Smuzhiyun Terminal::killProcess("hostapd");
140*4882a593Smuzhiyun Terminal::execCmd(QString("ifconfig %1 down").arg(m_d->interface));
141*4882a593Smuzhiyun this->stop();
142*4882a593Smuzhiyun QList<ScanInfoAp> info;
143*4882a593Smuzhiyun emit newStaInfo(info);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
setWifiName(const QString & ssid)146*4882a593Smuzhiyun void Hostapdcli::setWifiName(const QString &ssid)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun m_d->ssid = ssid;
149*4882a593Smuzhiyun send(QString(AP_SSID).arg(ssid));
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
setWifiPassword(const QString & passphrase)152*4882a593Smuzhiyun void Hostapdcli::setWifiPassword(const QString &passphrase)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun m_d->passphrase = passphrase;
155*4882a593Smuzhiyun send(QString(AP_WPA_PASSPHRASE).arg(passphrase));
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
setInterface(const QString & interface)158*4882a593Smuzhiyun void Hostapdcli::setInterface(const QString &interface)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun m_d->interface = interface;
161*4882a593Smuzhiyun send(QString(AP_INTERFACE).arg(interface));
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
reload()164*4882a593Smuzhiyun void Hostapdcli::reload()
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun send(AP_RELOAD);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
allsta()169*4882a593Smuzhiyun void Hostapdcli::allsta()
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun send(AP_ALL_STA);
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
processMessage(const QString & d)174*4882a593Smuzhiyun void Hostapdcli::processMessage(const QString &d)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun m_d->message +=d;
177*4882a593Smuzhiyun char enter ='\n';
178*4882a593Smuzhiyun char end='>';
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun QByteArray cmdData;
181*4882a593Smuzhiyun QByteArray rowData;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun char lastChar;
184*4882a593Smuzhiyun for(int i=0; i<m_d->message.size(); i++)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun char c = m_d->message.at(i).toLatin1();
187*4882a593Smuzhiyun cmdData +=c;
188*4882a593Smuzhiyun rowData +=c;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun if(c == enter)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun m_d->handAutoMessage(rowData);
193*4882a593Smuzhiyun qDebug()<<"+++++++++++++++++"<< rowData;
194*4882a593Smuzhiyun rowData.clear();
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if(c == end && lastChar == enter)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun m_d->handCmdMessage(cmdData);
200*4882a593Smuzhiyun qDebug()<<"#################"<< cmdData;
201*4882a593Smuzhiyun cmdData.clear();
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun lastChar = c;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun //保存未处理完消息.
207*4882a593Smuzhiyun m_d->message = cmdData;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun
handAutoMessage(const QByteArray & a)210*4882a593Smuzhiyun void HostapdcliPrivate::handAutoMessage(const QByteArray &a)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun if(a.contains("AP-STA-CONNECTED"))
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun QString ssid = get(a+"end", "AP-STA-CONNECTED", "end");
215*4882a593Smuzhiyun emit q->lostConnected(ssid);
216*4882a593Smuzhiyun }else if(a.contains("AP-STA-DISCONNECTED"))
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun QString ssid = get(a+"end", "AP-STA-DISCONNECTED", "end").trimmed();
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun qDebug()<<"lose ssid ="<<ssid;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun emit q->lostConnected(ssid);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
handCmdMessage(const QByteArray & d)226*4882a593Smuzhiyun void HostapdcliPrivate::handCmdMessage(const QByteArray &d)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun QList<ScanInfoAp> list;
229*4882a593Smuzhiyun pharsAllStaInfo(d, list);
230*4882a593Smuzhiyun if(!list.isEmpty())
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun emit q->newStaInfo(list);
233*4882a593Smuzhiyun // for(int i=0; i<list.size(); i++)
234*4882a593Smuzhiyun // {
235*4882a593Smuzhiyun // qDebug()<<"**************"<< list[i].ssid;
236*4882a593Smuzhiyun // }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun return;
241*4882a593Smuzhiyun QString cmdHead;
242*4882a593Smuzhiyun QByteArray data;
243*4882a593Smuzhiyun int index =0;
244*4882a593Smuzhiyun for(index =0; index<d.size(); index++){
245*4882a593Smuzhiyun cmdHead+=d[index];
246*4882a593Smuzhiyun if(d[index] == '\n'){
247*4882a593Smuzhiyun data = d.mid(index).trimmed();
248*4882a593Smuzhiyun break;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun if(cmdHead.isEmpty())
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun return;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun // qDebug()<<"cmdhad ="<<cmdHead ;
258*4882a593Smuzhiyun // qDebug()<<"data ="<< data;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun if(cmdHead.contains(AP_RELOAD))
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun return;
263*4882a593Smuzhiyun }else if(cmdHead.contains(AP_ALL_STA))
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun QList<ScanInfoAp> list;
266*4882a593Smuzhiyun pharsAllStaInfo(data, list);
267*4882a593Smuzhiyun emit q->newStaInfo(list);
268*4882a593Smuzhiyun return;
269*4882a593Smuzhiyun }if(cmdHead.contains(QString(AP_INTERFACE).arg(interface)))
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun }else if(cmdHead.contains(QString(AP_DRIVER).arg(driver)))
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun }else if(cmdHead.contains(QString(AP_SSID).arg(ssid)))
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun }else if(cmdHead.contains(QString(AP_WPA_PASSPHRASE).arg(passphrase)))
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun q->reload();
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
get(const QByteArray & a,const QByteArray & start,const QByteArray & end)286*4882a593Smuzhiyun QString HostapdcliPrivate::get(const QByteArray &a, const QByteArray &start, const QByteArray &end)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun //CTRL-EVENT-DISCONNECTED bssid=c2:5a:cd:8c:0f:f4 reason=3 //start ="bssid=" end="reaseo" result ="c2:5a:cd:8c:0f:f4"
289*4882a593Smuzhiyun QByteArray data;
290*4882a593Smuzhiyun QString result;
291*4882a593Smuzhiyun for(int i=0; i<a.size(); i++){
292*4882a593Smuzhiyun data +=a[i];
293*4882a593Smuzhiyun if(data.right(start.size()) == start){
294*4882a593Smuzhiyun data.clear();
295*4882a593Smuzhiyun }else if(data.right(end.size()) == end)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun result = data.left(data.size() - end.size());
298*4882a593Smuzhiyun result = result.trimmed();
299*4882a593Smuzhiyun break;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun return result;
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun
pharsAllStaInfo(const QByteArray & a,QList<ScanInfoAp> & infos)306*4882a593Smuzhiyun void HostapdcliPrivate::pharsAllStaInfo(const QByteArray &a, QList<ScanInfoAp> &infos)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun QList<QByteArray>list = a.split('\n');
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun ScanInfoAp ap;
311*4882a593Smuzhiyun foreach (QByteArray row, list) {
312*4882a593Smuzhiyun row +="end";
313*4882a593Smuzhiyun if(row.contains("dot11RSNAStatsSTAAddress"))
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun ap.ssid = get(row, "dot11RSNAStatsSTAAddress=" , "end");
316*4882a593Smuzhiyun }else if(row.contains("rx_bytes"))
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun ap.rx_bytes = get(row, "rx_bytes=" , "end");
319*4882a593Smuzhiyun }else if(row.contains("tx_bytes"))
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun ap.tx_bytes = get(row, "tx_bytes=" , "end");
322*4882a593Smuzhiyun }else if(row.contains("signal"))
323*4882a593Smuzhiyun {
324*4882a593Smuzhiyun ap.signal=get(row, "signal=" , "end").toInt();
325*4882a593Smuzhiyun }else if(row.contains("connected_time"))
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun ap.connected_time = get(row, "connected_time=" , "end");
328*4882a593Smuzhiyun infos << ap;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun // 4c:49:e3:19:65:aa
333*4882a593Smuzhiyun // flags=[AUTH][ASSOC][AUTHORIZED]
334*4882a593Smuzhiyun // aid=0
335*4882a593Smuzhiyun // capability=0x0
336*4882a593Smuzhiyun // listen_interval=0
337*4882a593Smuzhiyun // supported_rates=
338*4882a593Smuzhiyun // timeout_next=NULLFUNC POLL
339*4882a593Smuzhiyun // dot11RSNAStatsSTAAddress=4c:49:e3:19:65:aa
340*4882a593Smuzhiyun // dot11RSNAStatsVersion=1
341*4882a593Smuzhiyun // dot11RSNAStatsSelectedPairwiseCipher=00-0f-ac-4
342*4882a593Smuzhiyun // dot11RSNAStatsTKIPLocalMICFailures=0
343*4882a593Smuzhiyun // dot11RSNAStatsTKIPRemoteMICFailures=0
344*4882a593Smuzhiyun // hostapdWPAPTKState=11
345*4882a593Smuzhiyun // hostapdWPAPTKGroupState=0
346*4882a593Smuzhiyun // rx_packets=160
347*4882a593Smuzhiyun // tx_packets=38
348*4882a593Smuzhiyun // rx_bytes=0
349*4882a593Smuzhiyun // tx_bytes=0
350*4882a593Smuzhiyun // inactive_msec=256
351*4882a593Smuzhiyun // signal=-73
352*4882a593Smuzhiyun // rx_rate_info=0
353*4882a593Smuzhiyun // tx_rate_info=0
354*4882a593Smuzhiyun // connected_time=11
355*4882a593Smuzhiyun // supp_op_classes=515153547374757677787c7d7e7f8082
356*4882a593Smuzhiyun // 92:14:5b:9a:65:cd
357*4882a593Smuzhiyun // flags=[AUTH][ASSOC][AUTHORIZED]
358*4882a593Smuzhiyun // aid=0
359*4882a593Smuzhiyun // capability=0x0
360*4882a593Smuzhiyun // listen_interval=0
361*4882a593Smuzhiyun // supported_rates=
362*4882a593Smuzhiyun // timeout_next=NULLFUNC POLL
363*4882a593Smuzhiyun // dot11RSNAStatsSTAAddress=92:14:5b:9a:65:cd
364*4882a593Smuzhiyun // dot11RSNAStatsVersion=1
365*4882a593Smuzhiyun // dot11RSNAStatsSelectedPairwiseCipher=00-0f-ac-4
366*4882a593Smuzhiyun // dot11RSNAStatsTKIPLocalMICFailures=0
367*4882a593Smuzhiyun // dot11RSNAStatsTKIPRemoteMICFailures=0
368*4882a593Smuzhiyun // hostapdWPAPTKState=11
369*4882a593Smuzhiyun // hostapdWPAPTKGroupState=0
370*4882a593Smuzhiyun // rx_packets=1516
371*4882a593Smuzhiyun // tx_packets=1159
372*4882a593Smuzhiyun // rx_bytes=0
373*4882a593Smuzhiyun // tx_bytes=0
374*4882a593Smuzhiyun // inactive_msec=323
375*4882a593Smuzhiyun // signal=-57
376*4882a593Smuzhiyun // rx_rate_info=0
377*4882a593Smuzhiyun // tx_rate_info=0
378*4882a593Smuzhiyun // connected_time=236
379*4882a593Smuzhiyun }
380