iOS中的蓝牙操作

/ 0评 / 0

开发和硬件紧密合作的软件是件很有趣的事情。其实在很早苹果设备之间的串联就是很有优势的,然后苹果为了降低功耗开始使用毒攻好的蓝牙(BLE),蓝牙现在已经是家喻户晓了,它能够使拥有蓝牙芯片的两个设备在一定距离内做短时的通讯,这岂不是很爽!特别是蓝牙4.0的时代(也叫蓝牙LE或者蓝牙智能),看看我们的周围,健康、运动、安全系统、点对点游戏、零售终端等使用蓝牙LE的无处不在。

蓝牙SDK

苹果移动设备现在都内置了蓝牙芯片,而且苹果公司也为其设计开发了具体操作的SDK Bluetooth.framework,这为我们直接开发蓝牙功能提供了极大的便利。

在这套体系中分为服务器和客户端,任何的蓝牙LE网络都是服务器产生数据,客户端来消费数据。通常来讲,产生数据的就是服务器。他们可能是心率监控器、温控器、游戏操纵杆或者其他任何东西。这些围绕着你的小型蓝牙配件的就是服务器,通过广播表明自己能追踪你的活动或者健康,它们负责通过广播确定自己产生什么类型的数据并把数据发送给连接上自己的客户端。而那些对数据感兴趣的设备(一般是iPhone)必须自己发现感兴趣的服务器,客户端负责初始化对服务器的连接然后开始读取数据。

按照iOS的说法,服务器叫做外围设备,客户端叫做中心设备。中心设备用 Bluetooth.framework 中的 CBCentralManager 类来读取数据,外围设备用 CBPeripheral 类来发送广播。有的应用甚至可以为外围设备下载固件更新,然后自己作为服务器向外围设备发送新固件,可以使用 CBPeripheralManager 和 CBCentral 类来表示客户端设备。

使用蓝牙设备

1.作为客户端也就是中心设备来连接蓝牙设备

- (void)test{
    self.manger = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    self.array = [NSMutableArray array];
    
    self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, kDiviceSize.width, kDiviceSize.height - 64) style:UITableViewStylePlain];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
    [self.view addSubview:self.tableView];
}

#pragma mark -------- CBCentralManager Delegate
//开启蓝牙之后
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
        case CBCentralManagerStatePoweredOn:
            //开始扫描
            [self.manger scanForPeripheralsWithServices:nil options:nil];
            NSLog(@"正在扫描");
            break;
            
        default:
            NSLog(@"状态改了");
            break;
    }
}

//扫描获取外围设备的信息
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{

    //这里也可以不在扫描外围设备
    //[self.manger stopScan];
    
    //如果数组中不包含这个对象,就添加
    if (![self.array containsObject:peripheral]) {
        peripheral.delegate = self;
        [self.array addObject:peripheral];
        [self.tableView reloadData];
    }
    NSLog(@"advertisementData === %@ ==== peripheral ==== %@ ===== RSSI ====== %@",advertisementData, peripheral ,RSSI);
    
}

//如果连接成功走这里
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    //发现外围设备的服务
    [peripheral discoverServices:nil];
}

//发现新特性
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    [peripheral.services enumerateObjectsUsingBlock:^(CBService * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        //可以在这里通过UUID来判断是不是我们的服务然后去发现新特性
        NSLog(@"该设备的服务有 : %@", obj);
        CBService *service = obj;
        
        [peripheral discoverCharacteristics:nil forService:service];
    }];
}

//返回已经发现的新特性的委托方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    [service.characteristics enumerateObjectsUsingBlock:^(CBCharacteristic * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        //这里可以根据特性的UUID来做发出指令的判断
        CBCharacteristic *ch = obj;
        [peripheral setNotifyValue:YES forCharacteristic:ch];
    }];
}

//在委托中获取数值变化
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    NSLog(@"获得数值变化 %@", characteristic.value);
}

#pragma mark ------ TableViewDataSource && TableViewDelegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.array.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 44;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellID = @"cellID";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellID];
    }
    
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    
    if (self.array.count != 0) {
        CBPeripheral *bleInfo = [self.array objectAtIndex:indexPath.row];
        
        cell.textLabel.text = [bleInfo.identifier UUIDString];
//        cell.textLabel.text = bleInfo.name;
//        NSLog(@"%@", bleInfo.discoveredPeripheral.identifier);
    }
    
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    if (self.array.count != 0) {
        CBPeripheral *bleInfo = [self.array objectAtIndex:indexPath.row];
        
        //连接外围设备
        [self.manger connectPeripheral:bleInfo options:nil];
      
    }
    
}

这是我们得到的设备列表

bluetooth001

尝试连接一下,其实是可以连接上的。

bluetooth002

bluetooth003

2.创建自己的外围设备
在创建之前首先要使用 uuidgen 命令在 shell 中生成两个唯一的 UUID 号,一个给服务用,另一个给特征用

bluetooth004

#define kServiceUUID @"2F3E731C-8478-47C3-B636-E98BF36467B2"
#define kCharacteristicUUID @"02C53F8D-09DF-4FBF-80D9-AD23F30FCFF7"

- (void)test{ 
    self.peripheralManger = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
}

#pragma mark -------- CBPeripheralManager   Delegate
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
    switch (peripheral.state) {
        case CBPeripheralManagerStatePoweredOn:
            [self setupService];
            break;
        default:
            NSLog(@"改变状态");
            break;
    }
}
    
- (void)setupService{
    //服务的UUID
    CBUUID *serviceUUID = [CBUUID UUIDWithString:kServiceUUID];
    
    self.peripheralService = [[CBMutableService alloc] initWithType:serviceUUID primary:YES];
    
    //特征的UUID
    CBUUID *characteristicUUID = [CBUUID UUIDWithString:kCharacteristicUUID];
    
    //这里初始化特征,给出可读的权限(可选的)
    self.peripheralCharacteristic = [[CBMutableCharacteristic alloc] initWithType:characteristicUUID properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
    //给服务设置特征
    [self.peripheralService setCharacteristics:@[self.peripheralCharacteristic]];
    
    //将服务添加到管理中
    [self.peripheralManger addService:self.peripheralService];
    
}

//添加服务之后
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error{
    //如果成功
    if (!error) {
        //开启广播
        [self.peripheralManger startAdvertising:@{CBAdvertisementDataLocalNameKey : @"LocalWeather", CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:kServiceUUID]]}];
    }
}

//这里是订阅中心委托代理,很少使用
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic{
    if ([characteristic isEqual:self.peripheralCharacteristic]){
        NSLog(@"这是订阅委托");
    }
}

运行后使用其他的蓝牙设备就可以连接到我们的这个服务器端了

bluetooth005

评论已关闭。