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. 开启蓝牙。 623. 需要申请权限ohos.permission.ACCESS_BLUETOOTH。 634. 创建gattClient实例对象。 645. 连接gattServer。 656. 读取gattServer的特征值和描述符。 667. 向gattServer写入特征值和描述符。 678. 断开连接,销毁gattClient实例。 689. 示例代码: 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一般用于notification或者indication 84 mySecondDescriptorUuid: string = '00002903-0000-1000-8000-00805F9B34FB'; 85 found: boolean = false; 86 87 // 构造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 // 构造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. 订阅连接状态变化事件 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. client端主动连接时调用 198 public startConnect(peerDevice: string) { // 对端设备一般通过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 使用device构造gattClient,后续的交互都需要使用该实例 206 this.gattClient = ble.createGattClientDevice(peerDevice); 207 try { 208 this.onGattClientStateChange(); // 2.2 订阅连接状态 209 this.gattClient.connect(); // 2.3 发起连接 210 } catch (err) { 211 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 212 } 213 } 214 215 // 3. client端连接成功后,需要进行服务发现 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); // 要确保server端的服务内容有业务所需要的服务 226 }); 227 } catch (err) { 228 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 229 } 230 } 231 232 // 4. 在确保拿到了server端的服务结果后,读取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) { // 要确保server端有对应的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. 在确保拿到了server端的服务结果后,写入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) { // 要确保server端有对应的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. 在确保拿到了server端的服务结果后,读取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) { // 要确保server端有对应的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. 在确保拿到了server端的服务结果后,写入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) { // 要确保server端有对应的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.client端主动断开时调用 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 断开连接 343 this.gattClient.off('BLEConnectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { 344 }); 345 this.gattClient.close() // 8.2 如果不再使用此gattClient,则需要close 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. 错误码请参见[蓝牙服务子系统错误码](../../reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。 357 358 359### server端操作services和通知客户端信息 3601. import需要的ble模块。 3612. 开启蓝牙。 3623. 需要申请权限ohos.permission.ACCESS_BLUETOOTH。 3634. 创建gattServer实例对象。 3645. 添加services信息。 3656. 当向gattServer写入特征值通知gattClient。 3667. 移除services信息。 3678. 注销gattServer实例。 3689. 示例代码: 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一般用于notification或者indication 383 mySecondDescriptorUuid: string = '00002903-0000-1000-8000-00805F9B34FB'; 384 385 // 构造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 // 构造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. 订阅连接状态变化事件 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. 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 this.gattServer = ble.createGattServer(); // 2.1 构造gattServer,后续的交互都需要使用该实例 465 this.onGattServerStateChange(); // 2.2 订阅连接状态 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. 订阅来自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, // 0表示成功 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. 订阅来自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, // 0表示成功 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. 订阅来自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, // 0表示成功 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. 订阅来自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, // 0表示成功 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. 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 删除服务 630 this.gattServer.off('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { // 7.2 取消订阅连接状态 631 }); 632 this.gattServer.close() // 7.3 如果不再使用此gattServer,则需要close 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. 错误码请参见[蓝牙服务子系统错误码](../../reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。