CoreBluetoothを使用してiPhoneからMacにデータを送信したい。このために、iPhoneを「Peripheral」、Macを「Central」のようなコードを作成しました。
完全に機能しますが、直接切断した後、継続的に接続および切断する場合があります。
再接続を試みる場合、Centralでは「didDisconnectPeripheral」デリゲートメソッドを直接呼び出します。ただし、「didUpdateNotificationStateForCharacteristic」で「ハンドルが無効です」というエラーが発生する場合があります。
ネット内のすべてのリンクを参照しました。しかし、私はこの問題を解決することができません。 iPhoneではBluetoothキャッシュを保存していると思いました。
「ハンドルが無効です」エラーを解決する方法を提案してください。
以下は重要な方法のいくつかです。
周辺機器については、以下のようなコードを作成しました。
Appdelegateの場合:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.peripheral = [[PeripheralServerObject alloc] init];
self.peripheral.serviceUUID = [CBUUID UUIDWithString:@"4w24"];
return YES;
}
ペリフェラルオブジェクトファイル:
//To Check Bluetooth State
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
switch (peripheral.state) {
case CBPeripheralManagerStatePoweredOn:
[self enableService];
break;
case CBPeripheralManagerStatePoweredOff: {
[self disableService];
break;
}
}
// To Add characteristics to Service
- (void)enableService
{
[self.peripheral removeAllServices];
self.service = [[CBMutableService alloc]
initWithType:self.serviceUUID primary:YES];
self.authChar =
[[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"a86e"]
properties:CBCharacteristicPropertyNotify
value:nil
permissions:CBAttributePermissionsReadable];
self.respChar =
[[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"a86f"]
properties:CBCharacteristicPropertyWriteWithoutResponse
value:nil
permissions:CBAttributePermissionsWriteable];
self.service.characteristics = @[ self.authChar, self.respChar ];
// Add the service to the peripheral manager.
[self.peripheral addService:self.service];
}
//Peripheral Manager delegate method will be called after adding service.
- (void)peripheralManager:(CBPeripheralManager *)peripheral
didAddService:(CBService *)service
error:(NSError *)error {
[self startAdvertising];
}
//To disable service
- (void)disableService
{
[self.peripheral stopAdvertising];
[self.peripheral removeAllServices];
}
//To enable a service again.
-(void)refreshService {
[self disableService];
[self enableService];
}
If central subscribes the characteristic, then the below peripheral delegate method will be called. In this I implemented code to send data
- (void)peripheralManager:(CBPeripheralManager *)peripheral
central:(CBCentral *)central
didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
self.dataTimer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:@selector(sendData)
userInfo:nil
repeats:YES];
}
- (void)sendData
{
Here I am sending data like [Apple's BTLE Example Code][1]
}
//If unsubscribed then I am invalidating timer and refreshing service
- (void)peripheralManager:(CBPeripheralManager *)peripheral
central:(CBCentral *)central
didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic {
if (self.dataTimer)
[self.dataTimer invalidate];
[self refreshService];
}
Macの場合、周辺デリゲートメソッドを作成しました。
//I enables the notification for "a860" Characteristic.
- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverCharacteristicsForService:(CBService *)service
error:(NSError *)error {
CBUUID * authUUID = [CBUUID UUIDWithString:@"a86e"];
for (CBCharacteristic *characteristic in service.characteristics) {
if ([characteristic.UUID isEqual:authUUID]) {
}
[self.connectedPeripheral setNotifyValue:YES
forCharacteristic:characteristic];
}
}
-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
if (error) {
Here I am getting error sometimes "The handle is invalid".
}
}
私は最近同じ問題に遭遇しました。私が見つけた唯一の解決策は、Bluetoothを再起動することでした(Bluetoothをオフにしてからオンに戻す)。
私の場合、常にこの問題を引き起こしたのはBluetoothデバイスの変更(DFUモードでの再起動)であったため、Bluetoothを再起動するようにユーザーに警告することになりました。 centralManagerDidUpdateState:
のPoweredOffおよびPoweredback On状態イベントをリッスンして、再起動が行われたかどうかを判断しました。