1# GATT-based BLE Connection and Data Transmission 2 3## Introduction 4Generic Attribute Profile (GATT) provides profile discovery and description services for the BLE protocol. It defines how ATT attributes are organized and exchanged over a BLE connection.<br>A GATT server (referred to as server in this topic) is a device that stores attribute data locally and provides data access to a remote GATT client paired via BLE. A GATT client (referred to as client in this topic) is a device that accesses data on the remote GATT server via read, write, notify, or indicate operations. 5 6## When to Use 7 8You can use the APIs provided by the **gatt** module to: 9- Connect to the server to read and write data. 10- Manage services on the server and respond to the requests from the client. 11 12## Available APIs 13 14For details about the APIs and sample code, see [@ohos.bluetooth.ble](../../reference/apis-connectivity-kit/js-apis-bluetooth-ble.md). 15 16The following table describes the related APIs. 17 18| API | Description | 19| ------------------------------------------ | ------------------------------------------------------------------------------------------------------ | 20| connect() | Connects the client to the remote BLE device. | 21| disconnect() | Disconnects the client from the remote BLE device. | 22| close() | Closes this client to unregister it from the protocol stack. After this API is called, this **GattClientDevice** instance cannot be used any longer.| 23| getDeviceName() | Obtains the name of the remote BLE device for the client. | 24| getServices() | Obtains all services of the remote BLE device for the client. | 25| readCharacteristicValue() | Reads a characteristic value of a service of the remote BLE device. | 26| readDescriptorValue() | Reads the descriptor contained in a characteristic of the remote BLE device. | 27| writeCharacteristicValue() | Writes a characteristic value to the remote BLE device. | 28| writeDescriptorValue() | Writes binary data to a descriptor of the remote BLE device. | 29| getRssiValue() | Obtains the received signal strength indication (RSSI) of the peer BLE device. This API can be used only after a connection is set up by **connect()**.| 30| setBLEMtuSize() | Sets the maximum transmission unit (MTU) that can be transmitted between the client and its peer BLE device. This API can be used only after a connection is set up by **connect()**.| 31| setCharacteristicChangeNotification() | Sets the characteristic change notification. The client will be notified when the characteristic value of the remote BLE device changes. | 32| setCharacteristicChangeIndication() | Sets the characteristic change indication. The client will be indicated when the characteristic value of the remote BLE device changes. | 33| on(type: 'BLECharacteristicChange') | Subscribes to the BLE characteristic changes. The client can receive a notification from the server only after the **setNotifyCharacteristicChanged** method is called. | 34| off(type: 'BLECharacteristicChange') | Unsubscribes from the BLE characteristic changes. | 35| on(type: 'BLEConnectionStateChange') | Subscribes to the BLE connection state changes for the client. | 36| off(type: 'BLEConnectionStateChange') | Unsubscribes from the BLE connection state changes for the client. | 37| on(type: 'BLEMtuChange') | Subscribes to MTU status changes for the client. | 38| off(type: 'BLEMtuChange') | Unsubscribes from MTU status changes for the client. | 39| addService() | Adds a service to this server. | 40| removeService() | Removes a service from this server. | 41| close() | Closes this server to unregister it from the protocol stack. After this API is called, the **GattServer** instance cannot be used any longer. | 42| notifyCharacteristicChanged() | Notifies a connected client device when a characteristic value changes. | 43| sendResponse() | Sends a response to a read or write request from the client. | 44| on(type: 'characteristicRead') | Subscribes to the characteristic read request event for the server. | 45| off(type: 'characteristicRead') | Unsubscribes from the characteristic read request event for the server. | 46| on(type: 'characteristicWrite') | Subscribes to the characteristic write request event for the server. | 47| off(type: 'characteristicWrite') | Unsubscribes from the characteristic write request event for the server. | 48| on(type: 'descriptorRead') | Subscribes to the descriptor read request event for the server. | 49| off(type: 'descriptorRead') | Unsubscribes from the descriptor read request event for the server. | 50| on(type: 'descriptorWrite') | Subscribes to the descriptor write request event for the server. | 51| off(type: 'descriptorWrite') | Unsubscribes from the descriptor write request event for the server. | 52| on(type: 'connectionStateChange') | Subscribes to the BLE connection state changes for the server. | 53| off(type: 'connectionStateChange') | Unsubscribes from the BLE connection state changes for the server. | 54| on(type: 'BLEMtuChange') | Subscribes to MTU status changes for the server. | 55| off(type: 'BLEMtuChange') | Unsubscribes from MTU status changes for the server. | 56 57## How to Develop 58 59### Reading and Writing Data on the Server 601. Import the **ble** module. 612. Enable Bluetooth. 623. Apply for the **ohos.permission.ACCESS_BLUETOOTH** permission. 634. Create a **gattClient** instance. 645. Connect to the server. 656. Read characteristics and descriptors from the server. 667. Write characteristics and descriptors to the server. 678. Disconnect from the server and destroy the **gattClient** instance. 689. Example: 69 70 ```ts 71 import { ble } from '@kit.ConnectivityKit'; 72 import { constant } from '@kit.ConnectivityKit'; 73 import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit'; 74 75 const TAG: string = 'GattClientManager'; 76 77 export class GattClientManager { 78 device: string | undefined = undefined; 79 gattClient: ble.GattClientDevice | undefined = undefined; 80 connectState: ble.ProfileConnectionState = constant.ProfileConnectionState.STATE_DISCONNECTED; 81 myServiceUuid: string = '00001810-0000-1000-8000-00805F9B34FB'; 82 myCharacteristicUuid: string = '00001820-0000-1000-8000-00805F9B34FB'; 83 myFirstDescriptorUuid: string = '00002902-0000-1000-8000-00805F9B34FB'; // 2902 is generally used for notification or indication. 84 mySecondDescriptorUuid: string = '00002903-0000-1000-8000-00805F9B34FB'; 85 found: boolean = false; 86 87 // Construct BLEDescriptor. 88 private initDescriptor(des: string, value: ArrayBuffer): ble.BLEDescriptor { 89 let descriptor: ble.BLEDescriptor = { 90 serviceUuid: this.myServiceUuid, 91 characteristicUuid: this.myCharacteristicUuid, 92 descriptorUuid: des, 93 descriptorValue: value 94 }; 95 return descriptor; 96 } 97 98 // Construct BLECharacteristic. 99 private initCharacteristic(): ble.BLECharacteristic { 100 let descriptors: Array<ble.BLEDescriptor> = []; 101 let descBuffer = new ArrayBuffer(2); 102 let descValue = new Uint8Array(descBuffer); 103 descValue[0] = 11; 104 descValue[1] = 12; 105 descriptors[0] = this.initDescriptor(this.myFirstDescriptorUuid, new ArrayBuffer(2)); 106 descriptors[1] = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 107 let charBuffer = new ArrayBuffer(2); 108 let charValue = new Uint8Array(charBuffer); 109 charValue[0] = 1; 110 charValue[1] = 2; 111 let characteristic: ble.BLECharacteristic = { 112 serviceUuid: this.myServiceUuid, 113 characteristicUuid: this.myCharacteristicUuid, 114 characteristicValue: charBuffer, 115 descriptors: descriptors 116 }; 117 return characteristic; 118 } 119 120 private logCharacteristic(char: ble.BLECharacteristic) { 121 let message = 'logCharacteristic uuid:' + char.characteristicUuid + '\n'; 122 let value = new Uint8Array(char.characteristicValue); 123 message += 'logCharacteristic value: '; 124 for (let i = 0; i < char.characteristicValue.byteLength; i++) { 125 message += value[i] + ' '; 126 } 127 console.info(TAG, message); 128 } 129 130 private logDescriptor(des: ble.BLEDescriptor) { 131 let message = 'logDescriptor uuid:' + des.descriptorUuid + '\n'; 132 let value = new Uint8Array(des.descriptorValue); 133 message += 'logDescriptor value: '; 134 for (let i = 0; i < des.descriptorValue.byteLength; i++) { 135 message += value[i] + ' '; 136 } 137 console.info(TAG, message); 138 } 139 140 private checkService(services: Array<ble.GattService>): boolean { 141 for (let i = 0; i < services.length; i++) { 142 if (services[i].serviceUuid != this.myServiceUuid) { 143 continue; 144 } 145 for (let j = 0; j < services[i].characteristics.length; j++) { 146 if (services[i].characteristics[j].characteristicUuid != this.myCharacteristicUuid) { 147 continue; 148 } 149 for (let k = 0; k < services[i].characteristics[j].descriptors.length; k++) { 150 if (services[i].characteristics[j].descriptors[k].descriptorUuid == this.myFirstDescriptorUuid) { 151 console.info(TAG, 'find expected service from server'); 152 return true; 153 } 154 } 155 } 156 } 157 console.error(TAG, 'no expected service from server'); 158 return false; 159 } 160 161 // 1. Subscribe to the connection status change event. 162 public onGattClientStateChange() { 163 if (!this.gattClient) { 164 console.error(TAG, 'no gattClient'); 165 return; 166 } 167 try { 168 this.gattClient.on('BLEConnectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { 169 let state = ''; 170 switch (stateInfo.state) { 171 case 0: 172 state = 'DISCONNECTED'; 173 break; 174 case 1: 175 state = 'CONNECTING'; 176 break; 177 case 2: 178 state = 'CONNECTED'; 179 break; 180 case 3: 181 state = 'DISCONNECTING'; 182 break; 183 default: 184 state = 'undefined'; 185 break; 186 } 187 console.info(TAG, 'onGattClientStateChange: device=' + stateInfo.deviceId + ', state=' + state); 188 if (stateInfo.deviceId == this.device) { 189 this.connectState = stateInfo.state; 190 } 191 }); 192 } catch (err) { 193 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 194 } 195 } 196 197 // 2. Called when the client proactively connects to the server. 198 public startConnect(peerDevice: string) {// The peer device is generally discovered through BLE scan. 199 if (this.connectState != constant.ProfileConnectionState.STATE_DISCONNECTED) { 200 console.error(TAG, 'startConnect failed'); 201 return; 202 } 203 console.info(TAG, 'startConnect ' + peerDevice); 204 this.device = peerDevice; 205 // 2.1 Use device to construct gattClient. This instance is used for subsequent interactions. 206 this.gattClient = ble.createGattClientDevice(peerDevice); 207 try { 208 this.onGattClientStateChange(); // 2.2 Subscribe to the connection status. 209 this.gattClient.connect(); // 2.3 Initiate a connection. 210 } catch (err) { 211 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 212 } 213 } 214 215 // 3. After the client is connected, start service discovery. 216 public discoverServices() { 217 if (!this.gattClient) { 218 console.info(TAG, 'no gattClient'); 219 return; 220 } 221 console.info(TAG, 'discoverServices'); 222 try { 223 this.gattClient.getServices().then((result: Array<ble.GattService>) => { 224 console.info(TAG, 'getServices success: ' + JSON.stringify(result)); 225 this.found = this.checkService(result); // Ensure that the service required exists on the server. 226 }); 227 } catch (err) { 228 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 229 } 230 } 231 232 // 4. Read a specific characteristic after obtaining the services on the server. 233 public readCharacteristicValue() { 234 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 235 console.error(TAG, 'no gattClient or not connected'); 236 return; 237 } 238 if (!this.found) {// Ensure that the server has the corresponding characteristic. 239 console.error(TAG, 'no characteristic from server'); 240 return; 241 } 242 243 let characteristic = this.initCharacteristic(); 244 console.info(TAG, 'readCharacteristicValue'); 245 try { 246 this.gattClient.readCharacteristicValue(characteristic).then((outData: ble.BLECharacteristic) => { 247 this.logCharacteristic(outData); 248 }) 249 } catch (err) { 250 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 251 } 252 } 253 254 // 5. Write a characteristic value after obtaining the services on the server. 255 public writeCharacteristicValue() { 256 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 257 console.error(TAG, 'no gattClient or not connected'); 258 return; 259 } 260 if (!this.found) {// Ensure that the server has the corresponding characteristic. 261 console.error(TAG, 'no characteristic from server'); 262 return; 263 } 264 265 let characteristic = this.initCharacteristic(); 266 console.info(TAG, 'writeCharacteristicValue'); 267 try { 268 this.gattClient.writeCharacteristicValue(characteristic, ble.GattWriteType.WRITE, (err) => { 269 if (err) { 270 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 271 return; 272 } 273 console.info(TAG, 'writeCharacteristicValue success'); 274 }); 275 } catch (err) { 276 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 277 } 278 } 279 280 // 6. Read a specific service descriptor after obtaining the services on the server. 281 public readDescriptorValue() { 282 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 283 console.error(TAG, 'no gattClient or not connected'); 284 return; 285 } 286 if (!this.found) {// Ensure that the server has the corresponding descriptor. 287 console.error(TAG, 'no descriptor from server'); 288 return; 289 } 290 291 let descBuffer = new ArrayBuffer(0); 292 let descriptor = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 293 console.info(TAG, 'readDescriptorValue'); 294 try { 295 this.gattClient.readDescriptorValue(descriptor).then((outData: ble.BLEDescriptor) => { 296 this.logDescriptor(outData); 297 }); 298 } catch (err) { 299 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 300 } 301 } 302 303 // 7. Write a service descriptor after obtaining the services on the server. 304 public writeDescriptorValue() { 305 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 306 console.error(TAG, 'no gattClient or not connected'); 307 return; 308 } 309 if (!this.found) {// Ensure that the server has the corresponding descriptor. 310 console.error(TAG, 'no descriptor from server'); 311 return; 312 } 313 314 let descBuffer = new ArrayBuffer(2); 315 let descValue = new Uint8Array(descBuffer); 316 descValue[0] = 11; 317 descValue[1] = 12; 318 let descriptor = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 319 console.info(TAG, 'writeDescriptorValue'); 320 try { 321 this.gattClient.writeDescriptorValue(descriptor, (err) => { 322 if (err) { 323 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 324 return; 325 } 326 console.info(TAG, 'writeDescriptorValue success'); 327 }); 328 } catch (err) { 329 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 330 } 331 } 332 333 // 8. The client proactively disconnects from the server. 334 public stopConnect() { 335 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 336 console.error(TAG, 'no gattClient or not connected'); 337 return; 338 } 339 340 console.info(TAG, 'stopConnect ' + this.device); 341 try { 342 this.gattClient.disconnect (); // 8.1 Disconnect from the server. 343 this.gattClient.off('BLEConnectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { 344 }); 345 this.gattClient.close () // 8.2 Close this gattClient if it is no longer required. 346 } catch (err) { 347 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 348 } 349 } 350 } 351 352 let gattClientManager = new GattClientManager(); 353 export default gattClientManager as GattClientManager; 354 ``` 355 3569. For details about the error codes, see [Bluetooth Error Codes](../../reference/apis-connectivity-kit/errorcode-bluetoothManager.md). 357 358 359### Managing Services on the Server and Notifying the Client 3601. Import the **ble** module. 3612. Enable Bluetooth. 3623. Apply for the **ohos.permission.ACCESS_BLUETOOTH** permission. 3634. Create a **gattServer** object. 3645. Add services. 3656. Notify the client after a characteristic is written to the server. 3667. Remove services. 3678. Close the gattServer instance. 3689. Example: 369 370 ```ts 371 import { ble } from '@kit.ConnectivityKit'; 372 import { constant } from '@kit.ConnectivityKit'; 373 import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit'; 374 375 const TAG: string = 'GattServerManager'; 376 377 export class GattServerManager { 378 gattServer: ble.GattServer | undefined = undefined; 379 connectState: ble.ProfileConnectionState = constant.ProfileConnectionState.STATE_DISCONNECTED; 380 myServiceUuid: string = '00001810-0000-1000-8000-00805F9B34FB'; 381 myCharacteristicUuid: string = '00001820-0000-1000-8000-00805F9B34FB'; 382 myFirstDescriptorUuid: string = '00002902-0000-1000-8000-00805F9B34FB'; // 2902 is generally used for notification or indication. 383 mySecondDescriptorUuid: string = '00002903-0000-1000-8000-00805F9B34FB'; 384 385 // Construct BLEDescriptor. 386 private initDescriptor(des: string, value: ArrayBuffer): ble.BLEDescriptor { 387 let descriptor: ble.BLEDescriptor = { 388 serviceUuid: this.myServiceUuid, 389 characteristicUuid: this.myCharacteristicUuid, 390 descriptorUuid: des, 391 descriptorValue: value 392 }; 393 return descriptor; 394 } 395 396 // Construct BLECharacteristic. 397 private initCharacteristic(): ble.BLECharacteristic { 398 let descriptors: Array<ble.BLEDescriptor> = []; 399 let descBuffer = new ArrayBuffer(2); 400 let descValue = new Uint8Array(descBuffer); 401 descValue[0] = 31; 402 descValue[1] = 32; 403 descriptors[0] = this.initDescriptor(this.myFirstDescriptorUuid, new ArrayBuffer(2)); 404 descriptors[1] = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 405 let charBuffer = new ArrayBuffer(2); 406 let charValue = new Uint8Array(charBuffer); 407 charValue[0] = 21; 408 charValue[1] = 22; 409 let characteristic: ble.BLECharacteristic = { 410 serviceUuid: this.myServiceUuid, 411 characteristicUuid: this.myCharacteristicUuid, 412 characteristicValue: charBuffer, 413 descriptors: descriptors 414 }; 415 return characteristic; 416 } 417 418 // 1. Subscribe to the connection status change event. 419 public onGattServerStateChange() { 420 if (!this.gattServer) { 421 console.error(TAG, 'no gattServer'); 422 return; 423 } 424 try { 425 this.gattServer.on('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { 426 let state = ''; 427 switch (stateInfo.state) { 428 case 0: 429 state = 'DISCONNECTED'; 430 break; 431 case 1: 432 state = 'CONNECTING'; 433 break; 434 case 2: 435 state = 'CONNECTED'; 436 break; 437 case 3: 438 state = 'DISCONNECTING'; 439 break; 440 default: 441 state = 'undefined'; 442 break; 443 } 444 console.info(TAG, 'onGattServerStateChange: device=' + stateInfo.deviceId + ', state=' + state); 445 }); 446 } catch (err) { 447 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 448 } 449 } 450 451 // 2. Register a service with the server. 452 public registerServer() { 453 let characteristics: Array<ble.BLECharacteristic> = []; 454 let characteristic = this.initCharacteristic(); 455 characteristics.push(characteristic); 456 let gattService: ble.GattService = { 457 serviceUuid: this.myServiceUuid, 458 isPrimary: true, 459 characteristics: characteristics 460 }; 461 462 console.info(TAG, 'registerServer ' + this.myServiceUuid); 463 try { 464 The this.gattServer = ble.createGattServer(); // 2.1 Create a gattServer instance, which is used in subsequent interactions. 465 this.onGattServerStateChange(); // 2.2 Subscribe to the connection status. 466 this.gattServer.addService(gattService); 467 } catch (err) { 468 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 469 } 470 } 471 472 // 3. Subscribe to the characteristic read requests from the gattClient. 473 public onCharacteristicRead() { 474 if (!this.gattServer) { 475 console.error(TAG, 'no gattServer'); 476 return; 477 } 478 479 console.info(TAG, 'onCharacteristicRead'); 480 try { 481 this.gattServer.on('characteristicRead', (charReq: ble.CharacteristicReadRequest) => { 482 let deviceId: string = charReq.deviceId; 483 let transId: number = charReq.transId; 484 let offset: number = charReq.offset; 485 console.info(TAG, 'receive characteristicRead'); 486 let rspBuffer = new ArrayBuffer(2); 487 let rspValue = new Uint8Array(rspBuffer); 488 rspValue[0] = 21; 489 rspValue[1] = 22; 490 let serverResponse: ble.ServerResponse = { 491 deviceId: deviceId, 492 transId: transId, 493 status: 0, // The value 0 indicates the operation is successful. 494 offset: offset, 495 value: rspBuffer 496 }; 497 498 try { 499 this.gattServer.sendResponse(serverResponse); 500 } catch (err) { 501 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 502 } 503 }); 504 } catch (err) { 505 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 506 } 507 } 508 509 // 4. Subscribe to the characteristic write requests from the gattClient. 510 public onCharacteristicWrite() { 511 if (!this.gattServer) { 512 console.error(TAG, 'no gattServer'); 513 return; 514 } 515 516 console.info(TAG, 'onCharacteristicWrite'); 517 try { 518 this.gattServer.on('characteristicWrite', (charReq: ble.CharacteristicWriteRequest) => { 519 let deviceId: string = charReq.deviceId; 520 let transId: number = charReq.transId; 521 let offset: number = charReq.offset; 522 console.info(TAG, 'receive characteristicWrite: needRsp=' + charReq.needRsp); 523 if (!charReq.needRsp) { 524 return; 525 } 526 let rspBuffer = new ArrayBuffer(0); 527 let serverResponse: ble.ServerResponse = { 528 deviceId: deviceId, 529 transId: transId, 530 status: 0, // The value 0 indicates the operation is successful. 531 offset: offset, 532 value: rspBuffer 533 }; 534 535 try { 536 this.gattServer.sendResponse(serverResponse); 537 } catch (err) { 538 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 539 } 540 }); 541 } catch (err) { 542 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 543 } 544 } 545 546 // 5. Subscribe to the descriptor read requests from the gattClient. 547 public onDescriptorRead() { 548 if (!this.gattServer) { 549 console.error(TAG, 'no gattServer'); 550 return; 551 } 552 553 console.info(TAG, 'onDescriptorRead'); 554 try { 555 this.gattServer.on('descriptorRead', (desReq: ble.DescriptorReadRequest) => { 556 let deviceId: string = desReq.deviceId; 557 let transId: number = desReq.transId; 558 let offset: number = desReq.offset; 559 console.info(TAG, 'receive descriptorRead'); 560 let rspBuffer = new ArrayBuffer(2); 561 let rspValue = new Uint8Array(rspBuffer); 562 rspValue[0] = 31; 563 rspValue[1] = 32; 564 let serverResponse: ble.ServerResponse = { 565 deviceId: deviceId, 566 transId: transId, 567 status: 0, // The value 0 indicates the operation is successful. 568 offset: offset, 569 value: rspBuffer 570 }; 571 572 try { 573 this.gattServer.sendResponse(serverResponse); 574 } catch (err) { 575 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 576 } 577 }); 578 } catch (err) { 579 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 580 } 581 } 582 583 // 6. Subscribe to the descriptor write requests from the gattClient. 584 public onDescriptorWrite() { 585 if (!this.gattServer) { 586 console.error(TAG, 'no gattServer'); 587 return; 588 } 589 590 console.info(TAG, 'onDescriptorWrite'); 591 try { 592 this.gattServer.on('descriptorWrite', (desReq: ble.DescriptorWriteRequest) => { 593 let deviceId: string = desReq.deviceId; 594 let transId: number = desReq.transId; 595 let offset: number = desReq.offset; 596 console.info(TAG, 'receive descriptorWrite: needRsp=' + desReq.needRsp); 597 if (!desReq.needRsp) { 598 return; 599 } 600 let rspBuffer = new ArrayBuffer(0); 601 let serverResponse: ble.ServerResponse = { 602 deviceId: deviceId, 603 transId: transId, 604 status: 0, // The value 0 indicates the operation is successful. 605 offset: offset, 606 value: rspBuffer 607 }; 608 609 try { 610 this.gattServer.sendResponse(serverResponse); 611 } catch (err) { 612 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 613 } 614 }); 615 } catch (err) { 616 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 617 } 618 } 619 620 // 7. Unregister the service that is not required from the server. 621 public unRegisterServer() { 622 if (!this.gattServer) { 623 console.error(TAG, 'no gattServer'); 624 return; 625 } 626 627 console.info(TAG, 'unRegisterServer ' + this.myServiceUuid); 628 try { 629 this.gattServer.removeService (this.myServiceUuid); // 7.1 Remove the service. 630 this.gattServer.off('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { // 7.2 Unsubscribe from the connection state changes. 631 }); 632 this.gattServer.close() // 7.3 Close the gattServer if it is no longer required. 633 } catch (err) { 634 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 635 } 636 } 637 } 638 639 let gattServerManager = new GattServerManager(); 640 export default gattServerManager as GattServerManager; 641 ``` 642 6438. For details about the error codes, see [Bluetooth Error Codes](../../reference/apis-connectivity-kit/errorcode-bluetoothManager.md). 644