• 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(): { settingIcon: string, settingSummary: number, settingTitle: string, settingValue: string,
140    settingArrow: string, settingArrowStyle: string, settingUri: string, apInfo: WifiScanInfo } {
141    function generateArrow(that: ApScanResult): string {
142      let signalLevel: string = that.getSignalLevel().toString();
143      let lockPrefix: string = 'lock_';
144      if (that.isSecurityAp() !== true) {
145        lockPrefix = '';
146      }
147      let result: string = `/res/image/ic_wifi_${lockPrefix}signal_${signalLevel}_dark.svg`;
148      return result;
149    }
150
151    function generateSummary(that: ApScanResult): number {
152      if (that.isConnected()) {
153        return WiFiSummaryMap.CONNECTED;
154      }
155      if (that.connectStatus === ConnState.CONNECTING) {
156        return WiFiSummaryMap.CONNECTING;
157      }
158      if (that.connectStatus === ConnState.OBTAINING_IPADDR) {
159        return WiFiSummaryMap.OBTAINING_IP;
160      }
161      if (that.isSavedConfig()) {
162        if (that.isSecurityAp()) {
163          return WiFiSummaryMap.SAVE_ENCRYPTED;
164        } else {
165          return WiFiSummaryMap.SAVE_OPEN;
166        }
167      } else {
168        if (that.isSecurityAp()) {
169          return WiFiSummaryMap.ENCRYPTED;
170        } else {
171          return WiFiSummaryMap.OPEN;
172        }
173      }
174    }
175
176    let ret = {
177      settingIcon: '',
178      settingSummary: generateSummary(this),
179      settingTitle: this.apInfo.ssid,
180      settingValue: '',
181      settingArrow: generateArrow(this),
182      settingArrowStyle: 'wifi',
183      settingUri: '',
184      apInfo: this.apInfo,
185    };
186    return ret;
187  }
188
189  toString(): string {
190    return `apInfo is: ssid=${this.getApInfo().ssid} signal=${this.getSignalLevel()} isConnected=${this.isConnected()}`;
191  }
192
193  static compare(x: ApScanResult, y: ApScanResult): number {
194    let xApInfo = x.getApInfo();
195    let yApInfo = y.getApInfo();
196    // rssi value is negative number
197    return ((-xApInfo.rssi) - (-yApInfo.rssi));
198  }
199
200  static filter(arr: ApScanResult[]): ApScanResult[] {
201    let hash = {};
202    return arr.reduce((total, currItem) => {
203      if (!hash[currItem.getApInfo().ssid]) {
204        hash[currItem.getApInfo().ssid] = true;
205        total.push(currItem);
206      }
207      return total;
208    }, []);
209  }
210
211  static index(arr: ApScanResult[], target: ApScanResult): number {
212    return arr.map((item) => {
213      return item.getApInfo().ssid;
214    }).indexOf(target.getApInfo().ssid);
215  }
216}
217
218export class WifiModel extends BaseModel {
219  private userSelectedAp: ApScanResult = new ApScanResult();
220  private linkedApInfo: any = undefined;
221
222  private scanTaskId: number = Undefined_TaskId;
223  private isScanning: boolean = false;
224
225  destroyWiFiModelData() {
226    this.linkedApInfo = undefined;
227    this.setUserSelectedAp(null);
228    AppStorage.SetOrCreate('slConnectedWifi', (new ApScanResult()).renderToListModel());
229  }
230
231  registerWiFiStatusObserver(callback) {
232    LogUtil.info(MODULE_TAG + 'start register wifi status observer');
233    wifi.on('wifiStateChange', callback);
234  }
235
236  unregisterWiFiStatusObserver() {
237    LogUtil.info(MODULE_TAG + 'start unregister wifi status observer');
238    wifi.off('wifiStateChange');
239  }
240
241  registerWiFiConnectionObserver(callback) {
242    LogUtil.info(MODULE_TAG + 'start register wifi connection observer');
243    wifi.on('wifiConnectionChange', callback);
244  }
245
246  unregisterWiFiConnectionObserver() {
247    LogUtil.info(MODULE_TAG + 'start unregister wifi connection observer');
248    wifi.off('wifiConnectionChange');
249  }
250
251  setUserSelectedAp(apInfo?: any) {
252    if (apInfo === null || typeof apInfo === 'undefined') {
253      this.userSelectedAp = new ApScanResult();
254    }
255    this.userSelectedAp = new ApScanResult(apInfo);
256  }
257
258  isSavedAp(ssid: string): boolean {
259    let deviceConfigs: any[] = wifi.getDeviceConfigs();
260    for (let i = 0; i < deviceConfigs.length; i++) {
261      if (ssid === deviceConfigs[i].ssid) {
262        return true;
263      }
264    }
265    return false;
266  }
267
268  isWiFiActive(): boolean {
269    const isActive: boolean = wifi.isWifiActive();
270    LogUtil.info(MODULE_TAG + 'check WiFi active status is : ' + isActive);
271    return isActive;
272  }
273
274  isWiFiConnected(): boolean {
275    let ret = wifi.isConnected();
276    LogUtil.info(MODULE_TAG + 'check WiFi connected status is : ' + ret);
277    return ret;
278  }
279
280  enableWiFi() {
281    if (wifi.isWifiActive() === true) {
282      LogUtil.info(MODULE_TAG + 'wifi is already active');
283      return;
284    }
285    let ret: boolean = wifi.enableWifi();
286    LogUtil.info(MODULE_TAG + 'enable WiFi result is : ' + ret);
287    return ret;
288  }
289
290  disableWifi() {
291    this.setUserSelectedAp(null);
292
293    if (wifi.isWifiActive() !== true) {
294      LogUtil.info(MODULE_TAG + 'wifi is already inactive');
295      return;
296    }
297    const ret: boolean = wifi.disableWifi();
298    LogUtil.info(MODULE_TAG + 'disable WiFi result is : ' + ret);
299  }
300
301  scanWiFi(): boolean {
302    const ret: boolean = wifi.scan();
303    LogUtil.info(MODULE_TAG + 'start scan WiFi result is : ' + ret);
304    return ret;
305  }
306
307  connectWiFi(password: string) {
308    let apInfo = this.userSelectedAp.getApInfo();
309    let ret = false;
310    let connectParam: any = {
311      "ssid": apInfo.ssid,
312      "bssid": apInfo.bssid,
313      "preSharedKey": password,
314      "isHiddenSsid": false, // we don't support connect to hidden ap yet
315      "securityType": apInfo.securityType
316    };
317    LogUtil.info(MODULE_TAG + 'disconnect WiFi isConnected is ' + wifi.isConnected());
318    if (wifi.isConnected() === true) {
319      ret = wifi.disconnect();
320      LogUtil.info(MODULE_TAG + 'disconnect WiFi ret is ' + ret);
321      this.registerWiFiConnectionObserver((code: Number) => {
322        if (code === 0) {
323          ret = wifi.connectToDevice(connectParam);
324          this.unregisterWiFiConnectionObserver();
325        }
326      })
327    }else{
328      ret = wifi.connectToDevice(connectParam);
329      LogUtil.info(MODULE_TAG + 'connect WiFi ret is ' + ret);
330    }
331    return ret;
332  }
333
334  /**
335   * Disconnect wifi
336   */
337  disconnectWiFi() {
338    this.setUserSelectedAp(null);
339
340    let ret = wifi.disconnect();
341    LogUtil.info(MODULE_TAG + 'disconnect WiFi result is : ' + ret);
342    return ret;
343  }
344
345  getSignalIntensity(apInfo: WifiScanInfo) {
346    let result = wifi.getSignalLevel(apInfo.rssi, apInfo.band);
347    if (result <= 1) {
348      return WiFiIntensityMap.BAD;
349    }
350    if (result <= 2) {
351      return WiFiIntensityMap.NORMAL;
352    }
353    if (result <= 3) {
354      return WiFiIntensityMap.WELL;
355    }
356    return WiFiIntensityMap.GOOD;
357  }
358
359  getEncryptMethod(apInfo: WifiScanInfo) {
360    if (apInfo.securityType === 1) {
361      return WiFiEncryptMethodMap.OPEN;
362    }
363    if (apInfo.securityType === 2) {
364      return WiFiEncryptMethodMap.WEP;
365    }
366    return WiFiEncryptMethodMap.WPA2;
367  }
368
369  getLinkInfo() {
370    return this.linkedApInfo;
371  }
372
373  removeDeviceConfig(apInfo: WifiScanInfo) {
374    LogUtil.info(MODULE_TAG + 'start to removeDeviceConfig');
375    let deviceConfigs: any[] = wifi.getDeviceConfigs();
376    let networkId: number = -1;
377    for (let i = 0; i < deviceConfigs.length; i++) {
378      if (deviceConfigs[i].ssid === apInfo.ssid) {
379        networkId = deviceConfigs[i].netId;
380        break;
381      }
382    }
383    if (networkId === -1) {
384      return;
385    }
386    LogUtil.info(MODULE_TAG + 'start to removeDevice');
387    let ret = wifi.removeDevice(networkId);
388    LogUtil.info(MODULE_TAG + 'remove device config : ' + ret);
389  }
390
391  connectByDeviceConfig(apInfo: WifiScanInfo) {
392    let deviceConfigs: any[] = wifi.getDeviceConfigs();
393    // find the wifi device config
394    for (let i = 0; i < deviceConfigs.length; i++) {
395      if (deviceConfigs[i].ssid === apInfo.ssid) {
396        let ret = wifi.connectToDevice(deviceConfigs[i]);
397        LogUtil.info(MODULE_TAG + 'connect ret for : ' + i + ' = ' + ret);
398      }
399    }
400    LogUtil.info(MODULE_TAG + 'end connect by device config');
401  }
402
403  refreshApScanResults() {
404    wifi.getLinkedInfo((err, result) => {
405      if (err) {
406        LogUtil.info(MODULE_TAG + 'get linked info failed');
407        return;
408      }
409      LogUtil.info(MODULE_TAG + 'scan get linked info succeed');
410      this.linkedApInfo = result;
411    });
412
413    wifi.getScanInfos((err, results) => {
414      if (err) {
415        LogUtil.info(MODULE_TAG + "get scan info failed");
416        return;
417      }
418      LogUtil.info(MODULE_TAG + 'get scan info succeed');
419      function removeDuplicateResults(arr: any[]): ApScanResult[] {
420        let results: ApScanResult[] = [];
421        for (let i = 0; i < arr.length; i++) {
422          let apResult = new ApScanResult(arr[i]);
423          if (apResult.isValidAp()) {
424            results.push(apResult);
425          }
426        }
427        return ApScanResult.filter(results);
428      };
429
430      function removeConnectedAp(arr: ApScanResult[], needRemove: ApScanResult) {
431        let index = ApScanResult.index(arr, needRemove);
432        if (index !== -1) {
433          arr.splice(index, 1);
434        }
435        return arr;
436      }
437
438      function addSavedConfigFlag(aps: ApScanResult[]): ApScanResult[] {
439        let configs: ApScanResult[] = [];
440        let deviceConfigs: any[] = wifi.getDeviceConfigs();
441        for (let i = 0; i < deviceConfigs.length; i++) {
442          let temp = new ApScanResult(deviceConfigs[i]);
443          configs.push(temp);
444        }
445        for (let i = 0; i < configs.length; i++) {
446          let index = ApScanResult.index(aps, configs[i]);
447          if (index !== -1) {
448            let item = aps[index];
449            item.updateSavedStatus(true);
450            aps.splice(index, 1);
451            aps.unshift(item);
452          }
453        }
454        return aps;
455      }
456
457      function addConnectStatusFlag(arr: ApScanResult[], linked: any): ApScanResult {
458        let ap: ApScanResult = new ApScanResult();
459        for (let i = 0; i < arr.length; i++) {
460          if (arr[i].getApInfo().ssid === linked.ssid) {
461            ap = arr[i];
462            break;
463          }
464        }
465        ap.updateConnectStatus(linked.connState);
466        return ap;
467      }
468
469      function unshiftConnectingAp(arr: ApScanResult[], ap: ApScanResult): ApScanResult[] {
470        let index = ApScanResult.index(arr, ap);
471        if (index !== -1) {
472          arr.splice(index, 1);
473          arr.unshift(ap);
474        }
475        return arr;
476      }
477
478      // step 1 : remove duplicate ap info
479      let scanResults: ApScanResult[] = removeDuplicateResults(results);
480      LogUtil.info(MODULE_TAG + 'scan results items length is : ' + scanResults.length);
481
482      // step 2 : add saved config flags
483      scanResults = addSavedConfigFlag(scanResults);
484      scanResults.sort(ApScanResult.compare);
485
486      // step 3 : add wifi summary
487      if (this.linkedApInfo !== null && typeof this.linkedApInfo !== 'undefined') {
488        let linkInfoResult: ApScanResult = addConnectStatusFlag(scanResults, this.linkedApInfo);
489        if (linkInfoResult.isConnected()) {
490          LogUtil.info(MODULE_TAG + 'scan connected');
491          scanResults = removeConnectedAp(scanResults, linkInfoResult);
492          AppStorage.SetOrCreate('slConnectedWifi', linkInfoResult.renderToListModel());
493        } else {
494          LogUtil.info(MODULE_TAG + 'scan not connected');
495          scanResults = unshiftConnectingAp(scanResults, linkInfoResult);
496          AppStorage.SetOrCreate('slConnectedWifi', (new ApScanResult()).renderToListModel());
497        }
498      }
499      LogUtil.info(MODULE_TAG + 'scan list results');
500      AppStorage.SetOrCreate('slWiFiLists', scanResults.map((item) => {
501        return item.renderToListModel();
502      }));
503    });
504  }
505
506  startScanTask() {
507    LogUtil.info(MODULE_TAG + 'start the wifi scan task');
508
509    if (this.scanTaskId !== Undefined_TaskId) {
510      clearInterval(this.scanTaskId);
511      this.scanTaskId = Undefined_TaskId;
512    }
513
514    this.scanTaskId = setInterval(() => {
515      if (this.isWiFiActive() === true) {
516        LogUtil.info(MODULE_TAG + 'scan wifi started');
517        this.scanWiFi();
518        this.isScanning = true;
519        this.refreshApScanResults();
520      }
521    }, 5000);
522  }
523
524  stopScanTask() {
525    LogUtil.info(MODULE_TAG + 'stop the wifi scan task');
526    if (this.scanTaskId !== Undefined_TaskId) {
527      clearInterval(this.scanTaskId);
528      this.scanTaskId = Undefined_TaskId;
529    }
530    this.isScanning = false;
531  }
532}
533
534let wifiModel = new WifiModel();
535export default wifiModel as WifiModel;
536