9

iOS 用の Bluetooth LE アプリケーションに取り組んでいます。iOS 内で Core Bluetooth フレームワークを使用して、すべての通信を処理しています。

質問と説明:

単一のタグを使用すると、多数の接続と切断にもかかわらず、単一のタグはシームレスに接続され、電話はサービスを検出します。

また、複数の Bluetooth LE タグが初めて接続すると、それらはシームレスに接続され、電話はそれらのサービスを検出します。

タグが切断されて電話に再接続すると、タグは正常に接続されます。しかし、2 つのタグのうちの 1 つ (いずれか 1 つ) は、そのサービスを宣伝していないようです。つまり、アプリが開いていてタグが再接続されると、DiscoverServicesメソッドはdidDiscoverServicesデリゲートを呼び出しません。

複数のデバイスとの接続が行われた場合にのみ、これが発生するのはなぜですか。

私はperipheral.delegateを正しく設定しました。タグへの再接続の繰り返し、DiscoverServicesの呼び出しの繰り返しなど、すべてを試しました。何も機能していないようです。

電話に複数のタグを再接続し、すべてのサービスを検出するにはどうすればよいですか?

助けてください、

ありがとう、
まんじゅう

4

8 に答える 8

22

私は同じ問題を抱えていましたが、呼び出された後にdelegateto を設定していないことに気付きました。CBPeripheraldidConnectPeripheral

- (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"Peripheral Connected: %@", peripheral.name);

    peripheral.delegate = self;

    if (peripheral.services) {
        [self peripheral:peripheral didDiscoverServices:nil];
    } else {
        [peripheral discoverServices:@[[CBUUID UUIDWithString:CUSTOM_UUID]]];
    }  
}
于 2014-04-16T17:28:19.917 に答える
16

CoreBluetooth で Bluetooth LE デバイスに接続するという同様の問題に直面していました。私の場合は、Mac (中央) から iOS デバイス (周辺機器) に接続しています。

私が正しく理解している場合、パターンは非常に一貫しています。デバッグのために Mac アプリを初めて実行すると、Bluetooth LE デバイス (周辺機器) が常に検出され、接続されます。最も重要なことは、サービス/特性も正常に検出されることです。問題は 2 回目の実行で始まります (たとえば、コードを変更し、cmd-R を押してデバッグを再起動します)。セントラルは引き続き周辺機器を検出して接続しますが、サービスや特性の検出に失敗します。つまり、デリゲートは呼び出さperipheral:didDiscoverServices:peripheral:didDiscoverCharacteristicsForService:error:ません。

試行錯誤の末の解決策は、驚くほどシンプルです。CoreBluetooth がキャッシュservicescharacteristicsれ、まだ接続されている周辺機器の場合、ローカルではアプリから切断されたように見えますが、周辺機器はシステムへの Bluetooth 接続を維持しているようです。これらのタイプの接続では、サービスと特性を (再) 検出する必要はありません。周辺オブジェクトから直接アクセスするだけで、それらnilを検出する必要があるかどうかを確認できます。また、前述のように、ペリフェラルは接続の間の状態にあるため、cancelPeripheralConnection:接続を試みる直前に呼び出すのが最善です。接続先のペリフェラルがすでに見つかっていると仮定すると、その要点は次のとおりです。

-(void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    [central cancelPeripheralConnection:peripheral]; //IMPORTANT, to clear off any pending connections    
    [central connectPeripheral:peripheral options:nil];
}

-(void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    peripheral.delegate = self;

    if(peripheral.services)
        [self peripheral:peripheral didDiscoverServices:nil]; //already discovered services, DO NOT re-discover. Just pass along the peripheral.
    else
        [peripheral discoverServices:nil]; //yet to discover, normal path. Discover your services needed
}

-(void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    for(CBService* svc in peripheral.services)
    {
        if(svc.characteristics)
            [self peripheral:peripheral didDiscoverCharacteristicsForService:svc error:nil]; //already discovered characteristic before, DO NOT do it again
        else
            [peripheral discoverCharacteristics:nil
                                     forService:svc]; //need to discover characteristics
    }
}

-(void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    for(CBCharacteristic* c in service.characteristics)
    {
        //Do some work with the characteristic...
    }
}

これは、Mac アプリの CBCentralManager でうまく機能します。iOS でテストしたことはありませんが、かなり似ているはずです。

于 2014-02-03T14:58:12.527 に答える
1

場合によっては、ハードウェアの問題です。ハードウェアがスキャン可能で接続可能なスリープ モードに入るケースに遭遇しましたが、discoverServices に対してまったくコールバックしません。

また、一晩中 BLE を開発していたときに、突然、何をしてもデバイスが検出サービスに対して無音になるという状況が発生しました。最後に、iPhone5s を再起動すると正常になることがわかりました。

そしてある日、Bluetooth ハードウェア エンジニアから、BLE の仕様では、デバイスは 30 秒以内に再び接続できる必要があるとしか書かれていないと教えてくれました。そのため、接続と切断を何度も繰り返すと、期待どおりに機能しない可能性があります...私はまだそれを疑っています.

于 2016-01-28T06:59:15.030 に答える
1

「 didDiscovercharacteristicsForService 」デリゲートメソッドでデバイスに発行していたコマンドがあり、接続が不安定になっていることがわかりました。

同様の問題に直面している場合は、(いかなる種類の) 介入もなしにデリゲート メソッドを完了させ、CBPeripheral を設計した別の関数に渡して、任意の値を渡したり、デバイスにコマンドを発行したりすることをお勧めします。

とにかくありがとうウィルヘムセン。

手順は次のとおりです。
1> タグを検索、
2> 範囲内であればタグに
接続 3> 接続されている場合は、DISCOVER サービス メソッドを呼び出します (中断しないでください)
4> DidDiscoverServices で、DISCOVER 特性メソッドを呼び出し
ます ..
DidDiscoverCharacteristics でメソッド、すべての特性が検出されるまで待ちます。次に、最後に、必要なセットアップを行うコード内の関数を呼び出します。
...
コード サンプル

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{

    for (int i=0; i < peripheral.services.count; i++) {
        CBService *s = [peripheral.services objectAtIndex:i];
        printf("Fetching characteristics for service with UUID : %s\r\n",[self CBUUIDToString:s.UUID]);
        [peripheral discoverCharacteristics:nil forService:s];
    }

}


- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{        
    if (!error)
    {
        CBService *s = [peripheral.services objectAtIndex:(peripheral.services.count - 1)];
        if([self compareCBUUID:service.UUID UUID2:s.UUID])
        {
           // This is when the **Tag** is completely connected to the Phone and is in a mode where it can accept Instructions from Device well.

            printf("Finished discovering characteristics");
           // Now Do the Setup of the Tag
            [self setupPeripheralForUse:peripheral];

        }
    }

    else
    {
        printf("Characteristic discorvery unsuccessfull !\r\n");
    }
}

-(void) setupPeripheralForUse:(CBPeripheral *)peripheral
{

    // DO all your setup in this function. Separate Perpiheral Setup from the process that synchronizes the tag and the phone. 

}
于 2012-08-29T05:17:15.097 に答える
1

私は同じ問題を抱えています。私の場合、約1/3の時間で発生するようです。PL が提供するソリューションを試しましたが、iOS では成功しませんでした。この問題の原因となる可能性のある多くの可動部品 (Bluetooth デバイス ファームウェア、CoreBluetooth など) がここで動作している可能性がありますが、NSMutableDictionary で保留中のサービス/特性検出中のデバイスを追跡し、GCD を使用して解決しました。妥当な時間内に検出が完了したかどうかを確認し、必要に応じて再試行します。だから、このようなもの:

- (void)requestDiscoverServicesForPeripheral:(CBPeripheral *)peripheral 
{
      peripheral.delegate = self;
      NSString *uuid =[self stringUUIDForUUID:peripheral.UUID];
      NSLog(@"discovering %d services ", self.interestingServices.count);
      [peripheral discoverServices:self.interestingServices];
      [self.pendingConnectionDevices setObject:peripheral forKey:uuid];
       __weak typeof(self) weakSelf = self;
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 *NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if ([weakSelf.pendingConnectionDevices objectForKey:uuid]) {

               //request discover services again
               NSLog(@"services did not discover, requesting again!");
               [weakSelf.btManager cancelPeripheralConnection:peripheral];
               [weakSelf.btManager connectPeripheral:peripheral options:nil];
         }
    });
 }

次に、peripheral:didDiscoverServices:errorコールバックするときに、pendingConnectionDevices 辞書から削除します。これはかなりうまくいくようです。成功するまでに最大 3 回サービスを検出しようとするのを見てきました。これが役立つことを願っています。

于 2014-04-12T20:54:19.983 に答える
1

CBPeripheralDelegate上記のすべての回答を適用しようとしていましたが、クラスに参加できなかったため、うまくいきませんでした。

class BLEHandler : NSObject, CBCentralManagerDelegate, CBPeripheralDelegate{

  func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {

    peripheral.delegate = self

    peripheral.discoverServices(nil)

    print("Connected: \(peripheral.state == .connected ? "YES" : "NO")")
  }

  func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {

    for service: CBService in peripheral.services! {
        peripheral.discoverCharacteristics(nil, for: service)
        print(service)
    }
  }

}
于 2017-11-24T01:03:25.670 に答える
0

私はあなたの答えであなたが言うすべてをやっていますが、私はまだこの問題を時々見ています。私の推測では、おそらく接続、サブスクリプション、および切断の特定のシーケンスが原因で、Core Bluetooth が奇妙な状態になると思われます。

この問題を解決する唯一の方法は、iOS デバイスを再起動することです。ただし、この問題は iOS 7.1 で修正される可能性があります。

于 2014-01-20T16:05:34.463 に答える