蓝牙开发(4.0)

一、关于蓝牙开发的一些重要的理论概念:

1.当前ios中开发蓝牙所运使用的系统库是。

2.蓝牙外设必需为4.0及以上(2.0需要MFI认证),否则无法开发,蓝牙4.0设施由于低耗电,所以也叫做BLE。

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

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

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

6.我们用的蓝牙板块是在淘宝买的, 大概十多元一个, ios大概每次能接受90个字节, 安卓大概每次能接收20个字节, 具体数字可可以会浮动, 应该是与蓝牙板块有关。

二、蓝牙连接的主要步骤

1、创建一个CBCentralManager实例来进行蓝牙管理;

2、搜索扫描外围设备;

3、连接外围设备;

4、获得外围设备的服务;

5、获得服务的特征;

6、从外围设备读取数据;

7、给外围设备发送(写入)数据。

三、代码

// 加入权限访问, 否则上传AppStore会因为权限不足失败


1.初始化

#import

self.centralManager = [[CBCentralManager alloc] initWithDelegate:selfqueue:nil];


2.搜索扫描外围设备

/**

*  --  初始化成功自动调用

*  --  必须实现的代理,用来返回创建的centralManager的状态。

*  --  注意:必须确认当前是CBCentralManagerStatePoweredOn状态才可以调用扫描外设的方法:scanForPeripheralsWithServices

*/

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

switch(central.state) {

            case     CBCentralManagerStateUnknown:

                         NSLog(@">>>CBCentralManagerStateUnknown");

                        break;

            case    CBCentralManagerStateResetting:

                        NSLog(@">>>CBCentralManagerStateResetting");

                        break;

            case    CBCentralManagerStateUnsupported:

                        NSLog(@">>>CBCentralManagerStateUnsupported");

                        break;

            case    CBCentralManagerStateUnauthorized:

                        NSLog(@">>>CBCentralManagerStateUnauthorized");    

                        break;

            case    CBCentralManagerStatePoweredOff:

                        NSLog(@">>>CBCentralManagerStatePoweredOff");

                        break;

            case    CBCentralManagerStatePoweredOn:

            {

                        NSLog(@">>>CBCentralManagerStatePoweredOn");

                        // 开始扫描周围的外设。

                        /*

                        -- 两个参数为Nil表示默认扫描所有可见蓝牙设备。

                        -- 注意:第一个参数是用来扫描有指定服务的外设。然后有些外设    的服务是相同的,比如都有FFF5服务,那么都会发现;而有些外设的服务是不可见的,就会扫描不到设备。

                        -- 成功扫描到外设后调用didDiscoverPeripheral

                        */

                        [self.centralManager scanForPeripheralsWithServices:niloptions:nil];

}

                        break;

                default:

                        break;

    }

}

#pragma mark 发现外设

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

NSLog(@"Find device:%@", [peripheral name]);

if(![_deviceDic objectForKey:[peripheral name]]) {

    NSLog(@"Find device:%@", [peripheral name]);

    if(peripheral!=nil) {

        if([peripheral name]!=nil) {

            if([[peripheral name] hasPrefix:@"根据设备名过滤"]) {

                [_deviceDic setObject:peripheral forKey:[peripheral name]];

                // 停止扫描, 看需求决定要不要加

                // [_centralManager stopScan];

                // 将设备信息传到外面的页面(VC), 构成扫描到的设备列表

                if([self.delegate respondsToSelector:@selector(dataWithBluetoothDic:)])                                      {

                [self.delegate dataWithBluetoothDic:_deviceDic];

                    }

                }

            }

        }

    }

}

3.连接外围设备

// 连接设备(.h中声明出去的接口, 一般在点击设备列表连接时调用)

- (void)connectDeviceWithPeripheral:(CBPeripheral *)peripheral

{

           [self.centralManager connectPeripheral:peripheral options:nil];

}

#pragmamark 连接外设--成功

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

        //连接成功后停止扫描,节省内存

        [central stopScan];

        peripheral.delegate= self;

        self.peripheral = peripheral;

        //4.扫描外设的服务

        /**

        --     外设的服务、特征、描述等方法是CBPeripheralDelegate的内容,所以要先设置代理peripheral.delegate = self

        --     参数表示你关心的服务的UUID,比如我关心的是"FFE0",参数就可以为@[[CBUUID UUIDWithString:@"FFE0"]].那么didDiscoverServices方法回调内容就只有这两个UUID的服务,不会有其他多余的内容,提高效率。nil表示扫描所有服务

        --     成功发现服务,回调didDiscoverServices

        */

        [peripheral discoverServices:@[[CBUUID UUIDWithString:@"你要用的服务UUID"]]];

        if([self.delegaterespondsToSelector:@selector(didConnectBle)]) {

            // 已经连接

            [self.delegate didConnectBle];

        }

}

#pragma mark 连接外设——失败

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

        NSLog(@"%@", error);

}

#pragma mark 取消与外设的连接回调

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

        NSLog(@"%@", peripheral);

}

获得外围设备的服务

#pragma mark 发现服务回调

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

        //NSLog(@"didDiscoverServices,Error:%@",error);

        CBService * __nullablefindService =nil;

// 遍历服务

for(CBService *serviceinperipheral.services)

{

        //NSLog(@"UUID:%@",service.UUID);

        if([[service UUID] isEqual:[CBUUID UUIDWithString:@"你要用的服务UUID"]])

        {

                findService = service;

        }

    }

    NSLog(@"Find Service:%@",findService);

    if(findService)

    [peripheral discoverCharacteristics:NULLforService:findService];

}

#pragma mark 发现特征回调

/**

--  发现特征后,可以根据特征的properties进行:读readValueForCharacteristic、写writeValue、订阅通知setNotifyValue、扫描特征的描述discoverDescriptorsForCharacteristic。

**/

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

        for(CBCharacteristic *characteristicinservice.characteristics) {

                if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"你要用的特征UUID"]]) {

                    /**

                    -- 读取成功回调didUpdateValueForCharacteristic

                    */

                    self.characteristic = characteristic;

                        // 接收一次(是读一次信息还是数据经常变实时接收视情况而定, 再决定使用哪个)

                        //            [peripheral readValueForCharacteristic:characteristic];

                        // 订阅, 实时接收

                        [peripheral setNotifyValue:YESforCharacteristic:characteristic];

                          // 发送下行指令(发送一条)

                            NSData*data = [@"硬件工程师给我的指令, 发送给蓝牙该指令, 蓝牙会给我返回一条数据"dataUsingEncoding:NSUTF8StringEncoding];

                        // 将指令写入蓝牙

                        [self.peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];

                        }

                        /**

                        -- 当发现characteristic有descriptor,回调                                    didDiscoverDescriptorsForCharacteristic

                        */

                            [peripheral discoverDescriptorsForCharacteristic:characteristic];

                            }

}

6.从外围设备读取数据

#pragma mark - 获取值

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

            // characteristic.value就是蓝牙给我们的值(我这里是json格式字符串)

            NSData*jsonData = [characteristic.value         dataUsingEncoding:NSUTF8StringEncoding];

            NSDictionary*dataDic = [NSJSONSerializationJSONObjectWithData:jsonData options:NSJSONReadingMutableContainerserror:nil];

            // 将字典传出去就可以使用了

}

#pragma mark - 中心读取外设实时数据

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

            if(characteristic.isNotifying) {

            [peripheral readValueForCharacteristic:characteristic];

            }else{

               NSLog(@"Notification stopped on %@.  Disconnecting", characteristic);

                NSLog(@"%@", characteristic);

                [self.centralManager cancelPeripheralConnection:peripheral];

    }

}

给外围设备发送(写入)数据

// 上文中发现特征之后, 发送下行指令的时候其实就是向蓝牙中写入数据

// 例:

// 发送检查蓝牙命令

- (void)writeCheckBleWithBle

{

        _style =1;        

        // 发送下行指令(发送一条)

        NSData*data = [@"硬件工程师提供给你的指令, 类似于5E16010203...这种很长一串"dataUsingEncoding:NSUTF8StringEncoding];

        [self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];

}

#pragma mark 数据写入成功回调

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

        NSLog(@"写入成功");

        if([self.delegate respondsToSelector:@selector(didWriteSucessWithStyle:)])         {

        [self.delegate didWriteSucessWithStyle:_style];

    }

}

另外

- (void)scanDevice

{

        if(_centralManager ==nil) {

        self.centralManager = [[CBCentralManager alloc] initWithDelegate:selfqueue:nil];

        [_deviceDic removeAllObjects];

}

}

#pragmamark 断开连接

- (void)disConnectPeripheral{

/**

-- 断开连接后回调didDisconnectPeripheral

-- 注意断开后如果要重新扫描这个外设,需要重新调用[self.centralManager scanForPeripheralsWithServices:nil options:nil];

*/

        [self.centralManager cancelPeripheralConnection:self.peripheral];

}

#pragmamark 停止扫描外设

- (void)stopScanPeripheral{

        [self.centralManager stopScan];

}

文章出处:http://www.cocoachina.com/ios/20180731/24389.html

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

推荐阅读更多精彩内容