zoukankan      html  css  js  c++  java
  • 蓝牙基础

    参考

    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

  • 相关阅读:
    LeetCode 32. 最长有效括号(Longest Valid Parentheses)
    LeetCode 141. 环形链表(Linked List Cycle)
    LeetCode 160. 相交链表(Intersection of Two Linked Lists)
    LeetCode 112. 路径总和(Path Sum)
    LeetCode 124. 二叉树中的最大路径和(Binary Tree Maximum Path Sum)
    LightGBM新特性总结
    sql service 事务与锁
    C#泛型实例详解
    C# 中的委托和事件(详解)
    C# DateTime日期格式化
  • 原文地址:https://www.cnblogs.com/muouren/p/14133198.html
Copyright © 2011-2022 走看看