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

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

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

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

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

สิ่งที่คุณต้องดําเนินการ

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

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

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

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

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

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

2. ตั้งค่า

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

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

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

เวอร์ชัน Codelab

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

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

การอ้างอิง

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

  • Home Mobile SDK
    implementation 'com.google.android.gms:play-services-home:16.0.0'
    
  • ไลบรารี Matter SDK
    // Native libs
    implementation fileTree(dir: "third_party/connectedhomeip/libs", include: ["*.jar", "*.so"])
    
  • ดีไซน์ Material หากต้องการเรียนรู้เพิ่มเติม โปรดดูที่ MDC-103 Android: ธีม Material ด้วยสี ระดับความสูง และประเภท (Kotlin) และเครื่องมือสร้างธีม Material
    implementation 'com.google.android.material:material:1.5.0'
    
  • Proto DataStore ใช้เพื่อคงข้อมูลแอปไว้ ที่เก็บ Datastore และ Serializer จะจัดเก็บไว้ใน 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 ของ Home Mobile SDK
  • java/screens/DeviceViewModel: รวมการเรียกใช้ Share Device API

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

// CODELAB: add commissioningFunction()

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

3. ค่าคอมมิชชันกับ Google

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

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

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

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

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

ในส่วนถัดไป เราจะมาดูโค้ดขั้นต่ําที่จําเป็นในการกําหนดอุปกรณ์ให้ Fabric ของ 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 ในค่าคอมมิชชันอุปกรณ์กับ Fabric ของ 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 Fabric ผ่านการตั้งค่า Android เพื่อให้ขั้นตอนการมอบอุปกรณ์ไปยังผ้าอื่นๆ เป็นเรื่องง่าย

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

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

4. ส่งเสริมสิ่งก่อสร้างในการพัฒนา

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

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

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

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

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

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

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

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

class CommissioningRequest {
  static CommissioningRequest.Builder builder();

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

    CommissioningRequest build();
  }
}

ในขั้นตอนถัดไป เราจะแก้ไขฟังก์ชัน commissionDevice() เพื่อใช้บริการที่กําหนดเอง นอกจากนี้เราจะเพิ่มตัวเรียกใช้งานกิจกรรมลงในส่วนย่อยของหน้าแรกและใช้ออบเจ็กต์ 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. สร้าง CommissioningService

ในฟังก์ชัน 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 และ Kotlin Coroutine

ต่อไป เราจะสร้างเครื่องมือสร้างและตั้งค่าบางอย่าง รวมถึง 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 แบบ ได้แก่ ผ้าแอนดรอยด์ท้องถิ่นและผ้าสําหรับการพัฒนาท้องถิ่น ผ้าแต่ละชุดจะมีข้อมูลรับรองเป็นของตนเองและมีรหัสผ้า 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. แชร์อุปกรณ์กับระบบนิเวศอื่นๆ

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

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

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

SDK ของ Home Mobile มีฟังก์ชันนี้ใน 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.observe is called with [${intentSenderToString(sender)}]")
      if (sender != null) {
        // Share 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("ShareDevice: Launch GPS activity to share device")
        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 และ parameters เมื่อถึงขั้นตอนนี้ หน้าต่างการสั่งการชั่วคราวจะเปิดขึ้นในอุปกรณ์
              .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() เฉพาะครั้งนี้เท่านั้น ใช้ API ของ .shareDevice() การเรียกกลับของ 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. ผ้าที่ 3 ที่คุณเพิ่งแชร์อุปกรณ์

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

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

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

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

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

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

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