• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15import LogUtil from '../../../../../../../common/utils/src/main/ets/default/baseUtil/LogUtil';
16import ConfigData from '../../../../../../../common/utils/src/main/ets/default/baseUtil/ConfigData';
17import wifi from '@ohos.wifi';
18import BaseModel from '../../../../../../../common/utils/src/main/ets/default/model/BaseModel';
19
20const MODULE_TAG = ConfigData.TAG + 'WifiModel -> ';
21const Undefined_TaskId = -1;
22export interface WifiScanInfo {
23  ssid: string,
24  bssid: string,
25  rssi: number,
26  band: number,
27  frequency: number,
28  timestamp: number,
29  securityType: number,
30};
31
32export enum ConnState {
33  /** The device is searching for an available AP. */
34  SCANNING,
35
36  /** The Wi-Fi connection is being set up. */
37  CONNECTING,
38
39  /** The Wi-Fi connection is being authenticated. */
40  AUTHENTICATING,
41
42  /** The IP address of the Wi-Fi connection is being obtained. */
43  OBTAINING_IPADDR,
44
45  /** The Wi-Fi connection has been set up. */
46  CONNECTED,
47
48  /** The Wi-Fi connection is being torn down. */
49  DISCONNECTING,
50
51  /** The Wi-Fi connection has been torn down. */
52  DISCONNECTED,
53
54  /** Failed to set up the Wi-Fi connection. */
55  UNKNOWN
56}
57
58export enum WiFiSummaryMap {
59  CONNECTED,
60  CONNECTING,
61  SAVE_ENCRYPTED,
62  SAVE_OPEN,
63  ENCRYPTED,
64  OPEN,
65  OBTAINING_IP,
66}
67
68export enum WiFiIntensityMap {
69  GOOD,
70  WELL,
71  NORMAL,
72  BAD,
73}
74
75export enum WiFiEncryptMethodMap {
76  OPEN,
77  WEP,
78  WPA,
79  WPA2,
80}
81
82export class ApScanResult {
83  // interface WifiScanInfo
84  private apInfo = {
85    ssid:'',
86    bssid: '',
87    rssi: -100,
88    band: 0,
89    frequency: 0,
90    timestamp: 0,
91    securityType: 1,
92  };
93  private connectStatus: number = ConnState.UNKNOWN;
94  private isSaved: boolean = false;
95
96  constructor(apInfo?: any);
97
98  constructor(apInfo: any) {
99    if (apInfo === null || apInfo === undefined) {
100      return;
101    }
102    this.apInfo = apInfo;
103  };
104
105  getApInfo() {
106    return this.apInfo;
107  }
108
109  getSignalLevel(): number {
110    return wifi.getSignalLevel(this.apInfo.rssi, this.apInfo.band);;
111  }
112
113  isConnected(): boolean {
114    return (this.connectStatus === ConnState.CONNECTED);
115  }
116
117  isSavedConfig(): boolean {
118    return (this.isSaved === true);
119  }
120
121  isSecurityAp(): boolean {
122    // WiFiSecurityType is enum from 0 to 4, 0 is `Invalid`, 1 is `Open`, 2 to 4 is `Encrypted`
123    return (this.apInfo.securityType !== 1);
124  }
125
126  isValidAp(): boolean {
127    // no ssid or signal level 0 is invalid
128    return (this.apInfo.ssid !== '' && this.getSignalLevel() != 0);
129  }
130
131  updateConnectStatus(status: number) {
132    this.connectStatus = status;
133  }
134
135  updateSavedStatus(status: boolean) {
136    this.isSaved = status;
137  }
138
139  renderToListModel(): any {
140    function generateArrow(that: ApScanResult): string {
141      let signalLevel: string = that.getSignalLevel().toString();
142      let lockPrefix: string = 'lock_';
143      if (that.isSecurityAp() !== true) {
144        lockPrefix = '';
145      }
146      let result: string = `/res/image/ic_wifi_${lockPrefix}signal_${signalLevel}_dark.svg`;
147      return result;
148    }
149
150    function generateSummary(that: ApScanResult): number {
151      if (that.isConnected()) {
152        return WiFiSummaryMap.CONNECTED;
153      }
154      if (that.connectStatus === ConnState.CONNECTING) {
155        return WiFiSummaryMap.CONNECTING;
156      }
157      if (that.connectStatus === ConnState.OBTAINING_IPADDR) {
158        return WiFiSummaryMap.OBTAINING_IP;
159      }
160      if (that.isSavedConfig()) {
161        if (that.isSecurityAp()) {
162          return WiFiSummaryMap.SAVE_ENCRYPTED;
163        } else {
164          return WiFiSummaryMap.SAVE_OPEN;
165        }
166      } else {
167        if (that.isSecurityAp()) {
168          return WiFiSummaryMap.ENCRYPTED;
169        } else {
170          return WiFiSummaryMap.OPEN;
171        }
172      }
173    }
174
175    let ret = {
176      settingIcon: '',
177      settingSummary: generateSummary(this),
178      settingTitle: this.apInfo.ssid,
179      settingValue: '',
180      settingArrow: generateArrow(this),
181      settingArrowStyle: 'wifi',
182      settingUri: '',
183      apInfo: this.apInfo,
184    };
185    return ret;
186  }
187
188  toString(): string {
189    return `apInfo is: ssid=${this.getApInfo().ssid} signal=${this.getSignalLevel()} isConnected=${this.isConnected()}`;
190  }
191
192  static compare(x: ApScanResult, y: ApScanResult): number {
193    let xApInfo = x.getApInfo();
194    let yApInfo = y.getApInfo();
195    // rssi value is negative number
196    return ((-xApInfo.rssi) - (-yApInfo.rssi));
197  }
198
199  static filter(arr: ApScanResult[]): ApScanResult[] {
200    let hash = {};
201    return arr.reduce((total, currItem) => {
202      if (!hash[currItem.getApInfo().ssid]) {
203        hash[currItem.getApInfo().ssid] = true;
204        total.push(currItem);
205      }
206      return total;
207    }, []);
208  }
209
210  static index(arr: ApScanResult[], target: ApScanResult): number {
211    return arr.map((item) => {
212      return item.getApInfo().ssid;
213    }).indexOf(target.getApInfo().ssid);
214  }
215}
216
217export class WifiModel extends BaseModel {
218  private userSelectedAp: ApScanResult = new ApScanResult();
219  private linkedApInfo: any = undefined;
220
221  private scanTaskId: number = Undefined_TaskId;
222  private isScanning: boolean = false;
223
224  destroyWiFiModelData() {
225    this.linkedApInfo = undefined;
226    this.setUserSelectedAp(null);
227    AppStorage.SetOrCreate('slConnectedWifi', (new ApScanResult()).renderToListModel());
228  }
229
230  registerWiFiStatusObserver(callback) {
231    LogUtil.info(MODULE_TAG + 'start register wifi status observer');
232    wifi.on('wifiStateChange', callback);
233  }
234
235  unregisterWiFiStatusObserver() {
236    LogUtil.info(MODULE_TAG + 'start unregister wifi status observer');
237    wifi.off('wifiStateChange');
238  }
239
240  registerWiFiConnectionObserver(callback) {
241    LogUtil.info(MODULE_TAG + 'start register wifi connection observer');
242    wifi.on('wifiConnectionChange', callback);
243  }
244
245  unregisterWiFiConnectionObserver() {
246    LogUtil.info(MODULE_TAG + 'start unregister wifi connection observer');
247    wifi.off('wifiConnectionChange');
248  }
249
250  setUserSelectedAp(apInfo?: any) {
251    if (apInfo === null || typeof apInfo === 'undefined') {
252      this.userSelectedAp = new ApScanResult();
253    }
254    this.userSelectedAp = new ApScanResult(apInfo);
255  }
256
257  isSavedAp(ssid: string): boolean {
258    let deviceConfigs: any[] = wifi.getDeviceConfigs();
259    for (let i = 0; i < deviceConfigs.length; i++) {
260      if (ssid === deviceConfigs[i].ssid) {
261        return true;
262      }
263    }
264    return false;
265  }
266
267  isWiFiActive(): boolean {
268    const isActive: boolean = wifi.isWifiActive();
269    LogUtil.info(MODULE_TAG + 'check WiFi active status is : ' + isActive);
270    return isActive;
271  }
272
273  isWiFiConnected(): boolean {
274    let ret = wifi.isConnected();
275    LogUtil.info(MODULE_TAG + 'check WiFi connected status is : ' + ret);
276    return ret;
277  }
278
279  enableWiFi() {
280    if (wifi.isWifiActive() === true) {
281      LogUtil.info(MODULE_TAG + 'wifi is already active');
282      return;
283    }
284    let ret: boolean = wifi.enableWifi();
285    LogUtil.info(MODULE_TAG + 'enable WiFi result is : ' + ret);
286    return ret;
287  }
288
289  disableWifi() {
290    this.setUserSelectedAp(null);
291
292    if (wifi.isWifiActive() !== true) {
293      LogUtil.info(MODULE_TAG + 'wifi is already inactive');
294      return;
295    }
296    const ret: boolean = wifi.disableWifi();
297    LogUtil.info(MODULE_TAG + 'disable WiFi result is : ' + ret);
298  }
299
300  scanWiFi(): boolean {
301    const ret: boolean = wifi.scan();
302    LogUtil.info(MODULE_TAG + 'start scan WiFi result is : ' + ret);
303    return ret;
304  }
305
306  connectWiFi(password: string) {
307    let apInfo = this.userSelectedAp.getApInfo();
308    let ret = false;
309    let connectParam: any = {
310      "ssid": apInfo.ssid,
311      "bssid": apInfo.bssid,
312      "preSharedKey": password,
313      "isHiddenSsid": false, // we don't support connect to hidden ap yet
314      "securityType": apInfo.securityType
315    };
316    LogUtil.info(MODULE_TAG + 'disconnect WiFi isConnected is ' + wifi.isConnected());
317    if (wifi.isConnected() === true) {
318      ret = wifi.disconnect();
319      LogUtil.info(MODULE_TAG + 'disconnect WiFi ret is ' + ret);
320      this.registerWiFiConnectionObserver((code: Number) => {
321        if (code === 0) {
322          ret = wifi.connectToDevice(connectParam);
323          this.unregisterWiFiConnectionObserver();
324        }
325      })
326    }else{
327      ret = wifi.connectToDevice(connectParam);
328      LogUtil.info(MODULE_TAG + 'connect WiFi ret is ' + ret);
329    }
330    return ret;
331  }
332
333  /**
334   * Disconnect wifi
335   */
336  disconnectWiFi() {
337    this.setUserSelectedAp(null);
338
339    let ret = wifi.disconnect();
340    LogUtil.info(MODULE_TAG + 'disconnect WiFi result is : ' + ret);
341    return ret;
342  }
343
344  getSignalIntensity(apInfo: WifiScanInfo) {
345    let result = wifi.getSignalLevel(apInfo.rssi, apInfo.band);
346    if (result <= 1) {
347      return WiFiIntensityMap.BAD;
348    }
349    if (result <= 2) {
350      return WiFiIntensityMap.NORMAL;
351    }
352    if (result <= 3) {
353      return WiFiIntensityMap.WELL;
354    }
355    return WiFiIntensityMap.GOOD;
356  }
357
358  getEncryptMethod(apInfo: WifiScanInfo) {
359    if (apInfo.securityType === 1) {
360      return WiFiEncryptMethodMap.OPEN;
361    }
362    if (apInfo.securityType === 2) {
363      return WiFiEncryptMethodMap.WEP;
364    }
365    return WiFiEncryptMethodMap.WPA2;
366  }
367
368  getLinkInfo() {
369    return this.linkedApInfo;
370  }
371
372  removeDeviceConfig(apInfo: WifiScanInfo) {
373    LogUtil.info(MODULE_TAG + 'start to removeDeviceConfig');
374    let deviceConfigs: any[] = wifi.getDeviceConfigs();
375    let networkId: number = -1;
376    for (let i = 0; i < deviceConfigs.length; i++) {
377      if (deviceConfigs[i].ssid === apInfo.ssid) {
378        networkId = deviceConfigs[i].netId;
379        break;
380      }
381    }
382    if (networkId === -1) {
383      return;
384    }
385    LogUtil.info(MODULE_TAG + 'start to removeDevice');
386    let ret = wifi.removeDevice(networkId);
387    LogUtil.info(MODULE_TAG + 'remove device config : ' + ret);
388  }
389
390  connectByDeviceConfig(apInfo: WifiScanInfo) {
391    let deviceConfigs: any[] = wifi.getDeviceConfigs();
392    // find the wifi device config
393    for (let i = 0; i < deviceConfigs.length; i++) {
394      if (deviceConfigs[i].ssid === apInfo.ssid) {
395        let ret = wifi.connectToDevice(deviceConfigs[i]);
396        LogUtil.info(MODULE_TAG + 'connect ret for : ' + i + ' = ' + ret);
397      }
398    }
399    LogUtil.info(MODULE_TAG + 'end connect by device config');
400  }
401
402  refreshApScanResults() {
403    wifi.getLinkedInfo((err, result) => {
404      if (err) {
405        LogUtil.info(MODULE_TAG + 'get linked info failed');
406        return;
407      }
408      LogUtil.info(MODULE_TAG + 'scan get linked info succeed');
409      this.linkedApInfo = result;
410    });
411
412    wifi.getScanInfos((err, results) => {
413      if (err) {
414        LogUtil.info(MODULE_TAG + "get scan info failed");
415        return;
416      }
417      LogUtil.info(MODULE_TAG + 'get scan info succeed');
418      function removeDuplicateResults(arr: any[]): ApScanResult[] {
419        let results: ApScanResult[] = [];
420        for (let i = 0; i < arr.length; i++) {
421          let apResult = new ApScanResult(arr[i]);
422          if (apResult.isValidAp()) {
423            results.push(apResult);
424          }
425        }
426        return ApScanResult.filter(results);
427      };
428
429      function removeConnectedAp(arr: ApScanResult[], needRemove: ApScanResult) {
430        let index = ApScanResult.index(arr, needRemove);
431        if (index !== -1) {
432          arr.splice(index, 1);
433        }
434        return arr;
435      }
436
437      function addSavedConfigFlag(aps: ApScanResult[]): ApScanResult[] {
438        let configs: ApScanResult[] = [];
439        let deviceConfigs: any[] = wifi.getDeviceConfigs();
440        for (let i = 0; i < deviceConfigs.length; i++) {
441          let temp = new ApScanResult(deviceConfigs[i]);
442          configs.push(temp);
443        }
444        for (let i = 0; i < configs.length; i++) {
445          let index = ApScanResult.index(aps, configs[i]);
446          if (index !== -1) {
447            let item = aps[index];
448            item.updateSavedStatus(true);
449            aps.splice(index, 1);
450            aps.unshift(item);
451          }
452        }
453        return aps;
454      }
455
456      function addConnectStatusFlag(arr: ApScanResult[], linked: any): ApScanResult {
457        let ap: ApScanResult = new ApScanResult();
458        for (let i = 0; i < arr.length; i++) {
459          if (arr[i].getApInfo().ssid === linked.ssid) {
460            ap = arr[i];
461            break;
462          }
463        }
464        ap.updateConnectStatus(linked.connState);
465        return ap;
466      }
467
468      function unshiftConnectingAp(arr: ApScanResult[], ap: ApScanResult): ApScanResult[] {
469        let index = ApScanResult.index(arr, ap);
470        if (index !== -1) {
471          arr.splice(index, 1);
472          arr.unshift(ap);
473        }
474        return arr;
475      }
476
477      // step 1 : remove duplicate ap info
478      let scanResults: ApScanResult[] = removeDuplicateResults(results);
479      LogUtil.info(MODULE_TAG + 'scan results items length is : ' + scanResults.length);
480
481      // step 2 : add saved config flags
482      scanResults = addSavedConfigFlag(scanResults);
483      scanResults.sort(ApScanResult.compare);
484
485      // step 3 : add wifi summary
486      if (this.linkedApInfo !== null && typeof this.linkedApInfo !== 'undefined') {
487        let linkInfoResult: ApScanResult = addConnectStatusFlag(scanResults, this.linkedApInfo);
488        if (linkInfoResult.isConnected()) {
489          LogUtil.info(MODULE_TAG + 'scan connected');
490          scanResults = removeConnectedAp(scanResults, linkInfoResult);
491          AppStorage.SetOrCreate('slConnectedWifi', linkInfoResult.renderToListModel());
492        } else {
493          LogUtil.info(MODULE_TAG + 'scan not connected');
494          scanResults = unshiftConnectingAp(scanResults, linkInfoResult);
495          AppStorage.SetOrCreate('slConnectedWifi', (new ApScanResult()).renderToListModel());
496        }
497      }
498      LogUtil.info(MODULE_TAG + 'scan list results');
499      AppStorage.SetOrCreate('slWiFiLists', scanResults.map((item) => {
500        return item.renderToListModel();
501      }));
502    });
503  }
504
505  startScanTask() {
506    LogUtil.info(MODULE_TAG + 'start the wifi scan task');
507
508    if (this.scanTaskId !== Undefined_TaskId) {
509      clearInterval(this.scanTaskId);
510      this.scanTaskId = Undefined_TaskId;
511    }
512
513    this.scanTaskId = setInterval(() => {
514      if (this.isWiFiActive() === true && this.isScanning === true) {
515        this.refreshApScanResults();
516        return;
517      }
518      if (this.isWiFiActive() === true && this.scanWiFi() === true) {
519        LogUtil.info(MODULE_TAG + 'scan wifi started');
520        this.isScanning = true;
521        this.refreshApScanResults();
522      }
523    }, 3000);
524  }
525
526  stopScanTask() {
527    LogUtil.info(MODULE_TAG + 'stop the wifi scan task');
528    if (this.scanTaskId !== Undefined_TaskId) {
529      clearInterval(this.scanTaskId);
530      this.scanTaskId = Undefined_TaskId;
531    }
532    this.isScanning = false;
533  }
534}
535
536let wifiModel = new WifiModel();
537export default wifiModel as WifiModel;
538