الأجهزة المتعددة الأجزاء على Android

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

تمثيل مسطّح

قبل الإصدار 1.8 من واجهات برمجة التطبيقات لمنزل Google، كانت الأجهزة المتعددة الأجزاء ممثَّلة في واجهات برمجة التطبيقات لمنزل Google كمجموعة من الأجهزة المنفصلة وغير المرتبطة. ويُشار إلى ذلك باسم التمثيل المسطّح.

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

  • مثال على لوحة حائط تتضمّن مفاتيح متعددة تعرض تمثيل Matter الأصلي وعرضًا مسطّحًا لواجهة برمجة التطبيقات Home

    تمثيل مسطّح للوحة جدارية بأربعة مفاتيح

  • مثال على ثلاجة يعرض تمثيل Matter الأصلي وعرضًا مسطّحًا لواجهة برمجة التطبيقات Home API

    تمثيل مسطّح لثلاجة

الشكل 1: أمثلة على العرض المسطّح

تمثيل متعدد الأجزاء

بدءًا من الإصدار 1.8 من واجهات برمجة التطبيقات لمنزل Google، يمكن تمثيل الجهاز المتعدد الأجزاء في واجهة برمجة التطبيقات كجهاز واحد. لتفعيل هذا السلوك، استدعِ طريقة devices() على Structure أو Room أو HomeManager واضبط المَعلمة enableMultipartDevices على true:

let devices = try await self.home.devices(enableMultipartDevices: true).list()
    let device = try XCTUnwrap(devices.first { $0.id == powerstripID })
    let outlets = try await device.types.getAll(of: OnOffPluginUnitDeviceType.self)

توضّح المخطّطات التالية كيف يؤثّر الخيار enableMultipartDevices في طريقة عرض جهاز متعدّد الأجزاء في واجهات برمجة تطبيقات Home:

  • مثال على لوحة حائط مزوّدة بمفاتيح متعددة تعرض تمثيل Matter الأصلي وعرض متعدد الأجزاء باستخدام Home API

    تمثيل متعدد الأجزاء للوحة جدارية

  • مثال على ثلاجة يعرض تمثيل Matter الأصلي وعرض Home API المتعدد الأجزاء

    تمثيل متعدد الأجزاء لثلاجة

الشكل 2: أمثلة على العرض المتعدد الأجزاء

يمكنك دائمًا الحصول على التمثيل المسطّح من خلال إغفال المَعلمة enableMultipartDevices أو ضبطها على false.

في الجهاز المتعدد الأجزاء، يُطلق على كل مثيل من مكونات نوع الجهاز اسم جزء.

يمكن الوصول إلى الأجزاء مباشرةً على الجهاز الرئيسي أو جزء بطريقة هرمية، باستخدام أنواع الأجهزة أو علامات Matter الدلالية. يتم تنفيذ العلامات الدلالية في واجهات برمجة التطبيقات الخاصة بمنصة Home باستخدام DescriptorTrait.SemanticTagStruct.

يتم تنفيذ فئة DeviceType المجردة لواجهة HasParts، ما يتيح للمطوّرين التنقّل في شجرة الأجهزة من خلال السمة parts والطريقة part(). تنفّذ كل نسخة من الجزء أيضًا الواجهة HasParts، وبالتالي يؤدي استدعاء parts() على جزء إلى إنشاء قائمة تتضمّن صفرًا أو أكثر من الأجزاء الفرعية.

يوضّح المثال التالي كيفية الوصول إلى أجزاء الجهاز الذي يتضمّن مفاتيح متعددة:

val device =
      homeManager
        .devices(enableMultipartDevices = true)
        .itemFlow(Id(MULTI_SWITCH_DEVICE))
        .first()

// Here at top-level, we are using the homeDevice.parts() API to access flow of
// all the switches. Then we get the part ids.
val partIds =
      device
        .parts()
        .map { parts ->
          parts.filter { it.has(Switch) }.mapNotNull { it.metadata.partId }
        }
        .first()
        .toSet()

يوضّح المثال التالي كيفية الوصول إلى أجزاء جهاز الثلاجة:

val rootDevice = homeManager.devices(true).itemFlow(Id("device@uuid1"))

// On the top level, HomeDevice provides both plural (parts)
// and singular (part) APIs.
// The parts() API returns all the parts accessible from the top level,
// including Endpoint 0 and its children.
val childParts = rootDevice.parts().first()
// childParts contain (EP0 as RootNode, EP1 as Refrigerator)

// The singular part() API accepts DeviceType and tags (optional).
val refrigerator = rootDevice.part(Refrigerator).first()

// Get the refrigerator device which in this case is just device@uuid1
val refrigeratorDevice = homeManager.devices(false).itemFlow(refrigerator.metadata.partId.deviceId)

// DeviceType uses a synchronous API for providing access to parts
val cabinets = refrigerator.parts  // [EP2, EP3]

// Get the HomeDevice for these cabinets (device@uuid2 and device@uuid3)
val cabinetDeviceIds = cabinets.map { it.metadata.partId }

// Now use the devices API with enableMultipartDevices = false.
val cabinetDevices = homeManager.devices(false)
    .map { devices ->
devices.filter { it.id in cabinetDeviceIds }
}.first()