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;