网站建设的技巧,做域名跳转非法网站负什么责任,消息网站怎么做,家在宝安问题一#xff1a;WiFi名显示重复在前端页面使用WiFi网络扫描功能#xff0c;会产生多个重复的UUID#xff0c;用NetworkManager工具并未产生类似情况问题定位寻找接口#xff1a;networkmanage/wifiInfoint Handler::getWifi(const HttpContextPtr ctx) {hv::Json j;…问题一WiFi名显示重复在前端页面使用WiFi网络扫描功能会产生多个重复的UUID用NetworkManager工具并未产生类似情况问题定位寻找接口networkmanage/wifiInfoint Handler::getWifi(const HttpContextPtr ctx) { hv::Json j; j[msg] success; j[code] HTTP_STATUS_OK; string info; int ret selectDeployCode(dbCodeToString(SysDeployCode::WIFI_INFO), info); if (ret 0) { return response_status(ctx, HTTP_STATUS_INTERNAL_SERVER_ERROR, select error); } j[data][wifiInfo] hv::Json::parse(info); ret selectDeployCode(dbCodeToString(SysDeployCode::ONLINE), info); if (ret 0) { return response_status(ctx, HTTP_STATUS_INTERNAL_SERVER_ERROR, select error); } j[data][online] stringToBool(info); return ctx-sendJson(j); }wifi功能实现代码int Wifi::scanWifi() { string ssids; string scanCmd(nmcli -f SIGNAL,SSID d wifi list); if (!myPopen(scanCmd, ssids)) { hloge(failed to scan ssid); return -1; } stringstream ss; ss ssids; string item; getline(ss, item, \n); while(getline(ss, item, \n)) { int pos item.find_first_of( ); if (pos string::npos) { hloge(wifi scan result error); ssidVec.clear(); return -1; } string signal item.substr(0, pos); int sig 0; if(stringIsNumber(signal)) sig stoi(signal); int sigLevel 0; if (sig 20) { sigLevel 0; } else if (sig 20 sig 40) { sigLevel 1; } else if (sig 40 sig 60) { sigLevel 2; } else if (sig 60 sig 80) { sigLevel 3; } else { sigLevel 4; } while(item[pos] ) { pos; } string itemTrim hv::rtrim(item, ); string ssid itemTrim.substr(pos); if (ssid --) { continue; } string ssidUtf8Encoded convert_escape_sequences(ssid); ssidVec.emplace_back(sigLevel, ssid); } hlogi(scan end %d, ssidVec.size()); return 0; }罪魁祸首ssidVec.emplace_back(sigLevel, ssid);也就是说ssidVec是Wifi类的成员变量getWifiInfo()每调用一次scanWifi()就往ssidVec里继续 push在整个scanWifi()函数里没有任何地方清空ssidVec。导致SSID 重复UUID如果在 WifiInfo::toJson 里生成也会重复/变化每次“前端扫描”数量越来越多NM 工具不会这样它每次 scan 都是 fresh list修复点1.在scanWifi()一开始清空ssidVecint Wifi::scanWifi() { ssidVec.clear(); // ← 每次扫描必须清空历史结果2.nmcli -f SIGNAL,SSID d wifi list修改为nmcli -t -f SSID,BSSID,FREQ,SIGNAL dev wifi listnmcli -f SIGNAL,SSID d wifi list会丢失BSSID/FREQ信息导致没办法区分是同一个AP还是不同的AP程序如下int Wifi::scanWifi() { ssidVec.clear(); // ★ 必须清空 string ssids; string scanCmd(nmcli -t -f SSID,BSSID,FREQ,SIGNAL dev wifi list); if (!myPopen(scanCmd, ssids)) { hloge(failed to scan ssid); return -1; } stringstream ss(ssids); string line; while (getline(ss, line)) { // 格式SSID:BSSID:FREQ:SIGNAL hv::StringList fields hv::split(line, :); if (fields.size() 4) continue; string ssid fields[0]; string bssid fields[1]; string freq fields[2]; string signalStr fields[3]; if (ssid.empty() || ssid --) continue; int sig 0; if (stringIsNumber(signalStr)) { sig stoi(signalStr); } int sigLevel 0; if (sig 20) sigLevel 0; else if (sig 40) sigLevel 1; else if (sig 60) sigLevel 2; else if (sig 80) sigLevel 3; else sigLevel 4; // ★ 关键不要把 BSSID / FREQ 拼进 name ssidVec.emplace_back(sigLevel, ssid /* 这里只放纯 SSID */); } hlogi(scan end %d, ssidVec.size()); return 0; }但是出来的名字还是有重复的定位问题是因为只做了【解析】和【清空历史】没有做【按 SSID 聚合】nmcli 扫描结果本身就会返回同一个 SSID多个 BSSID多个频段2.4G / 5G / 5G-2你现在是“一条扫描结果 → 一条 WifiInfo”所以看到的:COMNOVA_Staff COMNOVA_Staff COMNOVA_Staff解决问题按SSID聚合后代码int Wifi::scanWifi() { ssidVec.clear(); string ssids; string scanCmd(nmcli -t -f SSID,BSSID,FREQ,SIGNAL dev wifi list); if (!myPopen(scanCmd, ssids)) { hloge(failed to scan ssid); return -1; } // 用 map 按 SSID 聚合只保留信号最强的 unordered_mapstring, int bestSignal; // SSID - sigLevel stringstream ss(ssids); string line; while (getline(ss, line)) { hv::StringList fields hv::split(line, :); if (fields.size() 4) continue; string ssid fields[0]; string signalStr fields[3]; if (ssid.empty() || ssid --) continue; int sig 0; if (stringIsNumber(signalStr)) { sig stoi(signalStr); } int sigLevel 0; if (sig 20) sigLevel 0; else if (sig 40) sigLevel 1; else if (sig 60) sigLevel 2; else if (sig 80) sigLevel 3; else sigLevel 4; auto it bestSignal.find(ssid); if (it bestSignal.end() || sigLevel it-second) { bestSignal[ssid] sigLevel; } } // 转成 ssidVec for (const auto kv : bestSignal) { ssidVec.emplace_back(kv.second, kv.first); } hlogi(scan end %d (after dedup), ssidVec.size()); return 0; }问题二信号不显示发的json里并不包含信号强度auto_connect: true, name: DIRECT-7t-客厅电视, password: , setting: false, signal: 0, status: false }, { auto_connect: true, name: DIRECT-xx-客厅电视, password: , setting: false, signal: 0, status: false }, { auto_connect: true, name: W51-Ch62-5G, password: , setting: false, signal: 0, status: false },问题定位先看一下wifi.hWifiInfo(int signal, const std::string name) : name(name), signal(signal) { status false; setting false; autoConnect true; }一开始以为是initWifiInfoCompareList覆盖掉了hv::Json Wifi::initWifiInfoCompareList(const string wifiList, bool shouldConnect) { string ssidOnline; if (!shouldConnect) { // 刷新时找到在线的wifi mac ssidOnline getOnlineWifiName(); } bool isConnected false; // 根据wifi_list中的信息更新搜索到的WifiInfo hv::Json wifiListJson hv::Json::parse(wifiList); for (auto listItem : wifiListJson) { WifiList wList WifiList::fromJson(listItem); string ssidName wList.getSsid(); for (auto info : ssidVec) { if (ssidName ! info.getName()) { continue; } string pwd wList.getPassword(); bool autoConnect wList.getAutoConnect(); info.setPassword(pwd); info.setAutoConnect(autoConnect); info.setSetting(true); if (!shouldConnect) { if (ssidOnline info.getName()) { info.setStatus(true); } } else { if (!isConnected autoConnect) { setSsid(ssidName); setPassword(pwd); setAutoConnect(autoConnect); hlogi(will auto connect %s, ssidName.c_str()); if (connect()) { isConnected true; info.setStatus(true); } } } break; } } hv::Json jsn hv::Json::array(); for (const auto item: ssidVec) { jsn.emplace_back(item.toJson()); } return jsn; }只更新了passwordautoConnectsettingstatus没有任何地方再更新 signal。所以添加代码验证int Wifi::getWifiInfo(hv::Json resp, bool tryConnect) { if (scanWifi() 0) { hloge(failed to scan wifi); return -1; } for (auto w : ssidVec) { hlogi([SCAN] %s signal%d, w.getName().c_str(), w.getSignal()); } // compare wifi list, connect if auto connect is true string wifiList; selectDeployCode(dbCodeToString(SysDeployCode::WIFI_LIST), wifiList); hv::Json wifiJson initWifiInfoCompareList(wifiList, tryConnect); int ret updateDatabaseWithEscape(dbCodeToString(SysDeployCode::WIFI_INFO), wifiJson); if (ret 0) { hloge(failed to update wifi info); return ret; } if (!tryConnect) { resp[data][wifiInfo] wifiJson; } else if (isConnected()) { ret updateDeployCode(dbCodeToString(SysDeployCode::ONLINE), true); if (ret 0) { hloge(failed to update wifi switch); return ret; } } for (auto w : ssidVec) { hlogi([FINAL] %s signal%d, w.getName().c_str(), w.getSignal()); } return 0; }打印出来为1970-01-05 06:53:41.586 INFO [SCAN] DIRECT-7t-客厅电视 signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.586 INFO [SCAN] DIRECT-xx-客厅电视 signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.586 INFO [SCAN] W51-Ch62-5G signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.586 INFO [SCAN] 萱萱超棒 signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.586 INFO [SCAN] CCORE_WIRELESS_2.4G signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.586 INFO [SCAN] OrayBox-2.4G-4D28 signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.586 INFO [SCAN] COMNOVA_Staff signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.586 INFO [SCAN] QL480_98797 signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.586 INFO [SCAN] CCORE_WIRELESS signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.587 INFO [SCAN] HONOR 90 signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.587 INFO [SCAN] test1 signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.587 INFO [SCAN] Hyper_Link signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.587 INFO [SCAN] 3F-R11-Display signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.587 INFO [SCAN] W51-Ch62 signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.587 INFO [SCAN] DIRECT-SU-tcl_mt5879_cn signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 06:53:41.637 INFO [FINAL] DIRECT-7t-客厅电视 signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.637 INFO [FINAL] DIRECT-xx-客厅电视 signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] W51-Ch62-5G signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] 萱萱超棒 signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] CCORE_WIRELESS_2.4G signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] OrayBox-2.4G-4D28 signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] COMNOVA_Staff signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] QL480_98797 signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] CCORE_WIRELESS signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] HONOR 90 signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] test1 signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] Hyper_Link signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] 3F-R11-Display signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] W51-Ch62 signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 06:53:41.638 INFO [FINAL] DIRECT-SU-tcl_mt5879_cn signal0 [wifi.cpp:72:getWifiInfo]说明不是initWifiInfoCompareList的问题是Scanwifi的问题排查发现fields[3]根本不是 SIGNAL。现在用的是nmcli -t -f SSID,BSSID,FREQ,SIGNAL dev wifi list-t模式的输出规则是SSID:BSSID:FREQ:SIGNALnmcli 会对 SSID 里的冒号:做转义显示为\:SIGNAL 根本不是fields[3]而是fields.back()解决问题修正scanwifistring ssid fields[0]; string signalStr fields[3];为string ssid fields[0]; string signalStr fields.back();完整代码int Wifi::scanWifi() { ssidVec.clear(); string ssids; string scanCmd(nmcli -t -f SSID,BSSID,FREQ,SIGNAL dev wifi list); if (!myPopen(scanCmd, ssids)) { hloge(failed to scan ssid); return -1; } // 用 map 按 SSID 聚合只保留信号最强的 unordered_mapstring, int bestSignal; // SSID - sigLevel stringstream ss(ssids); string line; while (getline(ss, line)) { hv::StringList fields hv::split(line, :); if (fields.size() 4) continue; string ssid fields[0]; string signalStr fields.back(); if (ssid.empty() || ssid --) continue; int sig 0; if (stringIsNumber(signalStr)) { sig stoi(signalStr); } int sigLevel 0; if (sig 20) sigLevel 0; else if (sig 40) sigLevel 1; else if (sig 60) sigLevel 2; else if (sig 80) sigLevel 3; else sigLevel 4; auto it bestSignal.find(ssid); if (it bestSignal.end() || sigLevel it-second) { bestSignal[ssid] sigLevel; } } // 转成 ssidVec for (const auto kv : bestSignal) { ssidVec.emplace_back(kv.second, kv.first); } hlogi(scan end %d (after dedup), ssidVec.size()); return 0; }检查1970-01-05 07:01:48.869 INFO [SCAN] DIRECT-7t-客厅电视 signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] DIRECT-SU-tcl_mt5879_cn signal0 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] W51-Ch62 signal4 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] CCORE_WIRELESS_2.4G signal3 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] OrayBox-2.4G-4D28 signal2 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] COMNOVA_Staff signal3 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] QL480_98797 signal2 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] CCORE_WIRELESS signal2 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] HONOR 90 signal3 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] test1 signal2 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] 3F-R11-Display signal1 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] W51-Ch62-5G signal4 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] 萱萱超棒 signal4 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.869 INFO [SCAN] DIRECT-xx-客厅电视 signal1 [wifi.cpp:50:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] DIRECT-7t-客厅电视 signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] DIRECT-SU-tcl_mt5879_cn signal0 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] W51-Ch62 signal4 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] CCORE_WIRELESS_2.4G signal3 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] OrayBox-2.4G-4D28 signal2 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] COMNOVA_Staff signal3 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] QL480_98797 signal2 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] CCORE_WIRELESS signal2 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] HONOR 90 signal3 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] test1 signal2 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] 3F-R11-Display signal1 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] W51-Ch62-5G signal4 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] 萱萱超棒 signal4 [wifi.cpp:72:getWifiInfo] 1970-01-05 07:01:48.923 INFO [FINAL] DIRECT-xx-客厅电视 signal1 [wifi.cpp:72:getWifiInfo]现在就有wifi信号啦问题三接口连上了WiFi但是报错500输入密码点确定后台检查nmcli -t -f active,ssid dev wifi no:W51-Ch62-5G no:W51-Ch62 yes:萱萱超棒但是前端显示500连接失败。问题定位定位到前端调用的对应功能函数int Handler::wifiPwdSet(const HttpContextPtr ctx) { hv::Json req ctx-json(); Wifi wifi(req[password], req[auto_connect], req[name]); int ret wifi.requestConnect(); if (ret -1 || !wifi.isConnected()) { return response_status(ctx, HTTP_STATUS_INTERNAL_SERVER_ERROR, wifi连接失败); } if (ret -2) { return response_status(ctx, HTTP_STATUS_INTERNAL_SERVER_ERROR, failed to update database); } return response_status(ctx, HTTP_STATUS_OK, success); }/** * only invoked when wifi item with ssid/password is clicked in front UI * return 0 on success, while -1 on failure */ int Wifi::updateDatabaseOnConnect() { if (updateWifiInfoOnConnect() 0) { hloge(failed to update wifi info); return -1; } if (updateWifiListOnConnect() 0) { hloge(failed to update wifi list); return -1; } return updateDeployCode(dbCodeToString(SysDeployCode::ONLINE), true); } /** * set wifi info status to be false when wifi disconnected * return 0 on success, while -1 on failure */ int Wifi::updateWifiInfoOnDisconnect() { string info; string dbInfoStr dbCodeToString(SysDeployCode::WIFI_INFO); selectDeployCode(dbInfoStr, info); hv::Json wifiJson hv::Json::parse(info); for (auto item: wifiJson) { item[status] false; } return updateDatabaseWithEscape(dbInfoStr, wifiJson); } /** * set auto_connect/password/setting/status when wifi connected * return 0 on success, while -1 on failure */ int Wifi::updateWifiInfoOnConnect() { string wifiInfo; string dbInfoStr dbCodeToString(SysDeployCode::WIFI_INFO); selectDeployCode(dbInfoStr, wifiInfo); hv::Json wifiJson hv::Json::parse(wifiInfo); bool found false; for (auto item: wifiJson) { if (found) { item[status] false; continue; } string ssid item[name]; if (ssid getSsid()) { item[auto_connect] isAutoConnect(); item[password] getPassword(); item[setting] true; item[status] true; found true; } } return updateDatabaseWithEscape(dbInfoStr, wifiJson); } /** * update wifiList when wifi connected * return 0 on success, while -1 on failure */ int Wifi::updateWifiListOnConnect() { string wifiList; string dbInfoStr dbCodeToString(SysDeployCode::WIFI_LIST); selectDeployCode(dbInfoStr, wifiList); hv::Json listJson hv::Json::parse(wifiList); listWifiList objWifiList; for (auto item: listJson) { WifiList obj WifiList::fromJson(item); objWifiList.push_back(obj); } string pwd getPassword(); string onlineSsid getSsid(); bool isAutoConn isAutoConnect(); int i 0; for (auto it objWifiList.begin(); it ! objWifiList.end(); it) { if (it-getSsid() onlineSsid) { it-setPassword(pwd); it-setAutoConnect(isAutoConn); objWifiList.splice(objWifiList.cbegin(), objWifiList, it); break; } i; } if (i objWifiList.size()) { objWifiList.emplace_front(pwd, ssid, isAutoConn); } listJson.clear(); for (auto item: objWifiList) { listJson.push_back(item.toJson()); } return updateDatabaseWithEscape(dbInfoStr, listJson); } /** * disconnect wifi * return true on success, while false on failure */ bool Wifi::disconnect() { if (!isConnected()) { return true; } string interface(wlan0); string cmd nmcli d disconnect interface; if (!mySystem(cmd)) { hloge(failed to disconnect wifi); return false; } return updateDeployCode(dbCodeToString(SysDeployCode::ONLINE), boolToString(false)); } /** * check wifi connected or not by /sys/class/net/mlan0/operstate * return true if content is up in the file, while false if down */ bool Wifi::isConnected() { const std::string interfaceName wlan0; std::ifstream file(/sys/class/net/ interfaceName /operstate); bool res false; if (file.is_open()) { std::string state; file state; file.close(); if (state up) { res true; } } hlogi(check wifi connected: %d, res); return res; }解决问题看代码立刻发现问题网卡名没改过来bool Wifi::isConnected() { const std::string interfaceName wlP1p1s0; //❗ std::ifstream file(/sys/class/net/ interfaceName /operstate); bool res false; if (file.is_open()) { std::string state; file state; file.close(); if (state up) { res true; } } hlogi(check wifi connected: %d, res); return res; }但是改了还是有可能报500猜想问题点1.在程序里连接成功和后续状态/数据库更新失败被当成了一回事。可能connet成功了但updateDatabaseOnConnect某一步失败了。如果是这样要不解决updateDatabaseOnConnect的bug要不连接成功了就返回0数据库更新失败不返回。2.可能wifi连接有延迟HTTP 请求已经结束500NetworkManager 还在后台继续几秒后 Wi-Fi 真正连上看日志1970-01-05 07:11:33.650 INFO [106289-106289][127.0.0.1:58332][GET /networkmanage/wifiScan][200 OK] [HttpServer.cpp:175:on_recv] 1970-01-05 07:11:38.222 INFO check wifi connected: 0 [wifi.cpp:395:isConnected] 1970-01-05 07:11:38.222 INFO [106289-106289][127.0.0.1:58352][POST /networkmanage/wifiPassSet][500 Internal Server Error] [HttpServer.cpp:175:on_recv] 1970-01-05 07:11:46.973 INFO check wifi connected: 0 [wifi.cpp:395:isConnected] 1970-01-05 07:11:46.973 INFO [106289-106289][127.0.0.1:58336][POST /networkmanage/wifiPassSet][500 Internal Server Error] [HttpServer.cpp:175:on_recv] 1970-01-05 07:11:53.834 INFO check wifi connected: 0 [wifi.cpp:395:isConnected] 1970-01-05 07:11:53.834 INFO [106289-106289][127.0.0.1:58334][POST /networkmanage/wifiPassSet][500 Internal Server Error] [HttpServer.cpp:175:on_recv] 1970-01-05 07:12:07.128 INFO check wifi connected: 0 [wifi.cpp:395:isConnected] 1970-01-05 07:12:07.129 INFO [106289-106289][127.0.0.1:58366][POST /networkmanage/wifiPassSet][500 Internal Server Error] [HttpServer.cpp:175:on_recv] 1970-01-05 07:12:13.744 INFO check wifi connected: 0 [wifi.cpp:395:isConnected] 1970-01-05 07:12:13.745 INFO [106289-106289][127.0.0.1:58356][POST /networkmanage/wifiPassSet][500 Internal Server Error] [HttpServer.cpp:175:on_recv]check wifi connected: %d来自bool Wifi::isConnected() { const std::string interfaceName wlan0; std::ifstream file(/sys/class/net/ interfaceName /operstate); bool res false; if (file.is_open()) { std::string state; file state; file.close(); if (state up) { res true; } } hlogi(check wifi connected: %d, res); return res; }没有出现failed to update wifi infofailed to update wifi list所以500 不是updateDatabaseOnConnect()里抛出来的。视角含义nmcli d wifi connect命令已下发NetworkManager 接受/sys/class/net/wlan0/operstate内核网卡是否 UPIP 是否拿到DHCP 是否完成UI 感觉Wi-Fi 图标亮了这些都不是同步发生但是我检查用的指令nmcli d wifi connect是异步的。NetworkManager先关联 AP再 WPA 握手再 DHCP最后内核接口才UP好的知道原因了是我查太早了。现在有两个修改方案方案1.wifiPwdSet只判断是否下发成功方案2.等待连接最佳方案为方案1为了尽量不影响逻辑先尝试用方案2。更新代码int Handler::wifiPwdSet(const HttpContextPtr ctx) { hv::Json req ctx-json(); Wifi wifi(req[password], req[auto_connect], req[name]); int ret wifi.requestConnect(); if (ret -1) { return response_status(ctx, HTTP_STATUS_INTERNAL_SERVER_ERROR, wifi连接命令失败); } if (ret -2) { return response_status(ctx, HTTP_STATUS_INTERNAL_SERVER_ERROR, failed to update database); } // 等待最多 2 次每次 1 秒 const int retry 2; for (int i 0; i retry; i) { if (Wifi::isConnected()) { return response_status(ctx, HTTP_STATUS_OK, success); } sleep(3); } // 两次都没连上判定失败 return response_status(ctx, HTTP_STATUS_INTERNAL_SERVER_ERROR, wifi连接失败); }完美解决问题四硬编码问题发现此问题的来源点击忘记网络wifi依然连接但界面上显示无wifi连接问题定位handler.cpp/** * ignore wifi: disconnect it and delete it in the wifi_list */ int Handler::wifiIgnore(const HttpContextPtr ctx) { hv::Json req ctx-json(); string ssidName req[name]; Wifi wifi; if (wifi.getWifiInfoFromDb() 0) { return response_status(ctx, HTTP_STATUS_INTERNAL_SERVER_ERROR, 操作失败); } hv::Json resp; if (wifi.ignore(ssidName, resp[data][wifiInfo]) 0) { return response_status(ctx, HTTP_STATUS_INTERNAL_SERVER_ERROR, 操作失败); } resp[msg] success; resp[code] HTTP_STATUS_OK; return ctx-sendJson(resp); }wifi.cppint Wifi::ignore(const std::string name, hv::Json wifiJson) { wifiJson hv::Json::array(); for(auto it : ssidVec) { if (name it.getName()) { if (it.getStatus()) { disconnect(); } it.setAutoConnect(true); it.setPassword(); it.setSetting(false); it.setStatus(false); } wifiJson.emplace_back(it.toJson()); } updateDatabaseWithEscape(dbCodeToString(SysDeployCode::WIFI_INFO), wifiJson); // 从wifi_list中删除此wifi string wifiList; selectDeployCode(dbCodeToString(SysDeployCode::WIFI_LIST), wifiList); hv::Json listJson hv::Json::parse(wifiList); for (auto it listJson.begin(); it ! listJson.end(); it) { WifiList item WifiList::fromJson(*it); if (item.getSsid() name) { listJson.erase(it); break; } } return updateDatabaseWithEscape(dbCodeToString(SysDeployCode::WIFI_LIST), listJson); } bool Wifi::disconnect() { if (!isConnected()) { return true; } string interface(wlan0); // ❗ string cmd nmcli d disconnect interface; if (!mySystem(cmd)) { hloge(failed to disconnect wifi); return false; } return updateDeployCode(dbCodeToString(SysDeployCode::ONLINE), boolToString(false)); }这里怎么又有一个网卡名要更改一搜有一堆硬编码解决方案可不可以程序初始化的时候获取wifi接口后面把网卡名存在一个变量里要用的地方就调用这个变量外部不允许可以修改这个变量当然肯定不用全局string解决问题直接贴代码wifi.h/** * Wi-Fi runtime environment * Initialized once at program startup */ class WifiEnv { public: // 程序启动时调用一次 static bool init(); // 只读获取 Wi-Fi 接口名 static const std::string iface(); private: WifiEnv() delete; static std::string wifi_iface_; static constexpr const char* DEFAULT_WIFI_IFACE wlP1p1s0; };wifi.cppstd::string WifiEnv::wifi_iface_; bool WifiEnv::init() { std::string out; std::string cmd nmcli -t -f DEVICE,TYPE,STATE d | awk -F: $2\wifi\ $3!\unavailable\ {print $1; exit}; if (myPopen(cmd, out)) { out.erase(std::remove(out.begin(), out.end(), \n), out.end()); } if (!out.empty()) { wifi_iface_ out; hlogi(wifi interface detected: %s, wifi_iface_.c_str()); return true; } // fallback使用默认接口名 wifi_iface_ DEFAULT_WIFI_IFACE; hloge(wifi interface detect failed, fallback to default: %s, wifi_iface_.c_str()); return true; } const std::string WifiEnv::iface() { return wifi_iface_; }main.cpp#include base/wifi.h ............. WifiEnv::init();调用const std::string interface WifiEnv::iface(); if (interface.empty()) return false;