1# 通用属性协议开发指导 2 3## 简介 4通用属性协议是GATT(Generic Attribute)的缩写,它是一种用于在蓝牙低功耗设备之间传输数据的协议,定义了一套通用的属性和服务框架。通过GATT协议,蓝牙设备可以向其他设备提供服务,也可以从其他设备获取服务。 5 6## 场景介绍 7 8主要场景有: 9- 连接server端读取和写入信息。 10- server端操作services和通知客户端信息。 11 12## 接口说明 13 14完整的 JS API 说明以及实例代码请参考:[GATT 接口](../../reference/apis-connectivity-kit/js-apis-bluetooth-ble.md)。 15 16具体接口说明如下表。 17 18| 接口名 | 功能描述 | 19| ------------------------------------------ | ------------------------------------------------------------------------------------------------------ | 20| connect() | client端发起连接远端蓝牙低功耗设备。 | 21| disconnect() | client端断开与远端蓝牙低功耗设备的连接。 | 22| close() | 关闭客户端功能,注销client在协议栈的注册,调用该接口后GattClientDevice实例将不能再使用。| 23| getDeviceName() | client获取远端蓝牙低功耗设备名。 | 24| getServices() | client端获取蓝牙低功耗设备的所有服务,即服务发现 。 | 25| readCharacteristicValue() | client端读取蓝牙低功耗设备特定服务的特征值。 | 26| readDescriptorValue() | client端读取蓝牙低功耗设备特定的特征包含的描述符。 | 27| writeCharacteristicValue() | client端向低功耗蓝牙设备写入特定的特征值。 | 28| writeDescriptorValue() | client端向低功耗蓝牙设备特定的描述符写入二进制数据。 | 29| getRssiValue() | client获取远端蓝牙低功耗设备的信号强度 (Received Signal Strength Indication, RSSI),调用connect接口连接成功后才能使用。| 30| setBLEMtuSize() | client协商远端蓝牙低功耗设备的最大传输单元(Maximum Transmission Unit, MTU),调用connect接口连接成功后才能使用。| 31| setCharacteristicChangeNotification() | 向服务端发送设置通知此特征值请求。 | 32| setCharacteristicChangeIndication() | 向服务端发送设置通知此特征值请求。 | 33| on(type: 'BLECharacteristicChange') | 订阅蓝牙低功耗设备的特征值变化事件。需要先调用setNotifyCharacteristicChanged接口才能接收server端的通知。 | 34| off(type: 'BLECharacteristicChange') | 取消订阅蓝牙低功耗设备的特征值变化事件。 | 35| on(type: 'BLEConnectionStateChange') | client端订阅蓝牙低功耗设备的连接状态变化事件。 | 36| off(type: 'BLEConnectionStateChange') | 取消订阅蓝牙低功耗设备的连接状态变化事件。 | 37| on(type: 'BLEMtuChange') | client端订阅MTU状态变化事件。 | 38| off(type: 'BLEMtuChange') | client端取消订阅MTU状态变化事件。 | 39| addService() | server端添加服务。 | 40| removeService() | 删除已添加的服务。 | 41| close() | 关闭服务端功能,去注销server在协议栈的注册,调用该接口后GattServer实例将不能再使用。 | 42| notifyCharacteristicChanged() | server端特征值发生变化时,主动通知已连接的client设备。 | 43| sendResponse() | server端回复client端的读写请求。 | 44| on(type: 'characteristicRead') | server端订阅特征值读请求事件。 | 45| off(type: 'characteristicRead') | server端取消订阅特征值读请求事件。 | 46| on(type: 'characteristicWrite') | server端订阅特征值写请求事件。 | 47| off(type: 'characteristicWrite') | server端取消订阅特征值写请求事件。 | 48| on(type: 'descriptorRead') | server端订阅描述符读请求事件。 | 49| off(type: 'descriptorRead') | server端取消订阅描述符读请求事件。 | 50| on(type: 'descriptorWrite') | server端订阅描述符写请求事件。 | 51| off(type: 'descriptorWrite') | server端取消订阅描述符写请求事件。 | 52| on(type: 'connectionStateChange') | server端订阅BLE连接状态变化事件。 | 53| off(type: 'connectionStateChange') | server端取消订阅BLE连接状态变化事件。 | 54| on(type: 'BLEMtuChange') | server端订阅MTU状态变化事件。 | 55| off(type: 'BLEMtuChange') | server端取消订阅MTU状态变化事件。 | 56 57## 主要场景开发步骤 58 59### 连接server端读取和写入信息 601. import需要的ble模块。 612. 创建gattClient实例对象。 623. 连接gattServer。 634. 读取gattServer的特征值和描述符。 645. 向gattServer写入特征值和描述符。 656. 断开连接,销毁gattClient实例。 667. 示例代码: 67 68 ```ts 69 import { ble } from '@kit.ConnectivityKit'; 70 import { constant } from '@kit.ConnectivityKit'; 71 import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit'; 72 73 const TAG: string = 'GattClientManager'; 74 75 export class GattClientManager { 76 device: string | undefined = undefined; 77 gattClient: ble.GattClientDevice | undefined = undefined; 78 connectState: ble.ProfileConnectionState = constant.ProfileConnectionState.STATE_DISCONNECTED; 79 myServiceUuid: string = '00001810-0000-1000-8000-00805F9B34FB'; 80 myCharacteristicUuid: string = '00001820-0000-1000-8000-00805F9B34FB'; 81 myFirstDescriptorUuid: string = '00002902-0000-1000-8000-00805F9B34FB'; // 2902一般用于notification或者indication 82 mySecondDescriptorUuid: string = '00002903-0000-1000-8000-00805F9B34FB'; 83 found: boolean = false; 84 85 // 构造BLEDescriptor 86 private initDescriptor(des: string, value: ArrayBuffer): ble.BLEDescriptor { 87 let descriptor: ble.BLEDescriptor = { 88 serviceUuid: this.myServiceUuid, 89 characteristicUuid: this.myCharacteristicUuid, 90 descriptorUuid: des, 91 descriptorValue: value 92 }; 93 return descriptor; 94 } 95 96 // 构造BLECharacteristic 97 private initCharacteristic(): ble.BLECharacteristic { 98 let descriptors: Array<ble.BLEDescriptor> = []; 99 let descBuffer = new ArrayBuffer(2); 100 let descValue = new Uint8Array(descBuffer); 101 descValue[0] = 11; 102 descValue[1] = 12; 103 descriptors[0] = this.initDescriptor(this.myFirstDescriptorUuid, new ArrayBuffer(2)); 104 descriptors[1] = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 105 let charBuffer = new ArrayBuffer(2); 106 let charValue = new Uint8Array(charBuffer); 107 charValue[0] = 1; 108 charValue[1] = 2; 109 let characteristic: ble.BLECharacteristic = { 110 serviceUuid: this.myServiceUuid, 111 characteristicUuid: this.myCharacteristicUuid, 112 characteristicValue: charBuffer, 113 descriptors: descriptors 114 }; 115 return characteristic; 116 } 117 118 private logCharacteristic(char: ble.BLECharacteristic) { 119 let message = 'logCharacteristic uuid:' + char.characteristicUuid + '\n'; 120 let value = new Uint8Array(char.characteristicValue); 121 message += 'logCharacteristic value: '; 122 for (let i = 0; i < char.characteristicValue.byteLength; i++) { 123 message += value[i] + ' '; 124 } 125 console.info(TAG, message); 126 } 127 128 private logDescriptor(des: ble.BLEDescriptor) { 129 let message = 'logDescriptor uuid:' + des.descriptorUuid + '\n'; 130 let value = new Uint8Array(des.descriptorValue); 131 message += 'logDescriptor value: '; 132 for (let i = 0; i < des.descriptorValue.byteLength; i++) { 133 message += value[i] + ' '; 134 } 135 console.info(TAG, message); 136 } 137 138 private checkService(services: Array<ble.GattService>): boolean { 139 for (let i = 0; i < services.length; i++) { 140 if (services[i].serviceUuid != this.myServiceUuid) { 141 continue; 142 } 143 for (let j = 0; j < services[i].characteristics.length; j++) { 144 if (services[i].characteristics[j].characteristicUuid != this.myCharacteristicUuid) { 145 continue; 146 } 147 for (let k = 0; k < services[i].characteristics[j].descriptors.length; k++) { 148 if (services[i].characteristics[j].descriptors[k].descriptorUuid == this.myFirstDescriptorUuid) { 149 console.info(TAG, 'find expected service from server'); 150 return true; 151 } 152 } 153 } 154 } 155 console.error(TAG, 'no expected service from server'); 156 return false; 157 } 158 159 // 1. 订阅连接状态变化事件 160 public onGattClientStateChange() { 161 if (!this.gattClient) { 162 console.error(TAG, 'no gattClient'); 163 return; 164 } 165 try { 166 this.gattClient.on('BLEConnectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { 167 let state = ''; 168 switch (stateInfo.state) { 169 case 0: 170 state = 'DISCONNECTED'; 171 break; 172 case 1: 173 state = 'CONNECTING'; 174 break; 175 case 2: 176 state = 'CONNECTED'; 177 break; 178 case 3: 179 state = 'DISCONNECTING'; 180 break; 181 default: 182 state = 'undefined'; 183 break; 184 } 185 console.info(TAG, 'onGattClientStateChange: device=' + stateInfo.deviceId + ', state=' + state); 186 if (stateInfo.deviceId == this.device) { 187 this.connectState = stateInfo.state; 188 } 189 }); 190 } catch (err) { 191 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 192 } 193 } 194 195 // 2. client端主动连接时调用 196 public startConnect(peerDevice: string) { // 对端设备一般通过ble scan获取到 197 if (this.connectState != constant.ProfileConnectionState.STATE_DISCONNECTED) { 198 console.error(TAG, 'startConnect failed'); 199 return; 200 } 201 console.info(TAG, 'startConnect ' + peerDevice); 202 this.device = peerDevice; 203 // 2.1 使用device构造gattClient,后续的交互都需要使用该实例 204 this.gattClient = ble.createGattClientDevice(peerDevice); 205 try { 206 this.onGattClientStateChange(); // 2.2 订阅连接状态 207 this.gattClient.connect(); // 2.3 发起连接 208 } catch (err) { 209 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 210 } 211 } 212 213 // 3. client端连接成功后,需要进行服务发现 214 public discoverServices() { 215 if (!this.gattClient) { 216 console.info(TAG, 'no gattClient'); 217 return; 218 } 219 console.info(TAG, 'discoverServices'); 220 try { 221 this.gattClient.getServices().then((result: Array<ble.GattService>) => { 222 console.info(TAG, 'getServices success: ' + JSON.stringify(result)); 223 this.found = this.checkService(result); // 要确保server端的服务内容有业务所需要的服务 224 }); 225 } catch (err) { 226 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 227 } 228 } 229 230 // 4. 在确保拿到了server端的服务结果后,读取server端特定服务的特征值时调用 231 public readCharacteristicValue() { 232 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 233 console.error(TAG, 'no gattClient or not connected'); 234 return; 235 } 236 if (!this.found) { // 要确保server端有对应的characteristic 237 console.error(TAG, 'no characteristic from server'); 238 return; 239 } 240 241 let characteristic = this.initCharacteristic(); 242 console.info(TAG, 'readCharacteristicValue'); 243 try { 244 this.gattClient.readCharacteristicValue(characteristic).then((outData: ble.BLECharacteristic) => { 245 this.logCharacteristic(outData); 246 }) 247 } catch (err) { 248 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 249 } 250 } 251 252 // 5. 在确保拿到了server端的服务结果后,写入server端特定服务的特征值时调用 253 public writeCharacteristicValue() { 254 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 255 console.error(TAG, 'no gattClient or not connected'); 256 return; 257 } 258 if (!this.found) { // 要确保server端有对应的characteristic 259 console.error(TAG, 'no characteristic from server'); 260 return; 261 } 262 263 let characteristic = this.initCharacteristic(); 264 console.info(TAG, 'writeCharacteristicValue'); 265 try { 266 this.gattClient.writeCharacteristicValue(characteristic, ble.GattWriteType.WRITE, (err) => { 267 if (err) { 268 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 269 return; 270 } 271 console.info(TAG, 'writeCharacteristicValue success'); 272 }); 273 } catch (err) { 274 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 275 } 276 } 277 278 // 6. 在确保拿到了server端的服务结果后,读取server端特定服务的描述符时调用 279 public readDescriptorValue() { 280 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 281 console.error(TAG, 'no gattClient or not connected'); 282 return; 283 } 284 if (!this.found) { // 要确保server端有对应的descriptor 285 console.error(TAG, 'no descriptor from server'); 286 return; 287 } 288 289 let descBuffer = new ArrayBuffer(0); 290 let descriptor = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 291 console.info(TAG, 'readDescriptorValue'); 292 try { 293 this.gattClient.readDescriptorValue(descriptor).then((outData: ble.BLEDescriptor) => { 294 this.logDescriptor(outData); 295 }); 296 } catch (err) { 297 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 298 } 299 } 300 301 // 7. 在确保拿到了server端的服务结果后,写入server端特定服务的描述符时调用 302 public writeDescriptorValue() { 303 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 304 console.error(TAG, 'no gattClient or not connected'); 305 return; 306 } 307 if (!this.found) { // 要确保server端有对应的descriptor 308 console.error(TAG, 'no descriptor from server'); 309 return; 310 } 311 312 let descBuffer = new ArrayBuffer(2); 313 let descValue = new Uint8Array(descBuffer); 314 descValue[0] = 11; 315 descValue[1] = 12; 316 let descriptor = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 317 console.info(TAG, 'writeDescriptorValue'); 318 try { 319 this.gattClient.writeDescriptorValue(descriptor, (err) => { 320 if (err) { 321 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 322 return; 323 } 324 console.info(TAG, 'writeDescriptorValue success'); 325 }); 326 } catch (err) { 327 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 328 } 329 } 330 331 // 8.client端主动断开时调用 332 public stopConnect() { 333 if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { 334 console.error(TAG, 'no gattClient or not connected'); 335 return; 336 } 337 338 console.info(TAG, 'stopConnect ' + this.device); 339 try { 340 this.gattClient.disconnect(); // 8.1 断开连接 341 this.gattClient.off('BLEConnectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { 342 }); 343 this.gattClient.close() // 8.2 如果不再使用此gattClient,则需要close 344 } catch (err) { 345 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 346 } 347 } 348 } 349 350 let gattClientManager = new GattClientManager(); 351 export default gattClientManager as GattClientManager; 352 ``` 353 3549. 错误码请参见[蓝牙服务子系统错误码](../../reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。 355 356 357### server端操作services和通知客户端信息 3581. import需要的ble模块。 3592. 创建gattServer实例对象。 3603. 添加services信息。 3614. 当向gattServer写入特征值通知gattClient。 3625. 移除services信息。 3636. 注销gattServer实例。 3647. 示例代码: 365 366 ```ts 367 import { ble } from '@kit.ConnectivityKit'; 368 import { constant } from '@kit.ConnectivityKit'; 369 import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit'; 370 371 const TAG: string = 'GattServerManager'; 372 373 export class GattServerManager { 374 gattServer: ble.GattServer | undefined = undefined; 375 connectState: ble.ProfileConnectionState = constant.ProfileConnectionState.STATE_DISCONNECTED; 376 myServiceUuid: string = '00001810-0000-1000-8000-00805F9B34FB'; 377 myCharacteristicUuid: string = '00001820-0000-1000-8000-00805F9B34FB'; 378 myFirstDescriptorUuid: string = '00002902-0000-1000-8000-00805F9B34FB'; // 2902一般用于notification或者indication 379 mySecondDescriptorUuid: string = '00002903-0000-1000-8000-00805F9B34FB'; 380 381 // 构造BLEDescriptor 382 private initDescriptor(des: string, value: ArrayBuffer): ble.BLEDescriptor { 383 let descriptor: ble.BLEDescriptor = { 384 serviceUuid: this.myServiceUuid, 385 characteristicUuid: this.myCharacteristicUuid, 386 descriptorUuid: des, 387 descriptorValue: value 388 }; 389 return descriptor; 390 } 391 392 // 构造BLECharacteristic 393 private initCharacteristic(): ble.BLECharacteristic { 394 let descriptors: Array<ble.BLEDescriptor> = []; 395 let descBuffer = new ArrayBuffer(2); 396 let descValue = new Uint8Array(descBuffer); 397 descValue[0] = 31; 398 descValue[1] = 32; 399 descriptors[0] = this.initDescriptor(this.myFirstDescriptorUuid, new ArrayBuffer(2)); 400 descriptors[1] = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 401 let charBuffer = new ArrayBuffer(2); 402 let charValue = new Uint8Array(charBuffer); 403 charValue[0] = 21; 404 charValue[1] = 22; 405 let characteristic: ble.BLECharacteristic = { 406 serviceUuid: this.myServiceUuid, 407 characteristicUuid: this.myCharacteristicUuid, 408 characteristicValue: charBuffer, 409 descriptors: descriptors 410 }; 411 return characteristic; 412 } 413 414 // 1. 订阅连接状态变化事件 415 public onGattServerStateChange() { 416 if (!this.gattServer) { 417 console.error(TAG, 'no gattServer'); 418 return; 419 } 420 try { 421 this.gattServer.on('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { 422 let state = ''; 423 switch (stateInfo.state) { 424 case 0: 425 state = 'DISCONNECTED'; 426 break; 427 case 1: 428 state = 'CONNECTING'; 429 break; 430 case 2: 431 state = 'CONNECTED'; 432 break; 433 case 3: 434 state = 'DISCONNECTING'; 435 break; 436 default: 437 state = 'undefined'; 438 break; 439 } 440 console.info(TAG, 'onGattServerStateChange: device=' + stateInfo.deviceId + ', state=' + state); 441 }); 442 } catch (err) { 443 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 444 } 445 } 446 447 // 2. server端注册服务时调用 448 public registerServer() { 449 let characteristics: Array<ble.BLECharacteristic> = []; 450 let characteristic = this.initCharacteristic(); 451 characteristics.push(characteristic); 452 let gattService: ble.GattService = { 453 serviceUuid: this.myServiceUuid, 454 isPrimary: true, 455 characteristics: characteristics 456 }; 457 458 console.info(TAG, 'registerServer ' + this.myServiceUuid); 459 try { 460 this.gattServer = ble.createGattServer(); // 2.1 构造gattServer,后续的交互都需要使用该实例 461 this.onGattServerStateChange(); // 2.2 订阅连接状态 462 this.gattServer.addService(gattService); 463 } catch (err) { 464 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 465 } 466 } 467 468 // 3. 订阅来自gattClient的读取特征值请求时调用 469 public onCharacteristicRead() { 470 if (!this.gattServer) { 471 console.error(TAG, 'no gattServer'); 472 return; 473 } 474 475 console.info(TAG, 'onCharacteristicRead'); 476 try { 477 this.gattServer.on('characteristicRead', (charReq: ble.CharacteristicReadRequest) => { 478 let deviceId: string = charReq.deviceId; 479 let transId: number = charReq.transId; 480 let offset: number = charReq.offset; 481 console.info(TAG, 'receive characteristicRead'); 482 let rspBuffer = new ArrayBuffer(2); 483 let rspValue = new Uint8Array(rspBuffer); 484 rspValue[0] = 21; 485 rspValue[1] = 22; 486 let serverResponse: ble.ServerResponse = { 487 deviceId: deviceId, 488 transId: transId, 489 status: 0, // 0表示成功 490 offset: offset, 491 value: rspBuffer 492 }; 493 494 try { 495 this.gattServer.sendResponse(serverResponse); 496 } catch (err) { 497 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 498 } 499 }); 500 } catch (err) { 501 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 502 } 503 } 504 505 // 4. 订阅来自gattClient的写入特征值请求时调用 506 public onCharacteristicWrite() { 507 if (!this.gattServer) { 508 console.error(TAG, 'no gattServer'); 509 return; 510 } 511 512 console.info(TAG, 'onCharacteristicWrite'); 513 try { 514 this.gattServer.on('characteristicWrite', (charReq: ble.CharacteristicWriteRequest) => { 515 let deviceId: string = charReq.deviceId; 516 let transId: number = charReq.transId; 517 let offset: number = charReq.offset; 518 console.info(TAG, 'receive characteristicWrite: needRsp=' + charReq.needRsp); 519 if (!charReq.needRsp) { 520 return; 521 } 522 let rspBuffer = new ArrayBuffer(0); 523 let serverResponse: ble.ServerResponse = { 524 deviceId: deviceId, 525 transId: transId, 526 status: 0, // 0表示成功 527 offset: offset, 528 value: rspBuffer 529 }; 530 531 try { 532 this.gattServer.sendResponse(serverResponse); 533 } catch (err) { 534 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 535 } 536 }); 537 } catch (err) { 538 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 539 } 540 } 541 542 // 5. 订阅来自gattClient的读取描述符请求时调用 543 public onDescriptorRead() { 544 if (!this.gattServer) { 545 console.error(TAG, 'no gattServer'); 546 return; 547 } 548 549 console.info(TAG, 'onDescriptorRead'); 550 try { 551 this.gattServer.on('descriptorRead', (desReq: ble.DescriptorReadRequest) => { 552 let deviceId: string = desReq.deviceId; 553 let transId: number = desReq.transId; 554 let offset: number = desReq.offset; 555 console.info(TAG, 'receive descriptorRead'); 556 let rspBuffer = new ArrayBuffer(2); 557 let rspValue = new Uint8Array(rspBuffer); 558 rspValue[0] = 31; 559 rspValue[1] = 32; 560 let serverResponse: ble.ServerResponse = { 561 deviceId: deviceId, 562 transId: transId, 563 status: 0, // 0表示成功 564 offset: offset, 565 value: rspBuffer 566 }; 567 568 try { 569 this.gattServer.sendResponse(serverResponse); 570 } catch (err) { 571 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 572 } 573 }); 574 } catch (err) { 575 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 576 } 577 } 578 579 // 6. 订阅来自gattClient的写入描述符请求时调用 580 public onDescriptorWrite() { 581 if (!this.gattServer) { 582 console.error(TAG, 'no gattServer'); 583 return; 584 } 585 586 console.info(TAG, 'onDescriptorWrite'); 587 try { 588 this.gattServer.on('descriptorWrite', (desReq: ble.DescriptorWriteRequest) => { 589 let deviceId: string = desReq.deviceId; 590 let transId: number = desReq.transId; 591 let offset: number = desReq.offset; 592 console.info(TAG, 'receive descriptorWrite: needRsp=' + desReq.needRsp); 593 if (!desReq.needRsp) { 594 return; 595 } 596 let rspBuffer = new ArrayBuffer(0); 597 let serverResponse: ble.ServerResponse = { 598 deviceId: deviceId, 599 transId: transId, 600 status: 0, // 0表示成功 601 offset: offset, 602 value: rspBuffer 603 }; 604 605 try { 606 this.gattServer.sendResponse(serverResponse); 607 } catch (err) { 608 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 609 } 610 }); 611 } catch (err) { 612 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 613 } 614 } 615 616 // 7. server端删除服务,不再使用时调用 617 public unRegisterServer() { 618 if (!this.gattServer) { 619 console.error(TAG, 'no gattServer'); 620 return; 621 } 622 623 console.info(TAG, 'unRegisterServer ' + this.myServiceUuid); 624 try { 625 this.gattServer.removeService(this.myServiceUuid); // 7.1 删除服务 626 this.gattServer.off('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { // 7.2 取消订阅连接状态 627 }); 628 this.gattServer.close() // 7.3 如果不再使用此gattServer,则需要close 629 } catch (err) { 630 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 631 } 632 } 633 } 634 635 let gattServerManager = new GattServerManager(); 636 export default gattServerManager as GattServerManager; 637 ``` 638 6398. 错误码请参见[蓝牙服务子系统错误码](../../reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。