iOS 蓝牙开发 - 学习

iOS 中使用 Core Bluetooth 框架实现蓝牙通信。Core Bluetooth 是基于蓝牙 4.0 的低功耗模式实现的。

蓝牙的连接类似于 Client/Server 构架模型。中心设备作为客户端,周边设备作为服务端,扫描并建立连接进行数据交换。

image

CBCentralManager 类表示中心设备,扫描发现周边蓝牙设备,周边蓝牙设备用 CBPeripheral 类表示。

一个蓝牙设备可能存在多种用途,每一种用途对应一个服务,使用 CBService 表示,比如心率传感器有心率监测服务。

一个服务可以细分为多种特征,使用 CBCharacteristic 表示,比如心率监测服务中,含有心率的测量值、地理位置的定位等 Characteristic。

一个特征可以有多种描述,用 CBDescriptor 表示。

以上涉及到的 CBService,CBCharacteristic,CBDescriptor 类都继承自 CBAttribute,它们有一个共同的属性 CBUUID,用来作为唯一的标识。

Peripheral 作为 Server 端, Central 作为 Client, Peripheral 广播自己的 Services 和 Characteristics, Central 可以选择订阅某一个具体的 Service, 也可以一次性订阅全部的 Server(不建议这么做)。获取到某个 Service 之后,同样需要继续发现这个服务下的 Characteristics。Peripheral 和 Central 之间通过 Characteristic 建立一个双向的数据通道。

注意一定要用真机测试。

编码

在 iOS 10 之后需要在 Info.plist 文件里面设置 NSBluetoothPeripheralUsageDescription 字段,添加访问蓝牙权限的描述,否则强行访问蓝牙功能会造成 Crash。

开始,初始化一个中心设备:

CBCentralManager *centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];

_centralManager = centralManager;

这里有一个注意点,CBCentralManager 的创建是异步的,如果初始化完成之后没有被当前创建它的类所持有,就会在下一次 RunLoop 迭代的时候释放。当然 CBCentralManager 实例如果不是在 ViewController 中创建的,那么持有 CBCentralManager 的这个类在初始化之后也必须被 ViewController 持有,否则控制台会有如下的错误输出:

[CoreBluetooth] XPC connection invalid

如果成功初始化,就会回调 CBCentralManagerDelegate:

// 在 cetral 的状态变为 CBManagerStatePoweredOn 的时候开始扫描

  • (void)centralManagerDidUpdateState:(CBCentralManager *)central {

if (central.state == CBManagerStatePoweredOn) {

[_centralManager scanForPeripheralsWithServices:nil options:nil];

}

}

中心设备处于 PowerOn 状态的时候开始扫描周边设备,可以使用指定的 UUID 发现特定的 Service,也可以传入 nil,表示发现所有周边的蓝牙设备,不过还是建议只发现自己需要服务的设备。发现之后会回调如下方法:

  • (void)centralManager:(CBCentralManager *)central

didDiscoverPeripheral:(CBPeripheral *)peripheral

advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {

if (!peripheral.name) return; // Ingore name is nil peripheral.

if (![_peripheralsList containsObject:peripheral]) {

[_peripheralsList addObject:peripheral];

_peripherals = _peripheralsList.copy;

}

}

成功发现设备后选择一个 peripheral 建立连接,在建立连接之后停止发现:

[_centralManager connectPeripheral:peripheral options:nil];

连接成功后会继续回调 CBCentralManagerDelegate 中的方法:

  • (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {

peripheral.delegate = self;

// Client to do discover services method...

CBUUID *seriveUUID = [CBUUID UUIDWithString:@"d2009d00-6000-1000-8000-XXXX"];

// nil 代表发现所有服务。

[peripheral discoverServices:@[seriveUUID]];

}

连接成功该周边设备之后,再发现需要使用该设备的具体服务。

接下来就是响应 CBPeripheralDelegate 代理方法了。

成功发现周边设备的某个服务之后响应方法:

// 发现服务

  • (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error {

NSArray *services = peripheral.services;

if (services) {

CBService *service = services[0];

CBUUID *writeUUID = [CBUUID UUIDWithString: TRANSFER_SERVICE_UUID];

CBUUID *notifyUUID = [CBUUID UUIDWithString: TRANSFER_SERVICE_UUID];

[peripheral discoverCharacteristics:@[writeUUID, notifyUUID] forService:service]; // 发现服务

}

}

发现服务(CBService)之后,还需要发现该服务下的特征(Characteristic)。这里通常会有两中特征:写特征和通知特征。

发现特征之后一定要打开通知特性,否者写入数据之后,不会收到回复数据。

// 发现特征

  • (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error {

if (!error) {

NSArray *characteristicArray = service.characteristics;

if(characteristicArray.count > 1) {

CBCharacteristic *writeCharacteristic = characteristicArray[0];

CBCharacteristic *notifyCharacteristic = characteristicArray[1];

// 通知使能, YES enable notification only, NO disable notifications and indications

[peripheral setNotifyValue:YES forCharacteristic:notifyCharacteristic];

}

} else {

NSLog(@"Discover Charactertics Error : %@", error);

}

}

使用 writeCharactersitc 写入数据:

[peripheral writeValue:writeData.copy forCharacteristic:writeCharactersitc type:CBCharacteristicWriteWithResponse];

写入数据之后,在需要回复的前提下会回调如下两个代理方法:

// 写入成功

  • (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error {

if (!error) {

NSLog(@"Write Success");

} else {

NSLog(@"WriteVale Error = %@", error);

}

}

// 写入成功后的应答

  • (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {

if (error) {

NSLog(@"update value error: %@", error);

} else {

NSData *responseData = characteristic.value;

}

}

至此,一次完整的蓝牙通信就完成了。

蓝牙数据包的载荷比较小,在应答的过程中,经常需要进行拆包、组合。包的第一个字节代表包的序列号。

Demo 地址

参考

Core Bluetooth Overview

iOS开发之玩转蓝牙CoreBluetooth

关键概念

谈到蓝牙,很容易让人联想到蓝牙穿戴设备,好像听起来更靠近硬件层一些。苹果其实对iOS和OSX上的蓝牙已做了一层很好的封装,看过CoreBluetooth Framework的大致API之后,基本上就将其流程明白个大概。难点在于理解其工作模式和理清一些关键概念,比如Peripehral, Central, Service, characteristics等等,不要被这些陌生的单词吓到,网络协议的应用大多脱不了CS的架构模型,这里和大家一起对照传统的Client/Server架构来梳理下iOS和OSX上CoreBluetooth的重要知识点。我画了一张图,方便大家一目了然的明白CoreBluetooth的工作原理。

image

我们只需要把Peripehral, Central, Service, characteristics几个概念理清,再各自对应到我们之前关于CS的知识体系之中就可以轻松的做一层自己的封装了。

初次查看CoreBluetooth文档的时候,很容易把Central理解成Server,其实刚好相反,Peripheral才是我们的Server。正如上图所示,Peripheral和Central之间建立的是一对多的关系。每个Peripheral会以广播的模式告诉外界自己能提供哪些Service,这里Service的概念和我们传统CS架构当中的Service基本是一致的,每个PeriPheral可以提供多个Service,而每个Service呢,会包含多个characteristic,characteristic是个陌生但十分关键的概念,可以把characteristic理解成一个Service模块具体提供哪些服务,比如一个心率监测Service同时包含心率测量characteristic和地理位置定位characteristic。

Peripheral作为Server,Central作为Client,Peripheral广播自己的Service和characteristic,Central订阅某一个具体的characteristic,Peripheral就和Central之间通过characteristic建立了一个双向的数据通道,整个模型非常简洁而且符合我们CS的架构体系。接下来具体看下CoreBluetooth的相关API。

优雅的CoreBluetooth

首先值得开心一把的是iOS和OSX使用的是同一套API封装,都是基于CoreBluetooth Framework,只在极细小的地方有些差异,完全可以做一层library的封装在两个平台上无缝衔接使用。

在具体搭建基于CoreBluetooth应用之前,要先确立到底哪一方作为Peripheral,哪一方又是Central。Macbook,iPhone,iPad都能成为Peripheral或者Central。我们通过代码的方式再看一遍上面的架构流程。

Server端

创建Peripheral,也就是我们的Server:

_peripheral = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];

生成Service以备添加到Peripheral当中:

CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID] primary:YES];

生成characteristics以备添加到Service当中:

self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID] properties:CBCharacteristicPropertyNotify|CBCharacteristicPropertyWrite

value:nil permissions:CBAttributePermissionsReadable|CBAttributePermissionsWriteable];

建立Peripheral,Server,characteristics三者之间的关系并开始广播服务:

//建立关系

transferService.characteristics = @[self.transferCharacteristic];

[self.peripheral addService:transferService];

//开始广播

[self.peripheral startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] }];

Client端

创建我们的Central,也就是client:

_central = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

扫描可用的Peripheral:

[self.central scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]

options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];

扫描到Peripheral之后连接:

[self.central connectPeripheral:targetPeripheral options:nil];

连接成功之后查找可用的Service:

[peripheral discoverServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]];

找到Service之后,进一步查找可用的Characteristics并订阅:

//查找Characteristics

[peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]] forService:service];

查找到Characteristics订阅:

//订阅

[peripheral setNotifyValue:YES forCharacteristic:characteristic];

订阅之后Central和Peripheral之间就建立了一个双向的数据通道,后续二者之间的数据传输就可以通过characteristic来完成了。

数据传输

有了数据通道,接下来就是如何传输数据了。说到数据传输就免不了要确定应用层的协议,类似平时我们使用socket实现游戏的网络模块时,需要自定义应用层协议才能实现业务数据的交换,协议的设计这里就不展开说了,之前有过相关经验的童鞋完全可以把协议层迁移过来。

再看下Peripheral是如何向Central发送数据的,首先Peripheral会向自己的characteristic写数据:

[self.peripheral updateValue:chunk forCharacteristic:self.transferCharacteristic onSubscribedCentrals:@[self.central]];

Central那一端会通过如下回调收到来自Peripheral的数据流:

  • (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;

这里值得注意的是二者数据的发送与获取,是以二进制流的方式发送的,是NSData的形式封装的,Peripheral可以持续不停的发送二进制流,所以Central端收到的时候需要自己做协议的解析,根据自定义协议将整个流拆成一个个的业务Packet包。

而Central发送的时候却是封装成了一个个的Request,比如Central端调用如下API发送数据:

[self.discoveredPeripheral writeValue:data forCharacteristic:self.discoveredCharacterstic type:CBCharacteristicWriteWithoutResponse];

Peripheral端会收到如下回调:

  • (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests

数据被封装成了单独的CBATTRequest,直接去Request当中取value就可以获取到Central所发送过来的数据。

已知的坑

我之前测试协议的时候发现一个不大不小的坑,多个Central(比如A和B)端同时一个Peripheral发送数据的时候,Peripheral会收到多个CBATTRequest,奇怪的是每个CBATTRequest当中的Central都会指向最先建立连接的A,结果导致Peripheral端无法判断write请求的数据来自哪一个Central。

简单脑洞

蓝牙不仅仅能应用于穿戴式设备,还能做一些好玩的小众应用或者游戏,其本质是一个小型封闭的局域网,不用经过第三方的Server或者Cloud,很安全。

比如两台iPhone设备之间通过基于蓝牙的IM App进行聊天(距离这么近,为什么不当面聊,黑人问号?)。

比如一些基于蓝牙对战的小游戏。

比如通过蓝牙在iPhone和Macbook之间做数据同步。

蓝牙常遇缩写

MFI ======= make for ipad ,iphone, itouch 专们为苹果设备制作的设备

BLE ==== buletouch low energy,蓝牙4.0设备因为低耗电,所以也叫做BLE

peripheral,central == 外设和中心,发起连接的时central,被连接的设备为perilheral

service and characteristic === 服务和特征 每个设备会提供服务和特征,类似于服务端的api,但是机构不同。每个外设会有很多服务,每个服务中包含很多字段,这些字段的权限一般分为 读read,写write,通知notiy几种,就是我们连接设备后具体需要操作的内容。

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

MFI === 开发使用ExternalAccessory 框架

4.0 BLE === 开发使用CoreBluetooth 框架

每个设备都会有一些服务,每个服务里面都会有一些特征,特征就是具体键值对,提供数据的地方。每个特征属性分为这么几种:读,写,通知这么几种方式。

//objcetive c特征的定义枚举

typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {

CBCharacteristicPropertyBroadcast = 0x01,

CBCharacteristicPropertyRead = 0x02,

CBCharacteristicPropertyWriteWithoutResponse = 0x04,

CBCharacteristicPropertyWrite = 0x08,

CBCharacteristicPropertyNotify = 0x10,

CBCharacteristicPropertyIndicate = 0x20,

CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,

CBCharacteristicPropertyExtendedProperties = 0x80,

CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x100,

CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x200

};

蓝牙中心模式流程

1. 建立中心角色

2. 扫描外设(discover)

3. 连接外设(connect)

4. 扫描外设中的服务和特征(discover)

  • 4.1 获取外设的services

  • 4.2 获取外设的Characteristics,获取Characteristics的值,获取Characteristics的Descriptor和Descriptor的值

5. 与外设做数据交互(explore and interact)

6. 订阅Characteristic的通知

7. 断开连接(disconnect)

准备环境

1 xcode

2 开发证书和手机(蓝牙程序需要使用使用真机调试,使用模拟器也可以调试,但是方法很蛋疼,我会放在最后说)

3 蓝牙外设

蓝牙外设模式流程

1. 启动一个Peripheral管理对象

2. 本地Peripheral设置服务,特性,描述,权限等等

3. Peripheral发送广告

4. 设置处理订阅、取消订阅、读characteristic、写characteristic的委托方法

蓝牙设备状态

1. 待机状态(standby):设备没有传输和发送数据,并且没有连接到任何设

2. 广播状态(Advertiser):周期性广播状态

3. 扫描状态(Scanner):主动寻找正在广播的设备

4. 发起链接状态(Initiator):主动向扫描设备发起连接。

5. 主设备(Master):作为主设备连接到其他设备。

6. 从设备(Slave):作为从设备连接到其他设备。

蓝牙设备的五种工作状态

准备(standby)

广播(advertising)

监听扫描(Scanning

发起连接(Initiating)

已连接(Connected)

蓝牙和版本的使用限制

蓝牙2.0 === 越狱设备

蓝牙4.0 === IOS6 以上

MFI认证设备(Make For ipod/ipad/iphone) === 无限制

名词解释

GAAT : Generic Attribute Profile , GATT配置文件是一个通用规范,用于在BLE链路上发送和接收被称为“属性”的数据块。目前所有的BLE应用都基于GATT。 蓝牙SIG规定了许多低功耗设备的配置文件。配置文件是设备如何在特定的应用程序中工作的规格说明。注意一个设备可以实现多个配置文件。例如,一个设备可能包括心率监测仪和电量检测。

Characteristic 一个characteristic包括一个单一变量和0-n个用来描述characteristic变量的descriptor,characteristic可以被认为是一个类型,类 似于类。

Descriptor Descriptor用来描述characteristic变量的属性。例如,一个descriptor可以规定一个可读的描述,或者一个characteristic变量可接受的范围,或者一个characteristic变量特定的测量单位。 Service service是characteristic的集合。例如,你可能有一个叫“Heart Rate Monitor(心率监测仪)”的service,它包括了很多characteristics,如“heart rate measurement(心率测量)”等。你可以在bluetooth.org 找到一个目前支持的基于GATT的配置文件和服务列表。

蓝牙2.0和4.0是什么区别

蓝牙2.0是我们所使用的最原始的版本,蓝牙4.0是截至目前研究出的最新版的蓝牙,是在原来蓝牙3.0的版本上进行升级之后的版本。两者区别是:

蓝牙4.0的兼容性很强,可以兼容蓝牙所有版本,但是蓝牙2.0的兼容性就不行了,不能兼容高级版本的蓝牙设备。

蓝牙2.0的传输速度只能达到当前速率的三倍左右,但是蓝牙4.0的传输速度是非常快,而且还可以多设备连接,最少的时候可以是8个,最多的时候可以达到27个。蓝牙2.0只能进行短距离的数据传输,扩大范围就不行了,但是蓝牙4.0的无线范围已经扩大很多了,现在最大范围已经可以超过100米了。

开着蓝牙时手机耗电就非常快,蓝牙4.0就在耗能减小很多,现在的4.0版本和2.0版本相比较,可以减少将近90%的耗电量。

在成本上蓝牙4.0所投入的远远低于蓝牙2.0,这也是升级后的蓝牙4.0的一大特性。

蓝牙2.0 是 1.2 的改良提升版,传输率约在 1.8M/s~2.1M/s,开始支持双工模式——即一面作语音通讯,同时亦可以传输档案/高质素图片,2.0 版本当然也支持 Stereo 运作。

蓝牙4.0规范于2010年7月7日正式发布,其最大意义在于低功耗,同时加强不同OEM厂商之间的设备兼容性,并且降低延迟,理论最高传输速度依然为24Mbps(即3MB/s),有效覆盖范围扩大到100米(之前的版本为10米)。该标准芯片被大量的手机、平板所采用。

蓝牙4.0的版本比蓝牙2.0的高,4.0的传输速度更快,同时功耗更低,2.0的蓝牙设备之间配对,需要手动输入密码,4.0的蓝牙设备之间配对,会自动生成密码,只需要点击确认即可。

关于蓝牙2.0和4.0区别

1、采用蓝牙4.0低功耗。

优点:不需做苹果解密芯片,不需MFI苹果认证。

缺点:数据量不能太大、手机必须是蓝牙4.0的;(蓝牙4.0可以支持苹果 iPhone4S、iPhone5等具有蓝牙4.0功能的苹果IOS设备)

2、采用蓝牙2.1。

优点:数据量可以大一些、手机不需要蓝牙4.0,

缺点:需要MFI认证,认证后可以购买苹果指定的解密芯片,方可使用蓝牙传输数据。MFI认证约9.9万美元/款产品,认证周期约半年。(蓝牙2.1+MFI认证芯片,可以支持苹果iPhone4、iPhone4S、iPhone5等具有蓝牙2.1以上功能的苹果IOS设备)

CoreBluetooth 框架

功能:蓝牙4.0协议之间信息传输,支持iOS和Android设备。

传输方式:蓝牙

支持系统:iOS、Android

http://blog.csdn.net/pony_maggie/article/details/26740237

Socket

功能:通过TCP或UDP进行相同局域网内信息传输,支持iOS和Android设备。

传输方式:WiFi

支持系统:iOS、Android

http://blog.csdn.net/kesalin/article/details/8798039

服务和特征都是用UUID来唯一标识的,UUID的概念如果不清楚请自行google,国际蓝牙组织为一些很典型的设备(比如测量心跳和血压的设备)规定了标准的service UUID(特征的UUID比较多,这里就不列举了),如下:

define BLE_UUID_ALERT_NOTIFICATION_SERVICE 0x1811

define BLE_UUID_BATTERY_SERVICE 0x180F

define BLE_UUID_BLOOD_PRESSURE_SERVICE 0x1810

define BLE_UUID_CURRENT_TIME_SERVICE 0x1805

define BLE_UUID_CYCLING_SPEED_AND_CADENCE 0x1816

define BLE_UUID_DEVICE_INFORMATION_SERVICE 0x180A

define BLE_UUID_GLUCOSE_SERVICE 0x1808

define BLE_UUID_HEALTH_THERMOMETER_SERVICE 0x1809

define BLE_UUID_HEART_RATE_SERVICE 0x180D

define BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812

define BLE_UUID_IMMEDIATE_ALERT_SERVICE 0x1802

define BLE_UUID_LINK_LOSS_SERVICE 0x1803

define BLE_UUID_NEXT_DST_CHANGE_SERVICE 0x1807

define BLE_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E

define BLE_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806

define BLE_UUID_RUNNING_SPEED_AND_CADENCE 0x1814

define BLE_UUID_SCAN_PARAMETERS_SERVICE 0x1813

define BLE_UUID_TX_POWER_SERVICE 0x1804

define BLE_UUID_CGM_SERVICE 0x181A

数据的读分为两种,一种是直接读(reading directly),另外一种是订阅(subscribe)。从名字也能基本理解两者的不同。实际使用中具体用一种要看具体的应用场景以及特征本身的属性。

经典蓝牙(classic Bluetooth)

低功耗蓝牙(Bluetooth low energy,简称BLE或者LE)

首先,在2010年以前,当我们谈论蓝牙的时候,就是在说经典蓝牙,因为那个时候还没有低功耗蓝牙。经典蓝牙由蓝牙技术联盟(Bluetooth special interest group,简称Bluetooth SIG)提出并维护,每次SIG发布一版新的蓝牙规格时,都会指明规格的版本号,比如说蓝牙规格1.0/2.0等,其中蓝牙1.0大概在1999年左右发布的,蓝牙2.0在2004年发布,蓝牙2.1在2007年发布,蓝牙3.0在2009年发布,他们都是在2010年之前发布的,因此蓝牙1.0/2.0/2.1/3.0都是讲经典蓝牙的,里面没有任何关于低功耗蓝牙的描述。如果你打开蓝牙3.0规格书,你会发现经典蓝牙包括BR,EDR和HS(AMP)三种模式。

简单来说,只要是蓝牙技术联盟(SIG)发布的技术,即可以称为蓝牙技术。2010年,SIG联盟合并了Wibree联盟(注:Wibree联盟由Nokia和Nordic等创立,旨在为手机周边设备寻找一种更低功耗的无线通信技术),并把Wibree联盟提出的低功耗无线技术重新命名为低功耗蓝牙技术(BLE),从此BLE也成了一种蓝牙技术。相应地,2010年发布的蓝牙4.0规格就同时包含经典蓝牙和低功耗蓝牙,也就是说,从蓝牙4.0之后,蓝牙才分经典蓝牙和低功耗蓝牙。其实,“经典蓝牙”这个称谓不是非常专业,它是人民群众为了口头上的方便而创造出来的,在蓝牙4.0规格中,SIG定义了四种蓝牙controller技术:BR,EDR,AMP和LE,也就是说,蓝牙只有一种蓝牙,那就是SIG的蓝牙,而蓝牙技术本身包含四种类型:BR,EDR,AMP和LE,由于LE是2010年才提出的,比较新,因此为了说起来方便,人们把之前的BR/EDR/AMP技术称为经典蓝牙技术。大家千万不要以为蓝牙4.0之后,蓝牙只有LE一种模式!

为了区分所谓的低功耗蓝牙和经典蓝牙,蓝牙4.0发布之初,SIG还特意将Bluetooth low engery对外宣传为Bluetooth smart,而“Bluetooth”继续用来指代经典蓝牙,Bluetooth smart ready则用来表示双模蓝牙(即同时支持经典蓝牙和低功耗蓝牙),所以市面上有很多关于Bluetooth smart,Bluetooth,Bluetooth smart ready的宣传材料,但是这些名字不仅没有起到传播Bluetooth品牌的作用,还让众多消费者和开发者感到混淆,所以后来SIG不再频繁使用Bluetooth smart等名字,更多的是与蓝牙4.0规格对齐,直接使用LE,BR,EDR等名字进行宣传,对外也不再宣传低功耗蓝牙和经典蓝牙的不同,并将两者统一到“Bluetooth(蓝牙)”这个大品牌下面一起宣传。

蓝牙技术联盟(SIG)后续发布的蓝牙4.1/4.2/5.0,都是同时包含低功耗蓝牙和经典蓝牙的。所以大家开发蓝牙应用的时候,一定要搞清楚自己是要开发低功耗蓝牙应用还是经典蓝牙应用,两者的应用场景是不同的。一般而言,经典蓝牙主要应用在蓝牙电话接听,蓝牙耳机,蓝牙音箱等场合,低功耗蓝牙应用在可穿戴设备,IoT智能设备,健身设备,蓝牙鼠标键盘等电池供电场合。当然,经典蓝牙也可以用电池供电,但LE对电池的要求更低,甚至可以用纽扣电池供电,而续航时间却很长,有的LE设备可以达到几年。下图对经典蓝牙和低功耗蓝牙的典型应用场景进行了总结。

image

需要引起大家注意的是,经典蓝牙和低功耗蓝牙两者物理层调制解调方式是不一样的,所以低功耗蓝牙设备和经典蓝牙设备两者之间是不能相互通信的,选型的时候千万不要搞混,如果主设备是低功耗蓝牙设备,从设备也必须是低功耗蓝牙设备;同样,经典蓝牙的从设备也只能和经典蓝牙的主设备进行通信。不过市场上还有一种双模蓝牙设备,即同时支持低功耗蓝牙和经典蓝牙,比如我们天天用到的手机,手机可以和经典蓝牙设备通信,也可以和低功耗蓝牙设备通信,如前所述,这不代表低功耗蓝牙设备可以和经典蓝牙设备通信,其实手机使用了分时机制来达到同时和低功耗蓝牙设备以及经典蓝牙设备通信的目的,即手机让双模蓝牙芯片不断地在低功耗蓝牙模式和经典蓝牙模式之间进行切换,以同时支持低功耗蓝牙设备和经典蓝牙设备。低功耗蓝牙方案,经典蓝牙方案,还是双模蓝牙方案,大家选型的时候一定要弄明白他们之间的区别,以选择适合自己的蓝牙方案。

你可能感兴趣的:(iOS 蓝牙开发 - 学习)