• 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  getDeviceConfigsInfo(ssid: string): wifi.WifiDeviceConfig {
252    let deviceConfigs: wifi.WifiDeviceConfig[] = wifi.getDeviceConfigs();
253    for (let i = 0; i < deviceConfigs.length; i++) {
254      if (ssid === deviceConfigs[i].ssid) {
255        return deviceConfigs[i];
256      }
257    }
258    return null;
259  }
260
261  setUserSelectedAp(apInfo?: any) {
262    if (apInfo === null || typeof apInfo === 'undefined') {
263      this.userSelectedAp = new ApScanResult();
264    }
265    this.userSelectedAp = new ApScanResult(apInfo);
266  }
267
268  isSavedAp(ssid: string): boolean {
269    let deviceConfigs: any[] = wifi.getDeviceConfigs();
270    for (let i = 0; i < deviceConfigs.length; i++) {
271      if (ssid === deviceConfigs[i].ssid) {
272        return true;
273      }
274    }
275    return false;
276  }
277
278  isWiFiActive(): boolean {
279    const isActive: boolean = wifi.isWifiActive();
280    LogUtil.info(MODULE_TAG + 'check WiFi active status is : ' + isActive);
281    return isActive;
282  }
283
284  isWiFiConnected(): boolean {
285    let ret = wifi.isConnected();
286    LogUtil.info(MODULE_TAG + 'check WiFi connected status is : ' + ret);
287    return ret;
288  }
289
290  enableWiFi() {
291    if (wifi.isWifiActive() === true) {
292      LogUtil.info(MODULE_TAG + 'wifi is already active');
293      return;
294    }
295    let ret: boolean = wifi.enableWifi();
296    LogUtil.info(MODULE_TAG + 'enable WiFi result is : ' + ret);
297    return ret;
298  }
299
300  disableWifi() {
301    this.setUserSelectedAp(null);
302
303    if (wifi.isWifiActive() !== true) {
304      LogUtil.info(MODULE_TAG + 'wifi is already inactive');
305      return;
306    }
307    const ret: boolean = wifi.disableWifi();
308    LogUtil.info(MODULE_TAG + 'disable WiFi result is : ' + ret);
309  }
310
311  scanWiFi(): boolean {
312    const ret: boolean = wifi.scan();
313    LogUtil.info(MODULE_TAG + 'start scan WiFi result is : ' + ret);
314    return ret;
315  }
316
317  connectWiFi(password: string) {
318    let apInfo = this.userSelectedAp.getApInfo();
319    let ret = false;
320    let connectParam: any = {
321      "ssid": apInfo.ssid,
322      "bssid": apInfo.bssid,
323      "preSharedKey": password,
324      "isHiddenSsid": false, // we don't support connect to hidden ap yet
325      "securityType": apInfo.securityType
326    };
327    LogUtil.info(MODULE_TAG + 'disconnect WiFi isConnected is ' + wifi.isConnected());
328    if (wifi.isConnected() === true) {
329      ret = wifi.disconnect();
330      LogUtil.info(MODULE_TAG + 'disconnect WiFi ret is ' + ret);
331      this.registerWiFiConnectionObserver((code: Number) => {
332        if (code === 0) {
333          ret = wifi.connectToDevice(connectParam);
334          this.unregisterWiFiConnectionObserver();
335        }
336      })
337    }else{
338      ret = wifi.connectToDevice(connectParam);
339      LogUtil.info(MODULE_TAG + 'connect WiFi ret is ' + ret);
340    }
341    return ret;
342  }
343
344  /**
345   * Disconnect wifi
346   */
347  disconnectWiFi() {
348    this.setUserSelectedAp(null);
349
350    let ret = wifi.disconnect();
351    LogUtil.info(MODULE_TAG + 'disconnect WiFi result is : ' + ret);
352    return ret;
353  }
354
355  getSignalIntensity(apInfo: WifiScanInfo) {
356    let result = wifi.getSignalLevel(apInfo.rssi, apInfo.band);
357    if (result <= 1) {
358      return WiFiIntensityMap.BAD;
359    }
360    if (result <= 2) {
361      return WiFiIntensityMap.NORMAL;
362    }
363    if (result <= 3) {
364      return WiFiIntensityMap.WELL;
365    }
366    return WiFiIntensityMap.GOOD;
367  }
368
369  getEncryptMethod(apInfo: WifiScanInfo) {
370    if (apInfo.securityType === 1) {
371      return WiFiEncryptMethodMap.OPEN;
372    }
373    if (apInfo.securityType === 2) {
374      return WiFiEncryptMethodMap.WEP;
375    }
376    return WiFiEncryptMethodMap.WPA2;
377  }
378
379  getLinkInfo() {
380    return this.linkedApInfo;
381  }
382
383  removeDeviceConfig(apInfo: WifiScanInfo) {
384    LogUtil.info(MODULE_TAG + 'start to removeDeviceConfig');
385    let deviceConfigs: any[] = wifi.getDeviceConfigs();
386    let networkId: number = -1;
387    for (let i = 0; i < deviceConfigs.length; i++) {
388      if (deviceConfigs[i].ssid === apInfo.ssid) {
389        networkId = deviceConfigs[i].netId;
390        break;
391      }
392    }
393    if (networkId === -1) {
394      return;
395    }
396    LogUtil.info(MODULE_TAG + 'start to removeDevice');
397    let ret = wifi.removeDevice(networkId);
398    LogUtil.info(MODULE_TAG + 'remove device config : ' + ret);
399  }
400
401  connectByDeviceConfig(apInfo: WifiScanInfo) {
402    let deviceConfigs: any[] = wifi.getDeviceConfigs();
403    // find the wifi device config
404    for (let i = 0; i < deviceConfigs.length; i++) {
405      if (deviceConfigs[i].ssid === apInfo.ssid) {
406        let ret = wifi.connectToDevice(deviceConfigs[i]);
407        LogUtil.info(MODULE_TAG + 'connect ret for : ' + i + ' = ' + ret);
408      }
409    }
410    LogUtil.info(MODULE_TAG + 'end connect by device config');
411  }
412
413  refreshApScanResults() {
414    wifi.getLinkedInfo((err, result) => {
415      if (err) {
416        LogUtil.info(MODULE_TAG + 'get linked info failed');
417        return;
418      }
419      LogUtil.info(MODULE_TAG + 'scan get linked info succeed');
420      this.linkedApInfo = result;
421    });
422
423    wifi.getScanInfos((err, results) => {
424      if (err) {
425        LogUtil.info(MODULE_TAG + "get scan info failed");
426        return;
427      }
428      LogUtil.info(MODULE_TAG + 'get scan info succeed');
429      function removeDuplicateResults(arr: any[]): ApScanResult[] {
430        let results: ApScanResult[] = [];
431        for (let i = 0; i < arr.length; i++) {
432          let apResult = new ApScanResult(arr[i]);
433          if (apResult.isValidAp()) {
434            results.push(apResult);
435          }
436        }
437        return ApScanResult.filter(results);
438      };
439
440      function removeConnectedAp(arr: ApScanResult[], needRemove: ApScanResult) {
441        let index = ApScanResult.index(arr, needRemove);
442        if (index !== -1) {
443          arr.splice(index, 1);
444        }
445        return arr;
446      }
447
448      function addSavedConfigFlag(aps: ApScanResult[]): ApScanResult[] {
449        let configs: ApScanResult[] = [];
450        let deviceConfigs: any[] = wifi.getDeviceConfigs();
451        for (let i = 0; i < deviceConfigs.length; i++) {
452          let temp = new ApScanResult(deviceConfigs[i]);
453          configs.push(temp);
454        }
455        for (let i = 0; i < configs.length; i++) {
456          let index = ApScanResult.index(aps, configs[i]);
457          if (index !== -1) {
458            let item = aps[index];
459            item.updateSavedStatus(true);
460            aps.splice(index, 1);
461            aps.unshift(item);
462          }
463        }
464        return aps;
465      }
466
467      function addConnectStatusFlag(arr: ApScanResult[], linked: any): ApScanResult {
468        let ap: ApScanResult = new ApScanResult();
469        for (let i = 0; i < arr.length; i++) {
470          if (arr[i].getApInfo().ssid === linked.ssid) {
471            ap = arr[i];
472            break;
473          }
474        }
475        ap.updateConnectStatus(linked.connState);
476        return ap;
477      }
478
479      function unshiftConnectingAp(arr: ApScanResult[], ap: ApScanResult): ApScanResult[] {
480        let index = ApScanResult.index(arr, ap);
481        if (index !== -1) {
482          arr.splice(index, 1);
483          arr.unshift(ap);
484        }
485        return arr;
486      }
487
488      // step 1 : remove duplicate ap info
489      let scanResults: ApScanResult[] = removeDuplicateResults(results);
490      LogUtil.info(MODULE_TAG + 'scan results items length is : ' + scanResults.length);
491
492      // step 2 : add saved config flags
493      scanResults = addSavedConfigFlag(scanResults);
494      scanResults.sort(ApScanResult.compare);
495
496      // step 3 : add wifi summary
497      if (this.linkedApInfo !== null && typeof this.linkedApInfo !== 'undefined') {
498        let linkInfoResult: ApScanResult = addConnectStatusFlag(scanResults, this.linkedApInfo);
499        if (linkInfoResult.isConnected()) {
500          LogUtil.info(MODULE_TAG + 'scan connected');
501          scanResults = removeConnectedAp(scanResults, linkInfoResult);
502          AppStorage.SetOrCreate('slConnectedWifi', linkInfoResult.renderToListModel());
503        } else {
504          LogUtil.info(MODULE_TAG + 'scan not connected');
505          scanResults = unshiftConnectingAp(scanResults, linkInfoResult);
506          AppStorage.SetOrCreate('slConnectedWifi', (new ApScanResult()).renderToListModel());
507        }
508      }
509      LogUtil.info(MODULE_TAG + 'scan list results');
510      AppStorage.SetOrCreate('slWiFiLists', scanResults.map((item) => {
511        return item.renderToListModel();
512      }));
513    });
514  }
515
516  startScanTask() {
517    LogUtil.info(MODULE_TAG + 'start the wifi scan task');
518
519    if (this.scanTaskId !== Undefined_TaskId) {
520      clearInterval(this.scanTaskId);
521      this.scanTaskId = Undefined_TaskId;
522    }
523
524    this.scanTaskId = setInterval(() => {
525      if (this.isWiFiActive() === true) {
526        LogUtil.info(MODULE_TAG + 'scan wifi started');
527        this.scanWiFi();
528        this.isScanning = true;
529        this.refreshApScanResults();
530      }
531    }, 5000);
532  }
533
534  stopScanTask() {
535    LogUtil.info(MODULE_TAG + 'stop the wifi scan task');
536    if (this.scanTaskId !== Undefined_TaskId) {
537      clearInterval(this.scanTaskId);
538      this.scanTaskId = Undefined_TaskId;
539    }
540    this.isScanning = false;
541  }
542}
543
544let wifiModel = new WifiModel();
545export default wifiModel as WifiModel;
546