0

テストBTLEアプリに取り組んでいます。ユーザーは、中央モードまたは周辺モードの開始を選択できます。2 つのデバイスが両方ともアクティブで範囲内にある場合、それらは即座にデータを検出、接続、転送しますが...

デバイス 1 がセントラル モードで起動されてからバックグラウンドに置かれた場合、デバイス 2 は範囲外に取り出されてペリフェラル モードになり、周辺機器がバックグラウンドのセントラルの隣に置かれると、セントラルはペリフェラルを検出してデータを取得します。

デバイス 1 がペリフェラル モードで起動され、バックグラウンドに配置された場合、デバイス 2 は範囲外に移動されて中央モードに配置され、その後範囲内に移動されてもペリフェラルは検出されません。(私は最大5分待ちました)もう一度「中央を開始」ボタンを押すと、すぐに検出されます!

「中央を開始」は次のことのみを行います。

-(id)init{
    if (self=[super init]) {
        dispatch_queue_t peripheralQueue=dispatch_queue_create("com.Dev.peripheralQueue", 0);
        dispatch_queue_t centralQueue=dispatch_queue_create("com.Dev.centralQueue", 0);

        // Initiate Managers with restore keys for background mode
        self.centralManager=[[CBCentralManager alloc]initWithDelegate:self
                                                                queue:centralQueue
                                                              options:@{CBCentralManagerOptionRestoreIdentifierKey: CM_RESTORE_KEY}];
        self.peripheralManager=[[CBPeripheralManager alloc]initWithDelegate:self
                                                                      queue:peripheralQueue
                                                                    options:@{CBPeripheralManagerOptionRestoreIdentifierKey: PM_RESTORE_KEY}];
        // 1. create The UUIDs
        // 2. create the service and characteristics
//service is alloc/inited and published in did update state
    }
    return self;
}

-(void)switchToCentral
{
    NSLog(@"BTM switchToCentral");
    [self.peripheralManager stopAdvertising];
    [self scan];
    self.isCentral = YES;
}

- (void)scan
{
    [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]
                                                options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@NO}];
    NSLog(@"CM Scanning started");
}

次の恥ずべきハックを追加しました。

-(void)switchToCentral
{
    NSLog(@"BTM switchToCentral");
    [self stopBroadcasting];
    [self scan];
    self.isCentral = YES;

    dispatch_async(dispatch_get_main_queue(), ^{
        [NSTimer scheduledTimerWithTimeInterval:5
                                         target:self
                                       selector:@selector(centralShouldRescan:)
                                       userInfo:nil
                                        repeats:YES];
    });
}

-(void)centralShouldRescan:(NSTimer*)timer{

    NSLog(@"BTM centralShouldRescan");
    if (self.isCentral) {
        NSLog(@"BTM centralShouldRescan isCentral");
        [self stopBroadcasting];
        [self scan];


    }else{
        NSLog(@"BTM centralShouldRescan isCentral");
        [timer invalidate];
    }
}

そして今、それは動作します! 私はこれを理解するのに途方に暮れています.CBCentralマネージャーがスキャンを開始すると、特にフォアグラウンドにある場合、停止するまでスキャンを続けることは私の理解と経験でした.

4

1 に答える 1

1

centralManagerDidUpdateStateデリゲート メソッドを実装しましたか? ペリフェラル モードを無効にすると、centralManager がスキャンする準備が整うまでに多少の遅延があると思われますが、これは単なる推測です。次のようなものを試すことができます-

-(void) centralManagerDidUpdateState:(CBCentralManager *)central
{
    if (central.state == CBCentralManagerStatePoweredOn)
    {
       [self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey:@NO}];
    }
}

これにより、中央マネージャーが電源オン状態から移行した場合に、スキャンが確実に再開されます。

于 2014-03-31T03:50:49.383 に答える