智能设备 和 app 通过 BLE通讯的两种模型

模型一:设备提供数据,app 展示数据; 比如小米手环

模型二:app提供数据,设备接收;

模型与corebluetooth的对应关系;

模型一:智能设备,对应 peripheral;app对应central

模型二:智能设备作为central ; app作为 peripheral

这里主要讨论模型一,这也是当前大多数手环设备和iOS 交互的方式;开发流程

1. 创建工程,导入CoreBluetooth.framework

2. 初始化 CBCentralManager 并准备扫描周围蓝牙设备



//初始化    
theManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];

//初始化完成会调用如下代理,返回当前手机的蓝牙状态
//当前蓝牙主设备状态
-(void)centralManagerDidUpdateState:(CBCentralManager *)central{
ifstate==CBCentralManagerStatePoweredOn) {
self.title@"蓝牙已就绪";
self.connectBtn.enabledYES;
else
    {
self.title@"蓝牙未准备好";
self.activeIDstopAnimating];
switchstate) {
caseCBCentralManagerStateUnknown:
NSLog(@">>>CBCentralManagerStateUnknown");
break;
caseCBCentralManagerStateResetting:
NSLog(@">>>CBCentralManagerStateResetting");
break;
caseCBCentralManagerStateUnsupported:
NSLog(@">>>CBCentralManagerStateUnsupported");
break;
caseCBCentralManagerStateUnauthorized:
NSLog(@">>>CBCentralManagerStateUnauthorized");
break;
caseCBCentralManagerStatePoweredOff:
NSLog(@">>>CBCentralManagerStatePoweredOff");
break;
                
default:
break;
        }
    }
    
}



3. 当蓝牙状态一切正常时,这时可以开始搜索周边设备了,比如手环



//开始连接action
- (IBAction)startConnectAction:(id)sender {
    
    if (theManager.state==CBCentralManagerStatePoweredOn) {
        NSLog(@"主设备蓝牙状态正常,开始扫描外设...");
        self.title = @"扫描小米手环...";
        //nil表示扫描所有设备
        [theManager scanForPeripheralsWithServices:nil options:nil];
        [self.activeID startAnimating];
        self.connectBtn.enabled = NO;
        self.resultTextV.text = @"";

    }

    
}



4. 在扫描到设备的代理里面,连接我们找到的智能设备



//扫描到设备会进入方法
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    NSLog(@"扫描连接外设:%@ %@",peripheral.name,RSSI);
    [central connectPeripheral:peripheral options:nil];
    if ([peripheral.name hasSuffix:@"MI"]) {
        thePerpher = peripheral;
        [central stopScan];
        [central connectPeripheral:peripheral options:nil];
        self.title = @"发现小米手环,开始连接...";
        self.resultTextV.text = [NSString stringWithFormat:@"发现手环:%@\n名称:%@\n",peripheral.identifier.UUIDString,peripheral.name];
    }
}



5. 连接成功之后,去扫描设备的服务;扫描到服务之后,紧接着去扫描设备的特征;好比一个类提供的接口,只有知道这些,我们才能操作智能设备




//扫描到特征
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    if (error)
    {
        NSLog(@"扫描外设的特征失败!%@->%@-> %@",peripheral.name,service.UUID, [error localizedDescription]);
        self.title = @"find characteristics error.";
        [self.activeID stopAnimating];
        self.connectBtn.enabled = YES;
        return;
    }
    
    NSLog(@"扫描到外设服务特征有:%@->%@->%@",peripheral.name,service.UUID,service.characteristics);
    //获取Characteristic的值
    for (CBCharacteristic *characteristic in service.characteristics){
        {
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
            
            //步数
            if ([characteristic.UUID.UUIDString isEqualToString:kMI_STEP])
            {
                [peripheral readValueForCharacteristic:characteristic];
            }
            
            //电池电量
            else if ([characteristic.UUID.UUIDString isEqualToString:kMI_BUTERY])
            {
                [peripheral readValueForCharacteristic:characteristic];
            }
            
            else if ([characteristic.UUID.UUIDString isEqualToString:kMI_SHAKE])
            {
                //震动
                theSakeCC = characteristic;
            }
            
            //设备信息
            else if ([characteristic.UUID.UUIDString isEqualToString:kMI_DEVICE])
            {
                [peripheral readValueForCharacteristic:characteristic];
            }
            

            
        }
    }
    
    
}


//扫描到服务
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    if (error)
    {
        NSLog(@"扫描外设服务出错:%@-> %@", peripheral.name, [error localizedDescription]);
        self.title = @"find services error.";
        [self.activeID stopAnimating];
        self.connectBtn.enabled = YES;

        return;
    }
    NSLog(@"扫描到外设服务:%@ -> %@",peripheral.name,peripheral.services);
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
    NSLog(@"开始扫描外设服务的特征 %@...",peripheral.name);

}



#pragma mark 设备扫描与连接的代理
//连接到Peripherals-成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    self.title = @"连接成功,扫描信息...";
    NSLog(@"连接外设成功!%@",peripheral.name);
    [peripheral setDelegate:self];
    [peripheral discoverServices:nil];
    NSLog(@"开始扫描外设服务 %@...",peripheral.name);
    
}
//连接外设失败
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"连接到外设 失败!%@ %@",[peripheral name],[error localizedDescription]);
    [self.activeID stopAnimating];
    self.title = @"连接失败";
    self.connectBtn.enabled = YES;

}

//与外设断开连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    NSLog(@"与外设备断开连接 %@: %@", [peripheral name], [error localizedDescription]);
    self.title = @"连接已断开";
    self.connectBtn.enabled = YES;
}


View Code


6. 当我们对设备发送一些指令时,会在如下代理里面响应到设备返回的数据



#pragma mark 设备信息处理
//扫描到具体的值
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error
{
    if (error) {
        NSLog(@"扫描外设的特征失败!%@-> %@",peripheral.name, [error localizedDescription]);
        self.title = @"find value error.";
        return;
    }
    NSLog(@"%@ %@",characteristic.UUID.UUIDString,characteristic.value);
    if ([characteristic.UUID.UUIDString isEqualToString:kMI_STEP]) {
        Byte *steBytes = (Byte *)characteristic.value.bytes;
        int steps = TCcbytesValueToInt(steBytes);
        NSLog(@"步数:%d",steps);
        self.resultTextV.text = [NSString stringWithFormat:@"%@步数:%d\n",self.resultTextV.text,steps];
    }
    else if ([characteristic.UUID.UUIDString isEqualToString:kMI_BUTERY])
    {
        Byte *bufferBytes = (Byte *)characteristic.value.bytes;
        int buterys = TCcbytesValueToInt(bufferBytes)&0xff;
        NSLog(@"电池:%d%%",buterys);
        self.resultTextV.text = [NSString stringWithFormat:@"%@电量:%d%%\n",self.resultTextV.text,buterys];
        
    }
    else if ([characteristic.UUID.UUIDString isEqualToString:kMI_DEVICE])
    {
        Byte *infoByts = (Byte *)characteristic.value.bytes;
        //这里解析infoByts得到设备信息
        
        
    }
    
    
    [self.activeID stopAnimating];
    self.connectBtn.enabled = YES;
    self.title = @"信息扫描完成";

    
}


View Code


7. 完整的代码工程;

https://github.com/cocoajin/BLE-miband