• 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. 创建gattClient实例对象。
623. 连接gattServer。
634. 获取gattServer的设备名称、services信息、信号强度。
645. 读取gattServer的特征值和描述符。
656. 向gattServer写入特征值和描述符。
667. 断开连接,销毁gattClient实例。
678. 示例代码:
68
69```ts
70import ble from '@ohos.bluetooth.ble';
71import { BusinessError } from '@ohos.base';
72
73// serverDeviceId的值,是开启ble扫描获取gattServer的deviceId的值。
74let serverDeviceId = 'xx:xx:xx:xx:xx:xx';
75
76// 创建客户端
77let clientDevice = ble.createGattClientDevice(serverDeviceId);
78
79// 连接GattServer服务
80clientDevice.connect();
81
82// 订阅连接状态改变事件
83clientDevice.on('BLEConnectionStateChange', (bleConnectionState) => {
84  let bleConnectionStateInfo = '';
85  switch (bleConnectionState.state) {
86    case 0:
87      bleConnectionStateInfo = 'DISCONNECTED';
88      break;
89    case 1:
90      bleConnectionStateInfo = 'CONNECTING';
91      break;
92    case 2:
93      bleConnectionStateInfo = 'STATE_CONNECTED';
94      break;
95    case 3:
96      bleConnectionStateInfo = 'STATE_DISCONNECTING';
97      break;
98    default:
99      bleConnectionStateInfo = 'undefined';
100      break;
101  }
102  console.info('status: ' + bleConnectionStateInfo);
103})
104
105// 获取gattServer设备名称
106clientDevice.getDeviceName((err: BusinessError, data: string) => {
107  console.info('getDeviceName success, deviceName = ' + JSON.stringify(data));
108})
109
110// 获取server的services信息
111clientDevice.getServices((code, gattServices) => {
112  let message = '';
113  if (code != null) {
114    console.error('getServices error, errCode: ' + (code as BusinessError).code + ', errMessage: ' + (code as BusinessError).message);
115  } else {
116    for (let i = 0; i < gattServices.length; i++) {
117      message += 'serviceUuid is ' + gattServices[i].serviceUuid + '\n';
118    }
119    console.info('getServices success, ' + message);
120  }
121})
122
123// 读取信号强度
124clientDevice.getRssiValue((err, cbRssi) => {
125  console.info('return code = ' + JSON.stringify(err) + ', RSSI = ' + JSON.stringify(cbRssi))
126});
127
128// 设置最大传输单元,示例为256
129clientDevice.setBLEMtuSize(256);
130
131// 读取特征值
132// 下面字段的值,是getServices之后,从结果中拿到的
133let serviceUuid = 'xxx';
134let characteristicUuid = 'xxx';
135let descriptorUuid = 'xxx';
136let descriptorValue = new Uint8Array('xxx'.length).buffer;
137let characteristicValue = new Uint8Array('xxx'.length).buffer;
138let descriptors: Array<ble.BLEDescriptor> = new Array<ble.BLEDescriptor>();
139let descriptor: ble.BLEDescriptor = {
140  serviceUuid: serviceUuid,
141  characteristicUuid: characteristicUuid,
142  descriptorUuid: descriptorUuid,
143  descriptorValue: descriptorValue
144}
145descriptors.push(descriptor);
146let bleCharacteristicDataIn: ble.BLECharacteristic = {
147  serviceUuid: serviceUuid,
148  characteristicUuid: characteristicUuid,
149  characteristicValue: characteristicValue,
150  descriptors: descriptors
151};
152clientDevice.readCharacteristicValue(bleCharacteristicDataIn, (err, bleCharacteristicDataOut) => {
153  if (err != null) {
154    console.error('readCharacteristicValue error, code = ' + (err as BusinessError).code)
155    return;
156  }
157  let message = 'characteristic value = ';
158  let value = new Uint8Array(bleCharacteristicDataOut.characteristicValue);
159  for (let i = 0; i < bleCharacteristicDataOut.characteristicValue.byteLength; i++) {
160    message += value[i];
161  }
162  console.info(message);
163});
164
165// 读取描述符
166let descriptorIn: ble.BLEDescriptor = {
167  serviceUuid: serviceUuid,
168  characteristicUuid: characteristicUuid,
169  descriptorUuid: descriptorUuid,
170  descriptorValue: descriptorValue
171};
172clientDevice.readDescriptorValue(descriptorIn, (err, descriptorOut) => {
173  if (err != null) {
174    console.error('readDescriptorValue error, code: ' + (err as BusinessError).code)
175    return;
176  }
177  let message = 'descriptor value: ';
178  let value = new Uint8Array(descriptorOut.descriptorValue);
179  for (let i = 0; i < descriptorOut.descriptorValue.byteLength; i++) {
180    message += value[i];
181  }
182  console.info(message);
183});
184
185// 写入特征值
186let string2ArrayBuffer: (str: string) => ArrayBuffer = (str: string): ArrayBuffer => {
187  let array = new Uint8Array(str.length);
188  for (let i = 0; i < str.length; i++) {
189    array[i] = str.charCodeAt(i);
190  }
191  return array.buffer;
192}
193
194let bufferCCC = string2ArrayBuffer('V');
195let characteristic: ble.BLECharacteristic = {
196  serviceUuid: serviceUuid,
197  characteristicUuid: characteristicUuid,
198  characteristicValue: bufferCCC,
199  descriptors: descriptors
200};
201clientDevice.writeCharacteristicValue(characteristic, ble.GattWriteType.WRITE);
202
203// 写入描述符
204let message = '';
205if (clientDevice.writeDescriptorValue(descriptor)) {
206  message = 'writeDescriptorValue success';
207} else {
208  message = 'writeDescriptorValue failed';
209}
210console.info(message);
211
212// 断开连接
213clientDevice.disconnect();
214console.info('disconnect success')
215
216// 关闭GattClient实例
217clientDevice.close();
218console.info('close gattClientDevice success');
219```
220
2219. 错误码请参见[蓝牙服务子系统错误码](../../reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。
222
223
224### server端操作services和通知客户端信息
2251. import需要的ble模块。
2262. 创建gattServer实例对象。
2273. 添加services信息。
2284. 当向gattServer写入特征值通知gattClient。
2295. 移除services信息。
2306. 注销gattServer实例。
2317. 示例代码:
232
233```ts
234import ble from '@ohos.bluetooth.ble';
235import { BusinessError } from '@ohos.base';
236
237// 创建gattServer实例
238let gattServerInstance = ble.createGattServer();
239
240// 添加services
241let string2ArrayBuffer: (str: string) => ArrayBuffer = (str: string): ArrayBuffer => {
242  let array = new Uint8Array(str.length);
243  for (let i = 0; i < str.length; i++) {
244    array[i] = str.charCodeAt(i);
245  }
246  return array.buffer;
247}
248
249let characteristicsArray: Array<ble.BLECharacteristic> = new Array<ble.BLECharacteristic>();
250let descriptorsArray: Array<ble.BLEDescriptor> = new Array<ble.BLEDescriptor>();
251let characteristics1: ble.BLECharacteristic = {
252  serviceUuid: '0000aaaa-0000-1000-8000-00805f9b34fb',
253  characteristicUuid: '00002a10-0000-1000-8000-00805f9b34fb',
254  characteristicValue: string2ArrayBuffer('I am charac1'),
255  descriptors: descriptorsArray
256};
257characteristicsArray.push(characteristics1);
258
259let descriptors1: ble.BLEDescriptor = {
260  serviceUuid: '0000aaaa-0000-1000-8000-00805f9b34fb',
261  characteristicUuid: '00002a10-0000-1000-8000-00805f9b34fb',
262  descriptorUuid: '00002904-0000-1000-8000-00805f9b34fb',
263  descriptorValue: string2ArrayBuffer('I am Server Descriptor1')
264}
265let descriptors2: ble.BLEDescriptor = {
266  serviceUuid: '0000aaaa-0000-1000-8000-00805f9b34fb',
267  characteristicUuid: '00002a10-0000-1000-8000-00805f9b34fb',
268  descriptorUuid: '00002905-0000-1000-8000-00805f9b34fb',
269  descriptorValue: string2ArrayBuffer('I am Server Descriptor2')
270}
271descriptorsArray.push(descriptors1);
272descriptorsArray.push(descriptors2);
273
274let service: ble.GattService = {
275  serviceUuid: '0000aaaa-0000-1000-8000-00805f9b34fb',
276  isPrimary: true,
277  characteristics: characteristicsArray
278};
279gattServerInstance.addService(service);
280console.info('addService success');
281
282// 订阅写特征值事件,向gattClient发送response
283gattServerInstance.on('characteristicWrite', (characteristicWriteReq) => {
284  let deviceId = characteristicWriteReq.deviceId;
285  let transId = characteristicWriteReq.transId;
286  let offset = characteristicWriteReq.offset;
287  let needRsp = characteristicWriteReq.needRsp;
288  let arrayBufferCCC: ArrayBuffer = string2ArrayBuffer('characteristicWriteForResponse');
289  let serverResponse: ble.ServerResponse = {
290    deviceId: deviceId,
291    transId: transId,
292    status: 0,
293    offset: offset,
294    value: arrayBufferCCC
295  };
296  // 发送response
297  if (needRsp) {
298    gattServerInstance.sendResponse(serverResponse);
299    console.info('sendResponse success, response data: ' + JSON.stringify(serverResponse));
300  }
301  // 关闭订阅写特征值事件
302  gattServerInstance.off('characteristicWrite');
303})
304
305// 订阅写特征值事件,特征值变化,通知gattClient
306gattServerInstance.on('characteristicWrite', (characteristicWriteReq) => {
307  let characteristicUuid = characteristicWriteReq.characteristicUuid;
308  let serviceUuid = characteristicWriteReq.serviceUuid;
309  let deviceId = characteristicWriteReq.deviceId;
310  let notifyCharacteristic: ble.NotifyCharacteristic = {
311    serviceUuid: serviceUuid,
312    characteristicUuid: characteristicUuid,
313    characteristicValue: string2ArrayBuffer('Value4notifyCharacteristic'),
314    confirm: false
315  }
316  // 特征值变化时,通知已连接的client设备
317  gattServerInstance.notifyCharacteristicChanged(deviceId, notifyCharacteristic);
318  console.info('notifyCharacteristicChanged success, deviceId = ' + deviceId);
319  // 关闭订阅写特征值事件
320  gattServerInstance.off('characteristicWrite');
321})
322
323// 移除service
324gattServerInstance.removeService('0000aaaa-0000-1000-8000-00805f9b34fb');
325console.info('removeService success')
326
327// 注销gattServer实例
328gattServerInstance.close();
329console.info('close gattServerInstance success');
330```
331
3328. 错误码请参见[蓝牙服务子系统错误码](../../reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。