สร้างแอป Android สําหรับกรณี

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

1. ยินดีต้อนรับ

Matter สร้างโดยมีเป้าหมายเป็นการรวมมาตรฐาน IoT เพื่อเชื่อมต่ออุปกรณ์ในบ้านอัจฉริยะผ่านระบบนิเวศต่างๆ เช่น Google Home, Zigbee, Bluetooth Mesh, Z-Wave และอีกมากมาย

อุปกรณ์เคลื่อนที่เป็นจุดศูนย์กลางของการโต้ตอบด้วยอุปกรณ์ในบ้านอัจฉริยะ หากต้องการสร้างแอป Android ของตนเองเพื่อรองรับอุปกรณ์ Matter เราช่วยคุณเริ่มต้นใช้งานได้อย่างรวดเร็ว

แอป Google Home Sample สําหรับ Matter (GHSA สําหรับ Matter) จะแสดง Home Mobile SDK API ซึ่งช่วยให้ผู้ใช้ค่าคอมมิชชันและแชร์อุปกรณ์ได้ คุณยังสามารถใช้แอปตัวอย่างเป็นเครื่องมือการเรียนรู้เพื่อทําความเข้าใจแนวคิดหลักของ Matter และเครื่องมือแก้ไขข้อบกพร่องและแก้ปัญหาการโต้ตอบกับอุปกรณ์ Matter ได้ดีขึ้น

สิ่งที่ต้องทํา

ใน Codelab นี้ คุณจะดาวน์โหลดซอร์สโค้ดสําหรับแอปตัวอย่างและเรียนรู้วิธีใช้ Home Mobile SDK เพื่อว่าจ้างและแชร์อุปกรณ์ นอกจากนี้ คุณจะยังดูวิธีใช้ไลบรารีค่าคอมมิชชันและคลัสเตอร์จากที่เก็บข้อมูล Matter (connectedhomeip) อีกด้วย

หลังจากที่คุณดาวน์โหลดแอปตัวอย่างแล้ว เราจะตรวจสอบซอร์สโค้ดใน Android Studio และใช้ Home Mobile SDK API ต่อไปนี้

รวมถึงข้อมูลเพิ่มเติมเกี่ยวกับแนวคิดการว่าจ้าง ผ้า Matter และวิธีควบคุมอุปกรณ์ Matter

สิ่งที่ต้องมี

ก่อนเริ่มต้น โปรดทําตามขั้นตอนต่อไปนี้

คุณไม่จําเป็นต้องมีฮับ เช่น Google Nest Hub (รุ่นที่ 2) เพื่อค่าคอมมิชชันและควบคุมอุปกรณ์ด้วยแอปตัวอย่าง

2. ตั้งค่า

ที่เก็บ GitHub ของแอปตัวอย่างมีไลบรารีของบุคคลที่สามจากที่เก็บข้อมูล Matter (connectedhomeip) ไลบรารีแบบเนทีฟเหล่านี้มีขนาดมากกว่า 50 MB และต้องใช้ Git Large File Storage (LFS)

แอป Codelab เริ่มต้นจะอยู่ในสาขา codelab หากต้องการเริ่มทํางานกับซอร์สโค้ด Codelab คุณสามารถดาวน์โหลดไฟล์ ZIP ได้ ไฟล์ ZIP นี้มีไลบรารีเนทีฟ Matter SDK โดยไม่ต้องใช้ Git LFS

คุณจะใช้ไฟล์ ZIP codelab นี้เพื่อสร้างตัวอย่างที่ใช้งานได้

เวอร์ชัน Codelab

สาขา codelab ติดแท็กด้วยรุ่น 1.2.2 ของแอปตัวอย่าง หากต้องการเปรียบเทียบการอัปเดตขณะทําตามขั้นตอนต่างๆ คุณสามารถดาวน์โหลดซอร์สโค้ดที่สมบูรณ์สําหรับรุ่นนี้ได้

หากต้องการโคลนที่เก็บ GitHub ให้ทําตามวิธีการในตัวอย่างแอป README

การอ้างอิง

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

  • SDK อุปกรณ์เคลื่อนที่สําหรับบ้าน
    implementation 'com.google.android.gms:play-services-home:16.0.0'
    
  • ไลบรารี SDK ของ Matter
    // Native libs
    implementation fileTree(dir: "third_party/connectedhomeip/libs", include: ["*.jar", "*.so"])
    
  • การออกแบบ Material ดูข้อมูลเพิ่มเติมได้ที่ MDC-103 Android: Material Themming with Color, Elevation and Type (Kotlin) และ Material Theme Builder
    implementation 'com.google.android.material:material:1.5.0'
    
  • Proto DataStore ที่ใช้ในการเก็บข้อมูลแอปไว้ ที่เก็บ Datastore และซีเรียลไลเซอร์จะจัดเก็บอยู่ใน java/data ซึ่งรวมถึงสคีมาสําหรับอุปกรณ์และค่ากําหนดของผู้ใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับ DataStore ได้ที่การทํางานกับ Proto DataStore
    implementation "androidx.datastore:datastore:$dataStoreVersion"
    implementation 'androidx.datastore:datastore-core:1.0.0'
    implementation 'com.google.protobuf:protobuf-javalite:3.18.0'
    
  • Hit เพื่อเก็บข้อมูลและรองรับการแทรกทรัพยากร Dependency
    kapt 'com.google.dagger:hilt-compiler:2.41'
    implementation 'com.google.dagger:hilt-android:2.41'
    

ซอร์สโค้ด

ระบบสร้างอินเทอร์เฟซผู้ใช้และฟังก์ชันการทํางานส่วนใหญ่ให้คุณแล้ว

สําหรับ Codelab นี้ เราจะเพิ่มฟังก์ชัน Matter ในไฟล์ต่อไปนี้

  • java/commissioning/AppCommissioningService: ให้คุณกําหนดอุปกรณ์ให้ผ้าสําหรับการพัฒนา
  • java/screens/HomeFragment และ java/screens/HomeViewModel.kt: มีฟังก์ชันค่าคอมมิชชัน SDK บนอุปกรณ์เคลื่อนที่
  • java/screens/DeviceViewModel: รวมการเรียก Share Device API

แต่ละไฟล์แสดงความคิดเห็นด้วยโค้ดบล็อกที่จะแก้ไข เช่น

// CODELAB: add commissioningFunction()

ซึ่งจะช่วยให้คุณค้นหาส่วนที่เกี่ยวข้องใน Codelab ได้อย่างรวดเร็ว

3. ค่าคอมมิชชันสําหรับ Google

ก่อนที่จะควบคุมอุปกรณ์และอนุญาตให้สื่อสารกันได้บนผ้าเดียวกัน อุปกรณ์เหล่านั้นต้องว่าจ้างโดย Commissioner ซึ่งในกรณีนี้ เป็นแอปพลิเคชันตัวอย่างของแอป Google Home Sample สําหรับ Matter

คุณควรทําความเข้าใจแนวคิดต่อไปนี้เกี่ยวกับการว่าจ้าง Matter

  • ผ้าจะช่วยให้อุปกรณ์สื่อสารกันได้
  • ผ้าจะเป็นการรักษาข้อมูลเข้าสู่ระบบที่ใช้ร่วมกันแบบไม่ซ้ํา
  • ระบบนิเวศจะรับผิดชอบในการออกใบรับรองรูทที่เชื่อถือได้ กําหนดรหัสผ้า และกําหนดรหัสโหนดที่ไม่ซ้ํากัน ระบบนิเวศคือบริการแบ็กเอนด์ของค่าคอมมิชชัน เช่น กราฟบ้านสําหรับระบบนิเวศของ Google Home
  • อาจมีการกําหนดให้อุปกรณ์ใช้ผ้ามากกว่า 1 ผืน (ฟีเจอร์สําหรับหลายผู้ดูแลระบบ)

คุณจะต้องใช้ CommissioningClient API เพื่อตั้งค่าอุปกรณ์ การเรียก .commissionDevice() จะแสดง IntentSender ซึ่งจะเปิดใช้กิจกรรมที่เหมาะสมในบริการ Google Play

interface CommissioningClient {
  Task<IntentSender> commissionDevice(CommissioningRequest request);
}

ในส่วนถัดไป เราจะกล่าวถึงโค้ดขั้นต่ําที่จําเป็นในการกําหนดให้อุปกรณ์ทํางานกับผ้า Google

ขั้นตอนที่ 1: ตัวเปิดใช้งานกิจกรรม

หากต้องการจัดการ IntentSender จาก CommissioningClient คุณสามารถใช้ ActivityResultLauncher ได้โดยทําดังนี้

private lateinit var commissioningLauncher: ActivityResultLauncher<IntentSenderRequest>
commissioningLauncher = registerForActivityResult(
    StartIntentSenderForResult()
) { result: ActivityResult ->
    if (result.resultCode == RESULT_OK) {
        Timber.d(TAG, "Commissioning succeeded.")
    } else {
        Timber.d(TAG, "Commissioning failed. " + result.resultCode)
    }
}

ขั้นตอนที่ 2: การว่าจ้างฟังก์ชัน

ตัวอย่างพื้นฐานที่ใช้ CommissioningClient API เพื่อกําหนดให้อุปกรณ์ทํางานกับผ้า Google

  1. ขั้นตอนการว่าจ้างจะเริ่มต้นด้วยฟังก์ชัน commissionDevice() ก่อนอื่นให้กําหนด CommissioningRequest การกําหนดค่าเริ่มต้นนี้กําหนดให้อุปกรณ์ดําเนินการกับผ้า Android ในพื้นที่เท่านั้น
  2. Matter เป็นจุดเริ่มต้นสําหรับ Home Mobile SDK ในการโทรครั้งถัดไป .getCommissioningClient จะได้รับค่าคอมมิชชันจาก this (กิจกรรม)
  3. .commissionDevice() ยอมรับCommissioningRequest
  4. และสุดท้าย ระบบจะเรียก .addOnSuccessListener ให้ประมวลผล CommissioningResult และเปิดตัวกิจกรรมอุปกรณ์ค่าคอมมิชชันของบริการ Google Play (GPS)
private fun commissionDevice() {
    val request: CommissioningRequest = CommissioningRequest.builder().build()
    Matter.getCommissioningClient(this)
        .commissionDevice(request)
        .addOnSuccessListener { result ->
            commissioningLauncher.launch(IntentSenderRequest.Builder(result).build())
        }
}

คุณสามารถใช้ประโยชน์จากผ้า Android ในพื้นที่ได้ผ่านการตั้งค่า Android เพื่อลดความซับซ้อนของค่าคอมมิชชันในอุปกรณ์ด้วยผ้าอื่นๆ

ถัดไป คุณจะได้ดูวิธีค่าคอมมิชชันอุปกรณ์ให้กับผ้าสําหรับการพัฒนา

สําหรับภาพรวมของอินเทอร์เฟซผู้ใช้ระหว่างขั้นตอนการว่าจ้าง โปรดอ่านคู่มือตัวอย่างแอป Google Home สําหรับกรณี

4. ค่าคอมมิชชันของการพัฒนาผลิตภัณฑ์

อุปกรณ์นี้ใช้ผ้ามากกว่า 1 ผืนได้ หากต้องการจัดการการจับคู่ที่เชื่อถือได้ อุปกรณ์จะจัดเก็บ FabricTable ที่มีสมาชิก FabricInfo หลายคน เช่น

  • การระบุผ้า
  • รหัสโหนดที่ผ้ากําหนดให้อุปกรณ์
  • รหัสผู้ให้บริการ
  • รหัสผ้า
  • ข้อมูลเข้าสู่ระบบการทํางานของอุปกรณ์

เครื่องมือจัดการการดูแลระบบ (ADM) จะกําหนดข้อมูลเข้าสู่ระบบของผ้า ในสถานการณ์ก่อนหน้านี้ บริการ Google Play คือระบบนิเวศที่ทําหน้าที่เป็นผู้ออกใบรับรองรูท (CA) ที่เชื่อถือได้ เมื่อคุณกําหนดอุปกรณ์ให้ทํางานกับผ้า Android ท้องถิ่น อุปกรณ์ทุกเครื่องจะมีข้อมูลเข้าสู่ระบบผ้าเดียวกันและ CA ชุดเดียวกัน

บริการรับทําตามสั่ง

เรานําพารามิเตอร์เริ่มต้นมาใช้ในการสร้าง CommissioningRequest ใน CommissioningClient API ดังนี้เพื่อเปลี่ยนไปใช้ผ้า Android ในพื้นที่

val request: CommissioningRequest = CommissioningRequest.builder().build()

หากต้องการควบคุมและจัดการอุปกรณ์ใหม่จากแอปของคุณ คุณต้องสร้างผ้าสําหรับการพัฒนาในท้องถิ่นและรับข้อมูลรับรองการดําเนินการเพื่อค่าคอมมิชชันอุปกรณ์ ในสถานการณ์นี้ แอปของคุณจะกลายเป็นระบบนิเวศที่เป็นเอกลักษณ์และไม่ซ้ํากันซึ่งจะกําหนดข้อมูลเข้าสู่ระบบโหนดที่เหมาะสมให้กับอุปกรณ์

คุณอาจแจ้ง Home Mobile SDK ที่ต้องการกําหนดอุปกรณ์ให้ทอผ้าของคุณเองโดยการส่งบริการที่กําหนดเองไปยัง CommissioningRequest ดังนี้

class CommissioningRequest {
  static CommissioningRequest.Builder builder();

  class Builder {
    Builder setCommissioningService(@Nullable ComponentName commissioningService);

    CommissioningRequest build();
  }
}

ในขั้นตอนต่อไป เราจะแก้ไขฟังก์ชัน commissionDevice() เพื่อใช้บริการที่กําหนดเอง เราจะเพิ่ม Launcher กิจกรรมไปยังส่วนย่อยของหน้าแรกและใช้ออบเจ็กต์ LiveData เพื่อจัดการโฟลว์ API ด้วย

ขั้นตอนที่ 1: สร้าง Launcher กิจกรรม GPS

ก่อนอื่น ให้สร้าง Launcher กิจกรรมเพื่อจัดการ IntentSender จาก CommissioningClient API

  1. เปิด HomeFragment ในโฟลเดอร์ java/screens/home/
  2. แทนที่ความคิดเห็น // CODELAB: commissionDeviceLauncher declaration ด้วยการประกาศต่อไปนี้
    // The ActivityResult launcher that launches the "commissionDevice" activity in Google Play
    // Services.
    private lateinit var commissionDeviceLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  3. แทนที่ // CODELAB: commissionDeviceLauncher definition ความคิดเห็นด้วยโค้ดต่อไปนี้เพื่อลงทะเบียนและจัดการผลลัพธ์ของกิจกรรมค่าคอมมิชชัน
    commissionDeviceLauncher =
        registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
          // Commission Device Step 5.
          // The Commission Device activity in GPS has completed.
          val resultCode = result.resultCode
          if (resultCode == Activity.RESULT_OK) {
            Timber.d("CommissionDevice: Success")
            // We now need to capture the device information for the app's fabric.
            // Once this completes, a call is made to the viewModel to persist the information
            // about that device in the app.
            showNewDeviceAlertDialog(result)
          } else {
            viewModel.commissionDeviceFailed(resultCode)
          }
        }    ```
    
    

ขั้นตอนที่ 2: สร้างออบเจ็กต์ LiveData

การเรียกกลับของ .commissionDevice() API ที่สําเร็จจะรวม IntentSender เพื่อใช้เปิดกิจกรรมอุปกรณ์ค่าคอมมิชชันในบริการของ Google Play ใน HomeViewModel เราจะสร้างออบเจ็กต์ LiveData 2 รายการเพื่อรายงานผลลัพธ์ของการเรียก API นี้

  • commissionDeviceStatus เพื่อติดตาม TaskStatus
  • commissionDeviceIntentSender เพื่อจัดการผลลัพธ์ของการโทร .commissionDevice() ออบเจ็กต์ LiveData นี้จะเปิดตัว ActivityLauncher ที่เราเพิ่งสร้างและแสดงกิจกรรมบนอุปกรณ์ค่าคอมมิชชัน GPS แก่ผู้ใช้
  1. ใน private fun setupObservers() ให้แทนที่ความคิดเห็น // CODELAB: commissionDeviceStatus ด้วยการสังเกตการณ์ต่อไปนี้
    // The current status of the share device action.
    viewModel.commissionDeviceStatus.observe(viewLifecycleOwner) { status ->
      Timber.d("commissionDeviceStatus.observe: status [${status}]")
    }
    
  2. จากนั้นแทนที่ความคิดเห็น // CODELAB: commissionDeviceIntentSender ด้วยผู้สังเกตการณ์ต่อไปนี้
    viewModel.commissionDeviceIntentSender.observe(viewLifecycleOwner) { sender ->
      Timber.d(
          "commissionDeviceIntentSender.observe is called with [${intentSenderToString(sender)}]")
      if (sender != null) {
        // Commission Device Step 4: Launch the activity described in the IntentSender that
        // was returned in Step 3 (where the viewModel calls the GPS API to commission
        // the device).
        Timber.d("CommissionDevice: Launch GPS activity to commission device")
        commissionDeviceLauncher.launch(IntentSenderRequest.Builder(sender).build())
        viewModel.consumeCommissionDeviceIntentSender()
      }
    }
    

ขั้นตอนที่ 3: เรียก API

เมื่อเราเขียนโค้ดเพื่อจัดการกับ API แล้ว ก็ถึงเวลาเรียก API ส่งผ่านบริการที่กําหนดเอง (ซึ่งเราจะกําหนดในขั้นตอนถัดไป) และโพสต์ไปยังออบเจ็กต์ LiveData

  1. เปิด HomeViewModel.kt ในโฟลเดอร์ java/screens/home/
  2. แทนที่ความคิดเห็น // CODELAB: commissionDevice ด้วย commissionDeviceRequest ต่อไปนี้ setCommissioningService เชื่อมโยง AppCommissioningService กับอินสแตนซ์ CommissioningService โดยแสดงผลในฟังก์ชันเรียกกลับ เมื่อคุณส่งบริการที่กําหนดเอง Home Mobile SDK จะค่าคอมมิชชันอุปกรณ์ให้กับผ้า Google ก่อน จากนั้นจึงส่งเพย์โหลดการเริ่มต้นใช้งานกลับไปยัง AppCommissioningService
    fun commissionDevice(context: Context) {
      _commissionDeviceStatus.postValue(TaskStatus.InProgress)
    
      val commissionDeviceRequest =
          CommissioningRequest.builder()
              .setCommissioningService(ComponentName(context, AppCommissioningService::class.java))
              .build()
    
  3. โทรหา .getCommissioningClient() แล้วโทร .commissionDevice()
    Matter.getCommissioningClient(context)
        .commissionDevice(commissionDeviceRequest)
    

หากต้องการเพิ่มฟังก์ชัน commissionDevice ให้เสร็จสิ้น ให้เพิ่ม addOnSuccessListener และ addOnFailureListener และโพสต์ลงในออบเจ็กต์ LiveData:

      .addOnSuccessListener { result ->
        // Communication with fragment is via livedata
        _commissionDeviceIntentSender.postValue(result)
      }
      .addOnFailureListener { error ->
        Timber.e(error)
        _commissionDeviceStatus.postValue(
          TaskStatus.Failed("Failed to to get the IntentSender.", error)
      }
}

หลังจากใช้ผู้ส่งแล้ว ควรเรียกใช้ consumeCommissionDeviceIntentSender() เพื่อหลีกเลี่ยงการรับผู้ส่งอีกครั้งหลังจากเปลี่ยนการกําหนดค่า

  /**
   * Consumes the value in [_commissionDeviceIntentSender] and sets it back to null. Needs to be
   * called to avoid re-processing the IntentSender after a configuration change (where the LiveData
   * is re-posted).
   */
  fun consumeCommissionDeviceIntentSender() {
    _commissionDeviceIntentSender.postValue(null)
  }

5. สร้างค่าคอมมิชชัน

ในฟังก์ชัน commissionDevice() เราได้ส่งคําขอรับ CommissioningService จาก CommissioningClient API ในขั้นนี้ CommissioningClient API จะกําหนดให้อุปกรณ์เปลี่ยนไปใช้ผ้า Android ในพื้นที่ก่อน จากนั้นจึงส่งคืนการเรียกกลับที่มีออบเจ็กต์ CommissioningRequestMetadata ดังนี้

public interface CommissioningService {
interface Callback {
    void onCommissioningRequested(CommissioningRequestMetadata metadata);
  }
}

ปัจจุบันเราต้องรับช่วงค่า CommissioningService.Callback และให้ฟังก์ชันที่จําเป็นสําหรับค่าคอมมิชชันอุปกรณ์ไปยังแอปตัวอย่างของเรา ตัวอย่างการติดตั้งใช้งาน CommissioningService พื้นฐานมีดังนี้

class MatterCommissioningService : Service(), CommissioningService.Callback {
   private val commissioningServiceDelegate =
     CommissioningService.Builder(this)
       .setCallback(this)
       .build()

   override fun onBind(intent: Intent) = commissioningServiceDelegate.asBinder()

   override fun onCommissioningRequested(metadata: CommissioningRequestMetadata) {
     // perform commissioning

     commissioningServiceDelegate
       .sendCommissioningComplete(CommissioningCompleteMetadata.builder().build())
   }
 }

ขั้นตอนที่ 1: สํารวจ AppCommissioningService ที่กําหนดเอง

เราได้กําหนดโครงสร้างพื้นฐานสําหรับ CommissioningService ที่กําหนดเองแล้วเพื่อช่วยคุณเริ่มต้นใช้งาน ภาพรวมคร่าวๆ เกี่ยวกับฟังก์ชันของบริการมีดังนี้ หากต้องการดําเนินการต่อ ให้เปิด AppCommissioningService ใน java/commissioning

เราได้เพิ่มการนําเข้าต่อไปนี้สําหรับ Home Mobile SDK API

import com.google.android.gms.home.matter.commissioning.CommissioningCompleteMetadata
import com.google.android.gms.home.matter.commissioning.CommissioningRequestMetadata
import com.google.android.gms.home.matter.commissioning.CommissioningService

AppCommissioningService ยังมีไลบรารีจากที่เก็บ Matter (connectedhomeip) ด้วย

import com.google.home_sample_app_for_matter.chip.ChipClient

สุดท้าย บริการจะมีการนําเข้าเพื่อรองรับ Hilt และ Corineine ของ Kotlin

ต่อไป เราจะสร้างเครื่องมือสร้างและตั้งค่าบางอย่าง รวมถึง commissioningServiceDelegate ซึ่งเราจะใช้เพื่อแจ้งให้บริการ Google Play ทราบเมื่อค่าคอมมิชชันเสร็จสมบูรณ์

private lateinit var commissioningServiceDelegate: CommissioningService
...
commissioningServiceDelegate = CommissioningService.Builder(this).setCallback(this).build()

ได้เวลาเพิ่มฟังก์ชันค่าคอมมิชชันแล้ว

ขั้นตอนที่ 2: ลบล้าง onCommissioningRequest

ทําตามขั้นตอนต่อไปนี้เพื่อเข้าร่วมอุปกรณ์กับการพัฒนาแอป

  1. เปิด AppCommissioningService ใน java/commissioning
  2. ค้นหาฟังก์ชัน onCommissioningRequested() เราได้ส่งข้อความบันทึกที่พิมพ์ไปยัง CommissioningRequestMetadata แทนที่ความคิดเห็น // CODELAB: onCommissioningRequested() เพื่อเริ่ม Coroutine ของ serviceScope และรับ deviceId
    // Perform commissioning on custom fabric for the sample app.
    serviceScope.launch {
      val deviceId = devicesRepository.incrementAndReturnLastDeviceId()
    
  3. ดําเนินการว่าจ้าง ในขั้นตอนนี้ เราสามารถส่งข้อมูลอุปกรณ์ที่แสดงในออบเจ็กต์ CommissioningRequestMetadata ChipClient ใช้ข้อมูลข้อมูลเมตานี้เพื่อสร้างช่องทางที่ปลอดภัยระหว่างแอป GHSA สําหรับ Matter กับอุปกรณ์ของคุณ
    Timber.d("Commissioning: App fabric -> ChipClient.establishPaseConnection(): deviceId [${deviceId}]")
    chipClient.awaitEstablishPaseConnection(
        deviceId,
        metadata.networkLocation.ipAddress.hostAddress!!,
        metadata.networkLocation.port,
        metadata.passcode)
    Timber.d("Commissioning: App fabric -> ChipClient.commissionDevice(): deviceId [${deviceId}]")
    chipClient.awaitCommissionDevice(deviceId, null)
    
  4. ใช้ commissioningServiceDelegate เพื่อแจ้งให้บริการ Google Play ทราบว่าค่าคอมมิชชันเสร็จสมบูรณ์แล้ว ใน .sendCommissioningComplete() ให้ส่งผ่าน CommissioningCompleteMetadata
      Timber.d("Commissioning: Calling commissioningServiceDelegate.sendCommissioningComplete()")
      commissioningServiceDelegate
          .sendCommissioningComplete(
              CommissioningCompleteMetadata.builder().setToken(deviceId.toString()).build())
          .addOnSuccessListener {
              Timber.d("Commissioning: OnSuccess for commissioningServiceDelegate.sendCommissioningComplete()")
          }
          .addOnFailureListener { ex -> 
            Timber.e(ex, "Commissioning: Failed to send commissioning complete.", ex)
          }
    }
    

เรียกใช้แอป

เมื่อรหัสที่จําเป็นทั้งหมดพร้อมสําหรับโครงสร้างในเครื่องแล้ว ก็ถึงเวลาทดสอบแล้ว เลือกอุปกรณ์ Android แล้วเรียกใช้แอป แตะเพิ่มอุปกรณ์จากหน้าจอหลักแล้วทําตามขั้นตอนเพื่อค่าคอมมิชชันอุปกรณ์

เมื่อค่าคอมมิชชันเสร็จสมบูรณ์แล้ว อุปกรณ์จะเข้าร่วมในผ้า 2 ผ้า ได้แก่ ผ้า Android ในพื้นที่และผ้าสําหรับการพัฒนาในท้องถิ่น ผ้าแต่ละรายการมีชุดข้อมูลเข้าสู่ระบบของตัวเองและรหัสผ้า 64 บิตที่ไม่ซ้ํากัน

6. ควบคุมอุปกรณ์

ค่าคอมมิชชันสําหรับการพัฒนาผลิตภัณฑ์ช่วยให้คุณใช้ไลบรารีจากที่เก็บข้อมูล Matter (connectedhomeip) เพื่อควบคุมอุปกรณ์จากแอปตัวอย่างได้

เราได้สร้างคลาสตัวช่วยบางอย่างเพื่อให้เข้าถึงคลัสเตอร์อุปกรณ์และส่งคําสั่งได้ง่ายขึ้น หากต้องการดูข้อมูลเพิ่มเติม ให้เปิด ClustersHelper ใน java/clusters ผู้ช่วย Singleton นี้จะนําเข้าไลบรารีต่อไปนี้เพื่อเข้าถึงข้อมูลอุปกรณ์

import chip.devicecontroller.ChipClusters
import chip.devicecontroller.ChipStructs

เราใช้ชั้นเรียนนี้เพื่อรับคลัสเตอร์เปิด/ปิดสําหรับอุปกรณ์ได้ จากนั้นโทรหา .toggle

suspend fun toggleDeviceStateOnOffCluster(deviceId: Long, endpoint: Int) {
  Timber.d("toggleDeviceStateOnOffCluster())")
  val connectedDevicePtr =
      try {
        chipClient.getConnectedDevicePointer(deviceId)
      } catch (e: IllegalStateException) {
        Timber.e("Can't get connectedDevicePointer.")
        return
      }
  return suspendCoroutine { continuation ->
    getOnOffClusterForDevice(connectedDevicePtr, endpoint)
        .toggle(
            object : ChipClusters.DefaultClusterCallback {
              override fun onSuccess() {
                continuation.resume(Unit)
              }
              override fun onError(ex: Exception) {
                Timber.e("readOnOffAttribute command failure: $ex")
                continuation.resumeWithException(ex)
              }
            })
  }
}

สลับอุปกรณ์

หลังจากค่าคอมมิชชันอุปกรณ์แล้ว ระบบจะเพิ่มเพย์โหลดที่แสดงผลใน CommissioningResult ไปยัง DataStore ซึ่งจะทําให้แอปของเราเข้าถึงข้อมูลอุปกรณ์ที่เราใช้ส่งคําสั่งได้

แอป Matter เป็นไปตามเหตุการณ์ เมื่อเริ่มต้นกลุ่ม Matter บริการคลัสเตอร์จะฟังข้อความขาเข้า เมื่ออุปกรณ์ได้รับค่าคอมมิชชัน ไคลเอ็นต์ Matter จะส่งคําสั่งผ่านช่องการดําเนินการที่ปลอดภัยซึ่งสร้างขึ้นระหว่างการกําหนดอุปกรณ์

ในอุปกรณ์ แพ็กเก็ตจะได้รับการตรวจสอบ ถอดรหัส และจัดส่งด้วยโค้ดเรียกกลับ ฟังก์ชันเรียกกลับประกอบด้วย EndpointId, ClusterId และ AttributeId ซึ่งเข้าถึงได้จาก attributePath เช่น นําโค้ดนี้ไปใช้กับอุปกรณ์ Matter ได้

void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t mask, uint8_t type,
                                       uint16_t size, uint8_t * value)
{
    // handle callback
    ClusterId clusterId     = attributePath.mClusterId;
    AttributeId attributeId = attributePath.mAttributeId;
}

ในขั้นตอนถัดไป คุณจะต้องใช้ Matter SDK และ ClustersHelper เพื่อสลับอุปกรณ์

  1. ไปที่ DeviceViewModel ใน java/screens/device
  2. ค้นหาฟังก์ชัน updateDeviceStateOn
  3. แทนที่ // CODELAB: toggle ความคิดเห็นด้วยรหัสเพื่อเรียกใช้ clustersHelper จากนั้นอัปเดตที่เก็บอุปกรณ์:
    Timber.d("Handling real device")
        try {
          clustersHelper.setOnOffDeviceStateOnOffCluster(deviceUiModel.device.deviceId, isOn, 1)
          devicesStateRepository.updateDeviceState(deviceUiModel.device.deviceId, true, isOn)
        } catch (e: Throwable) {
          Timber.e("Failed setting on/off state")
        }
    

ฟังก์ชันนี้ถูกเรียกจาก DeviceFragment:

// Change the on/off state of the device
binding.onoffSwitch.setOnClickListener {
  val isOn = binding.onoffSwitch.isChecked
  viewModel.updateDeviceStateOn(selectedDeviceViewModel.selectedDeviceLiveData.value!!, isOn)
}

เรียกใช้แอป

เรียกใช้แอปเพื่อโหลดการอัปเดตซ้ํา เปิดและปิดหน้าจอหลักของอุปกรณ์

7. แชร์อุปกรณ์กับระบบนิเวศอื่นๆ

การแชร์อุปกรณ์จะเรียกว่าขั้นตอนสําหรับผู้ดูแลระบบหลายคนในข้อมูลจําเพาะของ Matter

ในขั้นตอนก่อนหน้า เราได้เรียนรู้ว่า Home Mobile SDK ทําให้ค่าคอมมิชชันอุปกรณ์กับผ้า Android ในเครื่องและยังผ้าสําหรับการพัฒนาแอปตัวอย่างได้ ด้านล่างนี้เป็นตัวอย่างขั้นตอนสําหรับผู้ดูแลระบบหลายรายซึ่งอุปกรณ์ต่างๆ สามารถกําหนดให้ผ้ามากกว่า 1 ผ้าได้

ตอนนี้คุณอาจต้องการแชร์อุปกรณ์กับสิ่งทอเพิ่มเติม โดยเฉพาะอย่างยิ่งหากเป็นครอบครัวที่ผู้คนชื่นชอบการตั้งค่าแอปพลิเคชันและแพลตฟอร์ม

Home Mobile SDK มีฟังก์ชันการทํางานนี้ใน ShareDeviceRequest API ซึ่งช่วยให้คุณทําสิ่งต่อไปนี้ได้

  1. เปิดหน้าต่างค่าคอมมิชชันชั่วคราวสําหรับอุปกรณ์
  2. เปลี่ยนสถานะของอุปกรณ์เพื่อให้ค่าคอมมิชชันใช้กับผ้าอื่นได้
  3. ควบคุมอุปกรณ์จากแอปและระบบนิเวศอื่นๆ

ในขั้นตอนถัดไป คุณจะต้องใช้ Home Mobile SDK เพื่อแชร์อุปกรณ์

ขั้นตอนที่ 1: สร้าง Launcher กิจกรรม GPS

คล้ายกับ Launcher กิจกรรมค่าคอมมิชชันที่เราสร้างขึ้นเมื่อได้รับค่าคอมมิชชันสําหรับการพัฒนาพร็อพเพอร์ตี้ เราได้สร้าง Launcher กิจกรรมการแชร์อุปกรณ์เพื่อจัดการ IntentSender จาก CommissioningClient API

  1. เปิด DeviceFragment ในโฟลเดอร์ java/screens/device/
  2. แทนที่ // CODELAB: shareDeviceLauncher definition ความคิดเห็นด้วยโค้ดต่อไปนี้เพื่อลงทะเบียนและจัดการผลลัพธ์ของกิจกรรม .shareDevice()
    shareDeviceLauncher =
        registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
          // Share Device Step 5.
          // The Share Device activity in GPS (step 4) has completed.
          val resultCode = result.resultCode
          if (resultCode == RESULT_OK) {
            Timber.d("ShareDevice: Success")
            viewModel.shareDeviceSucceeded(selectedDeviceViewModel.selectedDeviceLiveData.value!!)
          } else {
            viewModel.shareDeviceFailed(
                selectedDeviceViewModel.selectedDeviceLiveData.value!!, resultCode)
          }
        }
    

ขั้นตอนที่ 2: ตรวจสอบออบเจ็กต์ LiveData

การเรียกกลับของ .shareDevice() API ที่สําเร็จจะรวม IntentSender เพื่อใช้เปิดกิจกรรมการแชร์อุปกรณ์ในบริการ Google Play ใน DeviceViewModel เราได้สร้างออบเจ็กต์ LiveData 2 รายการเพื่อรายงานผลลัพธ์ของการเรียก API นี้

  • _shareDeviceStatus เพื่อติดตาม TaskStatus
    // The current status of the share device action.
    viewModel.shareDeviceStatus.observe(viewLifecycleOwner) { status ->
      val isButtonEnabled = status !is InProgress
      updateShareDeviceButton(isButtonEnabled)
      if (status is TaskStatus.Failed) {
        showAlertDialog(errorAlertDialog, status.message, status.cause!!.toString())
      }
    }
    
  • _shareDeviceIntentSender เพื่อจัดการผลลัพธ์ของการโทร .sharedevice()
    
    

viewModel.shareDeviceIntentSender.observe(viewLifecycleOwner) {Sender -> Timber.d("shareDeviceIntentSender.observing จะเรียกใช้ด้วย [${intentSenderToString(sender)}]") หาก (sender != null) { // Share Device ขั้นตอนที่ 4: เปิดใช้กิจกรรมที่อธิบายไว้ใน IntentSender ว่า // ส่งคืนในขั้นตอนที่ 3 (โดยที่ API เรียกการเรียกค่าคอมมิชชัน // ให้ API เรียกใช้ขั้นตอนที่ 3) Timber.d("ShareDevice: เปิดใช้งานกิจกรรม GPS เพื่อแชร์อุปกรณ์") shareDeviceLauncher.launch(IntentSenderRequest.Builder(sender).build()) viewModel.consumeShareDeviceIntentSender() } } ```

ในขั้นตอนถัดไป เราจะใช้ออบเจ็กต์ LiveData เหล่านี้ในการเรียก API ของ .shareDevice()

ขั้นตอนที่ 3: เรียก API

ถึงเวลาเริ่มแชร์อุปกรณ์แล้ว

  1. เปิด DeviceViewModel.kt ในโฟลเดอร์ java/screens/device/
  2. ค้นหาฟังก์ชัน shareDevice() แทนที่ความคิดเห็น // CODELAB: shareDevice ด้วย ShareDeviceRequest DeviceDescriptor ระบุข้อมูลที่เจาะจงเกี่ยวกับอุปกรณ์ เช่น รหัสผู้ให้บริการ รหัสผลิตภัณฑ์ และประเภทอุปกรณ์ ในตัวอย่างนี้ เราฮาร์ดโค้ดค่าไว้
      Timber.d("ShareDevice: Setting up the IntentSender")
      val shareDeviceRequest =
          ShareDeviceRequest.builder()
              .setDeviceDescriptor(DeviceDescriptor.builder().build())
              .setDeviceName("temp device name")
    
  3. ตั้งค่า CommissioningWindow และพารามิเตอร์ ในขั้นนี้ หน้าต่างค่าคอมมิชชันชั่วคราวจะเปิดขึ้นในอุปกรณ์
              .setCommissioningWindow(
                  CommissioningWindow.builder()
                      .setDiscriminator(Discriminator.forLongValue(DISCRIMINATOR))
                      .setPasscode(SETUP_PIN_CODE)
                      .setWindowOpenMillis(SystemClock.elapsedRealtime())
                      .setDurationSeconds(OPEN_COMMISSIONING_WINDOW_DURATION_SECONDS.toLong())
                      .build())
              .build()
    
  4. เรียกใช้ .getCommissioningClient() เฉพาะครั้งนี้เท่านั้น ให้ใช้ .shareDevice() API การเรียกกลับของ commissioningClient.shareDevice() API ที่สําเร็จจะทําให้ IntentSender สามารถใช้เพื่อเปิดกิจกรรมการแชร์อุปกรณ์ในบริการ Google Play
    Matter.getCommissioningClient(activity)
        .shareDevice(shareDeviceRequest)
    
  5. หากต้องการเพิ่มฟังก์ชัน shareDevice ให้เสร็จสิ้น ให้เพิ่ม addOnSuccessListener และ addOnFailureListener และโพสต์ลงในออบเจ็กต์ LiveData:
          .addOnSuccessListener { result ->
            Timber.d("ShareDevice: Success getting the IntentSender: result [${result}]")
            // Communication with fragment is via livedata
            _backgroundWorkAlertDialogAction.postValue(BackgroundWorkAlertDialogAction.Hide)
            _shareDeviceIntentSender.postValue(result)
          }
          .addOnFailureListener { error ->
            Timber.e(error)
            _backgroundWorkAlertDialogAction.postValue(BackgroundWorkAlertDialogAction.Hide)
            _shareDeviceStatus.postValue(
                TaskStatus.Failed("Setting up the IntentSender failed", error))
          }
    

หลังจากใช้ผู้ส่งแล้ว ควรเรียกใช้ consumeShareDeviceIntentSender เพื่อหลีกเลี่ยงการรับผู้ส่งอีกครั้งหลังจากเปลี่ยนการกําหนดค่า

  /**
   * Consumes the value in [_shareDeviceIntentSender] and sets it back to null. Needs to be called
   * to avoid re-processing an IntentSender after a configuration change where the LiveData is
   * re-posted.
   */
  fun consumeShareDeviceIntentSender() {
    _shareDeviceIntentSender.postValue(null)
  }

เรียกใช้แอป

หากต้องการแชร์อุปกรณ์ Matter กับระบบนิเวศอื่นๆ คุณจะต้องติดตั้งแพลตฟอร์มอื่นในอุปกรณ์ Android เราได้สร้างอินสแตนซ์แอปตัวอย่างอีกรายการที่คุณสามารถใช้เป็นค่าคอมมิชชันเป้าหมาย

เมื่อติดตั้งค่าคอมมิชชันเป้าหมายในอุปกรณ์ Android แล้ว ให้ยืนยันว่าคุณแชร์อุปกรณ์ Matter ได้ แอปค่าคอมมิชชันเป้าหมายจะมีป้ายกํากับ GHSAFM-TC

ตอนนี้อุปกรณ์ของคุณเข้าร่วมผ้า 3 เส้นได้แล้ว

  1. ผ้า Android ในพื้นที่
  2. กลุ่มการพัฒนาของคุณ (แอปนี้)
  3. ผ้าที่สามที่คุณเพิ่งแชร์อุปกรณ์ไป

8. ขั้นตอนถัดไป

ขอแสดงความยินดี

ขอแสดงความยินดี คุณติดตั้งใช้งาน Codelab นี้เสร็จสมบูรณ์แล้ว และเรียนรู้วิธีค่าคอมมิชชันและแชร์อุปกรณ์โดยใช้ Home Mobile SDK

หากพบปัญหาเกี่ยวกับแอปตัวอย่าง ให้ลองทําตามขั้นตอนเพื่อยืนยันสภาพแวดล้อมให้เสร็จสมบูรณ์

หากมีข้อสงสัยเกี่ยวกับการใช้แอปตัวอย่างหรือค้นพบข้อบกพร่องของโค้ด คุณส่งปัญหาไปยังเครื่องมือติดตามปัญหาในที่เก็บ GitHub ได้โดยทําดังนี้

หากต้องการคําแนะนําอย่างเป็นทางการจาก Google สําหรับคําถามทางเทคนิค ให้ใช้ฟอรัมนักพัฒนาซอฟต์แวร์สมาร์ทโฮม โดยทําดังนี้

หากต้องการรับการสนับสนุนด้านเทคนิคจากชุมชน ให้ใช้แท็ก google-smart-home ใน Stack Overflow