• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
2import LogUtil from '../../Utils/LogUtil'
3import BaseModel from '../../Utils/BaseModel'
4import bluetooth from '@ohos.bluetooth';
5
6export enum ProfileCode {
7    CODE_BT_PROFILE_A2DP_SINK = 0,
8    CODE_BT_PROFILE_A2DP_SOURCE,
9    CODE_BT_PROFILE_AVRCP_CT,
10    CODE_BT_PROFILE_AVRCP_TG,
11    CODE_BT_PROFILE_HANDS_FREE_AUDIO_GATEWAY,
12    CODE_BT_PROFILE_HANDS_FREE_UNIT,
13    CODE_BT_PROFILE_HID_HOST,
14    CODE_BT_PROFILE_PAN_NETWORK,
15    CODE_BT_PROFILE_PBAP_CLIENT,
16    CODE_BT_PROFILE_PBAP_SERVER,
17};
18
19export enum BondState {
20    /** Indicate the bond state is invalid */
21    BOND_STATE_INVALID = 0,
22    /** Indicate the bond state is bonding */
23    BOND_STATE_BONDING = 1,
24    /** Indicate the bond state is bonded*/
25    BOND_STATE_BONDED = 2
26}
27
28export enum DeviceType {
29    BLUETOOTH = '1',
30    HEADPHONE = '2',
31    PHONE = '3',
32    COMPUTER = '4',
33    WATCH = '5'
34}
35
36export enum DeviceState {
37    /** the device is disconnected */
38    STATE_DISCONNECTED = 0,
39    /** the device is being connected */
40    STATE_CONNECTING = 1,
41    /** the device is connected */
42    STATE_CONNECTED = 2,
43    /** the device is being disconnected */
44    STATE_DISCONNECTING = 3,
45    /** the device is available */
46    STATE_AVAILABLE = 100,
47    /** the device is pairing */
48    STATE_PAIRING = 101,
49    /** the device is paired */
50    STATE_PAIRED = 102
51}
52
53export enum BluetoothErrorCode {
54    SUCCESS = -1,
55    HOLD_PAIRING_MODE = 1,
56    APP_PAIR = 2,
57    PAIR_FAILED = 3,
58    DEVICE_ILLEGAL = 4,
59    CONNECT_FAILED = 5
60}
61
62enum BluetoothState {
63    /** Indicates the local Bluetooth is off */
64    STATE_OFF = 0,
65    /** Indicates the local Bluetooth is turning on */
66    STATE_TURNING_ON = 1,
67    /** Indicates the local Bluetooth is on, and ready for use */
68    STATE_ON = 2,
69    /** Indicates the local Bluetooth is turning off */
70    STATE_TURNING_OFF = 3,
71    /** Indicates the local Bluetooth is turning LE mode on */
72    STATE_BLE_TURNING_ON = 4,
73    /** Indicates the local Bluetooth is in LE only mode */
74    STATE_BLE_ON = 5,
75    /** Indicates the local Bluetooth is turning off LE only mode */
76    STATE_BLE_TURNING_OFF = 6
77}
78
79enum ScanMode {
80    /** Indicates the scan mode is none */
81    SCAN_MODE_NONE = 0,
82    /** Indicates the scan mode is connectable */
83    SCAN_MODE_CONNECTABLE = 1,
84    /** Indicates the scan mode is general discoverable */
85    SCAN_MODE_GENERAL_DISCOVERABLE = 2,
86    /** Indicates the scan mode is limited discoverable */
87    SCAN_MODE_LIMITED_DISCOVERABLE = 3,
88    /** Indicates the scan mode is connectable and general discoverable */
89    SCAN_MODE_CONNECTABLE_GENERAL_DISCOVERABLE = 4,
90    /** Indicates the scan mode is connectable and limited discoverable */
91    SCAN_MODE_CONNECTABLE_LIMITED_DISCOVERABLE = 5
92}
93
94enum ProfileId {
95    PROFILE_A2DP_SOURCE = 1,
96    PROFILE_HANDS_FREE_AUDIO_GATEWAY = 4,
97}
98
99enum ProfileConnectionState {
100    /** the current profile is disconnected */
101    STATE_DISCONNECTED = 0,
102    /** the current profile is being connected */
103    STATE_CONNECTING = 1,
104    /** the current profile is connected */
105    STATE_CONNECTED = 2,
106    /** the current profile is being disconnected */
107    STATE_DISCONNECTING = 3
108}
109
110export class BluetoothModel extends BaseModel{
111
112    private TAG = 'BluetoothModel ';
113    private profiles: any[] = new Array(10);
114    public canUse: boolean = false;
115
116    /**
117     * constructor
118     */
119    constructor() {
120        super();
121        try{
122            LogUtil.info('bluetooth.getProfile start')
123            this.profiles[1] = bluetooth.getProfile(1);
124            this.profiles[4] = bluetooth.getProfile(4);
125            LogUtil.info('bluetooth.getProfile end')
126            this.canUse = true;
127        }
128        catch(error){
129            LogUtil.info('bluetooth.getProfile error')
130            this.canUse = false;
131            LogUtil.info(`BluetoothModel error: ${JSON.stringify(error)}.`);
132        }
133    }
134
135    getProfileConnState(profileId: ProfileId): string {
136        let state = bluetooth.getProfileConnState(profileId);
137        switch (state) {
138            case 0:
139                return 'STATE_DISCONNECTED';
140                break;
141            case 1:
142                return 'STATE_CONNECTING';
143                break;
144            case 2:
145                return 'STATE_CONNECTED';
146                break;
147            case 3:
148                return 'STATE_DISCONNECTING';
149                break;
150            default:
151                return '未知状态';
152                break;
153        }
154    }
155
156    getBtConnectionState(): string {
157        let connectionState = bluetooth.getBtConnectionState();
158        switch (connectionState) {
159            case 0:
160                return 'STATE_DISCONNECTED';
161                break;
162            case 1:
163                return 'STATE_CONNECTING';
164                break;
165            case 2:
166                return 'STATE_CONNECTED';
167                break;
168            case 3:
169                return 'STATE_DISCONNECTING';
170                break;
171            default:
172                return '未知状态';
173                break;
174        }
175    }
176
177    /**
178     * Get Bluetooth status
179     * @return value of bluetooth.BluetoothState type
180     */
181    getState(): number {
182        let bluetoothState = bluetooth.getState();
183        LogUtil.info(`${this.TAG} getState: bluetoothState = ${bluetoothState}`);
184        return bluetoothState;
185    }
186
187    setBluetoothScanMode(mode: ScanMode, duration: number): boolean {
188        return bluetooth.setBluetoothScanMode(mode, duration);
189    }
190
191    getBluetoothScanMode() : string {
192        let scanMode = bluetooth.getBluetoothScanMode();
193        LogUtil.info(`${this.TAG} getBluetoothScanMode: scanMode = ${scanMode}`);
194        switch (scanMode) {
195            case 0:
196                return 'SCAN_MODE_NONE';
197                break;
198            case 1:
199                return 'SCAN_MODE_CONNECTABLE';
200                break;
201            case 2:
202                return 'SCAN_MODE_GENERAL_DISCOVERABLE';
203                break;
204            case 3:
205                return 'SCAN_MODE_LIMITED_DISCOVERABLE';
206                break;
207            case 4:
208                return 'SCAN_MODE_CONNECTABLE_GENERAL_DISCOVERABLE';
209                break;
210            case 5:
211                return 'SCAN_MODE_CONNECTABLE_LIMITED_DISCOVERABLE';
212                break;
213            default:
214                return '';
215                break;
216        }
217    }
218
219    /**
220     * Get Bluetooth switch status
221     */
222    isStateOn(): boolean {
223        let result = false;
224        let state = bluetooth.getState();
225        LogUtil.info(`${this.TAG} isStateOn: state = ${state}`);
226        switch (state) {
227            case BluetoothState.STATE_ON:
228                result = true
229                break;
230            default:
231                break;
232        }
233        LogUtil.info(`${this.TAG} isStateOn: bluetoothState = ${result}`);
234        return result;
235    }
236
237    /**
238     * Subscribe Bluetooth switch status Change
239     */
240    subscribeStateChange(callback: (data: boolean) => void): void {
241        bluetooth.on('stateChange', (data) => {
242            LogUtil.info(`${this.TAG} subscribeStateChange->stateChange data:${data}`);
243            if (callback) {
244                switch (data) {
245                    case BluetoothState.STATE_ON:
246                        bluetooth.setBluetoothScanMode(4, 0);
247                        LogUtil.info(`${this.TAG} subscribeStateChange->stateChange return: true`);
248                        callback(true)
249                        break;
250
251                    case BluetoothState.STATE_OFF:
252                        LogUtil.info(`${this.TAG} subscribeStateChange->stateChange return: false`);
253                        callback(false)
254                        break;
255
256                    default:
257                        break;
258                }
259            }
260        })
261    }
262
263    /**
264     * unsubscribe Bluetooth switch status Change
265     */
266    unsubscribeStateChange(callback?: (data: boolean) => void): void {
267        bluetooth.off('stateChange', (data) => {
268            LogUtil.info(`${this.TAG} unsubscribeStateChange->stateChange data:${data}`);
269            if (callback) {
270                let result = false;
271                switch (data) {
272                    case BluetoothState.STATE_ON:
273                        LogUtil.info(`${this.TAG} unsubscribeStateChange->stateChange return : true`);
274                        callback(true)
275                        break;
276                    case BluetoothState.STATE_OFF:
277                        LogUtil.info(`${this.TAG} unsubscribeStateChange->stateChange return : false`);
278                        callback(false)
279                        break;
280                    default:
281                        break;
282                }
283            }
284        })
285    }
286
287    /**
288     * Turn on Bluetooth
289     */
290    enableBluetooth(): boolean {
291        return bluetooth.enableBluetooth();
292    }
293
294    /**
295     * Turn off Bluetooth
296     */
297    disableBluetooth(): boolean {
298        return bluetooth.disableBluetooth();
299    }
300
301    /**
302     * Get local name
303     */
304    getLocalName(): string {
305        return bluetooth.getLocalName();
306    }
307
308    /**
309     * Set local name
310     */
311    setLocalName(name: string): boolean {
312        return bluetooth.setLocalName(name);
313    }
314
315    /**
316     * Get paired device ids
317     */
318    getPairedDeviceIds(): Array<string> {
319        return bluetooth.getPairedDevices();
320    }
321
322    /**
323     * Start Bluetooth discovery
324     */
325    startBluetoothDiscovery(): boolean {
326        return bluetooth.startBluetoothDiscovery();
327    }
328
329    /**
330     * Stop Bluetooth discovery
331     */
332    stopBluetoothDiscovery(): boolean {
333        let ret = bluetooth.stopBluetoothDiscovery();
334        this.unsubscribeStateChange();
335        this.unsubscribeBluetoothDeviceFind();
336        this.unsubscribeBondStateChange();
337        this.unsubscribeDeviceStateChange();
338        return ret;
339    }
340
341    /**
342     * Subscribe Bluetooth status Change
343     */
344    subscribeBluetoothDeviceFind(callback: (data: Array<string>) => void): void {
345        bluetooth.on('bluetoothDeviceFind', (data: Array<string>) => {
346            LogUtil.info(`${this.TAG} subscribeBluetoothDeviceFind->deviceFind return:${JSON.stringify(data)}`);
347            if (callback) {
348                callback(data)
349            }
350        })
351    }
352
353    /**
354     * unsubscribe Bluetooth status Change
355     */
356    unsubscribeBluetoothDeviceFind(callback?: (data: Array<string>) => void): void {
357        bluetooth.off('bluetoothDeviceFind', (data) => {
358            LogUtil.info(`${this.TAG} unsubscribeBluetoothDeviceFind->deviceFind return:${JSON.stringify(data)}`);
359            if (callback) {
360                callback(data)
361            }
362        })
363    }
364
365    /**
366     * Pair device
367     */
368    pairDevice(deviceId: string): boolean {
369        return bluetooth.pairDevice(deviceId);
370    }
371
372    /**
373     * Subscribe PinRequired
374     */
375    subscribePinRequired(callback: (data: {
376        deviceId: string;
377        pinCode: string;
378    }) => void): void {
379        bluetooth.on('pinRequired', (data: {
380            deviceId: string;
381            pinCode: string;
382        }) => {
383            LogUtil.info(`${this.TAG} subscribePinRequired->pinRequired return:${JSON.stringify(data)}`);
384            if (callback) {
385                callback(data)
386            }
387        })
388    }
389
390    /**
391     * Unsubscribe PinRequired
392     */
393    unsubscribePinRequired(callback?: (data: {
394        deviceId: string;
395        pinCode: string;
396    }) => void): void {
397        bluetooth.off('pinRequired', (data: {
398            deviceId: string;
399            pinCode: string;
400        }) => {
401            LogUtil.info(`${this.TAG} unsubscribePinRequired->pinRequired return: ${JSON.stringify(data)}`);
402            if (callback) {
403                callback(data)
404            }
405        })
406    }
407
408    /**
409     * Set device PairingConfirmation
410     */
411    setDevicePairingConfirmation(deviceId: string, accept: boolean): boolean {
412        return bluetooth.setDevicePairingConfirmation(deviceId, accept);
413    }
414
415    /**
416     * Subscribe bondStateChange
417     */
418    subscribeBondStateChange(callback): void {
419        bluetooth.on('bondStateChange', (data) => {
420            LogUtil.info(`${this.TAG} subscribeBondStateChange->bondStateChange data:${JSON.stringify(data)}`);
421            if (callback) {
422                let result = {
423                    deviceId: data.deviceId,
424                    bondState: data.state
425                }
426                LogUtil.info(`${this.TAG} subscribeBondStateChange->bondStateChange return:${JSON.stringify(result)}`);
427                callback(result);
428            }
429        })
430    }
431
432    /**
433     * Unsubscribe bondStateChange
434     */
435    unsubscribeBondStateChange(callback?: (data: {
436        deviceId: string;
437        bondState: number;
438    }) => void): void {
439        bluetooth.off('bondStateChange', (data) => {
440            LogUtil.info(`${this.TAG} unsubscribeBondStateChange->bondStateChange data:${JSON.stringify(data)}`);
441            if (callback) {
442                let result = {
443                    deviceId: data.deviceId,
444                    bondState: data.state
445                }
446                LogUtil.info(`${this.TAG} unsubscribeBondStateChange->bondStateChange return:${JSON.stringify(result)}`);
447                callback(result);
448            }
449        })
450    }
451
452    /**
453     * Get device name
454     */
455    getDeviceName(deviceId: string): string {
456        return bluetooth.getRemoteDeviceName(deviceId);
457    }
458
459    /**
460     * Get device type
461     */
462    getDeviceType(deviceId: string): string {
463        let deviceType = 'BLUETOOTH';
464        let deviceClass = bluetooth.getRemoteDeviceClass(deviceId);
465        switch (deviceClass.majorClass) {
466            case 0x0100:
467                deviceType = 'COMPUTER';
468                break;
469            case 0x0400:
470                if (deviceClass.majorMinorClass === 0x0418 || deviceClass.majorMinorClass === 0x0404) {
471                    deviceType = 'HEADPHONE';
472                }
473                break;
474            case 0x0700:
475                if (deviceClass.majorMinorClass === 0x0704) {
476                    deviceType = 'WATCH';
477                }
478                break;
479            case 0x0200:
480                deviceType = 'PHONE';
481                break;
482            default:
483                deviceType = 'BLUETOOTH';
484                break;
485        }
486        return deviceType;
487    }
488
489    /**
490     * Get device state
491     */
492    getDeviceState(deviceId: string): Array<{
493        profileId: number;
494        profileConnectionState: number;
495    }> {
496        let result = [];
497        for (let i = 0;i < this.profiles.length; i++) {
498            if (this.profiles[i]) {
499                let state = this.profiles[i].getDeviceState(deviceId);
500                result.push({
501                    profileId: i,
502                    profileConnectionState: state
503                });
504            }
505        }
506        return result;
507    }
508
509    /**
510     * Unpair device
511     */
512    unpairDevice(deviceId: string): boolean {
513        return bluetooth.cancelPairedDevice(deviceId);
514    }
515
516    /**
517     * Connect device
518     */
519    connectDevice(deviceId: string): Array<{
520        profileId: number;
521        connectRet: boolean;
522    }> {
523        let result = [];
524        for (let i = 0;i < this.profiles.length; i++) {
525            if (this.profiles[i]) {
526                let profile = this.profiles[i];
527                let connectRet = profile.connect(deviceId);
528                result.push({
529                    profileId: i,
530                    connectRet: connectRet
531                });
532            }
533        }
534        return result;
535    }
536
537    /**
538     * Disconnect device
539     */
540    disconnectDevice(deviceId: string): Array<{
541        profileId: number;
542        disconnectRet: boolean;
543    }> {
544        let result = [];
545        for (let i = 0;i < this.profiles.length; i++) {
546            let profile = this.profiles[i];
547            if (this.profiles[i]) {
548                let profileConnectionState = profile.getDeviceState(deviceId);
549                let disconnectRet = true;
550                LogUtil.info(`${this.TAG} disconnectDevice deviceId = ${deviceId}, connectionState = ${profileConnectionState}`);
551                if (profileConnectionState === 2) {
552                    disconnectRet = profile.disconnect(deviceId);
553                    LogUtil.info(`${this.TAG} disconnectDevice call disconnect over. api return =  ${disconnectRet}, deviceId = ${deviceId}`);
554                }
555                result.push({
556                    profileId: i,
557                    disconnectRet: disconnectRet
558                });
559            }
560        }
561        return result;
562    }
563
564    /**
565     * Subscribe device connection state Change
566     */
567    subscribeDeviceStateChange(callback: (data: {
568        profileId: number;
569        deviceId: string;
570        profileConnectionState: number;
571    }) => void): void {
572        for (let i = 0;i < this.profiles.length; i++) {
573            if (this.profiles[i]) {
574                let profile = this.profiles[i];
575                profile.on('connectionStateChange', (data) => {
576                    LogUtil.info(`${this.TAG} subscribeDeviceStateChange->connectionStateChange data:${JSON.stringify(data)}`);
577                    if (callback) {
578                        let result = {
579                            profileId: i,
580                            deviceId: data.deviceId,
581                            profileConnectionState: data.state
582                        };
583                        LogUtil.info(`${this.TAG} subscribeDeviceStateChange->connectionStateChange return:${JSON.stringify(result)}`);
584                        callback(result);
585                    }
586                })
587            }
588        }
589    }
590
591    /**
592     * unsubscribe device connection state Change
593     */
594    unsubscribeDeviceStateChange(callback?: (data: {
595        profileId: number;
596        deviceId: string;
597        profileConnectionState: number;
598    }) => void): void {
599        for (let i = 0;i < this.profiles.length; i++) {
600            if (this.profiles[i]) {
601                let profile = this.profiles[i];
602                profile.off('connectionStateChange', (data) => {
603                    LogUtil.info(`${this.TAG} unsubscribeDeviceStateChange->connectionStateChange data:${JSON.stringify(data)}`);
604                    if (callback) {
605                        let result = {
606                            profileId: i,
607                            deviceId: data.deviceId,
608                            profileConnectionState: data.state
609                        };
610                        LogUtil.info(`${this.TAG} unsubscribeDeviceStateChange->connectionStateChange return:${JSON.stringify(result)}`);
611                        callback(result);
612                    }
613                })
614            }
615        }
616    }
617
618    // BLE public
619    createGattServer():bluetooth.GattServer{
620        return bluetooth.BLE.createGattServer();
621    }
622    createGattClient(deviceId: string):bluetooth.GattClientDevice{
623        return bluetooth.BLE.createGattClientDevice(deviceId);
624    }
625    getConnectedBLEDevices(): Array<string>
626    {
627        return bluetooth.BLE.getConnectedBLEDevices();
628    }
629    // start BLE scanning
630    startBLEScan(filters: Array<bluetooth.ScanFilter>, options?: bluetooth.ScanOptions): void
631    {
632        switch (arguments.length)
633        {
634            case 1:
635                LogUtil.info(`${this.TAG} startBLEScan with filters(or null) only `);
636                bluetooth.BLE.startBLEScan(filters);
637            break;
638            case 2:
639                LogUtil.info(`${this.TAG} startBLEScan with filters and options`);
640                bluetooth.BLE.startBLEScan(filters, options);
641            break;
642            default:
643                LogUtil.error(`${this.TAG} startBLEScan with unexpected input parameter!`);
644        }
645    }
646
647    /**
648     * Stops BLE scanning.
649     */
650    stopBLEScan():void
651    {
652        bluetooth.BLE.stopBLEScan();
653    }
654    /**
655     * Subscribe BLEDeviceFind
656    */
657    subscribeBLEDeviceFind(callback: (bleDeviceFindData: Array<bluetooth.ScanResult>) => void): void {
658
659        bluetooth.BLE.on("BLEDeviceFind", (bleDeviceFindData) => {
660            LogUtil.info(`${this.TAG} subscribeBLEDeviceFind->deviceFind return:${JSON.stringify(bleDeviceFindData)}`);
661            if (callback) {
662                callback(bleDeviceFindData);
663            }
664        })
665    }
666
667    /**
668     * unsubscribe BLEDeviceFind
669     */
670    unsubscribeBLEDeviceFind(callback?: (bleDeviceFindData: Array<bluetooth.ScanResult>) => void): void {
671        bluetooth.BLE.off('BLEDeviceFind', (bleDeviceFindData) => {
672            LogUtil.info(`${this.TAG} unsubscribeBLEDeviceFind->deviceFind return:${JSON.stringify(bleDeviceFindData)}`);
673            if (callback) {
674                callback(bleDeviceFindData);
675            }
676        })
677    }
678
679}
680
681let bluetoothModel = new BluetoothModel();
682
683export default bluetoothModel as BluetoothModel;