• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_BLUETOOTH634. 创建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_BLUETOOTH3634. 创建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)。