ios - 核心蓝牙框架 : How to obtain connected devices without knowing the Service IDs?

标签 ios bluetooth core-bluetooth

我有一个蓝牙手环,可以通过蓝牙连接到我的 iPhone 5s;它附带一个名为 Zeroner 的应用程序。现在我想在不使用App的情况下获取已连接并配对手环的信息。这是我尝试做的事情:

  1. 设置CBCentralManager
  2. 使用retrieveConnectedPeripheralsWithServices:获取已连接的设备

这是代码:

CBConnectedDevicesVC.h

#import <UIKit/UIKit.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import SERVICE_ID @"FB694B90-F49E-4597-8306-171BBA78F846"

@interface CBConnectedDevicesVC : UIViewController <CBCentralManagerDelegate, CBPeripheralDelegate>

@property (strong, nonatomic) CBCentralManager *centralManager;
@property (strong, nonatomic) CBPeripheral *discoveredPeripheral;

@end

CBConnectedDevicesVC.m

#import "CBConnectedDevicesVC.h"

@implementation CBConnectedDevicesVC

- (void)viewDidLoad {
    [super viewDidLoad];
    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    if (central.state != CBCentralManagerStatePoweredOn) {
        return;
    }

    if (central.state == CBCentralManagerStatePoweredOn) {
        NSArray* connectedDevices = [_centralManager retrieveConnectedPeripheralsWithServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]];
        for (CBUUID *uuid in connectedDevices) {
            NSLog(@"Device Found. UUID = %@", uuid);
        }
    }
}

@end

对于上面的代码,我必须在SERVICE_UUID中指定服务ID,我不知道手环的值是多少。有没有其他方法可以从连接的手环中获取信息?


更新LightBlue App测试结果

从 Zeroner 应用程序取消配对并在“设置”>“蓝牙”中“忘记此设备”> 选择名为“Bracelet-0366”的设备后,LightBlue 应用程序会发现该设备(终于!)。

这是结果截图:

LightBlue screenshot

我在这里有几个值,但我不确定应该使用哪些值。

进一步测试结果:

如果我将 LightBlue 中找到的 UUID(以 4EFF 开头)放入 SERVICE_ID 中,则上述代码不会调用任何委托(delegate)。

我尝试过的另一段代码是(从 Tut+ tutorial 获得):

NSArray *serviceID;

@implementation CBCentralManagerViewController


- (void)viewDidLoad {
    [super viewDidLoad];
    serviceID = @[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]];
    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    _data = [[NSMutableData alloc] init];
}

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    // You should test all scenarios
    if (central.state != CBCentralManagerStatePoweredOn) {
        return;
    }

    if (central.state == CBCentralManagerStatePoweredOn) {
        // Scan for devices
        [_centralManager scanForPeripheralsWithServices:serviceID options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
        NSLog(@"Scanning started");
    }
}

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

    NSLog(@"Discovered %@ at %@", peripheral.name, RSSI);

    if (_discoveredPeripheral != peripheral) {
        // Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it
        _discoveredPeripheral = peripheral;

        // And connect
        NSLog(@"Connecting to peripheral %@", peripheral);
        [_centralManager connectPeripheral:peripheral options:nil];
    }
}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"Failed to connect");
    [self cleanup];
}

- (void)cleanup {

    // See if we are subscribed to a characteristic on the peripheral
    if (_discoveredPeripheral.services != nil) {
        for (CBService *service in _discoveredPeripheral.services) {
            if (service.characteristics != nil) {
                for (CBCharacteristic *characteristic in service.characteristics) {
                    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
                        if (characteristic.isNotifying) {
                            [_discoveredPeripheral setNotifyValue:NO forCharacteristic:characteristic];
                            return;
                        }
                    }
                }
            }
        }
    }

    [_centralManager cancelPeripheralConnection:_discoveredPeripheral];
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"Connected");

    [_centralManager stopScan];
    NSLog(@"Scanning stopped");

    [_data setLength:0];

    peripheral.delegate = self;

    [peripheral discoverServices:serviceID];
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    if (error) {
        [self cleanup];
        return;
    }

    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]] forService:service];
    }
    // Discover other characteristics
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {
        [self cleanup];
        return;
    }

    for (CBCharacteristic *characteristic in service.characteristics) {
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"Error");
        return;
    }

    NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];

    // Have we got everything we need?
    if ([stringFromData isEqualToString:@"EOM"]) {

        [_textview setText:[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]];

        [peripheral setNotifyValue:NO forCharacteristic:characteristic];

        [_centralManager cancelPeripheralConnection:peripheral];
    }

    [_data appendData:characteristic.value];
}

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

    if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
        return;
    }

    if (characteristic.isNotifying) {
        NSLog(@"Notification began on %@", characteristic);
    } else {
        // Notification has stopped
        [_centralManager cancelPeripheralConnection:peripheral];
    }
}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    _discoveredPeripheral = nil;

    //
    [_centralManager scanForPeripheralsWithServices:serviceID options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
}

在上面的代码中,定义了 2 个常量 TRANSFER_SERVICE_IDTRANSFER_CHARACTERISTIC_ID。根据教程,TRANSFER_SERVICE_ID 应设置为以 4EFF 开头的值,TRANSFER_CHARACTERISTIC_ID 应设置为 0xFF20 > 或 FF20。然而,即使手环未配对并断开连接,这段代码也根本不会检测到手环。这次我错过了什么?

最佳答案

不必担心以 4EFF 开头的 UUID - 这是设备的 UUID,每个设备都不同。

服务 ID 为 FF20 - 您可以在 scanForPeripheralsWithServices 中使用它 - 这是上面代码中的 SERVICE_ID

那么你有两个特征 - FF21FF22

您可以使用 CBPeripheral 实例上的 writeValue 方法写入 FF21

使用 FF22,您可以使用 setNotify CBPeripheral 方法订阅通知。然后,每当设备更改值时,您都会调用 didUpdateValueForCharacteristic CBPeripheralDelegate 方法。

关于ios - 核心蓝牙框架 : How to obtain connected devices without knowing the Service IDs?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30450767/

相关文章:

objective-c - 有界和无界设备有什么区别?

ios - 是否可以在 NSAttributedString 中混合不同的对齐方式?

iphone - 当数据源只有 1 个项目时,UICollectionView 不会反弹

ios - 如何开发屏幕之间的滑动

安卓连接配对的蓝牙耳机

ios - 从 iOS 在后台进行蓝牙 LE 设备扫描

xamarin.ios - xamarin 支持 iOS 的 coreBluetooth 吗?

ios - [NSURLConnection sendAsynchronousRequest : . ..] 总是发送完成 block 吗?

Android - 检测我的应用程序的其他用户是否在附近

android - Android蓝牙 socket