iOS蓝牙开发(结合智能硬件)

在现在这份工作之前做了挺长时间的“智能门禁”“智能家居”方面的Ios开发,都是基于sip协议实现的手机与硬件设备的交互。用到的开源库分别是idoubs(doubango)、linphone,相比较而言linphone的通话效果会好些也更稳当一些。

在软硬件结合的产品中蓝牙开发是必不可少的,因为蓝牙是一种短距离、高效、无需网络的通讯方式。Ios蓝牙分为“中心者模式“和”外设模式“。前者是将手机作为蓝牙信号的接收端,用来连接蓝牙设备并实现手机与外设间的数据传递。后者是将手机作为蓝牙信号的发射端,无需连接蓝牙设备而只需通过发送广播包的形式将数据(加密)广播出去即可,外设中的蓝牙模块在接收到该数据后进行解密->信息比对,进而进行其他操作。

中心者模式 

这里需要使用到CoreBluetooth.framework中的CBCentralManager、CBPeripheral两个类,分别用来连接蓝牙和读写蓝牙传递的数据。

蓝牙连接:

1、创建蓝牙管理对象

CBCentralManager *manager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue() options:nil];

opetion: 设置系统自带选项

CBCentralManagerOptionShowPowerAlertKey   默认为NO即若手机蓝牙未打开则不弹框提示,可设置为YES CBCentralManagerOptionRestoreIdentifierKey   app被杀死,重新恢复manager的ID CBCentralManagerScanOptionAllowDuplicatesKey   默认为NO,过滤功能是否启用,每次寻找都会合并相同的peripheral。如果设为YES的话每次都能接受到来自peripherals的广播包数据。

CBCentralManagerScanOptionSolicitedServiceUUIDsKey   扫描的时候只会扫描到包含这些UUID的设备(数组)。CBConnectPeripheralOptionNotifyOnConnectionKey   默认为NO,APP被挂起时如果已连接到peripheral,是否要给APP一个提示框。

CBConnectPeripheralOptionNotifyOnDisconnectionKey 默认为NO,APP被挂起时,恰好在这个时候断开连接,要不要给APP一个断开提示。

CBConnectPeripheralOptionNotifyOnNotificationKey 默认为NO,APP被挂起时,是否接受到所有的来自peripheral的包都要弹出提示框。

2、检测手机蓝牙状态并扫描蓝牙设备

#pragma mark CBCentralManagerDelegate

//上面创建中心管理者后 这里会自动监测蓝牙的使用状态

- (void)centralManagerDidUpdateState:(CBCentralManager *)central;

根据central.state状态值判断:

CBCentralManagerStateUnknown未知状态/CBCentralManagerStateResetting复位/CBCentralManagerStateUnsupported不支持/CBCentralManagerStateUnauthorized未授权/CBCentralManagerStatePoweredOff未开启/CBCentralManagerStatePoweredOn已开启

在蓝牙开启后执行[manager scanForPeripheralsWithServices:nil options:nil];搜索全部蓝牙 或 [manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"EEFF"]] options:nil];搜索指定UUID的蓝牙。

3、连接蓝牙设备

//发现外设

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

{  //接下来在这里根据获取的外设peripheral信息对搜索到的(符合特定服务)蓝牙做筛选。 

if([peripheral.name isEqualToString:@"TESTNAME"]) {

[self.centralManager connectPeripheral:peripheral options:nil];    //连接

[self.centralManager stopScan];  }}         //停止扫描

4、检测与蓝牙设备的连接状态

//中心管理者连接外设成功

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

 //到这里上面中心管理者的代理方法就执行完了,并且已经连接到了指定的蓝牙设备,所以下面要设置_peripheral的代理并开始读取蓝牙携带的数据。

[peripheral setDelegate:self];

[peripheral discoverServices:nil]; //搜索该蓝牙对应的所有服务

}

//外设连接失败

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{

NSLog(@"%s, line = %d, %@=连接失败", __FUNCTION__, __LINE__, peripheral.name);

}

//丢失连接- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{

NSLog(@"%s, line = %d, %@=断开连接", __FUNCTION__, __LINE__, peripheral.name);

[self.centralManager connectPeripheral:peripheral options:nil];               //重新连接

}

读写蓝牙数据

5、搜索蓝牙特征

//已经发现该蓝牙对应的服务(根据蓝牙设备搜索服务)

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

for(CBService *service in _peripheral.services) {

[_peripheral discoverCharacteristics:nil forService:service]; //搜索service服务对应的特征

}}

6、根据特征属性做对应的读写操作

//已经搜索到服务对应的特征(根据服务搜索特征,然后判断特征是否可读、可写,最后根据特征的读写属性进行写入和读取操作)

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

for(CBCharacteristic *characteristic in service.characteristics) {

if((unsigned long)characteristic.properties == 10) { //支持读写的属性对应的特征才能写入数据

[peripheral writeValue:[_inputStr dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse]; //将数据写入指定的特征(即给蓝牙设备发送数据)

}}}

7、检测是否读写成功

//用于检测中心向外设写数据是否成功

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

if (error) {

NSLog(@"写入蓝牙特征数据失败 = %@",error.userInfo); }

else{

NSLog(@"写入蓝牙特征数据成功"); } 

[peripheral readValueForCharacteristic:characteristic];}

8、订阅特征并实时更新数据

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;

外设模式

这里需要用到CoreBluetooth.framework中的CBPeripheralManager类,把手机作为蓝牙广播包的发送者。

1、创建设备类对象并检测手机蓝牙状态

CBPeripheralManager *manager = [[CBPeripheralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue() options:nil];

#pragma mark CBPeripheralMangerDelegate

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral;

2、发广播包

[manager startAdvertising:@{CBAdvertisementDataLocalNameKey : @"将显示的蓝牙名称", CBAdvertisementDataServiceUUIDsKey:@"自定义的UUID"}];

注:startAdvertising这个方法只允许设置CBAdvertisementDataLocalNameKey(本地名称)、CBAdvertisementDataServiceUUIDsKey(UUID)两个参数,其他键值key可在“中心模式”下的设备中查看使用。 CBAdvertisementDataIsConnectable(外设的可连接数)这个参数是广播包自带的默认参数(1->可连接 0->不可连接)。广播包中能传输的数据最多为32个字节。

3、检测手机广播是否成功

//手机已经开始广播广播

- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(nullable NSError *)error;

下面简要说明下我们产品的蓝牙应用场景

“中心者模式”:

步骤:开启蓝牙->搜索固定标示的蓝牙设备->连接蓝牙->向蓝牙模块写入加密指令->蓝牙模块将指令信息输出到硬件主板->执行具体操作

注:为了用户有更好的使用体验,这里的连接蓝牙是自动连接即连接时无需授权(蓝牙模块开发人员处理),且为了保证蓝牙连接的稳定性我们使用的蓝牙最大连接数为一个。

“外设模式”:

步骤:开启蓝牙->将带有固定标示的加密数据写入广播包的CBAdvertisementDataLocalNameKey中->硬件中的蓝牙模块识别到该数据包并将相关数据输出到主板->解密数据并执行相应操作

注:这个方式需要和蓝牙模块开发人员、硬件开发人员共同制定数据传输协议

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

推荐阅读更多精彩内容