• 蓝牙基础


    参考

    https://www.jianshu.com/p/3a372af38103

    蓝牙版本的介绍

    深入了解Android蓝牙Bluetooth——《基础篇》 (qq.com)

    蓝牙发展至今经历了8个版本的更新。1.1、1.2、2.0、2.1、3.0、4.0、4.1、4.2、5.0。

    那么在1.x~3.0之间的我们称之为传统蓝牙,

    4.x开始的蓝牙我们称之为低功耗蓝牙也就是蓝牙ble,当然4.x版本的蓝牙也是向下兼容的。

    android手机必须系统版本4.3及以上才支持BLE API。

    蓝牙各版本间区别

    • 蓝牙1.0:传输速率约1M/s。
    • 蓝牙2.0+EDR:传输速率约2-3M/s,其中2.1+EDR是最经典的蓝牙,最大的特点是安全简易配对。
    • 蓝牙3.0+HS(高传输蓝牙):高传输24M/s,只有标注了"+HS"商标的设备才是真正支持802.11高速数据传输。
    • 蓝牙4.0(低功耗蓝牙):它包括经典蓝牙、高速蓝牙和蓝牙低功耗协议,在3.0基础上功耗更低,主要面向对功耗需求极低、用纽扣电池供电的应用。
    • 蓝牙5.0:4 倍通讯距离,2 倍传输速度,8 倍广播资料传输量

    现在主流 4.0BLE蓝牙

    蓝牙4.0有几种模式,如果是蓝牙4.0低功耗模式单模的设备(常称为BLE模式),是不向下兼容的。

    • 低功耗蓝牙比传统蓝牙,传输速度更快,覆盖范围更广,安全性更高,延迟更短,耗电极低等等优点
    • 传统的一般通过socket方式,而低功耗蓝牙是通过Gatt协议来实现。

    若是之前没做过传统蓝牙开发,也是可以直接上手低功耗蓝牙开发的。因为它们在通信协议上都有所改变,关联不大。

    那么我们现在所处的4.x的设备大多是属于主从模式的。

    什么是主从模式

    一个主设备比如手机,一个从设备(这里也成为子设备或从机)

    主设备搜索从机,可以发送,也可以接收,

    从机也可以发送和接收,但只能被搜索

    蓝牙协议规范

    https://www.bluetooth.com/specifications/archived-specifications/

    蓝牙GATT协议介绍

    http://murata.eetrend.com/article/2017-11/1000980.html

    https://blog.csdn.net/u013378580/article/details/52891462

    一、 引言

    现在低功耗蓝牙(BLE buletouch low energy)连接都是建立在 GATT (Generic Attribute Profile) 协议之上。GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范,这些很短的数据段被称为属性(Attribute)。

    二、 GAP

    详细介绍 GATT 之前,需要了解 GAP(Generic Access Profile),它在用来控制设备连接和广播。

    GAP 使你的设备被其他设备可见,并决定了你的设备是否可以 或者 怎样与合同设备进行交互。例如 Beacon 设备就只是向外广播,不支持连接,小米手环就等设备就可以与中心设备连接。

    1. 设备角色

    GAP 给设备定义了若干角色,其中主要的两个是:外围设备(Peripheral)和中心设备(Central)。

    • 外围设备:这一般就是非常小 或者 简单的低功耗设备,用来提供数据,并连接到一个更加相对强大的中心设备。例如小米手环。
    • 中心设备:中心设备相对比较强大,用来连接其他外围设备。例如手机等。

    2. 广播数据

    在 GAP 中外围设备通过两种方式向外广播数据: Advertising Data Payload(广播数据)和 Scan Response Data Payload(扫描回复),每种数据最长可以包含 31 byte。

    • 这里广播数据是必需的,因为外设必需不停的向外广播,让中心设备知道它的存在。
    • 扫描回复是可选的,中心设备可以向外设请求扫描回复,这里包含一些设备额外的信息,例如设备的名字。(广播的数据格式我将另外专门写一个篇博客来讲。)

    3. 广播流程

    GAP 的广播工作流程如下图所示。

    wps15
    从图中我们可以清晰看出广播数据和扫描回复数据是怎么工作的。

    外围设备会设定一个广播间隔,每个广播间隔中,它会重新发送自己的广播数据。广播间隔越长,越省电,同时也不太容易扫描到。

    4. 广播的网络拓扑结构

    大部分情况下,外设通过广播自己来让中心设备发现自己,并建立 GATT 连接,从而进行更多的数据交换。

    也有些情况是不需要连接的,只要外设广播自己的数据即可。用这种方式主要目的是让外围设备,把自己的信息发送给多个中心设备。因为基于 GATT 连接的方式的,只能是一个外设连接一个中心设备。使用广播这种方式最典型的应用就是苹果的 iBeacon。广播工作模式下的网络拓扑图如下:

    wps16

    三、GATT

    GATT 的全名是 Generic Attribute Profile(姑且翻译成:普通属性协议),它定义两个 BLE 设备通过叫做 Service 和 Characteristic 的东西进行通信。

    ATT(Attribute Protocol)属性协议 (ATT) 是 GATT 的构建基础,二者的关系也被称为 GATT/ATT。ATT 经过优化,可在 BLE 设备上运行。为此,该协议尽可能少地使用字节。

    ATT 协议把 Service, Characteristic以及对应的数据保存在一个查找表中,此查找表使用 16 bit ID 作为每一项的索引。

    一旦两个设备建立起了连接,GATT 就开始起作用了,这也意味着,你必需完成前面的 GAP 协议。这里需要说明的是,GATT 连接,必需先经过 GAP 协议。实际上,我们在 Android 开发中,可以直接使用设备的 MAC 地址,发起连接,可以不经过扫描的步骤。这并不意味不需要经过 GAP,实际上在芯片级别已经给你做好了,蓝牙芯片发起连接,总是先扫描设备,扫描到了才会发起连接。

    GATT 连接需要特别注意的是:GATT 连接是独占的。也就是一个 BLE 外设同时只能被一个中心设备连接。一旦外设被连接,它就会马上停止广播,这样它就对其他设备不可见了。当设备断开,它又开始广播。

    中心设备和外设需要双向通信的话,唯一的方式就是建立 GATT 连接。

    1. GATT 连接的网络拓扑

    下图展示了 GTT 连接网络拓扑结构。这里很清楚的显示,一个外设只能连接一个中心设备,而一个中心设备可以连接多个外设。

    wps17

    一旦建立起了连接,通信就是双向的了,对比前面的 GAP 广播的网络拓扑,GAP 通信是单向的。如果你要让两个设备外设能通信,就只能通过中心设备中转。

    2. GATT 通信事务

    GATT 通信的双方是 C/S 关系。外设作为 GATT 服务端(Server),它维持了 ATT 的查找表以及 service 和 characteristic 的定义。中心设备是 GATT 客户端(Client),它向 Server 发起请求。需要注意的是,所有的通信事件,都是由客户端(也叫主设备,Master)发起,并且接收服务端(也叫从设备,Slave)的响应。

    一旦连接建立,外设将会给中心设备建议一个连接间隔(Connection Interval),这样,中心设备就会在每个连接间隔尝试去重新连接,检查是否有新的数据。但是,这个连接间隔只是一个建议,你的中心设备可能并不会严格按照这个间隔来执行,例如你的中心设备正在忙于连接其他的外设,或者中心设备资源太忙。

    下图展示一个外设(GATT 服务端)和中心设备(GATT 客户端)之间的数据交换流程,可以看到的是,每次都是主设备发起请求:

    wps18

    3. GATT 结构

    GATT 事务是建立在嵌套的Profiles, Services 和 Characteristics之上的的,如下图所示:
    wps19

    • Profile

    并不是实际存在于 BLE 外设上的,它只是一个被 Bluetooth SIG 或者外设设计者预先定义的 Service 的集合。

    例如心率Profile(Heart Rate Profile)就是结合了 Heart Rate Service 和 Device Information Service。

    一个设备可以实现多个配置文件。例如,一个设备可能包括心率监测仪和电量检测。

    • Service

    每个profile中会包含多个service,每个service代表从机的一种能力。

    是把数据分成一个个的独立逻辑项,它包含一个或者多个 Characteristic。每个 Service 有一个 UUID 唯一标识。 UUID 有 16 bit 的,或者 128 bit 的。16 bit 的 UUID 是官方通过认证的,需要花钱购买,128 bit 是自定义的,这个就可以自己随便设置。

    官方通过了一些标准 Service,以 Heart Rate Service为例,可以看到它的官方通过 16 bit UUID 是 0x180D,包含 3 个 Characteristic:Heart Rate Measurement, Body Sensor Location 和 Heart Rate ControPoint,并且定义了只有第一个是必须的,它是可选实现的。

    service可以理解为一个服务,在ble从机中,通过有多个服务,例如电量信息服务、系统信息服务等,每个service中又包含多个characteristic特征值。每个具体的characteristic特征值才是ble通信的主题。比如当前的电量是80%,所以会通过电量信息服务的characteristic特征值存在从机的profile里,这样主机就可以通过这个characteristic来读取80%这个数据。

    你可以在bluetooth.org 找到一个目前支持的基于GATT的配置文件和服务列表。

    • Characteristic

    在 Service 下面,又包括了许多的独立数据项,我们把这些独立的数据项称作 Characteristic,

    一个characteristic包括一个单一变量和0-n个用来描述characteristic变量的descriptor。

    与 Service 类似,每个 Characteristic 用 16 bit 或者 128 bit 的 UUID 唯一标识。你可以免费使用 Bluetooth SIG 官方定义的标准 Characteristic,使用官方定义的,可以确保 BLE 的软件和硬件能相互理解。当然,你可以自定义 Characteristic,这样的话,就只有你自己的软件和外设能够相互理解。

    举个例子, Heart Rate Measurement Characteristic,这是上面提到的 Heart Rate Service 必需实现的 Characteristic,它的 UUID 是 0x2A37。它的数据结构是,开始 8 bit 定义心率数据格式(是UINT8 还是 UINT16?),接下来就是对应格式的实际心率数据。

    实际上,和 BLE 外设打交道,主要是通过 Characteristic。你可以从 Characteristic 读取数据,也可以往 Characteristic 写数据。这样就实现了双向的通信。所以你可以自己实现一个类似串口(UART)的 Sevice,这个 Service 中包含两个 Characteristic,一个被配置只读的通道(RX),另一个配置为只写的通道(TX)。

    在 Android 开发中,建立蓝牙连接后,我们说的通过蓝牙发送数据给外围设备就是往这些 Characteristic 中的 Value 字段写入数据;外围设备发送数据给手机就是监听这些 Charateristic 中的 Value 字段有没有变化,如果发生了变化,手机的 BLE API 就会收到一个监听的回调。

    • Descriptor

    Descriptor用来描述characteristic变量的属性。

    每个characteristic可以对应一个或多个Description用于描述characteristic的信息或属性

    例如,一个descriptor可以规定一个人类可读的可读的描述,或者一个characteristic变量可接受的范围,或者一个characteristic变量特定的测量单位。

    蓝牙广播数据解析

    https://www.cnblogs.com/Free-Thinker/archive/2014/03/07/5872239.html

    蓝牙协议规范中的vo3 Part C

    BLE 中有两种角色 Centra和 Periphera,也就是中心设备和外围设备。中心设备可以主动连接外围设备,外围设备发送广播或者被中心设备连接。外围通过广播被中心设备发现,广播中带有外围设备自身的相关信息。

    广播包有两种: 广播包 (Advertising Data)和 响应包 (Scan Response),其中广播包是每个设备必须广播的,而响应包是可选的。

    数据包的格式如下图所示(图片来自官方 Spec):

    wps20

    每个包都是 31 字节,数据包中分为有效数据(significant)和无效数据(non-significant)两部分。

    • 有效数据部分 :包含若干个广播数据单元,每个数据单元称为 AD Structure 。

    如图中所示,AD Structure 的组成是:

      • 第一个字节是长度值 Len ,表示接下来的 Len 个字节是数据部分。
      • 数据部分的第一个字节表示数据的类型 AD Type ,剩下的 Len - 1 个字节是真正的数据 AD data 。
      • 其中 AD type 非常关键,决定了 AD Data 的数据代表的是什么和怎么解析,这个在后面会详细讲;
    • 无效数据部分 :因为广播包的长度必须是 31 个 byte,如果有效数据部分不到 31 byte,剩下的就用 0 补全。这部分的数据是无效的,解释的时候,忽略即可。

    The non-significant part extends the data when necessary and shalcontain all-zero octets

    AD Type 包括如下类型

    https://blog.csdn.net/slimmm/article/details/100583655

    https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/

    定义

    说明

    备注

    #define GAP_ADTYPE_FLAGS 0x01

    Discovery Mode: @ref GAP_ADTYPE_FLAGS_MODES

    flag说明了物理连接功能,比如有限发现模式,不支持经典蓝牙等。

    bit 0: LE 有限发现模式。

    bit 1: LE 普通发现模式。

    bit 2: 不支持 BR/EDR。

    bit 3: 对 Same Device Capable(Controller) 同时支持 BLE 和 BR/EDR。

    bit 4: 对 Same Device Capable(Host) 同时支持 BLE 和 BR/EDR。

    bit 5..7: 预留。

    #define GAP_ADTYPE_16BIT_MORE 0x02

    Service: More 16-bit UUIDs available

    Service UUID: 广播数据中一般都会把设备支持的 GATT Service 广播出来,用来告诉外面本设备所支持的 Service。有三种类型的 UUID:16 bit, 32bit, 128 bit。广播中,每种类型类型有有两个类别:完整和非完整的。这样就共有 6 种 AD Type。
    服务的 UUID,通知中央设备什么服务包括在此外围设备
    更多的16位可用UUID,但不是全部

    #define GAP_ADTYPE_16BIT_COMPLETE 0x03

    Service: Complete list of 16-bit UUIDs

    服务的 UUID,通知中央设备什么服务包括在此外围设备
    可用16位uuid的完整列表

    #define GAP_ADTYPE_32BIT_MORE 0x04

    Service: More 32-bit UUIDs available

    服务的 UUID,通知中央设备什么服务包括在此外围设备
    更多的32位可用UUID,但不是全部

    #define GAP_ADTYPE_32BIT_COMPLETE 0x05

    Service: Complete list of 32-bit UUIDs

    服务的 UUID,通知中央设备什么服务包括在此外围设备
    可用32位uuid的完整列表

    #define GAP_ADTYPE_128BIT_MORE 0x06

    Service: More 128-bit UUIDs available

    服务的 UUID,通知中央设备什么服务包括在此外围设备
    更多的128位可用UUID,但不是全部

    #define GAP_ADTYPE_128BIT_COMPLETE 0x07

    Service: Complete list of 128-bit UUIDs

    服务的 UUID,通知中央设备什么服务包括在此外围设备
    可用128位uuid的完整列表

    #define GAP_ADTYPE_LOCAL_NAME_SHORT 0x08

    Shortened locaname

    简称

    #define GAP_ADTYPE_LOCAL_NAME_COMPLETE 0x09

    Complete locaname

    完整名称

    #define GAP_ADTYPE_POWER_LEVE0x0A

    TX Power Level: 0xXX: -127 to +127 dBm

    发送功率

    #define GAP_ADTYPE_OOB_CLASS_OF_DEVICE 0x0D

    Simple Pairing OOB Tag: Class of device (3 octets)

    out-of-band,OOB- 带外数据
    简单配对OOB标签:设备类

    #define GAP_ADTYPE_OOB_SIMPLE_PAIRING_HASHC 0x0E

    Simple Pairing OOB Tag: Simple Pairing Hash C (16 octets)

    简单配对OOB标签:简单配对散列C

    #define GAP_ADTYPE_OOB_SIMPLE_PAIRING_RANDR 0x0F

    Simple Pairing OOB Tag: Simple Pairing Randomizer R (16 octets)

    简单配对OOB标签:简单配对随机器R

    #define GAP_ADTYPE_SM_TK 0x10

    Security Manager TK Value

    安全管理器TK值

    #define GAP_ADTYPE_SM_OOB_FLAG 0x11

    Security Manager OOB Flags

    安全管理器OOB标志

    #define GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE 0x12

    Min and Max values of tde connection interva(2 octets Min, 2 octets Max) (0xFFFF indicates no conn intervamin or max)

    从机连接间隔的最小值和最大值

    #define GAP_ADTYPE_SIGNED_DATA 0x13

    Signed Data field

    签名数据字段

    #define GAP_ADTYPE_SERVICES_LIST_16BIT 0x14

    Service Solicitation: list of 16-bit Service UUIDs

    服务搜寻:外围设备可以要请中心设备提供相应的 Service
    服务征集:16位服务uuid列表

    #define GAP_ADTYPE_SERVICES_LIST_128BIT 0x15

    Service Solicitation: list of 128-bit Service UUIDs

    服务征集:128位服务uuid列表

    #define GAP_ADTYPE_SERVICE_DATA 0x16

    Service Data - 16-bit UUID

    服务数据- 16位UUID

    #define GAP_ADTYPE_PUBLIC_TARGET_ADDR 0x17

    Public Target Address

    公共目标地址
    表示希望这个广播包被指定的目标设备处理,此设备绑定了公开地址,DATA 是目标地址列表,每个地址 6 字节。

    #define GAP_ADTYPE_RANDOM_TARGET_ADDR 0x18

    Random Target Address

    随机目标地址
    表示希望这个广播包被指定的目标设备处理,此设备绑定了随机地址,DATA 是目标地址列表,每个地址 6 字节。

    #define GAP_ADTYPE_APPEARANCE 0x19

    Appearance

    外观特性

    #define GAP_ADTYPE_ADV_INTERVA0x1A

    Advertising Interval

    广播时间间隔

    #define GAP_ADTYPE_LE_BD_ADDR 0x1B

    LE Bluetootd Device Address

    LE 蓝牙设备地址

    #define GAP_ADTYPE_LE_ROLE 0x1C

    LE Role

    LE 角色

    #define GAP_ADTYPE_SIMPLE_PAIRING_HASHC_256 0x1D

    Simple Pairing Hash C-256

    简单配对哈希C-256

    #define GAP_ADTYPE_SIMPLE_PAIRING_RANDR_256 0x1E

    Simple Pairing Randomizer R-256

    简单配对随机发生器R-256

    #define GAP_ADTYPE_SERVICE_DATA_32BIT 0x20

    Service Data - 32-bit UUID

    服务数据- 32位UUID

    #define GAP_ADTYPE_SERVICE_DATA_128BIT 0x21

    Service Data - 128-bit UUID

    服务数据- 128位UUID

    #define GAP_ADTYPE_3D_INFO_DATA 0x3D

    3D Information Data

    三维信息数据

    #define GAP_ADTYPE_MANUFACTURER_SPECIFIC 0xFF

    Manufacturer Specific Data: first 2 octets contain tde Company Identifier Code followed by tde additionamanufacturer specific data

    特定于制造商的数据:

    前两个字节包含设备公司标识码,

    然后是设备附加的特定于制造商的数据

    16bit 转为128 bit uuid

    https://www.cnblogs.com/Free-Thinker/p/11375265.html

    熟悉BLE技术同学应该对UUID不陌生,服务、特征值、描述都是有UUID格式定义。

    蓝牙广播中对服务UUID格式定义都有三种16 bit UUID、32 bit UUID、128 bit UUID。

    但是熟悉安卓开发的小伙伴都知道接口都UUID格式,fromString时候16bit的UUID该咋办呢?

    16bit和32bit的UUID与128bit的值之间转换关系:

    128_bit_UUID = 16_bit_UUID * 2^96 + Bluetooth_Base_UUID

    128_bit_UUID = 32_bit_UUID * 2^96 + Bluetooth_Base_UUID

    其中 Bluetooth_Base_UUID定义为 00000000-0000-1000-8000-00805F9B34FB

    如果你想说这是啥呀,那我这样说你应该可以明白点:

    若16 bit UUID为xxxx,那么128 bit UUID为0000xxxx-0000-1000-8000-00805F9B34FB

    若32 bit UUID为xxxxxxxx,那么128 bit UUID为xxxxxxxx-0000-1000-8000-00805F9B34FB

  • 相关阅读:
    react之引用echarts
    vue之生命周期
    算法之冒泡排序
    算法之快速排序
    算法题之统计字符串中出现最多的字母
    使用http-proxy-middleware 代理跨域
    div产生的滚动条返回顶部
    Django实战(18):提交订单
    Django实战(17):ajax !
    Django实战(16):Django+jquery
  • 原文地址:https://www.cnblogs.com/muouren/p/14133198.html
Copyright © 2020-2023  润新知