• iOS ----Bluetooth


    (转)iOS开发 之 可穿戴设备 蓝牙4.0 BLE 开发,iosble

    1 前言

    当前有越来越多的可穿戴设备使用了蓝牙4.0 BLE(Bluetooth Low Energy)。对于iOS开发而言,Apple之前专门推出CoreBluetooth的Framework来支持BLE的开发。对于硬件开发有了解的朋友应该知道,在之前使用低版本的蓝牙的设备,要连接到iOS设备上,需要注册MFI,拥有MFI协议才能进行相应的开发。如果大家关注我之前对LEGO EV3的研究,就可以发现,EV3是使用了蓝牙2.1,因此需要MFI协议来进行开发。

    本文将一步一步讲解如何使用CoreBluetooth框架来与各种可穿戴设备进行通信,使用 小米手环 来进行基本的测试。 
    小米手环

    2 开发环境

    1 Macbook Pro Mac OS X 10.10 
    2 Xcode 6.3.2 
    3 iPhone 5s v8.1 
    4 小米手环

    3 基本流程

    要开发蓝牙,需要对整个通讯过程有个基本了解。这里我摘录一些Apple官方的文档Core Bluetooth Programming Guide的图片来加以说明。这个文档其实对于开发的流程写的是非常的清楚,大家最好可以看一下。

    3.1 可穿戴设备与iOS互联方式

    可穿戴设备与iOS互联

    从上面这幅图可以看到,我们的iOS设备是Central,用来接收数据和发送命令,而外设比如小米手环是Peripheral,向外传输数据和接收命令。我们要做的就是通过Central来连接Peripheral,然后实现数据的接收和控制指令的发送。在做到这一步之后,再根据具体的硬件,对接收到的数据进行parse解析。

    3.2 可穿戴设备蓝牙的数据结构

    可穿戴设备蓝牙的数据结构

    这里用的是心率设备来做说明,每个外设Peripheral都有对应的服务Service,比如这里是心率Service。一个外设可以有不止一个s、Service。每个service里面可以有多个属性Characteristic,比如这里有两个Characteristic,一个是用来测量心率,一个是用来定位位置。

    那么很关键的一点是每个Service,每个Characteristic都是用UUID来确定的。UUID就是每个Service或Characteristic的identifier。

    大家可以在iPhone上下载LightBlue这个应用。可以在这里查看一些设备的UUID。 
    LightBlue

    在实际使用中,我们都是要通过UUID来获取数据。这点非常重要。 
    在CoreBluetooth中,其具体的数据结构图如下: 
    这里写图片描述

    4 Step-By-Step 上手BLE开发

    4.1 Step 1 创建CBCentralManager

    从名字上大家可以很清楚的知道,这个类是用来管理BLE的。我们也就是通过这个类来实现连接。

    先创建一个:

    @property (nonatomic,strong) CBCentralManager *centralManager;
    
    dispatch_queue_t centralQueue = dispatch_queue_create("com.manmanlai", DISPATCH_QUEUE_SERIAL);
            self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue];

    然后关键在于CBCentralManagerDelegate的使用。这个之后再讲。

    4.2 Step 2 寻找CBPeripheral外设

    有了CBCentralManager,接下来就是寻找CBPeripheral外设,方法很简单:

    [self.centralManager scanForPeripheralsWithServices:@[] options:nil];

    这里的Service就是对应的UUID,如果为空,这scan所有service。

    4.3 Step 3 连接CBPeripheral

    在上一步中,如果找到了设备,则CBCentralManager的delegate会调用下面的方法:

    - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
    {
        NSLog(@"name:%@",peripheral);
        if (!peripheral || !peripheral.name || ([peripheral.name isEqualToString:@""])) {
            return;
        }
    
        if (!self.peripheral || (self.peripheral.state == CBPeripheralStateDisconnected)) {
            self.peripheral = peripheral;
            self.peripheral.delegate = self;
            NSLog(@"connect peripheral");
            [self.centralManager connectPeripheral:peripheral options:nil];
        }
    
    }

    我们在这里创建了一个CBPeripheral的对象,然后直接连接 
    CBPeripheral的对象也需要设置delegate.

    4.4 Step 4 寻找Service

    如果Peripheral连接成功的话,就会调用delegate的方法:

    - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
    {
        if (!peripheral) {
            return;
        }
    
        [self.centralManager stopScan];
    
        NSLog(@"peripheral did connect");
        [self.peripheral discoverServices:nil];
    
    
    }
    

    我们这里先停止Scan,然后让Peripheral外设寻找其Service。

    4.5 Step 5 寻找Characteristic

    找到Service后会调用下面的方法:

    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
    {
        NSArray *services = nil;
    
        if (peripheral != self.peripheral) {
            NSLog(@"Wrong Peripheral.
    ");
            return ;
        }
    
        if (error != nil) {
            NSLog(@"Error %@
    ", error);
            return ;
        }
    
        services = [peripheral services];
        if (!services || ![services count]) {
            NSLog(@"No Services");
            return ;
        }
    
        for (CBService *service in services) {
            NSLog(@"service:%@",service.UUID);
            [peripheral discoverCharacteristics:nil forService:service];
    
        }
    
    }
    

    我们根据找到的service寻找其对应的Characteristic。

    4.6 Step 6 找到Characteristic后读取数据

    找到Characteristic后会调用下面的delegate方法:

    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
    {
        NSLog(@"characteristics:%@",[service characteristics]);
        NSArray *characteristics = [service characteristics];
    
        if (peripheral != self.peripheral) {
            NSLog(@"Wrong Peripheral.
    ");
            return ;
        }
    
        if (error != nil) {
            NSLog(@"Error %@
    ", error);
            return ;
        }
    
        self.characteristic = [characteristics firstObject];
        //[self.peripheral readValueForCharacteristic:self.characteristic];
        [self.peripheral setNotifyValue:YES forCharacteristic:self.characteristic];

    这里我们可以使用readValueForCharacteristic:来读取数据。如果数据是不断更新的,则可以使用setNotifyValue:forCharacteristic:来实现只要有新数据,就获取。

    4.7 Step 7 处理数据

    读到数据后会调用delegate方法:

    - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    {
       NSData *data = characteristic.value;
       // Parse data ...
    
    }
    

    4.8 Step 8 向设备写数据

    这个很简单,只要使用:

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

    data是NSData类型。

    5 实验

    使用小米手环实验,得到如下结果:

    2015-06-10 16:52:31.607 KetherDemo[13786:1792995] scaning device
    2015-06-10 16:52:33.474 KetherDemo[13786:1793032] name:<CBPeripheral: 0x1700e4380, identifier = 6FF833E3-93C1-28C6-CBC0-74A706AAAE31, name = LS_SCA16, state = disconnected>
    2015-06-10 16:52:33.475 KetherDemo[13786:1793032] connect peripheral
    2015-06-10 16:52:37.538 KetherDemo[13786:1793031] peripheral did connect
    2015-06-10 16:52:37.984 KetherDemo[13786:1793031] service:FEE7
    2015-06-10 16:52:37.985 KetherDemo[13786:1793031] service:Device Information
    2015-06-10 16:52:38.099 KetherDemo[13786:1793032] characteristics:(
        "<CBCharacteristic: 0x17409c250, UUID = FEC8, properties = 0x20, value = (null), notifying = NO>",
        "<CBCharacteristic: 0x17409c200, UUID = FEC7, properties = 0x8, value = (null), notifying = NO>"
    )
    2015-06-10 16:52:38.100 KetherDemo[13786:1793032] Kether did connect
    2015-06-10 16:52:38.101 KetherDemo[13786:1793032] Kether did connect
    2015-06-10 16:52:38.280 KetherDemo[13786:1793031] characteristics:(
        "<CBCharacteristic: 0x17009f270, UUID = Manufacturer Name String, properties = 0x2, value = (null), notifying = NO>",
        "<CBCharacteristic: 0x17009f2c0, UUID = Model Number String, properties = 0x2, value = (null), notifying = NO>",
        "<CBCharacteristic: 0x17009f310, UUID = Serial Number String, properties = 0x2, value = (null), notifying = NO>",
        "<CBCharacteristic: 0x17009eb90, UUID = Hardware Revision String, properties = 0x2, value = (null), notifying = NO>",
        "<CBCharacteristic: 0x17009f0e0, UUID = Firmware Revision String, properties = 0x2, value = (null), notifyi``
    
     = NO>",
    

    6 小结

    通过上面的方法,我们就可以轻松的对BLE进行开发。实际上比想象的要简单。

    【本文为原创文章,转载请注明出处:blog.csdn.net/songrotek】

  • 相关阅读:
    对SpringIOC、AOP的理解
    Java后台与VUE跨域交接
    贼简单的Shiro框架之粗粒度控制菜单栏
    Json
    Spring MVC小DEMO
    面试问题
    多线程理解
    了解java语言
    单点登录如何设计
    进程的创建和调度分析
  • 原文地址:https://www.cnblogs.com/zhangshan/p/5231031.html
Copyright © 2020-2023  润新知