1# GATT Development 2 3## Introduction 4Generic Attribute Profile (GATT) provides profile discovery and description services for BLE protocol. It defines how ATT attributes are organized and exchanged over a BLE connection. 5 6A 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. 7 8## When to Use 9 10You can use the APIs provided by the **gatt** module to: 11- Connect to the server to read and write data. 12- Manage services on the server and respond to the requests from the client. 13 14## Available APIs 15 16For details about the APIs and sample code, see [@ohos.bluetooth.ble](../../reference/apis-connectivity-kit/js-apis-bluetooth-ble.md). 17 18The following table describes the related APIs. 19 20| API | Description | 21| ------------------------------------------ | ------------------------------------------------------------------------------------------------------ | 22| connect() | Connects the client to the remote BLE device. | 23| disconnect() | Disconnects the client from the remote BLE device. | 24| close() | Closes this client to unregister it from the protocol stack. After this API is called, this **GattClientDevice** instance cannot be used any longer.| 25| getDeviceName() | Obtains the name of the remote BLE device for the client. | 26| getServices() | Obtains all services of the remote BLE device for the client. | 27| readCharacteristicValue() | Reads a characteristic value of a service of the remote BLE device. | 28| readDescriptorValue() | Reads the descriptor contained in a characteristic of the remote BLE device. | 29| writeCharacteristicValue() | Writes a characteristic value to the remote BLE device. | 30| writeDescriptorValue() | Writes binary data to a descriptor of the remote BLE device. | 31| 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()**.| 32| 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()**.| 33| setCharacteristicChangeNotification() | Sets the characteristic change notification. The client will be notified when the characteristic value of the remote BLE device changes. | 34| setCharacteristicChangeIndication() | Sets the characteristic change indication. The client will be indicated when the characteristic value of the remote BLE device changes. | 35| 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. | 36| off(type: 'BLECharacteristicChange') | Unsubscribes from the BLE characteristic changes. | 37| on(type: 'BLEConnectionStateChange') | Subscribes to the BLE connection state changes for the client. | 38| off(type: 'BLEConnectionStateChange') | Unsubscribes from the BLE connection state changes for the client. | 39| on(type: 'BLEMtuChange') | Subscribes to MTU status changes for the client. | 40| off(type: 'BLEMtuChange') | Unsubscribes from MTU status changes for the client. | 41| addService() | Adds a service to this server. | 42| removeService() | Removes a service from this server. | 43| close() | Closes this server to unregister it from the protocol stack. After this API is called, the **GattServer** instance cannot be used any longer. | 44| notifyCharacteristicChanged() | Notifies a connected client device when a characteristic value changes. | 45| sendResponse() | Sends a response to a read or write request from the client. | 46| on(type: 'characteristicRead') | Subscribes to the characteristic read request event for the server. | 47| off(type: 'characteristicRead') | Unsubscribes from the characteristic read request event for the server. | 48| on(type: 'characteristicWrite') | Subscribes to the characteristic write request event for the server. | 49| off(type: 'characteristicWrite') | Unsubscribes from the characteristic write request event for the server. | 50| on(type: 'descriptorRead') | Subscribes to the descriptor read request event for the server. | 51| off(type: 'descriptorRead') | Unsubscribes from the descriptor read request event for the server. | 52| on(type: 'descriptorWrite') | Subscribes to the descriptor write request event for the server. | 53| off(type: 'descriptorWrite') | Unsubscribes from the descriptor write request event for the server. | 54| on(type: 'connectionStateChange') | Subscribes to the BLE connection state changes for the server. | 55| off(type: 'connectionStateChange') | Unsubscribes from the BLE connection state changes for the server. | 56| on(type: 'BLEMtuChange') | Subscribes to MTU status changes for the server. | 57| off(type: 'BLEMtuChange') | Unsubscribes from MTU status changes for the server. | 58 59## How to Develop 60 61### Reading and Writing Data on the Server 621. Import the **ble** module. 632. Create a **gattClient** instance. 643. Connect to the server. 654. Read characteristics and descriptors from the server. 665. Write characteristics and descriptors to the server. 676. Disconnect from the server and destroy the **gattClient** instance. 68Example: 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 356For 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. Create a **gattServer** object. 3623. Add services. 3634. Notify the client after a characteristic is written to the server. 3645. Remove services. 3656. Close the gattServer instance. 366Example: 367 368 ```ts 369 import { ble } from '@kit.ConnectivityKit'; 370 import { constant } from '@kit.ConnectivityKit'; 371 import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit'; 372 373 const TAG: string = 'GattServerManager'; 374 375 export class GattServerManager { 376 gattServer: ble.GattServer | undefined = undefined; 377 connectState: ble.ProfileConnectionState = constant.ProfileConnectionState.STATE_DISCONNECTED; 378 myServiceUuid: string = '00001810-0000-1000-8000-00805F9B34FB'; 379 myCharacteristicUuid: string = '00001820-0000-1000-8000-00805F9B34FB'; 380 myFirstDescriptorUuid: string = '00002902-0000-1000-8000-00805F9B34FB'; // 2902 is generally used for notification or indication. 381 mySecondDescriptorUuid: string = '00002903-0000-1000-8000-00805F9B34FB'; 382 383 // Construct BLEDescriptor. 384 private initDescriptor(des: string, value: ArrayBuffer): ble.BLEDescriptor { 385 let descriptor: ble.BLEDescriptor = { 386 serviceUuid: this.myServiceUuid, 387 characteristicUuid: this.myCharacteristicUuid, 388 descriptorUuid: des, 389 descriptorValue: value 390 }; 391 return descriptor; 392 } 393 394 // Construct BLECharacteristic. 395 private initCharacteristic(): ble.BLECharacteristic { 396 let descriptors: Array<ble.BLEDescriptor> = []; 397 let descBuffer = new ArrayBuffer(2); 398 let descValue = new Uint8Array(descBuffer); 399 descValue[0] = 31; 400 descValue[1] = 32; 401 descriptors[0] = this.initDescriptor(this.myFirstDescriptorUuid, new ArrayBuffer(2)); 402 descriptors[1] = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 403 let charBuffer = new ArrayBuffer(2); 404 let charValue = new Uint8Array(charBuffer); 405 charValue[0] = 21; 406 charValue[1] = 22; 407 let characteristic: ble.BLECharacteristic = { 408 serviceUuid: this.myServiceUuid, 409 characteristicUuid: this.myCharacteristicUuid, 410 characteristicValue: charBuffer, 411 descriptors: descriptors 412 }; 413 return characteristic; 414 } 415 416 // 1. Subscribe to the connection status change event. 417 public onGattServerStateChange() { 418 if (!this.gattServer) { 419 console.error(TAG, 'no gattServer'); 420 return; 421 } 422 try { 423 this.gattServer.on('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { 424 let state = ''; 425 switch (stateInfo.state) { 426 case 0: 427 state = 'DISCONNECTED'; 428 break; 429 case 1: 430 state = 'CONNECTING'; 431 break; 432 case 2: 433 state = 'CONNECTED'; 434 break; 435 case 3: 436 state = 'DISCONNECTING'; 437 break; 438 default: 439 state = 'undefined'; 440 break; 441 } 442 console.info(TAG, 'onGattServerStateChange: device=' + stateInfo.deviceId + ', state=' + state); 443 }); 444 } catch (err) { 445 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 446 } 447 } 448 449 // 2. Register a service with the server. 450 public registerServer() { 451 let characteristics: Array<ble.BLECharacteristic> = []; 452 let characteristic = this.initCharacteristic(); 453 characteristics.push(characteristic); 454 let gattService: ble.GattService = { 455 serviceUuid: this.myServiceUuid, 456 isPrimary: true, 457 characteristics: characteristics 458 }; 459 460 console.info(TAG, 'registerServer ' + this.myServiceUuid); 461 try { 462 The this.gattServer = ble.createGattServer(); // 2.1 Create a gattServer instance, which is used in subsequent interactions. 463 this.onGattServerStateChange(); // 2.2 Subscribe to the connection status. 464 this.gattServer.addService(gattService); 465 } catch (err) { 466 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 467 } 468 } 469 470 // 3. Subscribe to the characteristic read requests from the gattClient. 471 public onCharacteristicRead() { 472 if (!this.gattServer) { 473 console.error(TAG, 'no gattServer'); 474 return; 475 } 476 477 console.info(TAG, 'onCharacteristicRead'); 478 try { 479 this.gattServer.on('characteristicRead', (charReq: ble.CharacteristicReadRequest) => { 480 let deviceId: string = charReq.deviceId; 481 let transId: number = charReq.transId; 482 let offset: number = charReq.offset; 483 console.info(TAG, 'receive characteristicRead'); 484 let rspBuffer = new ArrayBuffer(2); 485 let rspValue = new Uint8Array(rspBuffer); 486 rspValue[0] = 21; 487 rspValue[1] = 22; 488 let serverResponse: ble.ServerResponse = { 489 deviceId: deviceId, 490 transId: transId, 491 status: 0, // The value 0 indicates the operation is successful. 492 offset: offset, 493 value: rspBuffer 494 }; 495 496 try { 497 this.gattServer.sendResponse(serverResponse); 498 } catch (err) { 499 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 500 } 501 }); 502 } catch (err) { 503 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 504 } 505 } 506 507 // 4. Subscribe to the characteristic write requests from the gattClient. 508 public onCharacteristicWrite() { 509 if (!this.gattServer) { 510 console.error(TAG, 'no gattServer'); 511 return; 512 } 513 514 console.info(TAG, 'onCharacteristicWrite'); 515 try { 516 this.gattServer.on('characteristicWrite', (charReq: ble.CharacteristicWriteRequest) => { 517 let deviceId: string = charReq.deviceId; 518 let transId: number = charReq.transId; 519 let offset: number = charReq.offset; 520 console.info(TAG, 'receive characteristicWrite: needRsp=' + charReq.needRsp); 521 if (!charReq.needRsp) { 522 return; 523 } 524 let rspBuffer = new ArrayBuffer(0); 525 let serverResponse: ble.ServerResponse = { 526 deviceId: deviceId, 527 transId: transId, 528 status: 0, // The value 0 indicates the operation is successful. 529 offset: offset, 530 value: rspBuffer 531 }; 532 533 try { 534 this.gattServer.sendResponse(serverResponse); 535 } catch (err) { 536 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 537 } 538 }); 539 } catch (err) { 540 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 541 } 542 } 543 544 // 5. Subscribe to the descriptor read requests from the gattClient. 545 public onDescriptorRead() { 546 if (!this.gattServer) { 547 console.error(TAG, 'no gattServer'); 548 return; 549 } 550 551 console.info(TAG, 'onDescriptorRead'); 552 try { 553 this.gattServer.on('descriptorRead', (desReq: ble.DescriptorReadRequest) => { 554 let deviceId: string = desReq.deviceId; 555 let transId: number = desReq.transId; 556 let offset: number = desReq.offset; 557 console.info(TAG, 'receive descriptorRead'); 558 let rspBuffer = new ArrayBuffer(2); 559 let rspValue = new Uint8Array(rspBuffer); 560 rspValue[0] = 31; 561 rspValue[1] = 32; 562 let serverResponse: ble.ServerResponse = { 563 deviceId: deviceId, 564 transId: transId, 565 status: 0, // The value 0 indicates the operation is successful. 566 offset: offset, 567 value: rspBuffer 568 }; 569 570 try { 571 this.gattServer.sendResponse(serverResponse); 572 } catch (err) { 573 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 574 } 575 }); 576 } catch (err) { 577 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 578 } 579 } 580 581 // 6. Subscribe to the descriptor write requests from the gattClient. 582 public onDescriptorWrite() { 583 if (!this.gattServer) { 584 console.error(TAG, 'no gattServer'); 585 return; 586 } 587 588 console.info(TAG, 'onDescriptorWrite'); 589 try { 590 this.gattServer.on('descriptorWrite', (desReq: ble.DescriptorWriteRequest) => { 591 let deviceId: string = desReq.deviceId; 592 let transId: number = desReq.transId; 593 let offset: number = desReq.offset; 594 console.info(TAG, 'receive descriptorWrite: needRsp=' + desReq.needRsp); 595 if (!desReq.needRsp) { 596 return; 597 } 598 let rspBuffer = new ArrayBuffer(0); 599 let serverResponse: ble.ServerResponse = { 600 deviceId: deviceId, 601 transId: transId, 602 status: 0, // The value 0 indicates the operation is successful. 603 offset: offset, 604 value: rspBuffer 605 }; 606 607 try { 608 this.gattServer.sendResponse(serverResponse); 609 } catch (err) { 610 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 611 } 612 }); 613 } catch (err) { 614 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 615 } 616 } 617 618 // 7. Unregister the service that is not required from the server. 619 public unRegisterServer() { 620 if (!this.gattServer) { 621 console.error(TAG, 'no gattServer'); 622 return; 623 } 624 625 console.info(TAG, 'unRegisterServer ' + this.myServiceUuid); 626 try { 627 this.gattServer.removeService (this.myServiceUuid); // 7.1 Remove the service. 628 this.gattServer.off('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { // 7.2 Unsubscribe from the connection state changes. 629 }); 630 this.gattServer.close() // 7.3 Close the gattServer if it is no longer required. 631 } catch (err) { 632 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 633 } 634 } 635 } 636 637 let gattServerManager = new GattServerManager(); 638 export default gattServerManager as GattServerManager; 639 ``` 640 641For details about the error codes, see [Bluetooth Error Codes](../../reference/apis-connectivity-kit/errorcode-bluetoothManager.md). 642