การสื่อสารแถบความถี่กว้างยิ่งยวด (UWB)

การสื่อสารย่านความถี่กว้างยิ่งยวดเป็นเทคโนโลยีวิทยุที่มุ่งเน้นการวัดระยะทางที่แม่นยำ (วัดตำแหน่งด้วยความแม่นยำ 10 ซม.) ระหว่างอุปกรณ์ เทคโนโลยีวิทยุนี้สามารถใช้ความหนาแน่นพลังงานต่ำสำหรับการวัดระยะสั้น และส่งสัญญาณแบนด์วิดท์สูงผ่านคลื่นความถี่วิทยุส่วนใหญ่ แบนด์วิดท์ของ UWB มากกว่า 500 MHz (หรือมากกว่า 20% ของแบนด์วิดท์เศษ)

ตัวควบคุม/ผู้เริ่มเทียบกับอุปกรณ์ที่ควบคุม/ผู้ตอบ

การสื่อสาร UWB เกิดขึ้นระหว่างอุปกรณ์ 2 เครื่อง โดยอุปกรณ์หนึ่งเป็นอุปกรณ์ควบคุมและอีกเครื่องหนึ่งเป็นอุปกรณ์ควบคุม ตัวควบคุมจะกำหนดแชแนลที่ซับซ้อน (UwbComplexChannel) ที่อุปกรณ์ 2 เครื่องจะแชร์ และเป็นอุปกรณ์ที่เริ่มต้น ในขณะที่ตัวควบคุมจะเป็นผู้ตอบ

ตัวควบคุมสามารถจัดการตัวควบคุมได้หลายตัว แต่ตัวควบคุมจะสมัครใช้บริการได้กับตัวควบคุมเพียงตัวเดียวเท่านั้น ระบบรองรับทั้งการกำหนดค่าตัวควบคุม/ผู้เริ่มและตัวควบคุม/ผู้ตอบ

พารามิเตอร์การวัดระยะ

ตัวควบคุมและอุปกรณ์ควบคุมต้องระบุตัวตนกันและสื่อสารพารามิเตอร์การกำหนดช่วงเพื่อเริ่มการกําหนดช่วง การรับส่งนี้ขึ้นอยู่กับแอปพลิเคชันที่จะนำไปใช้งานโดยใช้กลไกการสื่อสารนอกแบนด์ (OOB) ที่ปลอดภัยตามที่เลือก เช่น บลูทูธพลังงานต่ำ (BLE)

พารามิเตอร์การกําหนดช่วงได้แก่ ที่อยู่ภายใน แชแนลที่ซับซ้อน และคีย์เซสชัน และอื่นๆ โปรดทราบว่าพารามิเตอร์เหล่านี้อาจหมุนเวียนหรือเปลี่ยนแปลงหลังจากเซสชันการวัดระยะสิ้นสุดลง และจำเป็นต้องสื่อสารอีกครั้งเพื่อเริ่มการวัดระยะใหม่

การวัดระยะในเบื้องหลัง

แอปที่ทำงานอยู่เบื้องหลังสามารถเริ่มเซสชันการวัดระยะ UWB ได้หากอุปกรณ์รองรับ หากต้องการตรวจสอบความสามารถของอุปกรณ์ โปรดดูที่ RangingCapabilities

แอปจะไม่รับรายงานช่วงสัญญาณเมื่อทำงานอยู่เบื้องหลัง แต่จะได้รับรายงานช่วงสัญญาณเมื่อย้ายไปอยู่เบื้องหน้า

การกำหนดค่า STS

แอปหรือบริการจะจัดสรรคีย์เซสชันสำหรับแต่ละเซสชันโดยใช้ลำดับการประทับเวลาแบบสับ (STS) STS ที่เตรียมไว้จะปลอดภัยกว่าการกำหนดค่า STS แบบคงที่ อุปกรณ์ที่เปิดใช้ UWB ทั้งหมดที่ใช้ Android 14 ขึ้นไปจะรองรับ STS ที่เตรียมไว้

หมวดหมู่ภัยคุกคาม STS แบบคงที่ STS ที่กําหนดค่าไว้
อากาศ: ผู้สังเกตการณ์แบบไม่โต้ตอบ ลดลงแล้ว ลดลงแล้ว
อากาศ: การขยายสัญญาณ ลดลงแล้ว ลดลงแล้ว
อากาศ: การโจมตีแบบเล่นซ้ำ/รีเลย์ เสี่ยง ลดลงแล้ว

สำหรับ STS ที่จัดสรรแล้ว ให้ทำดังนี้

  1. ใช้ uwbConfigType ใน RangingParameters ที่รองรับ STS ที่เตรียมไว้

  2. ระบุคีย์ 16 ไบต์ในช่อง sessionKeyInfo

สำหรับ STS แบบคงที่

  1. ใช้ uwbConfigType ใน RangingParameters ที่รองรับ STS แบบคงที่

  2. ระบุคีย์ 8 ไบต์ในช่อง sessionKeyInfo

จำนวนก้าว

หากต้องการใช้ UWB API ให้ทำตามขั้นตอนต่อไปนี้

  1. ตรวจสอบว่าอุปกรณ์ Android ที่ใช้ Android 12 ขึ้นไปและรองรับ UWB โดยใช้PackageManager#hasSystemFeature("android.hardware.uwb")
  2. หากทำการวัดระยะกับอุปกรณ์ IoT โปรดตรวจสอบว่าอุปกรณ์ดังกล่าวเป็นไปตามข้อกำหนด FiRa MAC 1.3
  3. ค้นหาอุปกรณ์ที่รองรับ UWB โดยใช้กลไก OOB ที่คุณเลือก เช่น BluetoothLeScanner
  4. แลกเปลี่ยนพารามิเตอร์การวัดระยะโดยใช้กลไก OOB ที่ปลอดภัยซึ่งคุณเลือก เช่น BluetoothGatt
  5. หากผู้ใช้ต้องการหยุดเซสชัน ให้ยกเลิกขอบเขตของเซสชัน

ข้อจำกัดการใช้งาน

ข้อจำกัดต่อไปนี้มีผลกับการใช้ UWB API

  1. แอปที่เริ่มเซสชันการวัดระยะ UWB ใหม่ต้องเป็นแอปหรือบริการที่ทำงานอยู่เบื้องหน้า เว้นแต่ว่าอุปกรณ์จะรองรับการวัดระยะในเบื้องหลังตามที่แสดงไว้ก่อนหน้านี้
  2. เมื่อแอปย้ายไปยังเบื้องหลัง (ขณะที่เซสชันยังดำเนินอยู่) แอปอาจไม่ได้รับการรายงานช่วงอีกต่อไป อย่างไรก็ตาม เซสชัน UWB จะยังคงได้รับการดูแลรักษาในเลเยอร์ล่าง เมื่อแอปกลับมาที่เบื้องหน้า รายงานช่วงสัญญาณจะกลับมาทำงานต่อ

ตัวอย่างโค้ด

แอปตัวอย่าง

ดูตัวอย่างการใช้งาน UWB Jetpack Library ตั้งแต่ต้นจนจบได้ที่แอปพลิเคชันตัวอย่างใน GitHub แอปตัวอย่างนี้ครอบคลุมการตรวจสอบความเข้ากันได้ของ UWB ในอุปกรณ์ Android, การเปิดใช้กระบวนการค้นหาโดยใช้กลไก OOB และการตั้งค่า UWB ระหว่างอุปกรณ์ 2 เครื่องที่รองรับ UWB ตัวอย่างนี้ยังครอบคลุม Use Case การควบคุมอุปกรณ์และการแชร์สื่อด้วย

การกำหนดระยะ UWB

โค้ดตัวอย่างนี้จะเริ่มต้นและสิ้นสุดการวัดระยะ UWB สำหรับอุปกรณ์ที่ควบคุม

// 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()
    }
}

การรองรับ RxJava3

ตอนนี้เรารองรับ Rxjava3 เพื่อช่วยในการทํางานร่วมกันกับไคลเอ็นต์ Java แล้ว ไลบรารีนี้ให้วิธีรับผลลัพธ์ช่วงเป็นสตรีม Observable หรือ Flowable และดึงข้อมูล UwbClientSessionScope เป็นออบเจ็กต์เดี่ยว

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

การรองรับระบบนิเวศ

อุปกรณ์ของพาร์ทเนอร์และ SDK ของบุคคลที่สามที่รองรับมีดังนี้

อุปกรณ์เคลื่อนที่ที่เปิดใช้ UWB

อุปกรณ์ต่อไปนี้รองรับไลบรารี Jetpack UWB ของ Android ตั้งแต่เดือนมกราคม 2025

ตัวแทนจำหน่ายรายย่อย รุ่นอุปกรณ์
Google Pixel Pro (6 Pro ขึ้นไป), Fold, Tablet
Motorola Edge 50 Ultra
Samsung Galaxy Note 20, Galaxy Plus และ Ultra (S21 ขึ้นไป), Galaxy Z Fold (Fold2 ขึ้นไป)

หมายเหตุ: อุปกรณ์ทั้งหมดรองรับการวัดระยะ UWB เบื้องหลัง ยกเว้นอุปกรณ์ต่อไปนี้

  • Pixel 6 Pro และ Pixel 7 Pro
  • โทรศัพท์ Samsung ที่ใช้ Android 13 หรือต่ำกว่า
  • โทรศัพท์ Samsung จีนที่ใช้ Android 14 หรือต่ำกว่า

SDK ของบุคคลที่สาม

ตั้งแต่เดือนเมษายน 2023 โซลูชันของพาร์ทเนอร์เหล่านี้จะใช้งานร่วมกับไลบรารี Jetpack ปัจจุบันได้

ปัญหาที่ทราบ: ลำดับไบต์กลับกันสำหรับช่องที่อยู่ MAC และรหัสผู้ให้บริการ STS แบบคงที่

ใน Android 13 และต่ำกว่า สแต็ก UWB ของ Android จะกลับลําดับไบต์ของช่องต่อไปนี้อย่างไม่ถูกต้อง

  • ที่อยู่ MAC ของอุปกรณ์
  • ที่อยู่ MAC ปลายทาง
  • รหัสผู้ให้บริการ STS แบบคงที่

การเปลี่ยนลำดับไบต์เกิดขึ้นเนื่องจากสแต็ก Android ถือว่าช่องเหล่านี้เป็นค่า ไม่ใช่อาร์เรย์ เรากำลังดำเนินการร่วมกับ FiRa เพื่ออัปเดตข้อกำหนด UCI (CR-1112) เพื่อระบุอย่างชัดเจนว่าควรถือว่าช่องเหล่านี้เป็นอาร์เรย์

ปัญหานี้จะได้รับการแก้ไขผ่านการอัปเดต GMS Core ในรุ่น 2320XXXX ผู้ให้บริการ IOT จะต้องแก้ไขการใช้งานของคุณเพื่อไม่ให้การเรียงลำดับไบต์ของช่องเหล่านี้กลับกัน เพื่อให้เป็นไปตามข้อกำหนดของอุปกรณ์ Android นับจากจุดนั้นเป็นต้นไป