iOS蓝牙Ble4.0开发运动手环,数据的交互处理

背景:

最近公司项目需要接运动手环,获取运动步数,设备时间,重置设备时间等功能,需要进行蓝牙传输。

前言:

1.当前iOS中开发蓝牙所运用的系统库是<CoreBluetooth/CoreBluetooth.h>。

2.蓝牙外设必须为4.0及以上,否则无法开发,蓝牙4.0设备因为低耗电,所以也叫做BLE。

3.CoreBluetooth框架的核心其实是两个东西,peripheral和central, 可以理解成外设和中心,就是你的苹果手机就是中心,外部蓝牙称为外设。

4.服务和特征(service and characteristic):简而言之,外部蓝牙中它有若干个服务service(服务你可以理解为蓝牙所拥有的能力),而每个服务service下拥有若干个特征characteristic(特征你可以理解为解释这个服务的属性)。

5.Descriptor(描述)用来描述characteristic变量的属性。例如,一个descriptor可以规定一个可读的描述,或者一个characteristic变量可接受的范围,或者一个characteristic变量特定的单位。

图示

5361561449141_.pic.jpg
5371561449196_.pic.jpg

名词解释:

BLE:(Bluetooth low energy)蓝牙4.0设备因为低耗电;

Central:中心设备,相对比较强大,用来连接其他外围设备(手机);

Peripheral:外围设备,这一般就是非常小或者简单的低功耗设备,用来提供数据,并连接到一个更加相对强大的中心设备(小米手环等等等);

Services:服务,蓝牙外设对外广播的必定会有一个服务,可能也有多个,服务下面包含着一些特征,服务可以理解成一个模块的窗口;

Characteristic:特征,存在于服务下面的,一个服务下面也可以存在多个特征,特征可以理解成具体实现功能的窗口,一般特征都会有value,也就是特征值,特征是与外界交互的最小单位;

Description:描述,每个Characteristic可以对应一个或多个Description用于描述Characteristic的信息或属性(暂时不太了解)

UUID:可以理解成蓝牙上的唯一标识符(硬件上是Mac值,iOS应该是被系统拦截了,所以获取不到Mac值,相对于转化而来是的UUID),为了区分不同的服务和特征,或者给服务和特征取名字,我们就用UUID来代表服务和特征。

流程:

1、建立一个Central Manager实例进行蓝牙管理CBCentralManagerDelegate

2、搜索外围设备(一直目标设备名称可指定搜索)

3、连接外围设备(目标设备)CBPeripheralDelegate

4、获得外围设备的服务

5、获得服务的特征(该步骤进行特征的读、写、通知等属性)

6、从外围设备读数据

7、给外围设备发送数据

1.属性

// 外围设备(一般是手机)设备
@property (nonatomic, strong) CBCentralManager *mCentral;
// 外设设备
@property (nonatomic, strong) CBPeripheral *mPeripheral;
// 特征值
@property (nonatomic, strong) CBCharacteristic *mCharacteristic;
// 服务
@property (nonatomic, strong) CBService *mService;

2.协议<CBCentralManagerDelegate, CBPeripheralDelegate>

2.1. CBCentralManagerDelegate----设备链接需要的协议
/**
*  首先设备管理的类初始化,一旦初始化完成之后,就会遵循CBCentralManagerDelegate协议
*/
_mCentral = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
@required
/**
*  蓝牙的所有状态,根据状态进行相关操作
*  开启--扫描
*  未开启/不支持蓝牙等--友好提示
typedef NS_ENUM(NSInteger, CBCentralManagerState) {
    CBCentralManagerStateUnknown = CBManagerStateUnknown,
    CBCentralManagerStateResetting = CBManagerStateResetting,
    CBCentralManagerStateUnsupported = CBManagerStateUnsupported,
    CBCentralManagerStateUnauthorized = CBManagerStateUnauthorized,
    CBCentralManagerStatePoweredOff = CBManagerStatePoweredOff,
    CBCentralManagerStatePoweredOn = CBManagerStatePoweredOn,
} NS_DEPRECATED(10_7, 10_13, 5_0, 10_0, "Use CBManagerState instead");
*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central;

@optional
/**
*  发现外设蓝牙设备的方法
*  <这里进行会搜索到周边具有蓝牙功能的设备,可以通过对具体蓝牙名称或者已知蓝牙名称前缀进行筛选你要的蓝牙设备,并且目标设备在这里遵循CBPeripheralDelegate 协议,进行搜索设备的services>
*      [self.mCentral stopScan];          // 停止扫描
        self.mPeripheral = peripheral;  
        // CBPeripheralDelegate
        self.mPeripheral.delegate = self;  // 遵循协议
        [self.mCentral connectPeripheral:peripheral options:nil]; // 连接外设-->扫描services
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI;

/**
*  中心管理者(连接外设)连接成功
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;

/**
*  中心管理者(连接外设)连接失败
*/
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral;

/**
*  中心管理者(外设丢失)连接丢失
*/
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;

2.2 CBPeripheralDelegate
/**
*  扫描目标外设services回调
*  [peripheral discoverCharacteristics:nil forService:service]; // 扫描service下面的特征值characteristics
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error;

/**
*  获取特征值characteristics和描述
*  这里可以查询到具体characteristic属性properties(枚举类型)的读,写,通知,根据UUID(需要跟硬件工程师协商统一的)
*  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(10_9, 6_0)   = 0x100,
    CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(10_9, 6_0) = 0x200
};
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error;

/**
*  读取特征中的值和描述:更新特征值的时候调用,可以理解为获取蓝牙返回的数据(需要的所有数据均在这里进行处理)
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;

/**
*  状态改变和发现描述
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;

/**
*  发现外设的特征的描述数组
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error;

/**
*  写入数据成功与否的回调
*/
-(void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;


描述

  • 我们是从手环中获取到运动步数,怎么获取,如何接收数据,怎么处理数据?这是开发前就需要了解的。通常硬件工程师会制定一个蓝牙数据处理协议,就称之为蓝牙协议吧,因为它关系着你能否获取到你想要的数据,导致能否按时完成项目。

  • 我们的蓝牙协议是这样的


    WechatIMG535.jpeg
  • 读懂蓝牙协议,进行指令发送(按照工程师给的蓝牙协议拼接指令数组)

// 获取总步数指令
    Byte b[] = {0xC6};
    // 获取每个小时步数指令
    Byte b2[] = {0xC4, 0x03, 0x01, 0x8, 0x03};
    NSData *data = [NSData dataWithBytes:&b length:sizeof(b)];
    NSData *data2 = [NSData dataWithBytes:&b2 length:sizeof(b2)];
//    NSLog(@"%@", data);
//    [self.mPeripheral writeValue:data forCharacteristic:self.mCharacteristic type:CBCharacteristicWriteWithResponse];
    [self.mPeripheral writeValue:data2 forCharacteristic:self.mCharacteristic type:CBCharacteristicWriteWithResponse];
  • 数据的处理,这里根据不同的硬件工程师规定的蓝牙协议进行自行处理数据哈(根据工程师给的蓝牙协议按照对应字节进行解析16进制数据)
    首先看看硬件工程师返回给我们的数据:
A*小于20字节的返回一次就够了

如:<29071306 1c090303 05130000 00000000 00000000>

B*大于20字节的分段接受,每次20字节

如:<24281306 18080034 00000000 02fb0000 0000006d>
<00000000 00000000 00000000 00000000 00000000>
<0000a5>
上面数据的解析思路(以我们的协议为参考,具体情况按照你们的来):
24281306 1808 解析:命令头24,数据长度0x28,然后是19年6月24日8点。。
数据是每6个byte为一组,前两个是步数,比如 0034 00000000表示 0x0034步,高两bit是用来表示步数或是睡眠,00表示步数,01表示睡眠,步数用14bit表示

图形化解析
WechatIMG553.jpeg

开发这种东西首先要理解流程,其次才是代码,代码千千万,万变不离其宗,因为写这篇文章的时候还在开发公司的项目,而且离交付项目没多少时间了,所以代码写的只是为了调试,都有备注的,各位看官还请手下留情!!!

如果发现问题还请及时指出,与君共勉!!!

如果有需求,可以直接与本人联系,QQ:1749281699

最后再次发下Demo

附加:
可以使用以下测试软件进行测试:
LightBlue
nrf connect

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352