蓝牙ble的写响应到底是什么流程

蓝牙ble的写响应到底是什么流程,第1张

1、BLE设备首先执行GAP广播流程。

2、BLE设备接收连接请求,进入连接状态。

3、BLE设备做为GATT服务器,手机做为GATT客户端,手机使用GATT流程来查找BLE设备定义的服务、特征、并读写特征值属性和特征描述符属性。

安卓 bluetoothleservice怎么写数据

Generic Attribute Profile (GATT)

通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。

Attribute Protocol (ATT)

GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。

Characteristic

Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。

Descriptor

对Characteristic的描述,例如范围、计量单位等。

Service

Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement"的Characteristic。

21首先获取BluetoothManager

复制代码 代码如下:

BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(ContextBLUETOOTH_SERVICE);

22获取BluetoothAdapter

复制代码 代码如下:

BluetoothAdapter mBluetoothAdapter = bluetoothManagergetAdapter();

23创建BluetoothAdapterLeScanCallback

private BluetoothAdapterLeScanCallback mLeScanCallback = new BluetoothAdapterLeScanCallback() {

@Override

public void onLeScan(final BluetoothDevice device, int rssi, final byte[] scanRecord) {

runOnUiThread(new Runnable() {

@Override

public void run() {

try {

String struuid = NumberUtilsbytes2HexString(NumberUtilsreverseBytes(scanRecord))replace("-", "")toLowerCase();

if (device!=null && struuidcontains(DEVICE_UUID_PREFIXtoLowerCase())) {

mBluetoothDevicesadd(device);

}

} catch (Exception e) {

eprintStackTrace();

}

}

});

}

};

24开始搜索设备。

复制代码 代码如下:

mBluetoothAdapterstartLeScan(mLeScanCallback);

25BluetoothDevice 描述了一个蓝牙设备 提供了getAddress()设备Mac地址,getName()设备的名称。

26开始连接设备

/

Connects to the GATT server hosted on the Bluetooth LE device

@param address

The device address of the destination device

@return Return true if the connection is initiated successfully The

connection result is reported asynchronously through the

{@code BluetoothGattCallback#onConnectionStateChange(androidbluetoothBluetoothGatt, int, int)}

callback

/

public boolean connect(final String address) {

if (mBluetoothAdapter == null || address == null) {

Logw(TAG, "BluetoothAdapter not initialized or unspecified address");

return false;

}

// Previously connected device Try to reconnect (先前连接的设备。 尝试重新连接)

if (mBluetoothDeviceAddress != null && addressequals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {

Logd(TAG, "Trying to use an existing mBluetoothGatt for connection");

if (mBluetoothGattconnect()) {

mConnectionState = STATE_CONNECTING;

return true;

} else {

return false;

}

}

final BluetoothDevice device = mBluetoothAdaptergetRemoteDevice(address);

if (device == null) {

Logw(TAG, "Device not found Unable to connect");

return false;

}

// We want to directly connect to the device, so we are setting the

// autoConnect

// parameter to false

mBluetoothGatt = deviceconnectGatt(this, false, mGattCallback);

Logd(TAG, "Trying to create a new connection");

mBluetoothDeviceAddress = address;

mConnectionState = STATE_CONNECTING;

return true;

}

27连接到设备之后获取设备的服务(Service)和服务对应的Characteristic。

// Demonstrates how to iterate through the supported GATT

// Services/Characteristics

// In this sample, we populate the data structure that is bound to the

// ExpandableListView

// on the UI

private void displayGattServices(List<BluetoothGattService> gattServices) {

if (gattServices == null)

return;

String uuid = null;

ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<>();

ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<>();

mGattCharacteristics = new ArrayList<>();

// Loops through available GATT Services

for (BluetoothGattService gattService : gattServices) {

HashMap<String, String> currentServiceData = new HashMap<>();

uuid = gattServicegetUuid()toString();

if (uuidcontains("ba11f08c-5f14-0b0d-1080")) {//服务的uuid

//Systemoutprintln("this gattService UUID is:" + gattServicegetUuid()toString());

currentServiceDataput(LIST_NAME, "Service_OX100");

currentServiceDataput(LIST_UUID, uuid);

gattServiceDataadd(currentServiceData);

ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<>();

List<BluetoothGattCharacteristic> gattCharacteristics = gattServicegetCharacteristics();

ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<>();

// Loops through available Characteristics

for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {

charasadd(gattCharacteristic);

HashMap<String, String> currentCharaData = new HashMap<>();

uuid = gattCharacteristicgetUuid()toString();

if (uuidtoLowerCase()contains("cd01")) {

currentCharaDataput(LIST_NAME, "cd01");

} else if (uuidtoLowerCase()contains("cd02")) {

currentCharaDataput(LIST_NAME, "cd02");

} else if (uuidtoLowerCase()contains("cd03")) {

currentCharaDataput(LIST_NAME, "cd03");

} else if (uuidtoLowerCase()contains("cd04")) {

currentCharaDataput(LIST_NAME, "cd04");

} else {

currentCharaDataput(LIST_NAME, "write");

}

currentCharaDataput(LIST_UUID, uuid);

gattCharacteristicGroupDataadd(currentCharaData);

}

mGattCharacteristicsadd(charas);

gattCharacteristicDataadd(gattCharacteristicGroupData);

mCharacteristicCD01 = gattServicegetCharacteristic(UUIDfromString("0000cd01-0000-1000-8000-00805f9b34fb"));

mCharacteristicCD02 = gattServicegetCharacteristic(UUIDfromString("0000cd02-0000-1000-8000-00805f9b34fb"));

mCharacteristicCD03 = gattServicegetCharacteristic(UUIDfromString("0000cd03-0000-1000-8000-00805f9b34fb"));

mCharacteristicCD04 = gattServicegetCharacteristic(UUIDfromString("0000cd04-0000-1000-8000-00805f9b34fb"));

mCharacteristicWrite = gattServicegetCharacteristic(UUIDfromString("0000cd20-0000-1000-8000-00805f9b34fb"));

//Systemoutprintln("=======================Set Notification==========================");

// 开始顺序监听,第一个:CD01

mBluetoothLeServicesetCharacteristicNotification(mCharacteristicCD01, true);

mBluetoothLeServicesetCharacteristicNotification(mCharacteristicCD02, true);

mBluetoothLeServicesetCharacteristicNotification(mCharacteristicCD03, true);

mBluetoothLeServicesetCharacteristicNotification(mCharacteristicCD04, true);

}

}

}

28获取到特征之后,找到服务中可以向下位机写指令的特征,向该特征写入指令。

public void wirteCharacteristic(BluetoothGattCharacteristic characteristic) {

if (mBluetoothAdapter == null || mBluetoothGatt == null) {

Logw(TAG, "BluetoothAdapter not initialized");

return;

}

mBluetoothGattwriteCharacteristic(characteristic);

}

29写入成功之后,开始读取设备返回来的数据。

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

@Override

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

String intentAction;

//Systemoutprintln("=======status:" + status);

if (newState == BluetoothProfileSTATE_CONNECTED) {

intentAction = ACTION_GATT_CONNECTED;

mConnectionState = STATE_CONNECTED;

broadcastUpdate(intentAction);

Logi(TAG, "Connected to GATT server");

// Attempts to discover services after successful connection

Logi(TAG, "Attempting to start service discovery:" + mBluetoothGattdiscoverServices());

} else if (newState == BluetoothProfileSTATE_DISCONNECTED) {

intentAction = ACTION_GATT_DISCONNECTED;

mConnectionState = STATE_DISCONNECTED;

Logi(TAG, "Disconnected from GATT server");

broadcastUpdate(intentAction);

}

}

@Override

public void onServicesDiscovered(BluetoothGatt gatt, int status) {

if (status == BluetoothGattGATT_SUCCESS) {

broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);

} else {

Logw(TAG, "onServicesDiscovered received: " + status);

}

}

//从特征中读取数据

@Override

public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

//Systemoutprintln("onCharacteristicRead");

if (status == BluetoothGattGATT_SUCCESS) {

broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);

}

}

//向特征中写入数据

@Override

public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

//Systemoutprintln("--------write success----- status:" + status);

}

/

when connected successfully will callback this method this method can

dealwith send password or data analyze

当连接成功将回调该方法

/

@Override

public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);

if (characteristicgetValue() != null) {

//Systemoutprintln(characteristicgetStringValue(0));

}

//Systemoutprintln("--------onCharacteristicChanged-----");

}

@Override

public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {

//Systemoutprintln("onDescriptorWriteonDescriptorWrite = " + status + ", descriptor =" + descriptorgetUuid()toString());

UUID uuid = descriptorgetCharacteristic()getUuid();

if (uuidequals(UUIDfromString("0000cd01-0000-1000-8000-00805f9b34fb"))) {

broadcastUpdate(ACTION_CD01NOTIDIED);

} else if (uuidequals(UUIDfromString("0000cd02-0000-1000-8000-00805f9b34fb"))) {

broadcastUpdate(ACTION_CD02NOTIDIED);

} else if (uuidequals(UUIDfromString("0000cd03-0000-1000-8000-00805f9b34fb"))) {

broadcastUpdate(ACTION_CD03NOTIDIED);

} else if (uuidequals(UUIDfromString("0000cd04-0000-1000-8000-00805f9b34fb"))) {

broadcastUpdate(ACTION_CD04NOTIDIED);

}

}

@Override

public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {

//Systemoutprintln("rssi = " + rssi);

}

};

----------------------------------------------

//从特征中读取数据

@Override

public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

//Systemoutprintln("onCharacteristicRead");

if (status == BluetoothGattGATT_SUCCESS) {

broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);

}

}

Generic Attribute Profile (GATT)

通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。

Attribute Protocol (ATT)

GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。

Characteristic

Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。

Descriptor

对Characteristic的描述,例如范围、计量单位等。

Service

Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement"的Characteristic。

二、角色和职责:

Android设备与BLE设备交互有两组角色:

中心设备和外围设备(Central vs peripheral);

GATT server vs GATT client

Central vs peripheral:

中心设备和外围设备的概念针对的是BLE连接本身。Central角色负责scan advertisement。而peripheral角色负责make advertisement。

GATT server vs GATT client:

这两种角色取决于BLE连接成功后,两个设备间通信的方式。

举例说明:

现 有一个活动追踪的BLE设备和一个支持BLE的Android设备。Android设备支持Central角色,而BLE设备支持peripheral角 色。创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。

当 连接建立后,它们之间就需要传输GATT数据。谁做server,谁做client,则取决于具体数据传输的情况。例如,如果活动追踪的BLE设备需要向 Android设备传输sensor数据,则活动追踪器自然成为了server端;而如果活动追踪器需要从Android设备获取更新信息,则 Android设备作为server端可能更合适。

三、权限及feature:

和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,如果需要扫描设备或者 *** 作蓝牙设置,则还需要BLUETOOTH_ADMIN权限:

<uses-permission android:name="androidpermissionBLUETOOTH"/>

<uses-permission android:name="androidpermissionBLUETOOTH_ADMIN"/>

除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature:

<uses-feature android:name="androidhardwarebluetooth_le" android:required="true"/>

按时required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature:

// Use this check to determine whether BLE is supported on the device Then

// you can selectively disable BLE-related features

if (!getPackageManager()hasSystemFeature(PackageManagerFEATURE_BLUETOOTH_LE)) {

ToastmakeText(this, Rstringble_not_supported, ToastLENGTH_SHORT)show();

finish();

}

四、启动蓝牙:

在使用蓝牙BLE之前,需要确认Android设备是否支持BLE feature(required为false时),另外要需要确认蓝牙是否打开。

如果发现不支持BLE,则不能使用BLE相关的功能。如果支持BLE,但是蓝牙没打开,则需要打开蓝牙。

打开蓝牙的步骤:

1、获取BluetoothAdapter

BluetoothAdapter是Android系统中所有蓝牙 *** 作都需要的,它对应本地Android设备的蓝牙模块,在整个系统中BluetoothAdapter是单例的。当你获取到它的示例之后,就能进行相关的蓝牙 *** 作了。

获取BluetoothAdapter代码示例如下:

// Initializes Bluetooth adapter

final BluetoothManager bluetoothManager =

(BluetoothManager) getSystemService(ContextBLUETOOTH_SERVICE);

mBluetoothAdapter = bluetoothManagergetAdapter();

注:这里通过getSystemService获取BluetoothManager,再通过BluetoothManager获取BluetoothAdapter。BluetoothManager在Android43以上支持(API level 18)。

2、判断是否支持蓝牙,并打开蓝牙

获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。

如果没打开,需要让用户打开蓝牙:

private BluetoothAdapter mBluetoothAdapter;

// Ensures Bluetooth is available on the device and it is enabled If not,

// displays a dialog requesting user permission to enable Bluetooth

if (mBluetoothAdapter == null || !mBluetoothAdapterisEnabled()) {

Intent enableBtIntent = new Intent(BluetoothAdapterACTION_REQUEST_ENABLE);

startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

}

五、搜索BLE设备:

通过调用BluetoothAdapter的startLeScan()搜索BLE设备。调用此方法时需要传入 BluetoothAdapterLeScanCallback参数。

因此你需要实现 BluetoothAdapterLeScanCallback接口,BLE设备的搜索结果将通过这个callback返回。

由于搜索需要尽量减少功耗,因此在实际使用时需要注意:

1、当找到对应的设备后,立即停止扫描;

2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。

搜索的示例代码如下:

/

Activity for scanning and displaying available BLE devices

/

public class DeviceScanActivity extends ListActivity {

private BluetoothAdapter mBluetoothAdapter;

private boolean mScanning;

private Handler mHandler;

// Stops scanning after 10 seconds

private static final long SCAN_PERIOD = 10000;

private void scanLeDevice(final boolean enable) {

if (enable) {

// Stops scanning after a pre-defined scan period

mHandlerpostDelayed(new Runnable() {

@Override

public void run() {

mScanning = false;

mBluetoothAdapterstopLeScan(mLeScanCallback);

}

}, SCAN_PERIOD);

mScanning = true;

mBluetoothAdapterstartLeScan(mLeScanCallback);

} else {

mScanning = false;

mBluetoothAdapterstopLeScan(mLeScanCallback);

}

}

}

如果你只需要搜索指定UUID的外设,你可以调用 startLeScan(UUID[], BluetoothAdapterLeScanCallback)方法。

其中UUID数组指定你的应用程序所支持的GATT Services的UUID。

BluetoothAdapterLeScanCallback的实现示例如下:

private LeDeviceListAdapter mLeDeviceListAdapter;

// Device scan callback

private BluetoothAdapterLeScanCallback mLeScanCallback =

new BluetoothAdapterLeScanCallback() {

@Override

public void onLeScan(final BluetoothDevice device, int rssi,

byte[] scanRecord) {

runOnUiThread(new Runnable() {

@Override

public void run() {

mLeDeviceListAdapteraddDevice(device);

mLeDeviceListAdapternotifyDataSetChanged();

}

});

}

};

注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索。

六、连接GATT Server:

两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT Server。

连接GATT Server,你需要调用BluetoothDevice的connectGatt()方法。此函数带三个参数:Context、autoConnect(boolean)和BluetoothGattCallback对象。调用示例:

mBluetoothGatt = deviceconnectGatt(this, false, mGattCallback);

函数成功,返回BluetoothGatt对象,它是GATT profile的封装。通过这个对象,我们就能进行GATT Client端的相关 *** 作。BluetoothGattCallback用于传递一些连接状态及结果。

BluetoothGatt常规用到的几个 *** 作示例:

connect() :连接远程设备。

discoverServices() : 搜索连接设备所支持的service。

disconnect():断开与远程设备的GATT连接。

close():关闭GATT Client端。

readCharacteristic(characteristic) :读取指定的characteristic。

setCharacteristicNotification(characteristic, enabled) :设置当指定characteristic值变化时,发出通知。

getServices() :获取远程设备所支持的services。

等等。

注:

1、某些函数调用之间存在先后关系。例如首先需要connect上才能discoverServices。

2、 一些函数调用是异步的,需要得到的值不会立即返回,而会在BluetoothGattCallback的回调函数中返回。例如 discoverServices与onServicesDiscovered回调,readCharacteristic与 onCharacteristicRead回调,setCharacteristicNotification与 onCharacteristicChanged回调等。

这次介绍一下蓝牙协议栈(BLE)的基础知识,蓝牙协议栈组成如下图所示,首先我们说说GAP和GATT

GAP层是负责连接的,其中包含广播、扫描、连接、断开的过程和参数

11 角色

蓝牙设备的角色主要有中心(Central)和外围设备(Peripheral)两种,中心设备向外围设备发起连接。链路层的主机(Master)和从机(Slave)的概念跟中心和外围的概念是对应的。

除了中心和外围之外,还有Observer和Broadcaster角色,Observer一直进行监听,Broadcaster一直进行发送,这两种角色都只广播,不能发起连接或者被连接,这里就不详细说了

12 广播

建立连接之前,外围设备每隔一段时间发送一个广播包,让正在扫描的设备知道这是一个可以连接的设备,扫描设备才能对外围设备开始连接,这个广播包的时间间隔叫advertising interval,这个间隔可以在10ms到1024s之间,间隔的长短会影响建立连接所花时间。

中心要收到广播包之后才能发送连接请求,相应的,外围设备在发送广播包之后会等待连接请求。

蓝牙广播包最多可以包含31字节数据,包含设备名称和一些标志。中心收到广播包之后可以发送Scan Request以请求更多的广播信息,外围设备会回复一个同样是31个字节的Scan Response。

BLE有37个数据信道和3个广播信道,广播包,Scan Request,Scan Response使用广播信道

13 扫描

扫描是指中心监听广播包并且发送Scan request。扫描中有两个参数:Scan window(扫描窗口) 和Scan interval(扫描间隔)

14 发起连接

中心发起连接的过程类似于扫描的过程,中心收到广播包之后会发送一个连接请求给外围设备

15 连接

中心和外围设备连接上之后,中心会按照一定的连接间隔(Connection interval)向外围设备请求数据,这个间隔是由中心定的,在75ms到4s之间。

如果要提高吞吐量,可以在一个连接间隔中传输多个数据包,每个包最多可以包含20字节数据。如果要省电,并且外围设备并没有什么数据需要传输,可以跳过几个连接间隔,这称之为Slave latency。

如果外围设备没有在规定时间内响应中心的请求就会认为是连接中断,称之为Supervision Time-out(01s-32s),所以在使用Slave latency的时候要注意不要引起Supervision Time-out

这些参数是建立连接的时候中心确定的,如果建立连接之后外围设备想要更改,可以向中心发送Connection parameter update request。

整个数据交换的过程会在不同的频段中跳频(除了广播频段),跳频是自动完成的,不需要我们去管。

设备之间的数据传输是在GATT这层完成的

21 角色

除了GAP里面的角色,BLE在GATT里面也定义了两个角色,分别是GATT Server 和GATT Client,一般来说产生数据的设备是GATT Server,访问数据的设备是GATT Client,一个设备可以既是GATT Server也是GATT Client。这两个角色跟GAP中的角色并没有关系。

22 GATT结构

GATT Server通过属性表(Attribute table)来组织数据,

221 Attribute

上图中每一行就是一个属性Attribute。

每个属性具有一个handle,一个UUID,和一个Value。

Handle是Attribute的一个索引,每个Attribute的Handle都是唯一的。

UUID(universal unique identifier)表示的是Attribute中数据的类型信息。UUID在一个设备里面不是唯一的,可以有多个Attribute的UUID都一样

222 Characteristic

可以把Characteristic看作是上图中几行的集合(几个Attribute的集合)

每个Characteristic至少有两个Attribute,其中一个是声明,另一个包含数据。前面说过,蓝牙传输数据是通过GATT来传的,更具体的来说,是通过一个个Characteristic来传的。

223 Descriptors 描述符

Characteristic除了包含声明和数据之外,还可以有描述符(Descriptors,但不是必须有),Descriptors是用来进一步描述Characteristic(但不提供数据)的Attribute,比如说用自然语言描述该Characteristic是用来干什么的。

有一类特殊的描述符,叫CCCD(Client Characteristic Configuration Descriptor),支持Notify和Indicate的Characteristic 必须包含CCCD

224 Service

Service 是一个或者多个Characteristic的逻辑组合

一个GATT Service 通常包含了一些相关的功能,举例来说,一个人机界面Service包含了各种人机交互输入输出的数据,而其中的每个Characteristic 是一类信号或者设备

介绍几个常见的Service。

GAP GATT Service:作为Central或者Peripheral的BLE设备都需要有这个Service。这个Service包含了如何发现和连接设备的信息

Generic Attribute Service: GATT Server都要有这个Service,这个Service包含了GATT Server的信息

225 Profile

一个或者多个Service组合在一起称为Profile。Profile 是逻辑上的概念,自己并不具备单独的Attribute。

23 标准和自定义的Service和Characteristic

蓝牙联盟定义了一些标准的Profile, Service, Characteristic 和Attribute。由于Profile和Service是在具体应用中规定的,所以用户可以进行自定义

24 UUID

图2中每一个Attribute都有UUID,UUID是一个128位的数字,是用来描述Attribute的类型的

241 蓝牙联盟UUID

蓝牙联盟把UUID分为基础UUID(base UUID)和16位UUID。

蓝牙联盟规定的UUID都具有同样的base UUID:

0x0000xxxx-0000-1000-8000-00805F9B34FB

蓝牙联盟规定了一些16位UUID,替换掉base UUID中的xxxx就组成一个完整的128位UUID了。举例来说,0x2A37是一个16位Heart Rate Measurement Characteristic,那么对应的128位的UUID就是:

0x00002A37-0000-1000-8000-00805F9B34FB。

由于所有蓝牙联盟的UUID都具有同样的base UUID,所以用16位UUID就可以区分蓝牙联盟规定的Attribute了

但我们自定义的Attribute, Characteristic, Service,不能使用这个base UUID,因此也不能用16位UUID,只能使用制造商自定义的128位UUID。

25 空中接口 *** 作和属性

由于每个Attribute具有唯一的Handle,所以几乎所有的 *** 作都是通过Handle去完成,Characteristic常用的属性有:Write, Write without response, Read, Notify, Indicate。 Characteristic的属性决定了我们可以如何使用它

Write, Write without response

这两种属性允许GATT Client 对Server的characteristic的值进行写 *** 作,两者的区别是Write without response对写 *** 作不会有确认

Read

GATT Client可以读Server的Characteristic的值。

Notify 和Indicate

这两种属性表示的是当GATT Server 中该Characteristic 的值发生变化的时候会通知Client。两者的区别是Indicate 会进行确认但Notify不会

接下来举例说明一下前面介绍的概念

Thingy 的Services,作为Server需要有GAP Service和GATT Service,另外还有一个标准的Battery Service,后面是几个自定义的服务

详细的看看GAP Service,这个服务的Handle是1到9,那么把这些Characteristics和Attribute都打出来

可以看到这个Service的结构是这样的

这是一个标准的Service,使用标准Service/Characteristic的时候要符合蓝牙SIG对这个Service/Characteristic的规定,我们可以到 蓝牙SIG 看看是不是一致

以上就是BLE的一些基础知识和示例

以上就是关于蓝牙ble的写响应到底是什么流程全部的内容,包括:蓝牙ble的写响应到底是什么流程、安卓 bluetoothleservice怎么写数据、android蓝牙ble4.0开发共享失败怎么办等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9573658.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-29
下一篇 2023-04-29

发表评论

登录后才能评论

评论列表(0条)

保存