2014-05-15 10:01:33 mzy202 阅读数 32188
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3510 人正在学习 去看看 许英俊

       蓝牙4.0BLE 手机控制 cc2540 CC2541 的串口透传功能已实现

       虽然蓝牙4.0 BLE芯片CC2540 是单芯片(即用户可以对它进行芯片级代码编写), 是8051增强型主控, 带蓝牙4.0功能, 但很多时候很多客户都只需要他的透传功能, 现在随着Android4.3 和IOS 的兴起, 支持蓝牙4.0BLE的手机越来越多,所以如何实现手机控制CC2540的透传是一个非常实用的功能,有了这个功能, 我们可以用手机来连接CC2540通过串口来连接的设备,纵观淘宝上有销售的几种模块, 小部分研发实力不足的,都只是提供裸模块,有两家提供了串口透传的模块的, 售价比裸片要高不少, AmoMcu 根据客户需求以及网友的需要, 现在已经实现了此商业模块的功能, 即手机通过蓝牙4.0BLE发送串字符cc2540中, cc2540把该字符串透传出去,同时外面送进来的串口数据也能透传到手机上来,HC-08 模块就是这样的功能, 现在我们这里也实现了, 并且以源码的形式公开给大家, 用于交流和学习。

      由于时间关系, 尚未整理出文档, 但源码都经过验证, ok了。

      目前用ios 测试成功老, Android的源码在进一步整理中。请等待。谢谢。

      先mark, 后面会增加图文介绍。




    如果需要cc2540 BLE开发板, 请看这里  http://amomcu.taobao.com/ , 这里能提供基于cc2540cc2541的蓝牙4.0BLE开发的详细硬件和软件资料, QQ群257318688

2014-08-13 16:15:48 xhalone 阅读数 1768
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3510 人正在学习 去看看 许英俊

蓝牙4.0 BLE 入门

1. 手机需要android 4.3 及以上版本

2. 权限:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

只允许支持BLE 的手机安装还需要添加uses-feature

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

3. BLE 设备扫描

3.1 获取蓝牙适配器:  mBluetoothAdapter = bluetoothManager.getAdapter();  

3.2 开始扫描: mBluetoothAdapter.startLeScan(mLeScanCallback);

在调用扫描时, 需要实现LeScanCallback 回调接口, 用于扫描结果的返回: 

protected LeScanCallback mLeScanCallback = new  BluetoothAdapter.LeScanCallback() {

		@Override
		public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {
			Log.d(TAG, "find device -> "+ device.getName()+"mac:"+device.getAddress());
			runOnUiThread(new Runnable() {
				public void run() {
					String mac = device.getAddress();
					String name = device.getName();
//					deviceAdapter.addDevice(new BluetoothItem(name, mac));
					deviceAdapter.addDevice(new BluetoothItem(name, mac, rssi));
					deviceAdapter.notifyDataSetChanged();
				}
			});
		}
	};
3.3 获取扫描结果后,可以通过得到的设备地址, 来对设备进行连接, 连接上将得到一个BluetoothGatt 用于操作, 其中需要实现BluetoothGattCallback 回调, 其用于结果的返回, 如连接的状态,以及后面的读写等操作

	final BluetoothDevice device = mBluetoothAdapter
				.getRemoteDevice(address);
		if (device == null) {
			Log.w(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 = device.connectGatt(this, true, mGattCallback);
		
mGattCallback 回调函数:

	private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

		@Override
		public void onConnectionStateChange(BluetoothGatt gatt, int status,
				int newState) {
			if (newState == BluetoothProfile.STATE_CONNECTED) {
				broadcastUpdate(ACTION_GATT_CONNECTED);
				Log.i(TAG, "Connected to GATT server.");
				// Attempts to discover services after successful connection.
				Log.i(TAG, "Attempting to start service discovery:"
						+ mBluetoothGatt.discoverServices());
				isConnectd = true;
			} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
				Log.i(TAG, "Disconnected from GATT server.");
				isConnectd = false;
				broadcastUpdate(ACTION_GATT_DISCONNECTED, gatt.getDevice().getAddress());
			}
		}
		//...略
	}

3.4 在蓝牙设备中, 其包含有多个BluetoothGattService, 而每个BluetoothGattService中又包含有多个BluetoothGattCharacteristic

在连接上蓝牙后, 通过调用 mBluetoothGatt.discoverServices(), 来发现蓝牙设备中的服务, 接下来就可以获取到设备中的服务列表  mBluetoothGatt.getServices(); 或者通过uuid 来获取某一个服务 BluetoothGattService gattService = mBluetoothGatt.getService(uuid); 

服务中, 获得Characteristic 集合则调用 gattService.getCharacteristics(); 

在 Characteristic中, 可以通过 mBluetoothGatt.readCharacteristic(characteristic); 来读取其里面的数据, 其结果在mGattCallback 回调函数中获取.

写如数据: characteristic.setValue(data); 

mBluetoothGatt.wirteCharacteristic(mCurrentcharacteristic);

4. 关闭连接 mBluetoothGatt.close();



2017-06-19 13:29:47 weilexuexi12 阅读数 436
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3510 人正在学习 去看看 许英俊

在使用蓝牙4.0BLE协议栈进行应用程序开发时,如何在应用程序中添加一个新任务

下面结合工程示例SimpleBLEPeripheral来讲解,打开OSAL_SimpleBLEPeripheral.c文件可以找到数组tasksArr[]和函数osalInitTasks()。tasksArr[]数组里存放了所有任务的事件处理函数的地址;osalInitTasks()是OSAL的任务初始化函数,所有任务的初始化工作都在这里面完成,并且自动给每个任务分配一个任务ID。

      要添加新任务,只需要编写两个函数:

(1)新任务的初始化函数;

(2)新任务的事件处理函数。

      将事件处理函数的地址加入tasksArr[]数组,代码如下所示。

const pTaskEventHandlerFn tasksArr[] =
{
  LL_ProcessEvent,                                                  // task 0
  Hal_ProcessEvent,                                                 // task 1
  HCI_ProcessEvent,                                                 // task 2
#if defined ( OSAL_CBTIMER_NUM_TASKS )
  OSAL_CBTIMER_PROCESS_EVENT( osal_CbTimerProcessEvent ),           // task 3
#endif
  L2CAP_ProcessEvent,                                               // task 4
  GAP_ProcessEvent,                                                 // task 5
  GATT_ProcessEvent,                                                // task 6
  SM_ProcessEvent,                                                  // task 7
  GAPRole_ProcessEvent,                                             // task 8
  GAPBondMgr_ProcessEvent,                                          // task 9
  GATTServApp_ProcessEvent,                                         // task 10
  SimpleBLEPeripheral_ProcessEvent                                  // task 11
};

     将新任务的初始化函数添加在osalInitTasks()函数的最后,如下代码所示。

void osalInitTasks( void )
{
  uint8 taskID = 0;

  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
  osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

  /* LL Task */
  LL_Init( taskID++ );

  /* Hal Task */
  Hal_Init( taskID++ );

  /* HCI Task */
  HCI_Init( taskID++ );

#if defined ( OSAL_CBTIMER_NUM_TASKS )
  /* Callback Timer Tasks */
  osal_CbTimerInit( taskID );
  taskID += OSAL_CBTIMER_NUM_TASKS;
#endif

  /* L2CAP Task */
  L2CAP_Init( taskID++ );

  /* GAP Task */
  GAP_Init( taskID++ );

  /* GATT Task */
  GATT_Init( taskID++ );

  /* SM Task */
  SM_Init( taskID++ );

  /* Profiles */
  GAPRole_Init( taskID++ );
  GAPBondMgr_Init( taskID++ );

  GATTServApp_Init( taskID++ );

  /* Application */
  SimpleBLEPeripheral_Init( taskID );
}

在此例中,SimpleBLEPeripheral_ProcessEvent函数添加到了函数的末尾,将SimpleBLEPeripheral_Init()函数添加到osalInitTasks()任务初始化函数中。

需要注意两点:

(1)taskArr[]数组里各事件处理函数的排列顺序要与osalInitTasks()函数中调用各任务初始化函数的顺序保持一致,只有这样才能保持一致,只有这样才能保证每个任务的事件处理函数能够接收到正确的任务ID(在osalInitTasks()函数中分配)

(2)为了保证osalInitTasks()函数所分配的任务ID,需要给每一个任务定义一个全局变量来保存这个ID。如在SimpleBLEPeripheral.c中定义了一个全局变量SimpleBLEPeripheral_TaskID,并且SimpleBLEPeripheral_Init函数中对其进行赋值。



2016-06-20 15:34:44 zzfenglin 阅读数 20056
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3510 人正在学习 去看看 许英俊

蓝牙4.0BLE协议与协议栈的关系


协议定义的是一系列的通信标准,通信双方需要共同按照这一标准进行正常的数据收发。

协议栈是协议的具体实现形式,通俗的理解为用代码实现的函数库,以便于开发人员调用。


蓝牙4.0BLE协议栈就是将各个层定义的协议都集合在一起,以函数的形式实现,并提供一些应用层API,供用户调用。


注意:虽然协议是统一的,但是协议的具体实现形式是变化的,即不同厂商提供的协议栈是有区别的,例如:函数名称和参数列表可能有区别,选择协议栈以后,需要学习具体的例子,查看厂商提供的Demo演示程序、说明文档(通常,实现协议栈的厂商会提供一些API手册供用户查询)来学习各个函数的使用方式,进而快速地使用协议栈进行应用程序的开发工作。




如何使用蓝牙4.0BLE协议栈


既然蓝牙4.0BLE协议栈已经实现了蓝牙4.0BLE协议,那么用户就可以使用协议栈提供的API进行应用程序的开发,在开发过程中不必过多的关注蓝牙4.0BLE协议的具体实现细节,只需要关注一个核心的问题:应用程序数据从哪里来到哪里去。

 

至于调用协议栈中函数后,如何初始化应用进行数据发送等工作,蓝牙4.0BLE协议栈已经完成了所需要的初始化。

 

如果开发过程中确实需要或者是想要了解蓝牙4.0BLE协议,可以查看SIG提供的标准协议规范。




深入理解蓝牙4.0BLE协议栈


协议栈概述


我们以TI的CC254X系列BLE芯片为例来深入了解下蓝牙4.0BLE协议栈。TI的蓝牙4.0BLE协议栈包含两部分:主机和控制器。主机和控制器的分离要追溯到蓝牙BR/EDR设备时期,控制器和主机通常会分开实现。

 

协议栈的实现方式采用分层的思想,控制器部分包括:物理层、链路层、主机控制接口层;主机部分包括:逻辑链路控制及自适应协议层、安全管理层、属性协议层、通用访问配置文件层、通用属性配置文件层;上层可以调用下层提供的函数来实现需要的功能。


蓝牙技术联盟提供的标准规范下载链接:

https://www.bluetooth.com/zh-cn/specifications/adopted-specifications


蓝牙4.0标准规范CSDN下载链接:

点击打开下载页链接



协议栈基础


蓝牙4.0BLE协议栈的结构图如下:



详细介绍如下:

1.物理层(Physical Layer,简写 PHY):

是1Mbps自适应跳频的GFSK射频,工作于免许可证的2.4GHz ISM(工业、科学与医疗)频段。


2.链路层(Link Layer,简写 LL):

用于控制设备的射频状态,设备将处于五种状态之一:等待、广告、扫描、初始化、连接。广播设备不需要建立连接就可以发送数据,而扫描设备接收广播设备发送的数据;发起连接的设备通过发送连接请求来回应广播设备,如果广播设备接受连接请求,那么广播设备与发起连接的设备将会进入连接状态。发起连接的设备称为主机,接受连接请求的设备称为从机。


3.主机控制接口层(Host Controller Interface,简写 HCI):

为主机和控制器之间提供标准通信接口。这一层可以是软件或者硬件接口,如UART、SPI、USB等。


4.逻辑链路控制及自适应协议层(Logical Link Control and Adaptation Protocol,简写 L2CAP):

为上层提供数据封装服务,允许逻辑上的点对点数据通信。


5.安全管理层(Security Manager,简写 SM):

定义了配对和秘钥分配方式,并为协议栈其他层与另一个设备之间的安全连接和数据交换提供服务。


6.属性协议层(Attribute protocol,简写 ATT):

允许设备向另外一个设备展示一块特定的数据,称之为属性。在ATT环境中,展示属性的设备称为服务器,与之配对的设备称为客户端。链路层状态(主机和从机)与设备的ATT角色是相互独立的。例如:主机设备既可以是ATT服务器,也可以是ATT客户端;从机设备既可以是ATT服务器,也可以是ATT客户端。


7.通用属性配置文件层(Generic Attribute profile,简写 GATT):

定义了使用ATT的服务框架。GATT规定配置文件(profile)的结构。在BLE中,所有被profile或者服务用到的数据块称为特性,两个建立连接的设备之间的所有数据通信都是通过GATT子程序处理。GATT层用于已连接的蓝牙设备之间的数据通信,应用程序和profile直接使用GATT层。


当两个设备建立连接之后,它们就处于下面两种角色之一:

GATT服务器:为GATT客户端提供数据服务的设备。

GATT客户端:从GATT服务器读写应用数据的设备。


注意:GATT角色中的客户端和服务器的概念与链路层的主机和从机的概念完全独立,与GAP层角色中的外设和集中器的概念也是完全独立。 主机既可以是GATT客户端也可以是GATT服务器;从机既可以是GATT客户端也可以是GATT服务器。


一个GATT服务器中可包含一个或多个GATT服务,GATT服务是完成特定功能的一系列数据的集合。每一个应用工程大致包含下列三种服务:

(1)强制的GAP服务。这一服务包含了设备和访问信息。例如,设备、设备供应商和产品标示。它是协议栈的一部分,是BLE规范对每一个BLE设备的强制要求。这部分没有提供源代码,而是直接编译到协议栈库文件中了。

(2)强制的GATT服务。这一服务包含了GATT服务器的信息,是协议栈的一部分,同样也是BLE规范对每一个BLE设备的要求。这部分同样没有提供源代码而是直接编译到协议栈库文件中了。

(3)自定义服务。这部分服务包含应用数据的信息,与应用数据的传递密切相关,我们可以按照特定的格式编写自己的GATT服务。


特性(Characteristic)是服务用到的值,以及其内容和配置信息。GATT定义了在BLE连接中发现、读取和写入属性的子过程。GATT服务器上的特性值及其内容和配置信息(称为描述符)存储于属性表中。属性表是一个数据库,包含了成为属性的小块数据,除了值本身,每个属性都包含下列属性:  

(1)句柄:属性在表中的地址,每个属性有唯一的句柄。

(2)类型:表示数据代表的事物,通常是蓝牙技术联盟规定或用户自定义的UUID(Universally Unique Identifier)。

(3)权限:规定了GATT客户端设备对属性的访问权限,包括是否能访问和怎样访问。


GATT定义了若干在GATT服务器和客户端之间的通信的子过程:

(1)读特性值:客户端设备请求读取句柄处的特性值,服务器将此值回应给客户端(假定属性有读权限)。

(2)使用特性的UUID读:客户端请求读基于一个特定类型的所有特性值,服务器将所有与指定类型匹配的特性的句柄和值回应给客户端设备(假设属性有读权限)。  

(3)读多个特性值:客户端一次请求中读取几个句柄的特性值,服务器将这些特性值回应给客户端(假设属性有读权限),客户端需要知道如何解析这些不同的特性值数据。

(4)读特性描述符:客户端请求读特定句柄处的特性描述符,服务器将特性描述符的值回应给客户端设备(假设属性有读权限)。  

(5)使用UUID发现特性:客户端通过发送特性的类型UUID来请求发现这个特性的句柄。服务器将这个”特性”的声明回应给客户端设备,其中包括特性值的句柄以及特性的权限。

(6)写特性值:客户端设备请求向服务器特定的句柄处写入特性值,服务器将数据是否写入成功的信息反馈给客户端(假设特性有写权限,另外有一种特殊的写类型是不需要服务器来反馈是否写入成功的信息的,使用的时候根据具体应用来具体分析使用)。

(7)写特性描述符:客户端设备请求向服务器特定的句柄处写入特性描述符,服务器将特性描述符是否写入成功的信息反馈给客户端(假设特性描述有写权限)。  

(8)特性值通知:服务器将一个特性值通知给客户端,客户端设备不需要向服务器请求这个数据,客户端收到这个数据时,不需要属性协议层确认特性值是否被成功接收。

(9)特性值指示:服务器将一个特性值指示给客户端,客户端设备同样不需要向服务器请求这个数据,但是跟通知不一样的是,客户端收到这个数据之后,属性协议层必须确认特性值被成功接收。


通知与指示功能的流程如下:





何时发送通知或指示的条件可以在配置文件中设置,也可以通过应用来设置。要想使能通知和指示功能,需要分别在相应的句柄特性描述符写入0x00010x0002,如下表所示:



每个Profile初始化其相应的服务并内在的通过设备的GATT服务器来注册服务。GATT服务器将整个服务加到属性表中,并为每个属性分配唯一句柄。GATT属性表中有一些特殊的属性类型,其值由蓝牙技术联盟定义:

(1)GATT_PRIMARY_SERVICE_UUID:表示新服务的起始和提供的服务类型。

(2)GATT_CHARACTER_UUID:称为特性声明,紧随其后的是GATT特性值。

(3)GATT_CLIENT_CHAR_CFG_UUID:这一属性代表特性描述符,它与属性表中它前面最近的句柄处的特性值相关,它允许GATT客户端设备使能特性值通知或者指示。

(4)GATT_CHAR_USER_DESC_UUID:这一属性代表描述符,它与属性表中它前面最近的句柄处的特性值相关,包含一个ASCII字符串,是对相关特性的描述。


8.通用访问配置文件层(Generic Access Profile,简写 GAP):

负责处理设备访问模式和程序,包括设备发现、建立连接、终止连接、初始化安全特性和设备配置。


GAP层总是作为下面四种角色之一:

(1)广播者:不可连接的广播设备。

(2)观察者:扫描设备,但不发起建立连接。

(3)外部设备:可连接的广播设备,可以在单个链路层连接中作为从机。

(4)集中器:扫描广播设备并发起连接,可以在单个链路层连接中作为主机。


外部设备广播特定的数据使集中器知道它是一个可以连接的设备。广播内容包括设备地址以及一些额外的数据,如设备名等,当然也可以是自定义的数据,只要满足广播数据中广告的格式即可。集中器收到广播数据后向外部设备发送扫描请求,然后外部设备将特定的数据回应给集中器,称为扫描回应。集中器收到扫描回应后便知道这是一个可以建立连接的外部设备。这就是设备发现的全过程。此时集中器可以向外部设备发起建立连接的请求。连接请求包括一些链接参数。关于蓝牙4.0BLE的广播和连接,请参看下面几篇博文:


蓝牙BLE报文:

http://blog.csdn.net/zzfenglin/article/details/51165093


蓝牙BLE广播:

http://blog.csdn.net/zzfenglin/article/details/51165543

http://blog.csdn.net/zzfenglin/article/details/51166830


蓝牙BLE连接:

http://blog.csdn.net/zzfenglin/article/details/51303211

http://blog.csdn.net/zzfenglin/article/details/51304084



GAP层也处理BLE连接中安全特征的初始化。只有在已认证的连接中特定的数据才能被读写,一旦连接建立,两个设备进行配对,当配对完成后,形成加密链接的密钥。典型应用中外设请求集中器提供密钥来完成配对工作,密钥可以是一个固定的值,如000000,也可以随机生成一个数据提供给使用者,集中器设备发送正确的密钥后,两设备交换安全密钥并加密认证链接。


在许多情况下,同一对外设和集中器会不定时地连接和断开,BLE的安全机制中有一项特性允许两个设备之间建立长期的安全密钥信息,这种特性称为绑定,它允许两设备重新连接时快速地完成加密认证,而不需要每次连接时执行配对的完整过程。




蓝牙4.0BLE协议栈分层思想的优点


蓝牙4.0BLE协议栈采用分层思路的最大优点是:将服务、接口和协议这三个概念明确的区分开来。服务说明某一层为上一层提供了一些什么样的功能;接口说明上一层如何使用下一层的服务;而协议涉及到如何实现本层的服务。这样,各层之间就具有很强的独立性,当协议的一部分发送变化时,只需对与此相关的分层进行修改即可,其他分层不需要改变。






2019-03-27 11:48:15 fanxinshr 阅读数 963
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3510 人正在学习 去看看 许英俊

透彻理解蓝牙5.0 BLE ATT分析

 

BLE是传统蓝牙的简化版本,其特点就是低功耗。

在BLE中使用了ATT协议。ATT运行在GATT上,在接触GATT之前,先简单了解一下ATT的相关内容


ATT的主要作用是发现,并且在对端设备上读取属性, ATT主要是作为服务器去暴露一组属性和相关的数值。这些属性和数值可以被客户端发现,读取和写入

ATT中有2个角色,一个是服务器,一个是客户端。服务器暴露属性,客户端访问属性。

客户端可以发送ATT协议请求给服务端,服务器端会响应这个请求。一个设备既可以是服务器端,也可以是客户端。

属性由3部分组成,属性类型(UUID),句柄和一组权限。

属性协议数据单元 Attribute PDU 有6种类型

Commands, Requests, Responses, Notifications, Indications, Confirmations

服务器可以接受并且响应阆中请求, Find Information Request, Read Request.

ATT 使用了序列化的协议,也就是说客户端给服务器端发送一个请求之后,如果没有收到响应的消息,就不会发送下一条请求。


抓取到BLE的btsnoop文件以后,可以使用Frontline Viewer打开查看,如下图

选择ATT选项卡,就可以看到ATT协议的交互内容。结合BLE的规格和源码来分析一下BLE ATT 的内容

首先服务器端发送一个request请求,然后客户端会发出response的响应数据


具体查看一下包的内容

服务器端发送了一个ATT的包给客户端,类型是Read by Group Type Request,属性组的类型是Primary Service,也就是查看客户端的主要服务。接到这个request之后,客户端在查看了自己的主要服务以后,给客户端发回了响应。

响应的数据包中包含了客户端包含的主要服务,使用UUID来标识,客户端支持GAP和GATT还有Device Information. 服务器端获取到这些数据以后,就可以根据客户端支持的服务类型进行后续的继续request。


查看时序图可以发现,request包先由客户端发送HCI给客户端,然后解析HCI的包之后,发送到客户端的ATT,之后,客户端发送HCI给服务器端,服务器端HCI解析后,可以看到是一个response包发给了服务器端。这就是一个完整的ATT协议的交互过程。

结合btsnoop的内容,查看相关的logcat日志

 

因为要查看的是BLE的内容,所以从logcat的日志中提取GATT相关的日志,如下图。

 

然后分析BLE的相关日志,找到ATT对应的部分

通过查看日志,可以找到对应的att日志部分               

        Line 39737: 03-25 20:37:43.948 18572 18590 D BluetoothGatt: onClientRegistered() - status=0 clientIf=10
	Line 39740: 03-25 20:37:43.949 19626 19649 D bt_btif : btif_gattc_open_impl Transport=2, device type=2, phy=1
	Line 39746: 03-25 20:37:43.950 19626 19678 I bt_stack: [INFO:gatt_api.cc(1122)] GATT_Connectgatt_if=10 d2:04:17:39:1c:00
	Line 39746: 03-25 20:37:43.950 19626 19678 I bt_stack: [INFO:gatt_api.cc(1122)] GATT_Connectgatt_if=10 d2:04:17:39:1c:00
	Line 39746: 03-25 20:37:43.950 19626 19678 I bt_stack: [INFO:gatt_api.cc(1122)] GATT_Connectgatt_if=10 d2:04:17:39:1c:00
	Line 39750: 03-25 20:37:43.950 19626 19678 D bt_btif : bta_gattc_conn: server cache state=4
	Line 39751: 03-25 20:37:43.950 19626 19678 D bt_btif : bta_gattc_conn: conn_id=10
	Line 39755: 03-25 20:37:43.950 19626 19649 I bt_btif : HAL bt_gatt_callbacks->client->open_cb
	Line 39765: 03-25 20:37:43.953 18572 18590 D BluetoothGatt: onClientConnectionState() - status=0 clientIf=10 device=D2:04:17:39:1C:00
	Line 39766: 03-25 20:37:43.953 18572 18590 I [BLE] [Binder:18572_3] BLEGattClient#onConnectionStateChange: bdaddr:D2:04:17:39:1C:00, status:0, newState:2
	Line 39776: 03-25 20:37:43.956 18572 20046 I [BLE] [BLE:D2:04:17:39:1C:00(3)] BLEDevice#issueEventSyncWithLog: change : state=[CONNECTING[GATT_CONNECTED[WAIT_TRANSFER_CONNECTED][WAIT_BEFORE_DISCOVER_SERVICES]]] / EVT_GATT_CONNECTED
	Line 39776: 03-25 20:37:43.956 18572 20046 I [BLE] [BLE:D2:04:17:39:1C:00(3)] BLEDevice#issueEventSyncWithLog: change : state=[CONNECTING[GATT_CONNECTED[WAIT_TRANSFER_CONNECTED][WAIT_BEFORE_DISCOVER_SERVICES]]] / EVT_GATT_CONNECTED
	Line 39801: 03-25 20:37:43.967 19626 19678 D bt_btif : bta_gattc_add_srvc_to_list handle=768, service type=ecbe3980-c9a2-11e1-b1bd-0002a5d5c51b
首先通过UUID可以找到对应的代码,即函数bta_gattc_add_srvc_to_list

表示服务器端添加了一个找到的服务,并且把这个服务添加到列表中

 

查看一下这个函数,发现是被下面这个函数调用执行了。

而且is_primary的参数上设置为true,可以印证btsnoop中查询主要服务的内容。

 


 

没有更多推荐了,返回首页