diverta / onecard-fido

MIT License
0 stars 0 forks source link

[障害] 接続障害発生時、以降のBLEペアリングが実行されない #783

Closed makmorit closed 1 year ago

makmorit commented 1 year ago

概要

macOS版管理ツールの「ペアリング情報削除」機能により、nRF5340からすべてのペアリング情報を消去した後、PC側に残存しているペアリング情報を使用して、再度ペアリングを試行すると、接続障害が発生します。 (#782 ご参照)

この時、基板上のボタンを押してペアリングモードに遷移させた後、再度macOS版管理ツールからペアリングを実行すると、エラーメッセージが表示され、以降管理ツールを再立ち上げするまで、BLEペアリングが実行されない不具合が確認されています。

管理ツールのログには、このエラーメッセージ表示時[error] helperWillConnectWithUUID: Connected peripheral already existというエラーログが記録されます。 おそらくですが、接続を保持するオブジェクトが、接続障害時にクリアされていない可能性があります。

makmorit commented 1 year ago

原因と対策

おそらくですが、接続を保持するオブジェクトが、接続障害時にクリアされていない可能性があります。

スキャンが成功すると、ヘルパークラスの内部変数discoveredPeripheralに、接続済みペリフェラルの参照が保持されます。

他方、本件障害ケースでは、前述の接続障害が発生した場合、この内部変数がクリアされないようです。 したがって、次のペアリング実行時に、下記のようなロジックで「接続済みペリフェラルの参照が存在する」ためエラーとなってしまいます。

- (void)helperWillConnectWithUUID:(NSString *)uuidString {
    // すでに接続が確立されている場合は通知
    if ([self discoveredPeripheral] != nil) {
        [[ToolLogFile defaultLogger] error:@"helperWillConnectWithUUID: Connected peripheral already exist"];
        [[self delegate] helperDidFailConnectionWithError:nil reason:BLE_ERR_DEVICE_CONNECT_FAILED];
        return;
    }
    :
}

とるべき対策

接続障害が発生した場合、ヘルパークラスの外部からdiscoveredPeripheralをクリアしておく必要があります。 以下のようなコーディングになるかと思われます。

- (void)helperDidFailConnectionWithError:(NSError *)error reason:(NSUInteger)reason {
    :
    // 接続前のエラーである場合は、上位クラスに完了通知を行う
    if (reason == BLE_ERR_DEVICE_CONNECT_FAILED || reason == BLE_ERR_BLUETOOTH_OFF || reason == BLE_ERR_DEVICE_SCAN_TIMEOUT) {
        // ここで接続済みペリフェラルの参照をクリア
        [[self toolBLEHelper] clearDiscoveredPeripheral];
        [[self delegate] didCompleteCommand:[self command] success:[self lastCommandSuccess] errorMessage:[self lastCommandMessage]];
        return;
    }
    // デバイス接続を切断
    [[self toolBLEHelper] helperWillDisconnect];
}
makmorit commented 1 year ago

対応結果の確認

af35093までの対応の結果、接続障害発生時、以降のBLEペアリングが実行されない不具合が解消された事を確認いたしました。