CoreBluetooth で Bluetooth LE デバイスに接続するという同様の問題に直面していました。私の場合は、Mac (中央) から iOS デバイス (周辺機器) に接続しています。
私が正しく理解している場合、パターンは非常に一貫しています。デバッグのために Mac アプリを初めて実行すると、Bluetooth LE デバイス (周辺機器) が常に検出され、接続されます。最も重要なことは、サービス/特性も正常に検出されることです。問題は 2 回目の実行で始まります (たとえば、コードを変更し、cmd-R を押してデバッグを再起動します)。セントラルは引き続き周辺機器を検出して接続しますが、サービスや特性の検出に失敗します。つまり、デリゲートは呼び出さperipheral:didDiscoverServices:
れperipheral:didDiscoverCharacteristicsForService:error:
ません。
試行錯誤の末の解決策は、驚くほどシンプルです。CoreBluetooth がキャッシュservices
さcharacteristics
れ、まだ接続されている周辺機器の場合、ローカルではアプリから切断されたように見えますが、周辺機器はシステムへの 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 でテストしたことはありませんが、かなり似ているはずです。