الوصول إلى الأجهزة والبيانات الوصفية للأجهزة في نظام التشغيل iOS

يمكن الوصول إلى واجهات برمجة تطبيقات الأجهزة من خلال واجهات برمجة تطبيقات Home لنظام التشغيل iOS. استورِد الحِزم التالية إلى تطبيقك:

import GoogleHomeSDK
import GoogleHomeTypes

لمزيد من المعلومات، يُرجى الاطّلاع على نموذج البيانات على أجهزة iOS.

معالجة الأخطاء

تعرض بعض الطرق في واجهات برمجة التطبيقات الخاصة بالمنزل الخطأ HomeError، لذا ننصحك باستخدام كتلة do-catch لرصد الخطأ HomeError في هذه المكالمات.

عند التعامل مع HomeError، تحقَّق من الحقلَين code وmessage لمعرفة سبب حدوث الخطأ.

سيؤدي حدوث أي أخطاء لم تتم معالجتها إلى تعطُّل تطبيقك.

لمزيد من المعلومات، يُرجى الاطّلاع على التعامل مع الأخطاء.

يمكنك الاطّلاع على إرسال أمر إلى جهاز للحصول على مثال.

أمثلة على المكالمات

الحصول على قائمة بالأجهزة

باستخدام مرجع إلى العنصر Home، استدعِ devices() للحصول على Query من الأجهزة التي يمكن الوصول إليها. استدعِ طريقة Query's batched()، التي تعرض مجموعة تعكس الحالة الحالية للمنزل مع كل تغيير في البيانات الوصفية للأجهزة. يمكنك أيضًا الاتصال بالرقم Query.list() للحصول على لمحة سريعة عن الأجهزة المتاحة. هذه طريقة ملائمة للاشتراك في بث batched() وعرض القيمة الأولى التي تم إرسالها. ينتج عن Query.stream() مصدر بيانات يرسل قيمًا جديدة عند حدوث تغييرات في البيانات الوصفية للجهاز، مثل الاسم أو الغرفة أو البنية. داخليًا، تستخدم هذه الطريقة batched() ولا تعرض سوى الخصائص التي تم تغييرها.

// Get a list of all devices accessible to the user
let homeDevices = try await self.home.devices().list()

يمكنك من هناك الوصول إلى حالات كل جهاز وإرسال الأوامر المتوافقة إلى الجهاز.

الحصول على أنواع الأجهزة

للحصول على أنواع الأجهزة المرتبطة بجهاز معيّن، اقرأ السمة types الخاصة بالجهاز، والتي تعرض DeviceTypeController.

اتّصِل بالرقم DeviceTypeController.subscribe(_:) للاشتراك في تلقّي إشعارات بشأن نوع جهاز معيّن:

let devices = try await self.home.devices().list()
if let device = devices.first(where: { $0.id == myDeviceId }) {
  var receivedUpdate1 = false
  var receivedUpdate2 = false
  device.types.subscribe(OnOffLightDeviceType.self)
    .assertNoFailure()
    .sink { device in
      if !receivedUpdate1 {
        receivedUpdate1 = true
        Task {
          try await device.matterTraits.onOffTrait?.on()
        }
        return
      }
      if !receivedUpdate2 {
        receivedUpdate2 = true
        return
      }
      fatalError("Received unexpected update")
    }
}

إذا كان الجهاز لا يتوافق مع نوع الجهاز المحدّد، سيعرض Empty Publisher يكتمل على الفور.

إذا كان الجهاز يتيح استخدام نوع جهاز معيّن، يمكنك الحصول على معرّف لهذا النوع من خلال استدعاء get():

if let device = devices.first(where: { $0.id == myDeviceId }) {
  let deviceType = await device.types.get(OnOffLightDeviceType.self)
}

إذا كان الجهاز لا يتوافق مع النوع المحدّد، سيعرض القيمة nil.

اتصل على DeviceTypeController.subscribeAll() للحصول على Publisher من DeviceTypeCollection. تتيح لك هذه الفئة التحقّق مما إذا كان الجهاز يتضمّن نوعًا معيّنًا من الأجهزة:

if let device = devices.first(where: { $0.id == myDeviceId }) {
  device.types.subscribeAll()
    .assertNoFailure()
    .sink { types in
      let lightDeviceType = types[OnOffLightDeviceType.self]
      let fanDeviceType = types[FanDeviceType.self]
    }
}

الحصول على سمة نوع الجهاز

أنواع الأجهزة هي نقطة البداية لقراءة السمات، لأنّها تقسم الجهاز إلى أجزائه الوظيفية (مثل نقاط النهاية في Matter).

وتأخذ هذه السمة في الاعتبار أيضًا حالات تعارض السمات في حال كان الجهاز يتضمّن نوعَين من الأجهزة، وكلاهما قد يتضمّن السمة نفسها. على سبيل المثال، إذا كان الجهاز عبارة عن مكبّر صوت ومصباح قابل للتعتيم، سيتضمّن سماتَين من نوع "تشغيل/إيقاف" وسماتَين من نوع "التحكّم في المستوى".

يمكن أن يحدث نوع آخر من تضارب السمات عندما يتضمّن الجهاز سمتَين بالاسم نفسه. على سبيل المثال، يمكن أن يشير onOff إلى مثيل من السمة العادية OnOff، أو يمكن أن يشير إلى مثيل من السمة OnOff التي يحدّدها المصنّع. لإزالة أي غموض محتمل بشأن السمة المقصودة، يجب الرجوع إلى سمة من خلال إحدى مجموعتَي السمات على كل نوع جهاز.

بالنسبة إلى السمات العادية، أي تلك التي تشبه المجموعات العادية Matter، استخدِم matterTraits. على سبيل المثال، للحصول على سمة معيّنة لنوع الجهاز "مصباح قابل للتعتيم":

if let dimmableLightDeviceType =
  await device.types.get(DimmableLightDeviceType.self)
{
  // Accessing standard trait on the type.
  let levelControlTrait =
    dimmableLightDeviceType.matterTraits.levelControlTrait.self
}

بالنسبة إلى سمات Google، استخدِم googleTraits:

if let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) {
  // Accessing Google trait on the type.
  let doorbellPressTrait =
    doorbellDeviceType.googleTraits.doorbellPressTrait.self
}

للوصول إلى سمة خاصة بالشركة المصنّعة، يمكنك الرجوع إليها من خلال السمة traits ، ولكن يجب أن تسبقها باسم حزمة الشركة المصنّعة:

let deviceType = await device1?.types.get(OnOffLightDeviceType.self)
// Accessing custom trait on the type.
if let spinnerTrait = deviceType?.traits[ExampleOrganization.SpinnerTrait.self] {
  let rpmVal = spinnerTrait.attributes.rpm
}

قراءة حالة الجهاز

إليك مثالاً على التحقّق من السمة OnOff من السمة On/Off (تشغيل/إيقاف) الخاصة بالجهاز:

let lightDevices = devices.filter {
  $0.types.contains(OnOffLightDeviceType.self)
}
let light1 = lightDevices.first
let lightDeviceTypeOptional = await light1?.types.get(OnOffLightDeviceType.self)
if let onOffTrait = lightDeviceTypeOptional?.matterTraits.onOffTrait {
  let onOffVal = onOffTrait.attributes.onOff
}

الحصول على قائمة بالأجهزة التي تتضمّن سمة معيّنة

للحصول على قائمة بالأجهزة التي تتضمّن سمة معيّنة، عليك تكرار عملية البحث في الأجهزة وأنواع الأجهزة لكل جهاز وسمات كل نوع جهاز. على سبيل المثال، للحصول على قائمة بالأجهزة في المنزل التي تتضمّن السمة On/Off:

// Get all light devices that support levelControl
var levelControlDevices: [HomeDevice] = []
var allDevices = try await home.devices().list()
for device in allDevices {
  if let deviceType = await device.types.get(OnOffLightDeviceType.self) {
    if deviceType.traits.contains(Matter.LevelControlTrait.self) {
      levelControlDevices.append(device)
    }
  }
}

يمكنك الاطّلاع على فهرس السمات على أجهزة iOS للحصول على قائمة كاملة بالسمات المتاحة في واجهات برمجة تطبيقات Home.

الحصول على قائمة بالأجهزة التي تتضمّن أنواع أجهزة مشابهة

للحصول على قائمة بالأجهزة التي تمثّل جميع الأضواء في المنزل، اتّبِع الخطوات التالية:

// Get a list of devices with similar device types (lights)
let lightDevices =
  try await self.home.devices().list().compactMap {
    $0.types.contains(DimmableLightDeviceType.self)
      || $0.types.contains(OnOffLightDeviceType.self)
      || $0.types.contains(ColorTemperatureLightDeviceType.self)
      || $0.types.contains(ExtendedColorLightDeviceType.self)
  }

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

اطّلِع على أنواع الأجهزة المتوافقة على iOS للحصول على قائمة كاملة بأنواع الأجهزة وسماتها المتوفّرة في واجهات برمجة التطبيقات Home.

الحصول على اسم المورّد أو رقم تعريف المورّد أو رقم تعريف المنتج لجهاز

يتضمّن نوع البيانات BasicInformationTrait معلومات مثل معرّف المورّد ومعرّف المنتج واسم المنتج والرقم التسلسلي للجهاز:

guard
  let vendorName =
    basicInfoTrait.attributes.vendorName
else {
  fatalError("Failed to get vendorName")
}
guard
  let vendorID =
    basicInfoTrait.attributes.vendorID
else {
  fatalError("Failed to get vendorID")
}
guard
  let productID =
    basicInfoTrait.attributes.productID
else {
  fatalError("Failed to get productID")
}

تحديد هوية الأجهزة من السحابة الإلكترونية إلى السحابة الإلكترونية لمصنّعي الأجهزة

إذا كنت من مصنّعي الأجهزة وتصنع أجهزة Cloud-to-cloud، يمكنك تضمين حقول السلسلة التالية في ردّ SYNC لتحديد أجهزة Cloud-to-cloud من خلال السمة BasicInformation:

  • أصدرت منظمة Connectivity Standards Alliance (CSA) رقم تعريف المورّد: "matterOriginalVendorId": "0xfff1",

  • معرّف المنتج الذي يحدّد منتجًا خاصًا ببائع بشكلٍ فريد: "matterOriginalProductId": "0x1234",

  • معرّف فريد للجهاز، ويتم إنشاؤه بطريقة خاصة بالشركة المصنّعة: "matterUniqueId": "matter-device-id",

عند إدخال حقول السلسلة هذه، استخدِم Matterمعرّفات المورّد والمنتج إذا كانت متوفّرة لديك. إذا لم تكن عضوًا في CSA ولم يتم تعيين أرقام التعريف هذه لك، يمكنك ترك الحقلَين matterOriginalVendorId وmatterOriginalProductId فارغَين وتقديم matterUniqueId كمعرّف.

يعرض مثال استجابة SYNC استخدام الحقول التالية:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "456",
        "type": "action.devices.types.LIGHT",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorSetting",
        ],
        "willReportState": true,
        "deviceInfo": { ... },
        "matterOriginalVendorId": "0xfff1",
        "matterOriginalProductId": "0x1234",
        "matterUniqueId": "matter-device-id",
        "otherDeviceIds": [
          {
            "deviceId": "local-device-id",
          }
        ]
      }
    ]
  }
}

لمزيد من المعلومات، يُرجى الاطّلاع على مستندات Cloud-to-cloud SYNC.

البيانات الوصفية للأجهزة والسمات

تحتوي الأجهزة والسمات في واجهات برمجة تطبيقات Home على بيانات وصفية مرتبطة بها، ما يساعد في إدارة تجربة المستخدم في التطبيق.

تحتوي كل سمة في واجهات برمجة التطبيقات Home APIs على السمة sourceConnectivity التي تتضمّن معلومات حول حالة السمة على الإنترنت وموقعها الجغرافي (التوجيه المحلي أو البعيد).

الحصول على النوع الأساسي للجهاز

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

if let deviceType =
  await device?.types.get(HumiditySensorDeviceType.self)
{
  if deviceType.metadata.isPrimaryType {
    print("Humidity Sensor is the primary type on this device.")
  } else {
    print("Humidity Sensor isn't the primary type on this device.")
  }
}

التحقّق مما إذا كانت السمة متاحة على الإنترنت

اقرأ السمة connectivityState للتحقّق من إمكانية ربط سمة معيّنة:

let levelControlConnectivity =
  levelControlTrait.metadata.sourceConnectivity
  .connectivityState

قد تظهر بعض السمات، مثل سمات Google smart home عادةً، في وضع عدم الاتصال بالإنترنت إذا لم يكن الجهاز متصلاً بالإنترنت. ويرجع ذلك إلى أنّ هذه السمات مستندة إلى السحابة الإلكترونية ولا تتضمّن توجيهًا محليًا.

التحقّق من إمكانية الاتصال بجهاز

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

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

قد يتم رصد حالة partiallyOnline في حال استخدام أنواع أجهزة مختلطة عندما لا يتوفّر اتصال بالإنترنت. قد تظل سمات Matter العرض القياسيMatter متاحة على الإنترنت بسبب التوجيه المحلي، ولكن ستكون السمات المستندة إلى السحابة الإلكترونية غير متاحة.

التحقّق من توجيه الشبكة لسمة

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

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

let levelControlLocality =
  levelControlTrait.metadata.sourceConnectivity
  .dataSourceLocality

التحقّق من توجيه الشبكة لجهاز

كما هو الحال مع الاتصال، يتم التحقّق من الموقع الجغرافي على مستوى نوع الجهاز. الحالة التي يتم عرضها هي مزيج من الموقع الجغرافي لجميع السمات على هذا الجهاز.

let lightLocality =
  dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality

قد يتم رصد حالة mixed في سيناريو مشابه لسيناريو الاتصال partiallyOnline: بعض السمات مستندة إلى السحابة الإلكترونية بينما البعض الآخر محلي.

تغيير اسم جهاز

استدعِ طريقة setName(_:) لتغيير اسم الجهاز:

let updatedDevice = try await theDevice.setName("new device name")

عند تغيير اسم جهاز، يظل البنية الأصلية HomeDevice كما هي، ويظهر التغيير في الكائن HomeDevice المعدَّل الذي تم إرجاعه.

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

قائمة واجهات برمجة التطبيقات

بعد إنشاء مثيل من Home، يمكن الوصول إلى واجهات برمجة التطبيقات التالية الخاصة بالجهاز من خلاله:

واجهة برمجة التطبيقات الوصف
device(id:) تعرض هذه السمة Publisher للجهاز المحدّد الذي يرسل حالة الجهاز كلما تغيّرت.
devices() الحصول على جميع الأجهزة في جميع المباني من حساب Google تعرض هذه الدالة Query<HomeDevice> يوفّر خيارات إضافية للاسترداد والفلترة.

بعد الحصول على HomeDevice، يمكنك الوصول إلى واجهات برمجة التطبيقات التالية من خلاله:

واجهة برمجة التطبيقات الوصف
id المعرّف الفريد للنظام الخاص بالجهاز
name اسم الجهاز الذي يحدّده المستخدم.
structureID رقم تعريف البنية التي تم تخصيص الجهاز لها. تعرض هذه السمة String?.
roomID رقم تعريف الغرفة التي تم تخصيص الجهاز لها تعرض هذه السمة String?.
types الحصول على نوع معيّن أو جميع الأنواع المتاحة على الجهاز
isMatterDevice إذا كان الجهاز مزوّدًا بخدمة Matter
sourceConnectivity تمثّل هذه السمة إمكانية اتصال الجهاز بالشبكة، وتعرض حالات الاتصال المجمّعة وموقع الشبكة الجغرافي لسمات الجهاز.