Communication à bande ultralarge (UWB)

La communication à bande ultralarge est une technologie radio axée sur une mesure de distance précise (mesure de la position jusqu'à une précision de 10 cm) entre les appareils. Cette technologie radio peut utiliser une densité à faible énergie pour les mesures de courte portée et générer un signal à bande passante élevée sur une grande partie du spectre radio. La bande passante de l'UWB est supérieure à 500 MHz (ou dépasse 20% de bande passante fractionnaire).

Responsable du traitement/Initiateur par rapport au responsable/répondant

La communication UWB se produit entre deux appareils, l'un étant un contrôleur et l'autre un contrôleur. Le contrôleur détermine le canal complexe (UwbComplexChannel) que les deux appareils partageront et en est l'initiateur, tandis que le contrôleur est le répondeur.

Un contrôleur peut gérer plusieurs contrôleurs, mais un contrôleur ne peut s'abonner qu'à un seul contrôleur. Les configurations de contrôleur/déclencheur et de contrôleur/répondeur sont acceptées.

Paramètres de portée

Le contrôleur et le contrôleur doivent s'identifier mutuellement et communiquer des paramètres de mesure pour commencer à les utiliser. Cet échange est confié aux applications qui doivent mettre en œuvre l'utilisation d'un mécanisme hors bande sécurisé de leur choix, tel que le Bluetooth à basse consommation (BLE).

Les paramètres de plage incluent, entre autres, l'adresse locale, le canal complexe et la clé de session. Notez que ces paramètres peuvent pivoter ou changer d'une manière ou d'une autre après la fin de la session de mesure des distances. Ils doivent donc être communiqués à nouveau pour redémarrer cette fonctionnalité.

Portée de l'arrière-plan

Une application exécutée en arrière-plan peut démarrer une session de mesure des distances avec la UWB si l'appareil le permet. Pour vérifier les fonctionnalités de votre appareil, consultez RangingCapabilities.

L'application ne reçoit pas de rapports de mesure des distances lorsqu'elle s'exécute en arrière-plan. Elle reçoit des rapports sur les distances lorsqu'elle passe au premier plan.

Configurations STS

L'application ou le service provisionne une clé de session pour chaque session à l'aide d'un séquence d'horodatage crypté (STS). Le service STS provisionné est plus sécurisé qu'une configuration STS statique. Le protocole STS provisionné est compatible avec tous les appareils compatibles UWB équipés d'Android 14 ou version ultérieure.

Catégorie de la menace STS statique STS anticipé
Air: observateur passif Atténué Atténué
Air: amplification du signal Atténué Atténué
Air: attaque par relais/rejeu Susceptible Atténué

Pour le protocole STS provisionné:

  1. Utilisez le uwbConfigType dans RangingParameters, qui est compatible avec le protocole STS provisionné.

  2. Indiquez la clé à 16 octets dans le champ sessionKeyInfo.

Pour un STS statique:

  1. Utilisez le uwbConfigType dans RangingParameters, qui accepte le STS statique.

  2. Indiquez la clé à huit octets dans le champ sessionKeyInfo.

Étapes

Pour utiliser l'API UWB, procédez comme suit:

  1. Assurez-vous que les appareils Android sont équipés d'Android 12 ou version ultérieure et qu'ils sont compatibles avec la technologie UWB à l'aide de PackageManager#hasSystemFeature("android.hardware.uwb").
  2. Si vous utilisez des appareils IoT, assurez-vous qu'ils sont conformes à la norme FiRa MAC 1.3.
  3. Découvrez les appareils similaires compatibles avec la UWB à l'aide d'un mécanisme OOB de votre choix, tel que BluetoothLeScanner.
  4. Échangez des paramètres de portée à l'aide d'un mécanisme OOB sécurisé de votre choix, tel que BluetoothGatt.
  5. Si l'utilisateur souhaite arrêter la session, annulez le champ d'application de la session.

Restrictions d'utilisation

Les restrictions suivantes s'appliquent à l'utilisation de l'API UWB:

  1. L'application qui lance de nouvelles sessions de mesure des distances avec l'UWB doit être une application ou un service de premier plan, sauf si la mesure des distances en arrière-plan est compatible, comme illustré précédemment.
  2. Lorsque l'application passe en arrière-plan (pendant que la session est en cours), il est possible qu'elle ne reçoive plus de rapports sur les distances. La session UWB continue toutefois d'être conservée dans les couches inférieures. Lorsque l'application revient au premier plan, les rapports de mesure des distances reprennent.

Exemples de code

Application exemple

Pour obtenir un exemple complet d'utilisation de la bibliothèque UWB Jetpack, consultez notre exemple d'application sur GitHub. Cet exemple d'application explique comment valider la compatibilité avec la UWB sur un appareil Android, activer le processus de découverte à l'aide d'un mécanisme OOB et configurer la UWB entre deux appareils compatibles. L'exemple couvre également des cas d'utilisation du contrôle des appareils et du partage de contenus multimédias.

Rangage UWB

Cet exemple de code lance et met fin aux fourchettes de valeurs UWB pour un Controlee:

// The coroutineScope responsible for handling uwb ranging.
// This will be initialized when startRanging is called.
var job: Job?

// A code snippet that initiates uwb ranging for a Controlee.
suspend fun startRanging() {

    // Get the ranging parameter of a partnering Controller using an OOB mechanism of choice.
    val partnerAddress : Pair<UwbAddress, UwbComplexChannel> = listenForPartnersAddress()

    // Create the ranging parameters.
    val partnerParameters = RangingParameters(
        uwbConfigType = UwbRangingParameters.UWB_CONFIG_ID_1,
        // SessionKeyInfo is used to encrypt the ranging session.
        sessionKeyInfo = null,
        complexChannel = partnerAddress.second,
        peerDevices = listOf(UwbDevice.createForAddress(partnerAddress.first)),
        updateRateType = UwbRangingParameters.RANGING_UPDATE_RATE_AUTOMATIC
    )

    // Initiate a session that will be valid for a single ranging session.
    val clientSession = uwbManager.clientSessionScope()

    // Share the localAddress of the current session to the partner device.
    broadcastMyParameters(clientSession.localAddress)

    val sessionFlow = clientSession.prepareSession(partnerParameters)

    // Start a coroutine scope that initiates ranging.
    CoroutineScope(Dispatchers.Main.immediate).launch {
        sessionFlow.collect {
            when(it) {
                is RangingResultPosition -> doSomethingWithPosition(it.position)
                is RangingResultPeerDisconnected -> peerDisconnected(it)
            }
        }
    }
}

// A code snippet that cancels uwb ranging.
fun cancelRanging() {

    // Canceling the CoroutineScope will stop the ranging.
    job?.let {
        it.cancel()
    }
}

Compatibilité avec RxJava3

La compatibilité avec Rxjava3 est désormais disponible pour faciliter l'interopérabilité avec les clients Java. Cette bibliothèque permet d'obtenir des résultats de plage de valeurs en tant que flux observable ou fluide, et de récupérer l'UwbClientSessionScope en tant qu'objet unique.

private final UwbManager uwbManager;

// Retrieve uwbManager.clientSessionScope as a Single object
Single<UwbClientSessionScope> clientSessionScopeSingle =
                UwbManagerRx.clientSessionScopeSingle(uwbManager);
UwbClientSessionScope uwbClientSessionScope = clientSessionScopeSingle.blockingGet();

// Retrieve uwbClientSessionScope.prepareSession Flow as an Observable object
Observable<RangingResult> rangingResultObservable =
                UwbClientSessionScopeRx.rangingResultsObservable(clientSessionScope,
                        rangingParameters);

// Consume ranging results from Observable
rangingResultObservable.subscribe(
   rangingResult -> doSomethingWithRangingResult(result), // onNext
   (error) -> doSomethingWithError(error), // onError
   () -> doSomethingOnResultEventsCompleted(), //onCompleted
);
// Unsubscribe
rangingResultObservable.unsubscribe();
   

// Retrieve uwbClientSessionScope.prepareSession Flow as a Flowable object
Flowable<RangingResult> rangingResultFlowable =
                UwbClientSessionScopeRx.rangingResultsFlowable(clientSessionScope,
                        rangingParameters);

// Consume ranging results from Flowable using Disposable
Disposable disposable = rangingResultFlowable
   .delay(1, TimeUnit.SECONDS)
   .subscribeWith(new DisposableSubscriber<RangingResult> () {
      @Override public void onStart() {
          request(1);
      }
      
      @Override public void onNext(RangingResult rangingResult) {
             doSomethingWithRangingResult(rangingResult);
             request(1);
      }


      @Override public void onError(Throwable t) {
             t.printStackTrace();
      }


         @Override public void onComplete() {
            doSomethingOnEventsCompleted();
         }
   });

// Stop subscription
disposable.dispose();

Prise en charge de l'écosystème

Voici les appareils partenaires et les SDK tiers compatibles.

Appareils mobiles compatibles UWB

Depuis mars 2024, ces appareils sont compatibles avec la bibliothèque UWB Jetpack Android:

Sous-revendeur Modèle de l'appareil
Google Pixel 6 Pro, 7 Pro, 8 Pro, Fold, tablette
Samsung Galaxy Note 20, S21+, S22+, S23+, S24+ Z Fold 2, 3, 4, 5

SDK tiers

Depuis avril 2023, ces solutions partenaires sont compatibles avec la bibliothèque Jetpack actuelle.

Problème connu: l'ordre des octets est inversé pour les champs d'adresse MAC et d'ID de fournisseur STS statique

Sur Android 13 et versions antérieures, la pile UWB Android inverse de manière incorrecte l'ordre des octets pour les champs suivants:

  • Adresse MAC de l'appareil
  • Adresse MAC de destination
  • ID du fournisseur STS statique

L'inversion de l'ordre des octets se produit, car la pile Android traite ces champs comme des valeurs et non comme des tableaux. Nous travaillons avec FiRa pour mettre à jour la spécification UCI (CR-1112) afin d'indiquer explicitement que ces champs doivent être traités comme des tableaux.

Ce problème sera résolu via la mise à jour GMS Core dans la version 2320XXXX. À partir de ce moment-là, pour se conformer aux appareils Android, les fournisseurs IoT doivent modifier votre implémentation pour éviter d'inverser l'ordre des octets de ces champs.