iOS Core蓝牙 / iBeacon: 同时播发 iBeacon 和外围服务

iOS CoreBluetooth / iBeacon: Advertise an iBeacon and a peripheral service concurrently

提问人:user2876951 提问时间:10/14/2013 最后编辑:user2876951 更新时间:8/16/2014 访问量:5942

问:

我正在为 iOS 编写一个应用程序,该应用程序要求该应用程序同时通告 iOS iBeacon 和通告外围服务.有必要对服务进行宣传,而不是简单地在外围设备上发现,因为用例需要中央 (在 BLE 术语中) 在被 iOS 唤醒后连接到外围设备 (但仍在后台) 由于靠近 iBeacon.在中心后台运行的应用程序只能通过可用服务发现外围设备,而不是发现所有外围设备 [] ;我的代码可以宣传服务或 iBeacon,但我还没有弄清楚如何同时做这两者.iBeacon 可能使用了 21 个字节中的 38 个可用空间中的字节,并且根本没有足够的空间来宣传信标和服务?

这工作(信标):

self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid 
    major:1 
    minor:1 
    identifier:@"bentboolean"];
NSMutableDictionary *dict = [[self.beaconRegion peripheralDataWithMeasuredPower:nil] mutableCopy];    
[self.peripheralManager startAdvertising:dict ];

这工作(服务):

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:@[serviceUUID] forKey:CBAdvertisementDataServiceUUIDsKey];
[self.peripheralManager startAdvertising:dict ];

将两者相加,尝试同时宣传这两种服务是行不通的。它只宣传信标,不宣传服务:

self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid 
    major:1 
    minor:1 
    identifier:@"bentboolean"];
NSMutableDictionary *dict = [[self.beaconRegion peripheralDataWithMeasuredPower:nil] mutableCopy];  
[dict setValue:@[serviceUUID] forKey:CBAdvertisementDataServiceUUIDsKey];  
[self.peripheralManager startAdvertising:dict ];

感谢您的观看!

iPhone 核心-蓝牙 蓝牙-低功耗 信标

评论

0赞 CW0007007 10/18/2013
嗨,你有没有解决这个问题?由于蓝牙的容量,我认为这是不可能的......

答:

0赞 d2burke 11/27/2013 #1

我能够分别为接收器和信标使用单独的 CLLocationManager 和 CLBeaconRegion 来做到这一点:

#import "GRBothViewController.h"

@interface GRBothViewController ()

@end

@implementation GRBothViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];


    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;

    self.locationScanner = [[CLLocationManager alloc] init];
    self.locationScanner.delegate = self;

    [self initBeacon];
    [self initRegion];
    [self locationManager:self.locationManager didStartMonitoringForRegion:self.scannerRegion];
}

- (void)initBeacon {
    NSLog(@"Starting beacon");

    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString: @"23542266-18D1-4FE4-B4A1-23F8195B9D39"];
    self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
                                                                major:1
                                                                minor:1
                                                           identifier:@"com.thisisgrow.Grow"];
    [self transmitBeacon:self];
}

- (IBAction)transmitBeacon:(id)sender {
    self.beaconPeripheralData = [self.beaconRegion peripheralDataWithMeasuredPower:nil];
    self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self
                                                                     queue:nil
                                                                   options:nil];
}

-(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
    if (peripheral.state == CBPeripheralManagerStatePoweredOn) {
        NSLog(@"Powered On");
        [self.peripheralManager startAdvertising:self.beaconPeripheralData];
    } else if (peripheral.state == CBPeripheralManagerStatePoweredOff) {
        NSLog(@"Powered Off");
        [self.peripheralManager stopAdvertising];
    }
}

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}

- (void)initRegion {
    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"23542266-18D1-4FE4-B4A1-23F8195B9D39"];
    _scannerRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.thisisgrow.Grow"];
    _scannerRegion.notifyEntryStateOnDisplay = YES;
    [_locationScanner startMonitoringForRegion:self.scannerRegion];
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
    //SCANNER
    [self.locationScanner startRangingBeaconsInRegion:self.scannerRegion];
}

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
    //SCANNER HAS LEFT THE AREA
    [self.locationScanner stopRangingBeaconsInRegion:self.scannerRegion];
}

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
    CLBeacon *beacon = [[CLBeacon alloc] init];
    NSLog(@"Beacons: %d", [beacons count]);
    if(beacons && [beacons count]>0){
        beacon = [beacons firstObject];
    }
    else{

    }
}

这里唯一的限制是设备无法检测到自身。

评论

0赞 davidgyoung 11/27/2013
我看到的另一个有趣的观察结果: 即使另一个应用程序作为 iBeacon 进行广告, 您的应用程序也无法检测到它.更重要的是, 如果存在通告相同标识符的外部 iBeacon, 您的应用程序仍然无法检测到它.换句话说, 通告 iBeacon ID 集会阻止对同一 ID 集的任何检测.
0赞 d2burke 12/3/2013
然而, 当使用设备作为 iBeacon 时, 如果您想将它们用于此目的,则为设备自动生成唯一的 UUID (如果需要,即使在启动时也是如此)非常简单.对我来说, 最限制的因素是这样一个事实 1) 用作 iBeacon 的设备根本不会在后台广播, 和 2) 应用程序不能在后台为单个 iBeacon 设置范围,除非在 onEnter 和 onLeave 事件中被唤醒,这些事件仅在进入或离开 UUID 区域时触发.
0赞 darrinm 12/21/2013
@d2burke 您提到用作 iBeacon 的设备根本不会在后台广播.即使应用程序使用蓝牙外设背景模式,您知道是否是这种情况吗?
0赞 d2burke 12/25/2013
@darrinm - 不幸的是,是的。iBeacon框架实际上与核心蓝牙是分开的,并且行为不同.
2赞 Michael McGuire 4/25/2014
我不确定这个回答是如何接近回答这个问题的。问题是: “我可以将自己宣传为具有服务的信标和 BLE 外围设备吗?此响应将广告作为信标和尝试检测信标进行了讨论。
0赞 ET Worker 8/16/2014 #2

在我的实践中, iBeacon 和 BLE 服务不能同时做广告.

如果与iBeacon混合播发,BLE服务无法在前台播发. iBeacon无法在后台播发.

iBeacon & BLE 服务可以逐个播发, 例如 iBeacon 播发 0.5 秒, 然后 BLE 服务通告 30.0 秒。

希望这会有所帮助