之蓝牙5.0使用,Bluetooth荣辱与共基础知识

亚洲城ca88手机版官网 4
亚洲城ca88手机版官网

故事背景:

本文介绍了蓝牙的概念以及具体的使用步骤.

蓝牙2.0为传统蓝牙,传统蓝牙也称为经典蓝牙.蓝牙4.0因为低耗电,所以也叫做低功耗蓝.它将三种规格集一体,包括传统蓝牙技术、高速技术和低耗能技术.

  1. 双模式低功耗蓝牙功能集成在现有的经典蓝牙控制器中,或在现有经典蓝牙技术芯片上增加低功耗堆栈,整体架构基本不变,因此成本增加有限.
  2. 单模式面向高度集成、紧凑的设备,使用一个轻量级连接层(Link
    Layer)提供超低功耗的待机模式操作、简单设备恢复和可靠的点对多点数据传输,还能让联网传感器在蓝牙传输中安排好低功耗蓝牙流量的次序,同时还有高级节能和安全加密连接.

  1. 蓝牙2.0,不上架使用私有API,手机需要越狱.
  2. 蓝牙2.0,要上架进行MFI认证,使用ExternalAccessory框架.手机不需要越狱.
  3. 蓝牙4.0,要上架使用CoreBluetooth框架,手机不需要越狱.(CoreBluetooth是基于BLE来开发的)
  4. 说明对于小的硬件厂商来说,MFI认证通过几率不大,不仅耗钱还耗时,所以,还是推荐使用蓝牙4.0.(MFI:Make
    for ipad ,iphone, itouch 专们为苹果设备制作的设备)

公司要求iOS端需要和钢琴进行蓝牙连接并进行数据通信,我以为钢琴是蓝牙4.0,然后快速集成CoreBluetooth框架写了一个demo,扫描外设时,没有发现钢琴的蓝牙名称,可是用iphone打开系统设置,可以发现钢琴对应的蓝牙.问了安卓的同事,得知钢琴的蓝牙只有2.0的模块,所以,安卓端是用2.0蓝牙进行交互的.公司决定不做MFI认证,改用蓝牙4.0.在与硬件厂商交涉的过程中,得知钢琴中的蓝牙是4.0的,但是,他们在设计蓝牙板子的时候,没有集成低功耗技术.之后,板子寄回硬件厂商,添加BLE模块.这才踏上蓝牙4.0的正轨.

蓝牙常见名称和缩写

  • 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 框架

为什么要研究IOS的蓝牙呢?

1.基本知识

central:中心,连接硬件的设备.peripheral:外设,被连接的硬件.说明:外设在一直广播,当你创建的中心对象在扫描外设时,就能够发现外设.如图所示:

亚洲城ca88手机版官网 1中心和外设关系图

service:服务.characteristic:特征.说明:一个外设包含多个服务,而每一个服务中又包含多个特征,特征包括特征的值和特征的描述.每个服务包含多个字段,字段的权限有read、write、notify.

亚洲城ca88手机版官网 2设备、服务、特征关系图

蓝牙基础知识

CoreBluetooth框架的核心其实是两个东西,peripheral和central,
可以理解成外设和中心。对应他们分别有一组相关的API和类

亚洲城ca88手机版官网 3

截图1

  • 这两组api分别对应不同的业务场景,左侧叫做中心模式,就是以你的app作为中心,连接其他的外设的场景,而右侧称为外设模式,使用手机作为外设别其他中心设备操作的场景。

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

//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
  };

外设、服务、特征间的关系

亚洲城ca88手机版官网 4

答:当然是工作需要啦,公司有个项目是做心电测量的,主要就是通过手持嵌入式设备测量心电,通过蓝牙将数据传送到手机(安卓,IOS),然后手机端解析数据包并绘制曲线,最后上传到服务器保存。目前已经完成了安卓设备的APP开发工作,支持大多数的主流安卓设备(主要安卓各厂商的蓝牙不同,完全兼容希望不大),然后Boss就打算继续开发IOS的版本了,遂让我这个做QT的小白从头搞起IOS。

2.蓝牙4.0分为两种模式
  • 中心模式流程
    1. 建立中心角色
      [[CBCentralManager alloc] initWithDelegate:self queue:nil]
    2. 扫描外设 scanForPeripherals
    3. 发现外设 didDiscoverPeripheral
    4. 连接外设 connectPeripheral4.1 连接失败
      didFailToConnectPeripheral4.2 连接断开
      didDisconnectPeripheral4.3 连接成功 didConnectPeripheral
    5. 扫描外设中的服务 discoverServices5.1 发现并获取外设中的服务
      didDiscoverServices
    6. 扫描外设对应服务的特征 discoverCharacteristics6.1
      发现并获取外设对应服务的特征
      didDiscoverCharacteristicsForService亚洲城ca88手机版官网,6.2 给对应特征写数据
      writeValue:forCharacteristic:type:
    7. 订阅特征的通知 setNotifyValue:forCharacteristic:7.1
      根据特征读取数据 didUpdateValueForCharacteristic
  • 外设模式流程
    1. 建立外设角色
    2. 设置本地外设的服务和特征
    3. 发布外设和特征
    4. 广播服务
    5. 响应中心的读写请求
    6. 发送更新的特征值,订阅中心

1.本文采用中心模式导入CoreBluetooth框架,#import <CoreBluetooth/CoreBluetooth.h>2.遵守CBCentralManagerDelegate,CBPeripheralDelegate协议3.添加属性

// 中心管理者(管理设备的扫描和连接)@property (nonatomic, strong) CBCentralManager *centralManager;// 存储的设备@property (nonatomic, strong) NSMutableArray *peripherals;// 扫描到的设备@property (nonatomic, strong) CBPeripheral *cbPeripheral;// 文本@property (weak, nonatomic) IBOutlet UITextView *peripheralText;// 外设状态@property (nonatomic, assign) CBManagerState peripheralState;

常量,具体服务和特征是读还是写的类型,问公司硬件厂商,或者问同事.

// 蓝牙4.0设备名static NSString * const kBlePeripheralName = @"公司硬件蓝牙名称";// 通知服务static NSString * const kNotifyServerUUID = @"FFE0";// 写服务static NSString * const kWriteServerUUID = @"FFE1";// 通知特征值static NSString * const kNotifyCharacteristicUUID = @"FFE2";// 写特征值static NSString * const kWriteCharacteristicUUID = @"FFE3";

4.创建中心管理者

- (CBCentralManager *)centralManager{ if (!_centralManager) { _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; } return _centralManager;}

创建存储设备数组

- (NSMutableArray *)peripherals{ if (!_peripherals) { _peripherals = [NSMutableArray array]; } return _peripherals;}

5.扫描设备之前会调用中心管理者状态改变的方法

// 当状态更新时调用- centralManagerDidUpdateState:(CBCentralManager *)central{ switch (central.state) { case CBManagerStateUnknown:{ NSLog; self.peripheralState = central.state; } break; case CBManagerStateResetting: { NSLog; self.peripheralState = central.state; } break; case CBManagerStateUnsupported: { NSLog(@"不支持的状态"); self.peripheralState = central.state; } break; case CBManagerStateUnauthorized: { NSLog(@"未授权的状态"); self.peripheralState = central.state; } break; case CBManagerStatePoweredOff: { NSLog; self.peripheralState = central.state; } break; case CBManagerStatePoweredOn: { NSLog(@"开启状态-可用状态"); self.peripheralState = central.state; } break; default: break; }}

扫描设备

// 扫描设备- scanForPeripherals{ [self.centralManager stopScan]; NSLog; [self showMessage:@"扫描设备"]; if (self.peripheralState == CBManagerStatePoweredOn) { // 扫描所有设备,传入nil,代表所有设备. [self.centralManager scanForPeripheralsWithServices:nil options:nil]; }}

6.扫描到设备并开始连接

/** 扫描到设备 @param central 中心管理者 @param peripheral 扫描到的设备 @param advertisementData 广告信息 @param RSSI 信号强度 */- centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{ [self showMessage:[NSString stringWithFormat:@"发现设备,设备名:%@",peripheral.name]]; if (![self.peripherals containsObject:peripheral]) { [self.peripherals addObject:peripheral]; NSLog(@"%@",peripheral); if ([peripheral.name isEqualToString:kBlePeripheralName]) { [self showMessage:[NSString stringWithFormat:@"设备名:%@",peripheral.name]]; self.cbPeripheral = peripheral; [self showMessage:@"开始连接"]; [self.centralManager connectPeripheral:peripheral options:nil]; } }}

7.连接的三种状态,如果连接成功,则扫描所有服务(也可以扫描指定服务)连接失败重连

/** 连接失败 @param central 中心管理者 @param peripheral 连接失败的设备 @param error 错误信息 */- centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{ [self showMessage:@"连接失败"]; if ([peripheral.name isEqualToString:kBlePeripheralName]) { [self.centralManager connectPeripheral:peripheral options:nil]; }}

连接断开重连

/** 连接断开 @param central 中心管理者 @param peripheral 连接断开的设备 @param error 错误信息 */- centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{ [self showMessage:@"断开连接"]; if ([peripheral.name isEqualToString:kBlePeripheralName]) { [self.centralManager connectPeripheral:peripheral options:nil]; }}

连接成功并扫描服务

/** 连接成功 @param central 中心管理者 @param peripheral 连接成功的设备 */- centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{ NSLog(@"连接设备:%@成功",peripheral.name); [self showMessage:[NSString stringWithFormat:@"连接设备:%@成功",peripheral.name]]; // 设置设备的代理 peripheral.delegate = self; // services:传入nil代表扫描所有服务 [peripheral discoverServices:nil];}

8.发现服务并扫描服务对应的特征

/** 扫描到服务 @param peripheral 服务对应的设备 @param error 扫描错误信息 */- peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{ // 遍历所有的服务 for (CBService *service in peripheral.services) { NSLog(@"服务:%@",service.UUID.UUIDString); // 获取对应的服务 if ([service.UUID.UUIDString isEqualToString:kWriteServerUUID] || [service.UUID.UUIDString isEqualToString:kNotifyServerUUID]) { // 根据服务去扫描特征 [peripheral discoverCharacteristics:nil forService:service]; } }}

9.扫描到对应的特征,写入特征的值,并订阅指定的特征通知.

/** 扫描到对应的特征 @param peripheral 设备 @param service 特征对应的服务 @param error 错误信息 */- peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{ // 遍历所有的特征 for (CBCharacteristic *characteristic in service.characteristics) { NSLog(@"特征值:%@",characteristic.UUID.UUIDString); // 获取对应的特征 if ([characteristic.UUID.UUIDString isEqualToString:kWriteCharacteristicUUID]) { // 写入数据 [self showMessage:@"写入特征值"]; for (Byte i = 0x0; i < 0x73; i++) { // 让钢琴的每颗灯都亮一次 Byte byte[] = {0xf0, 0x3d, 0x3d, i, 0x02,0xf7}; NSData *data = [NSData dataWithBytes:byte length:6]; [peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse]; } } if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID]) { // 订阅特征通知 [peripheral setNotifyValue:YES forCharacteristic:characteristic]; } }}

10.根据特征读取到数据

/** 根据特征读到数据 @param peripheral 读取到数据对应的设备 @param characteristic 特征 @param error 错误信息 */- peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error{ if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID]) { NSData *data = characteristic.value; NSLog(@"%@",data); }}

读取值打印结果:

2017-04-25 12:34:41.876974+0800 蓝牙4.0Demo[1745:346611] <9f5436>2017-04-25 12:34:41.983016+0800 蓝牙4.0Demo[1745:346611] <8f5440>2017-04-25 12:34:42.154821+0800 蓝牙4.0Demo[1745:346611] <9f5649>2017-04-25 12:34:42.239481+0800 蓝牙4.0Demo[1745:346611] <8f5640>

提示:上Appstore下载LightBlue,进行蓝牙通信测试.

iOS开发之蓝牙使用

iOS开发之蓝牙使用

蓝牙4.0Demo

蓝牙中心模式流程

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. 启动一个Peripheral管理对象
2. 本地Peripheral设置服务,特性,描述,权限等等
3. Peripheral发送广告
4. 设置处理订阅、取消订阅、读characteristic、写characteristic的委托方法

做IOS的蓝牙开发需要哪些准备工作?

蓝牙设备状态

1. 待机状态(standby):设备没有传输和发送数据,并且没有连接到任何设
2. 广播状态(Advertiser):周期性广播状态
3. 扫描状态(Scanner):主动寻找正在广播的设备
4. 发起链接状态(Initiator):主动向扫描设备发起连接。
5. 主设备(Master):作为主设备连接到其他设备。
6. 从设备(Slave):作为从设备连接到其他设备。

答:用了一上午的时间看了各种大神的解答,受益匪浅,打算选择一种较好的方案实现我的IOS蓝牙之旅,上网各种找啊,把CocoaChina和Code4App翻了个底朝天,大多数都是坏消息,为什么呢,客官听我娓娓道来。

蓝牙设备的五种工作状态

  • 准备(standby)
  • 广播(advertising)
  • 监听扫描(Scanning)
  • 发起连接(Initiating)
  • 已连接(Connected)

 

蓝牙和版本的使用限制

  • 蓝牙2.0 === 越狱设备
  • 蓝牙4.0 === IOS6 以上
  • MFI认证设备(Make For ipod/ipad/iphone) === 无限制

你对IOS蓝牙了解多少?

名词解释

  • 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的配置文件和服务列表。

答:首先IOS设备本身的蓝牙并不是用来给你传输文件的,这点你要深切的理解,苹果之所以给他们装上蓝牙不过是让你练练蓝牙耳机啊,蓝牙音箱之类的,因为非越狱苹果上面听歌不都是要花钱的么,如果你用蓝牙把歌曲传给别人,那不是侵权了么(当然,在TC没有侵权一说),所以啊,苹果在硬件上面就把你传输文件给限制了。

参考阅读

GATT
Profile简介

本文转载自:http://liuyanwei.jumppo.com/

而且苹果在蓝牙4.0之前还有个特别变态的,就是只有IOS设备和苹果认证的MFI设备才可以被IOS设备检索到,所以啊,什么安卓蓝牙啊,自己做的蓝牙啊,想连上苹果,告诉你,木有可能!!!

但是,在蓝牙4.0出来之后(注意,硬件上要4s以上,系统要ios6以上才能支持4.0),苹果开放了BLE通道,真是屌丝的福音啊,我们这些没有MFI认证的蓝牙设备终于可以连接非越狱的苹果了,所以也可以开发蓝牙应用咯。但是啊,这得是蓝牙4.0才有的,也就是说爱疯4也不支持哦,所以完全兼容还是没可能。

注:上面说的都是针对非越狱的IOS设备的,越狱的当然有更好的办法了,办法下面细说。

 

首先,你要了解你的目的是什么,一般的IOS蓝牙开发有以下三种目的:

  1. IOS设备和IOS设备之间交互

好消息是:ios6.0可以把iPhone手机当从设备了,可以两台iPhone通过蓝牙通信传数据了,有点类似spp协议

坏消息是:我们需要的不是这种模式

这种模式通常用于两个使用IOS设备的土豪之间互相切磋游戏,玩个飞车什么的,需要注意的是

 

  1. IOS设备与MFI认证设备交互

什么是MFI认证呢?意思是(Make For
ipod/ipad/iphone),只有少数的硬件厂商才有苹果的MFI认证,如果你看到这,你的蓝牙设备还没设计,而且想发布在AppStore上,而且打算使用蓝牙4.0以下(4.0就不需要MFI了,福音),那你还是找个MFI认证的硬件开始做吧,我们公司已经有产品了,不可能重新设计,方案Pass了。

好消息是:如果你的蓝牙模块还没设计,打算在AppStore上发布,打算使用蓝牙4.0以下(IOS设备都兼容),那你就抓紧找MFI认证的蓝牙模块吧

坏消息是:我们不可能重新设计,所以舍弃

 

  1. IOS设备与非IOS设备交互

这就是我们的现状了,根据这个现状,我们能分析出两种情况:

a. 我想做蓝牙4.0以下的,这样iphone4也能用了

好消息:确实可以兼容iphone4,但是由于苹果封闭,没有那个API给你调,苹果上也根本检索不到非IOS设备,所以你就需要越狱了,调用私有Api连接设备

坏消息:只有越狱的手机才能用,发布到AppStore是妄想

b. 我想做蓝牙4.0的,不全兼容也没事,我想发布在AppStore上

好消息:苹果开放了4.0的BLE通道,你可以用BLE通道通信,而且4.0设备也能检索到

坏消息:对IOS版本和IOS设备双重要求,肯定不能全兼容了

 

所以,根据你自己的实际情况,选择方案,现总结出以下几种方案:

  1. 情景:蓝牙2.0,发布在AppStore上

答:使用MFI认证的蓝牙模块设计你的蓝牙产品

特点:不越狱就能用,IOS设备全兼容

  1. 情景:蓝牙2.0,不用MFI

答:不能用苹果的Api了,使用私有Api连接设备

特点:只能越狱的手机才能用了,IOS设备全兼容

  1. 情景:蓝牙4.0

答:使用BLE通道

特点:IOS设备不完全兼容,无需越狱,无需使用MFI,可发布在AppStore上

为什么要研究IOS的蓝牙呢?
答:当然是工作需要啦,公司有个项目是做心电测量的,主要就是通过手持嵌入式设备测量心电,通…

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图