Komunikacja ultraszerokopasmowa (UWB)

Komunikacja ultraszerokopasmowa to technologia radiowa skoncentrowana na precyzyjnym określaniu odległości (mierzonej z dokładnością do 10 cm) między urządzeniami. Ta technologia radiowa może wykorzystywać niską gęstość energii do pomiarów w niewielkiej odległości oraz sygnalizację o wysokiej przepustowości w dużej części pasma radiowego. Przepustowość UWB jest większa niż 500 MHz (lub przekracza 20-procentową przepustowość).

Urządzenie sterujące/inicjator a urządzenie kontrolowane/odpowiadający

Komunikacja UWB odbywa się między 2 urządzeniami, z których jedno jest kontrolerem, a drugie urządzeniem kontrolowanym. Kontroler określa złożony kanał (UwbComplexChannel), który będą udostępniać 2 urządzenia, i jest inicjatorem, a kontrolowany jest odbiorcą.

Kontroler może obsługiwać wiele kontrolowanych elementów, ale kontrolowany element może subskrybować tylko jednego kontrolera. Obsługiwane są konfiguracje zarówno sterownika/inicjatora, jak i sterowanego urządzenia/odpowiadającego.

Parametry ustalania kolejności

Kontroler i kontrolowany muszą się wzajemnie zidentyfikować i przekazać parametry zakresu, aby rozpocząć pomiar. Aplikacje mogą wykorzystywać do tego celu dowolny bezpieczny mechanizm pozapasmowy (OOB), np. Bluetooth Low Energy (BLE).

Parametry zakresu obejmują m.in. adres lokalny, kanał złożony i klucz sesji. Pamiętaj, że te parametry mogą się zmieniać po zakończeniu sesji pomiaru zasięgu i należy je ponownie przesłać, aby wznowić pomiar zasięgu.

Wyszukiwanie w tle

Aplikacja działająca w tle może rozpocząć sesję pomiaru zasięgu UWB, jeśli urządzenie obsługuje tę technologię. Aby sprawdzić możliwości urządzenia, zapoznaj się z RangingCapabilities.

Aplikacja nie otrzymuje raportów o zakresie działania, gdy działa w tle. Otrzymuje je, gdy przejdzie na pierwszy plan.

Konfiguracje STS

Aplikacja lub usługa udostępnia klucz sesji dla każdej sesji za pomocą zaszyfrowanej sekwencji sygnatur czasowych (STS). Zarezerwowany STS jest bezpieczniejszy niż statyczna konfiguracja STS. Zarezerwowany STS jest obsługiwany na wszystkich urządzeniach z UWB z Androidem 14 lub nowszym.

Kategoria zagrożenia Statyczny STS STS z zabezpieczeniem
Powietrze: obserwator bierny Złagodzono Złagodzono
Air: wzmacnianie sygnału Złagodzono Złagodzono
Air: atak replay/relay Wrażliwy Złagodzono

W przypadku STS:

  1. Użyj uwbConfigTypeRangingParameters, który obsługuje zarezerwowany STS.

  2. W polu sessionKeyInfo wpisz klucz 16-bajtowy.

W przypadku statycznych STS:

  1. Użyj uwbConfigTypeRangingParameters, który obsługuje statyczny STS.

  2. W polu sessionKeyInfo wpisz 8-bajtowy klucz.

Kroki

Aby korzystać z interfejsu UWB API, wykonaj te czynności:

  1. Upewnij się, że urządzenia z Androidem mają system Android 12 lub nowszy i obsługują UWB (PackageManager#hasSystemFeature("android.hardware.uwb")).
  2. Jeśli chcesz skanować urządzenia IoT, upewnij się, że są one zgodne ze specyfikacją FiRa MAC 1.3.
  3. Wykrywanie urządzeń z dostępem do UWB za pomocą wybranego mechanizmu OOB, takiego jak BluetoothLeScanner.
  4. Wymień parametry pomiarowania za pomocą wybranego bezpiecznego mechanizmu OOB, takiego jak BluetoothGatt.
  5. Jeśli użytkownik chce przerwać sesję, anuluj jej zakres.

Ograniczenia w zakresie użytkowania

W przypadku korzystania z interfejsu UWB API obowiązują te ograniczenia:

  1. Aplikacja inicjująca nowe sesje pomiaru zasięgu UWB musi być aplikacją lub usługą działającą na pierwszym planie, chyba że pomiar w tle jest obsługiwany (jak opisano wcześniej).
  2. Gdy aplikacja przejdzie do działania w tle (podczas trwania sesji), może przestać otrzymywać raporty o zakresie. Sesja UWB będzie jednak nadal utrzymywana na niższych warstwach. Gdy aplikacja wróci na pierwszy plan, raporty dotyczące pomiaru odległości zostaną wznowione.

Przykłady kodu

Przykładowa aplikacja

Pełny przykład użycia biblioteki Jetpack UWB znajdziesz w naszej aplikacji przykładowej na GitHubie. Ta przykładowa aplikacja obejmuje sprawdzanie zgodności z UWB na urządzeniu z Androidem, włączanie procesu wykrywania za pomocą mechanizmu OOB oraz konfigurowanie pomiaru zasięgu UWB między dwoma urządzeniami obsługującymi UWB. Przykład obejmuje też przypadki użycia związane z kontrolowaniem urządzenia i udostępnianiem multimediów.

Ranking UWB

Ten przykładowy kod inicjuje i kończy pomiar UWB w 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()
    }
}

Obsługa RxJava3

Obsługa Rxjava3 jest już dostępna, aby ułatwić współdziałanie z klientami Java. Ta biblioteka umożliwia uzyskiwanie wyników pomiarów w postaci strumienia Observable lub Flowable oraz pobieranie obiektu UwbClientSessionScope jako pojedynczego obiektu.

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();

Pomoc dotycząca ekosystemu

Oto obsługiwane urządzenia partnerów i pakiety SDK innych firm.

Urządzenia mobilne z obsługą UWB

Od stycznia 2025 r. te urządzenia obsługują bibliotekę Jetpack UWB na Androida:

Dostawca Model urządzenia
Google Pixel Pro (6 Pro i nowsze), Fold, Tablet
Motorola Edge 50 Ultra
Samsung Galaxy Note 20, Galaxy Plus i Ultra (S21 i nowsze), Galaxy Z Fold (Fold2 i nowsze)

Uwaga: pomiar odległości w tle za pomocą UWB jest obsługiwany na wszystkich urządzeniach, z wyjątkiem tych:

  • Pixel 6 Pro i Pixel 7 Pro.
  • telefony Samsung z Androidem 13 lub starszym.
  • chińskie telefony Samsunga z Androidem 14 lub starszym;

Pakiety SDK firm zewnętrznych

Od kwietnia 2023 r. te rozwiązania partnerów są zgodne z bieżącą biblioteką Jetpacka.

Znane problemy: odwrócony porządek bajtów w przypadku pól adresu MAC i statycznych pól identyfikatora dostawcy STS

W Androidzie 13 i starszych pakiet usług UWB nieprawidłowo odwraca kolejność bajtów w tych polach:

  • Adres MAC urządzenia
  • Docelowy adres MAC
  • Statyczny identyfikator dostawcy STS

Odwrócenie kolejności bajtów występuje, ponieważ pakiet Android traktuje te pola jako wartości, a nie tablice. Współpracujemy z FiRa nad aktualizacją specyfikacji UCI (CR-1112), aby wyraźnie wskazać, że te pola powinny być traktowane jako tablice.

Ten problem zostanie rozwiązany w ramach aktualizacji GMS Core w wersji 2320XXXX. Aby od tego momentu spełniać wymagania dotyczące urządzeń z Androidem, dostawcy urządzeń IoT muszą zmodyfikować implementację, aby uniknąć odwrócenia kolejności bajtów w tych polach.