إنشاء تطبيق Android لـ Matter

1. مرحبًا

صُمِّمت Matter بهدف توحيد معايير إنترنت الأشياء (IoT)، وهي تربط الأجهزة المنزلية الذكية عبر أنظمة بيئية مختلفة، مثل Google Home وZigbee وBluetooth Mesh وZ-Wave وغيرها.

تُعد الأجهزة المحمولة نقطة تفاعل مركزية مع الأجهزة المنزلية الذكية. إذا أردت إنشاء تطبيقات Android الخاصة بك لتتوافق مع أجهزة Matter، يمكننا مساعدتك على البدء بسرعة.

يعرض نموذج تطبيق Google Home النموذجي لمعيار Matter (GHSA for Matter) واجهات برمجة تطبيقات حزمة تطوير البرامج (SDK) للأجهزة الجوّالة Home، ما يسمح للمستخدمين بتكليف الأجهزة ومشاركتها. يمكنك أيضًا استخدام نموذج التطبيق كأداة تعلُّم لفهم مفاهيم Matter الأساسية بشكل أفضل، بالإضافة إلى أداة لتصحيح أخطاء التفاعلات مع أجهزة Matter وحلّها.

الإجراءات التي ستنفذّها

في هذا الدرس التطبيقي حول الترميز، عليك تنزيل رمز المصدر لنموذج التطبيق والتعرّف على كيفية استخدام حزمة تطوير البرامج (SDK) لـ Home للأجهزة الجوّالة لمنح الأجهزة عمولة ومشاركتها. ستتعرَّف أيضًا على كيفية استخدام مكتبات التجميع والتنفيذ من خلال مستودع المسألة القانونية (connectedhomeip).

بعد تنزيل نموذج التطبيق، سنراجع رمز المصدر في "استوديو Android" ونطبّق واجهات برمجة تطبيقات Home Mobile SDK التالية:

ستتعرّف أيضًا على مزيد من المعلومات حول مفاهيم تشغيل الأجهزة وأقمشة Matter وكيفية التحكّم في أجهزة Matter.

المتطلبات

قبل البدء، تأكَّد من إكمال الخطوات التالية:

لا تحتاج إلى مركز تحكُّم، مثل Google Nest Hub (الجيل الثاني)، لتشغيل الأجهزة والتحكّم فيها باستخدام نموذج التطبيق.

2. الإعداد

يتوفّر تطبيق بدء الدرس التطبيقي حول الترميز في فرع codelab. لبدء العمل باستخدام رمز المصدر الخاص بالدرس التطبيقي حول الترميز، يمكنك تنزيل ملف ZIP.

ستستخدم ملف ZIP هذا البالغ codelab لإنشاء نموذج عمل.

إصدارات الدروس التطبيقية حول الترميز

تم وضع علامة على فرع codelab باستخدام الإصدار 2.0.0 من نموذج التطبيق. لمقارنة التحديثات أثناء تنفيذ كل خطوة، يمكنك تنزيل رمز المصدر المكتمل لهذا الإصدار.

إذا كنت ترغب في استنساخ مستودع GitHub، يُرجى اتباع التعليمات الواردة في نموذج الملف التمهيدي للتطبيق.

التبعيات

سنرشدك إلى رمز المصدر المطلوب لمشاركة الأجهزة واعتمادها، ولكن قد يكون من المفيد أن تكون على دراية بالتبعيات التالية قبل البدء. يُرجى العلم أنّه يتم تعريف هذه التبعيات في الملف libs.versions.toml واستخدامها المحدد في الملف build.gradle.kts

رمز مصدر

تم إنشاء واجهة المستخدم ومعظم الوظائف لك من قبل.

في هذا الدرس التطبيقي حول الترميز، سنضيف وظيفة Matter إلى الملفات التالية:

  • java/com/google/homesampleapp/commissioning/AppCommissioningService: يسمح لك بتكليف الأجهزة بتصميم البنية الأساسية.
  • java/com/google/homesampleapp/screens/home/HomeScreen وjava/com/google/homesampleapp/screens/home/HomeViewModel.kt: يتضمنان وظيفة التفويض بحزمة تطوير البرامج (SDK) للأجهزة الجوّالة من Home.
  • java/com/google/homesampleapp/screens/device/DeviceScreen وjava/com/google/homesampleapp/screens/device/DeviceViewModel: يتضمّنان طلبات البيانات من واجهة برمجة التطبيقات Share Device API

ويتم التعليق على كل ملف بكتلة التعليمات البرمجية التي ستعدِّلها، على سبيل المثال:

// CODELAB: add commissioningFunction()

ويتيح لك ذلك العثور سريعًا على القسم المقابل في الدرس التطبيقي حول الترميز.

3- العمولة إلى Google

قبل أن تتمكن من التحكم في الأجهزة والسماح لها بتواصل بعضها مع بعض داخل القماش نفسه، يجب أن يتم تكليفها بتكليف من مُفوّض، وهو في هذه الحالة نموذج التطبيق هذا، وهو تطبيق Google Home النموذجي لمعيار Matter.

من المهم التعرّف على المفاهيم التالية حول تكليف المادة:

  • تتيح الأقمشة للأجهزة الاتصال ببعضها بعضًا.
  • تحتفظ الأقمشة بمجموعة مشتركة من بيانات الاعتماد الفريدة.
  • تكون المنظومات المتكاملة مسؤولة عن إصدار شهادات الجذر الموثوق بها وتحديد أرقام تعريف الأقمشة وتحديد أرقام تعريف فريدة للعُقد. النظام الشامل هو خدمة الخلفية التي يقدمها المفوض، مثل الرسم البياني المنزلي لمنظومة Google Home المتكاملة.
  • يمكن تفويض الأجهزة لأكثر من نسيج واحد (ميزة متعددة المشرفين).

لإصدار جهاز، عليك استخدام CommissioningClient API. عند الاتصال بـ .commissionDevice()، يتم عرض رمز IntentSender، ما يؤدي إلى تشغيل النشاط المناسب في "خدمات Google Play":

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

في الأقسام التالية، سنستعرض الحد الأدنى من الرموز المطلوبة لتشغيل الأجهزة في أجهزة Google.

الخطوة 1: مشغّل الأنشطة

للتعامل مع IntentSender من CommissioningClient، يمكنك استخدام ActivityResultLauncher:

val 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 هي نقطة دخول حزمة تطوير البرامج (SDK) الخاصة بتطبيق Home للأجهزة الجوّالة. في المكالمة التالية، يحصل .getCommissioningClient على عميل المفوَّض حسب this (نشاط).
  3. تقبل .commissionDevice() CommissioningRequest.
  4. وأخيرًا، على ".addOnSuccessListener" معالجة نشاط CommissioningResult وتفعيل سجلّ جهاز العمولة على "خدمات Google Play" (نظام تحديد المواقع العالمي).
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 لمعيار Matter.

4. عمولة لنسيج التطوير

يمكن توصيل الأجهزة بأكثر من قطعة قماش واحدة. لإدارة عمليات الإقران الموثوق بها، تخزِّن الأجهزة FabricTable يحتوي على عدة أفراد من FabricInfo، على سبيل المثال:

  • تحديد هوية النسيج
  • رقم تعريف العُقدة الذي حدّده النظام للجهاز
  • رقم تعريف المورّد
  • معرّف النسيج
  • بيانات الاعتماد التشغيلية للجهاز

يحدد مدير النطاق الإداري (ADM) بيانات الاعتماد النسيجية. في السيناريو السابق، كانت "خدمات Google Play" هي المنظومة المتكاملة التي تعمل كمرجع تصديق موثوق به لشهادات الجذر (CA). عند ضبط الأجهزة على نظام Android المحلّي، يشتمل كل جهاز على مجموعة بيانات الاعتماد ذات الصلة النسيجية ومجموعة مراجع التصديق نفسها.

خدمات التفويض المخصّص

لإجراء العمولة على نموذج Android المحلي، استخدمنا المَعلمات التلقائية لإنشاء CommissioningRequest في CommissioningClient API:

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() لاستخدام خدمة مخصّصة. وسنضيف أيضًا "مشغّل الأنشطة" إلى جزء "الصفحة الرئيسية" وسنستخدم كائنات LiveData لإدارة مسار واجهة برمجة التطبيقات.

الخطوة 1: إنشاء مشغّل أنشطة نظام تحديد المواقع العالمي (GPS)

لنبدأ أولاً بإنشاء مشغّل الأنشطة للتعامل مع IntentSender من واجهة برمجة تطبيقات CommissioningClient.

  1. افتح "HomeScreen" في المجلد "java/com/google/homesampleapp/screens/home/".
  2. استبدِل التعليق // CODELAB: commissionDeviceLauncher definition بالرمز التالي لتسجيل نتيجة نشاط التفويض والتعامل معها:
    val commissionDeviceLauncher =
      rememberLauncherForActivityResult(
        contract = ActivityResultContracts.StartIntentSenderForResult()
      ) { result ->
        // Commission Device Step 5.
        // The Commission Device activity in GPS (step 4) has completed.
        val resultCode = result.resultCode
        if (resultCode == Activity.RESULT_OK) {
          Timber.d("CommissionDevice: Success")
          // We let the ViewModel know that GPS commissioning has completed successfully.
          // The ViewModel knows that we still need to capture the device name and will\
          // update UI state to trigger the NewDeviceAlertDialog.
          homeViewModel.gpsCommissioningDeviceSucceeded(result)
        } else {
          homeViewModel.commissionDeviceFailed(resultCode)
        }
      }
    

الخطوة 2: تشغيل إجراء جهاز العمولات

في هذه الخطوة، يشغِّل المستخدم "جهاز العمولة" الإجراء بالنقر على "+" الزر في أسفل يسار الشاشة الرئيسية. ثم يتم إجراء مكالمة إلى commissionDevice().

val onCommissionDevice = {
  ...
  commissionDevice(activity!!.applicationContext, commissionDeviceLauncher)
}

الخطوة 3: طلب بيانات من واجهة برمجة التطبيقات

  1. لا تزال في مجلد "HomeScreen.kt" في المجلد "java/com/google/homesampleapp/screens/home".
  2. استبدِل التعليق // CODELAB: commissionDevice بـ commissionDeviceRequest التالي. تربط setCommissioningService AppCommissioningService بمثيل CommissioningService، ويتم عرضه في دالة استدعاء. عند تقديم خدمة مخصّصة، ستعمل حزمة تطوير البرامج (SDK) لحزمة تطوير البرامج (SDK) مع تطبيق Home Mobile أولاً على عمولة الأجهزة في نظام Android المحلي، ثم إعادة حمولة البيانات الإعدادية إلى AppCommissioningService.
    val commissionDeviceRequest =
        CommissioningRequest.builder()
            .setCommissioningService(ComponentName(
                context, AppCommissioningService::class.java))
            .build()
    
  3. يمكنك الاتصال بالرقم .getCommissioningClient()، ثم الاتصال بالرقم .commissionDevice().
Matter.getCommissioningClient(context)
    .commissionDevice(commissionDeviceRequest)

لإكمال دالة commissionDevice، أضف addOnSuccessListener وaddOnFailureListener:

    .addOnSuccessListener { result ->
      commissionDeviceLauncher.launch(IntentSenderRequest.Builder(result).build())
    }
    .addOnFailureListener { error ->
      Timber.e(error)
    }

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:

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 أيضًا مكتبات من مستودع المسألة القانونية (connectedhomeip):

import com.google.homesampleapp.chip.ChipClient

أخيرًا، تتضمّن الخدمة عمليات استيراد تتوافق مع كوروتين Hilt وKotlin.

بعد ذلك، سننشئ الصيغة ونعدّ بعض الأمور، بما في ذلك commissioningServiceDelegate، والذي سنستخدمه لإعلام "خدمات Google Play" عند اكتمال عملية الإعداد.

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

حان الوقت الآن لإضافة دوال التكليف.

الخطوة 2: إلغاء صفحة onCommissioning Request

لإعداد الأجهزة لكي تتوافق مع بنية تطوير التطبيق، عليك إكمال الخطوات التالية:

  1. فتح AppCommissioningService في java/commissioning.
  2. حدِّد موقع الدالة onCommissioningRequested(). لقد قدّمنا رسالة سجلّ تطبع CommissioningRequestMetadata. استبدِل التعليق // CODELAB: onCommissioningRequested() لبدء الكوروتين serviceScope والحصول على deviceId.
    // Perform commissioning on custom fabric for the sample app.
    serviceScope.launch {
      val deviceId = devicesRepository.incrementAndReturnLastDeviceId()
    
  3. تنفيذ المهام بالنسبة إلى هذه الخطوة، يمكننا تمرير معلومات الجهاز التي يتم عرضها في كائن CommissioningRequestMetadata. يستخدم ChipClient معلومات البيانات الوصفية هذه لإنشاء قناة آمنة بين تطبيق GHSA لتطبيق Matter وجهازك.
    try {
      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)
    } catch (e: Exception) {
      Timber.e(e, "onCommissioningRequested() failed")
      // No way to determine whether this was ATTESTATION_FAILED or DEVICE_UNREACHABLE.
      commissioningServiceDelegate
          .sendCommissioningError(CommissioningError.OTHER)
          .addOnSuccessListener {
            Timber.d(
                "Commissioning: commissioningServiceDelegate.sendCommissioningError() succeeded")
          }
          .addOnFailureListener { e2 ->
            Timber.e(e2, "Commissioning: commissioningServiceDelegate.sendCommissioningError() failed")
          }
      return@launch
    }
    
  4. استخدِم commissioningServiceDelegate لإبلاغ "خدمات Google Play" باكتمال عملية الإعداد. في .sendCommissioningComplete()، أدخِل CommissioningCompleteMetadata.
    commissioningServiceDelegate
        .sendCommissioningComplete(
            CommissioningCompleteMetadata.builder().setToken(deviceId.toString()).build())
        .addOnSuccessListener {
          Timber.d("Commissioning: commissioningServiceDelegate.sendCommissioningComplete() succeeded")
        }
        .addOnFailureListener { e ->
          Timber.e(e, "Commissioning: commissioningServiceDelegate.sendCommissioningComplete() failed")
        }
    }
    

تشغيل التطبيق

بعد أن تم تطبيق كل الرموز المطلوبة للعمولة على الأقمشة المحلية لدينا، حان الوقت لاختبارها. اختر جهاز Android وشغِّل التطبيق. من الشاشة الرئيسية، انقر على إضافة جهاز وأكمِل الخطوات لمنح جهازك الإذن.

عند اكتمال عملية الإعداد، يشارك جهازك الآن في تصميمَين: نسيج Android المتوفّر على الجهاز وجهاز التطوير المحلي. ولكل نسيج مجموعة خاصة من بيانات الاعتماد ومعرّف قماش فريد بحجم 64 بت.

6- التحكُّم في الأجهزة

يسمح لك التفويض بإنشاء نسيج للتطوير باستخدام المكتبات من مستودع المسألة القانونية (connectedhomeip) للتحكُّم في الأجهزة من نموذج التطبيق.

لقد أنشأنا بعض الفئات المساعدة لتسهيل الوصول إلى مجموعات الأجهزة وإرسال الأوامر. لمزيد من المعلومات، افتح ClustersHelper في java/clusters. يستورد مساعدلنغتون هذا المكتبات التالية للوصول إلى معلومات الجهاز:

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;
}

في الخطوات التالية، عليك استخدام حزمة تطوير البرامج (SDK) المتوافقة مع معيار Matter و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")
        }
    

هذه الدالة مستدعاة من DeviceScreen:

// On/Off Switch click.
val onOnOffClick: (value: Boolean) -> Unit = { value ->
  deviceViewModel.updateDeviceStateOn(deviceUiModel!!, value)
}

تشغيل التطبيق

شغِّل التطبيق لإعادة تحميل التحديثات. من الشاشة الرئيسية، فعِّل جهازك أو أوقِفه.

7. مشاركة الأجهزة مع المنظومات المتكاملة الأخرى

يُشار إلى مشاركة الجهاز باسم تدفق تعدد المشرفين في مواصفات المسألة القانونية.

في الخطوات السابقة، تعلّمنا أنّ حزمة تطوير البرامج (SDK) للأجهزة الجوّالة Home من أجل السماح للأجهزة بتصنيع أجهزة Android المحلية، وكذلك إلى نموذج تطوير للتطبيق. هذا مثال على تدفق متعدد المشرفين، حيث يمكن توصيل الأجهزة بأكثر من بنية.

قد ترغب الآن في مشاركة الأجهزة مع المزيد من الأقمشة، خاصةً إذا كان هذا منزلاً يكون لدى الأشخاص تفضيلاتهم الخاصة في ما يتعلق بالتطبيقات والأنظمة الأساسية.

وتوفّر حزمة تطوير برامج Home للأجهزة الجوّالة هذه الوظيفة في ShareDeviceRequest API، ما يسمح لك بما يلي:

  1. افتح نافذة تشغيل مؤقت للأجهزة.
  2. غيِّر حالة أجهزتك، مع السماح بتحويلها إلى قماش آخر.
  3. التحكّم في أجهزتك من خلال التطبيقات والمنظومات المتكاملة الأخرى

في الخطوات التالية، ستستخدم حزمة تطوير البرامج (SDK) الخاصة بتطبيق Home للأجهزة الجوّالة لمشاركة الأجهزة.

الخطوة 1: إنشاء مشغّل أنشطة نظام تحديد المواقع العالمي (GPS)

على غرار "مشغِّل التطبيقات" الذي ابتكرناه عندما عمِلنا على إنشاء نموذج تطوير، أنشأنا مشغّل مشاركة نشاط الجهاز الذي يتيح التعامل مع IntentSender من واجهة برمجة التطبيقات CommissioningClient API.

  1. افتح "DeviceScreen" في المجلد "java/com/google/homesampleapp/screens/device/".
  2. استبدِل التعليق // CODELAB: shareDeviceLauncher definition بالرمز التالي لتسجيل نتيجة نشاط .shareDevice() والتعامل معها:
    val shareDeviceLauncher = rememberLauncherForActivityResult(
      contract = ActivityResultContracts.StartIntentSenderForResult()
    ) { result ->
      // Commission Device Step 5.
      // The Share Device activity in GPS (step 4) has completed.
      val resultCode = result.resultCode
      if (resultCode == Activity.RESULT_OK) {
        deviceViewModel.shareDeviceSucceeded()
      } else {
        deviceViewModel.shareDeviceFailed(resultCode)
      }
    }
    

الخطوة 2: تشغيل إجراء مشاركة الجهاز

في هذه الخطوة، يشغّل المستخدم زر "مشاركة الجهاز" الإجراء بالنقر على زر "مشاركة" على شاشة الجهاز. بعد ذلك، يتم إجراء مكالمة إلى deviceViewModel لفتح نافذة إقران لمشاركة الجهاز.

// Share Device button click.
val onShareDevice: () -> Unit = remember {
 {
   deviceViewModel.openPairingWindow(deviceUiModel!!.device.deviceId)
 }
}

بعد فتح نافذة الإقران بنجاح، تنقل السمة deviceViewModel هذه المعلومة إلى واجهة المستخدم. يتم إجراء الاتصال بين ViewModel وواجهة المستخدم من خلال كائنات StateFlow.

// Communicate to the UI that the pairing window is open.
// UI can then launch the GPS activity for device sharing.
_pairingWindowOpenForDeviceSharing.value = true

عند رؤية التغيير الذي تم إجراؤه على عنصر StateFlow، يُجري الجهاز الاتصال التالي:

shareDevice(activity!!.applicationContext, shareDeviceLauncher, deviceViewModel)

الخطوة 3: طلب بيانات من واجهة برمجة التطبيقات

حان الوقت الآن لبدء مهمة مشاركة الجهاز.

  1. افتح "DeviceScreen.kt" في المجلد "java/com/google/homesampleapp/screens/device/".
  2. حدِّد موقع الدالة shareDevice(). استبدِل التعليق // CODELAB: shareDevice بـ ShareDeviceRequest. توفّر DeviceDescriptor معلومات محدّدة حول الجهاز، مثل رقم تعريف المورّد ومعرّف المنتج ونوع الجهاز. في هذا المثال، نجري ترميزًا ثابتًا للقيم.
    val shareDeviceRequest =
      ShareDeviceRequest.builder()
        .setDeviceDescriptor(DeviceDescriptor.builder().build())
        .setDeviceName("GHSAFM 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.
    Matter.getCommissioningClient(context)
        .shareDevice(shareDeviceRequest)
    

إنّ معاودة الاتصال الناجحة لواجهة برمجة التطبيقات commissioningClient.shareDevice() يوفّر IntentSender لاستخدامه لإطلاق نشاط "مشاركة نشاط الجهاز" في "خدمات Google Play".

  1. لإكمال دالة shareDevice، أضف addOnSuccessListener وaddOnFailureListener. عند النجاح، تم استدعاء launch في shareDeviceLauncher لإطلاق نشاط نظام تحديد المواقع العالمي (GPS) لمشاركة الأجهزة.
        .addOnSuccessListener { result ->
          Timber.d("ShareDevice: Success getting the IntentSender: result [${result}]")
          shareDeviceLauncher.launch(IntentSenderRequest.Builder(result).build())
        }
        .addOnFailureListener { error ->
          Timber.e(error)
          deviceViewModel.showMsgDialog("Share device failed", error.toString())
        }
    

تشغيل التطبيق

لمشاركة جهاز Matter مع منظومات متكاملة أخرى، يجب أن يكون لديك نظام أساسي آخر مثبّت على جهاز Android. لقد أنشأنا مثيلاً آخر لنموذج التطبيق الذي يمكنك استخدامه كمفوض مستهدف.

بعد تثبيت المفوَّض المستهدَف على جهاز Android، تأكَّد من أنّه يمكنك مشاركة جهاز Matter. يحمل التطبيق المفوَّض المستهدَف التصنيف GHSAFM-TC.

يمكن لأجهزتك الآن المشاركة في ثلاثة أنواع:

  1. قماش Android المحلي.
  2. بنية التطوير (هذا التطبيق)
  3. هذا النسيج الثالث الذي شاركت الجهاز معه للتو.

8. الخطوات التالية

تهانينا

تهانينا، لقد أكملت هذا الدرس التطبيقي حول الترميز وتعلَّم كيفية إعداد الأجهزة ومشاركتها باستخدام حزمة تطوير البرامج (SDK) للأجهزة الجوّالة من Home.

إذا كنت تواجه مشاكل في نموذج التطبيق، جرِّب إكمال الخطوات للتحقّق من بيئتك:

إذا كانت لديك أسئلة حول استخدام نموذج التطبيق أو اكتشاف خطأ في التعليمات البرمجية، فيمكنك إرسال المشكلات إلى أداة تتبع المشكلات في مستودع GitHub:

للحصول على إرشادات رسمية من Google بشأن الأسئلة الفنية، يُرجى الانتقال إلى منتدى مطوّري المنازل المزوّدة بأجهزة ذكية:

للحصول على الدعم الفني من المنتدى، استخدِم العلامة google-smart-home في Stack Overflow: