دسترسی به دستگاه‌ها و فراداده دستگاه برای Android

API های دستگاه ممکن است از طریق API های Home برای اندروید قابل دسترسی باشند. این بسته ها را به برنامه خود وارد کنید:

import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id

برای استفاده از انواع یا ویژگی‌های خاص دستگاه با APIهای دستگاه، آنها باید به‌صورت جداگانه وارد شوند.

برای مثال، برای استفاده از ویژگی Matter On/Off و نوع دستگاه On/Off Plug-in Unit، بسته‌های زیر را به برنامه خود وارد کنید:

import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice

برای اطلاعات بیشتر، به مدل داده در اندروید مراجعه کنید.

مدیریت خطا

هر متدی در APIهای Home می‌تواند یک HomeException ایجاد کند، بنابراین توصیه می‌کنیم از یک بلوک try-catch برای گرفتن HomeException در تمام فراخوانی‌ها استفاده کنید.

هنگام مدیریت HomeException ، فیلدهای error.code و error.message آن را بررسی کنید تا متوجه شوید چه مشکلی پیش آمده است. ممکن است کدهای خطای فرعی نیز وجود داشته باشد، بنابراین متد getSubErrorCodes() را فراخوانی کرده و نتیجه را بررسی کنید.

هرگونه خطای مدیریت نشده منجر به از کار افتادن برنامه شما خواهد شد.

برای اطلاعات بیشتر، به بخش مدیریت خطا مراجعه کنید.

برای مثال به ارسال دستور به دستگاه مراجعه کنید.

نمونه تماس‌ها

دریافت لیست دستگاه‌ها

با در دسترس بودن ساختار، فراخوانی devices() جریانی از دستگاه‌های قابل دسترسی از آن ساختار را برمی‌گرداند:

// Get a flow of all devices accessible to the user
val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allDevices: Set<HomeDevice> = allDevicesFlow.list()

از آنجا، وضعیت هر دستگاه قابل دسترسی است و دستورات پشتیبانی شده می‌توانند به دستگاه ارسال شوند.

خواندن وضعیت دستگاه

بیایید به مثالی از بررسی ویژگی OnOff از ویژگی روشن/خاموش دستگاه نگاهی بیندازیم. با استفاده از مدل داده ویژگی APIهای Home، که در آن این ویژگی به عنوان OnOff شناسایی می‌شود، می‌توانید داده‌های ویژگی را از طریق کلاس standardTraits نوع دستگاه بازیابی کنید:

// Assuming we have a device.
val deviceFlow = home.devices().itemFlow(myDeviceId)

val device = deviceFlow.first()

// Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger
// on the specific trait changes and not the whole type.
val onOffTraitFlow: Flow<OnOff?> =
  device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged()

val onOffTrait: OnOff = onOffTraitFlow.first()!!

برای کسب اطلاعات بیشتر در مورد تابع جریان کاتلین، به distinctUntilChanged مراجعه کنید.

وضعیت را در یک اشتراک صفت نامعتبر کنید

رابط TraitStateInvalidation امکانی را فراهم می‌کند تا در مواردی که وضعیت به درستی گزارش نمی‌شود، وضعیت بازیابی شده از طریق اشتراک‌ها در دستگاه هدف را نامعتبر کند. نمونه‌هایی از مواردی که ممکن است وضعیت به درستی گزارش نشود شامل استفاده از ویژگی‌هایی در ویژگی‌های Matter با کیفیت "C" یا به دلیل پیاده‌سازی دستگاهی است که به طور غیرمنتظره‌ای باعث ایجاد مشکل می‌شود.

این API یک خواندن اجباری از وضعیت فعلی ویژگی (trait) را انجام می‌دهد و نتیجه را از طریق جریان‌های ویژگی موجود برمی‌گرداند.

ویژگی را دریافت کنید، سپس یک forceRead روی ویژگی اجرا کنید:

val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()

لیستی از ویژگی‌های نوع دستگاه را دریافت کنید

انواع دستگاه‌ها باید به عنوان نقطه ورود برای خواندن صفات استفاده شوند، زیرا آنها یک دستگاه را به قطعات عملکردی آن تجزیه می‌کنند (مانند نقاط پایانی در Matter ).

آنها همچنین تداخل ویژگی‌ها را در صورتی که یک دستگاه دارای دو نوع دستگاه باشد، که هر دو ممکن است ویژگی یکسانی داشته باشند، در نظر می‌گیرند. به عنوان مثال، اگر یک دستگاه هم بلندگو و هم چراغ قابل تنظیم باشد، دو ویژگی روشن/خاموش و دو ویژگی کنترل سطح خواهد داشت.

برای دریافت لیست ویژگی‌های موجود برای نوع دستگاه Dimmable Light:

// Get all types available on this device. Requires the types to be part of the registry during
// SDK initialization.
val typesFlow: Flow<Set<DeviceType>> = device.types()

// Get a snapshot of all types.
val types: Set<DeviceType> = typesFlow.first()

// Get the DimmableLightDevice instance from the set of types.
val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull()

// Get all traits in the type + traits registered
val allTraits: Set<Trait> = dimmableLightDevice!!.traits()

نوع دیگری از تصادم ویژگی‌ها می‌تواند زمانی رخ دهد که یک دستگاه دو ویژگی با نام یکسان داشته باشد. به عنوان مثال، onOff می‌تواند به نمونه‌ای از ویژگی استاندارد OnOff اشاره کند، یا می‌تواند به نمونه‌ای از ویژگی OnOff تعریف شده توسط سازنده اشاره کند. برای از بین بردن هرگونه ابهام احتمالی در مورد اینکه کدام ویژگی مورد نظر است، باید قبل از یک نمونه Trait که از طریق یک دستگاه به آن اشاره می‌شود، یک فضای نام واجد شرایط قرار گیرد. برای ویژگی‌های استاندارد، یعنی آن‌هایی که مشابه خوشه‌های استاندارد Matter هستند، از standardTraits استفاده کنید. برای ویژگی‌های Google، از googleTraits استفاده کنید:

// Accessing standard traits on the type.
val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff
val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl

برای دسترسی به یک ویژگی خاص سازنده، مستقیماً به آن مراجعه کنید:

// Accessing a custom trait on the type.
val customTrait = dimmableLightDevice.trait(MyCustomTrait)

لیستی از دستگاه‌هایی با یک ویژگی خاص دریافت کنید

تابع filter در کاتلین می‌تواند برای اصلاح بیشتر فراخوانی‌های API استفاده شود. برای مثال، برای دریافت لیستی از دستگاه‌های موجود در خانه که همگی دارای ویژگی روشن/خاموش هستند:

// Get all devices that support OnOff
val onOffDevices: Flow<List<HomeDevice>> =
  home.devices().map { devices -> devices.filter { it.has(OnOff) } }

برای مشاهده لیست کاملی از ویژگی‌های موجود در رابط‌های برنامه‌نویسی کاربردی (API) صفحه اصلی، به رابط Trait مراجعه کنید.

لیستی از دستگاه‌هایی با انواع دستگاه‌های مشابه دریافت کنید

برای دریافت لیستی از دستگاه‌هایی که نمایانگر تمام چراغ‌های یک خانه هستند:

// Get a list of devices with similar device types (lights)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }

چندین نوع دستگاه در APIهای Home وجود دارد که می‌توانند نشان‌دهنده یک نوع دستگاه اصلی باشند. برای مثال، هیچ نوع دستگاه "Light" وجود ندارد. در عوض، چهار نوع دستگاه مختلف وجود دارد که می‌توانند نشان‌دهنده یک چراغ باشند، همانطور که در مثال قبلی نشان داده شده است. به این ترتیب، برای داشتن یک دید جامع از نوع سطح بالاتر دستگاه در یک خانه، باید چندین نوع دستگاه در جریان‌های فیلتر شده گنجانده شوند.

برای مشاهده لیست کامل انواع دستگاه‌های موجود در رابط‌های برنامه‌نویسی کاربردی Home، به رابط DeviceType مراجعه کنید.

دریافت شناسه فروشنده یا شناسه محصول برای یک دستگاه

ویژگی BasicInformation شامل اطلاعاتی مانند شناسه فروشنده، شناسه محصول، نام محصول و شماره سریال برای یک دستگاه است:

// Get device basic information. All general information traits are on the RootNodeDevice type.
val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!!
println("vendorName ${basicInformation.vendorName}")
println("vendorId ${basicInformation.vendorId}")
println("productId ${basicInformation.productId}")

شناسایی دستگاه از طریق ابر به ابر برای تولیدکنندگان دستگاه

اگر شما سازنده دستگاه هستید و دستگاه‌های Cloud-to-cloud می‌سازید، برای شناسایی دستگاه‌های Cloud-to-cloud خود از طریق ویژگی BasicInformation ، می‌توانید این فیلدهای رشته‌ای را در پاسخ SYNC آنها قرار دهید:

  • اتحادیه استانداردهای اتصال (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",
          }
        ]
      }
    ]
  }
}

برای اطلاعات بیشتر، به مستندات SYNC Cloud-to-cloud مراجعه کنید.

فراداده دستگاه و ویژگی

دستگاه‌ها و ویژگی‌های موجود در APIهای Home دارای فراداده‌هایی هستند که به آنها مرتبط هستند و می‌توانند در مدیریت تجربه کاربری در یک برنامه کمک کنند.

هر ویژگی در APIهای Home شامل یک ویژگی sourceConnectivity است که اطلاعاتی در مورد وضعیت آنلاین و موقعیت مکانی (مسیریابی محلی یا از راه دور) یک ویژگی دارد.

نوع اصلی یک دستگاه را دریافت کنید

برخی از دستگاه‌ها ممکن است چندین نوع دستگاه را از طریق APIهای Home ارائه دهند. برای اطمینان از اینکه کاربران گزینه‌های مناسب در یک برنامه (مانند کنترل دستگاه و اتوماسیون‌های پیشنهادی) را برای دستگاه‌های خود دریافت می‌کنند، بررسی نوع دستگاه اصلی برای یک دستگاه مفید است.

ابتدا، نوع(های) دستگاه را با استفاده از type() دریافت کنید، سپس نوع(های) اصلی را تعیین کنید:

val types = device.types().first()
val primaryTypes = types.filter { it.metadata.isPrimaryType }

بررسی کنید که آیا یک ویژگی آنلاین است یا خیر

از متد connectivityState() برای بررسی اتصال یک trait استفاده کنید:

val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState

برخی از ویژگی‌ها، معمولاً ویژگی‌های smart home گوگل، ممکن است در صورت عدم اتصال دستگاه به اینترنت، به صورت آفلاین نمایش داده شوند. دلیل این امر این است که این ویژگی‌ها مبتنی بر ابر هستند و مسیریابی محلی ندارند.

بررسی اتصال دستگاه

اتصال برای یک دستگاه در واقع در سطح نوع دستگاه بررسی می‌شود زیرا برخی از دستگاه‌ها از چندین نوع دستگاه پشتیبانی می‌کنند. حالت برگردانده شده ترکیبی از حالت‌های اتصال برای همه ویژگی‌های آن دستگاه است.

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

در صورت عدم اتصال به اینترنت، ممکن است در مورد انواع دستگاه‌های مختلف، حالت PARTIALLY_ONLINE مشاهده شود. ویژگی‌های استاندارد Matter ممکن است به دلیل مسیریابی محلی هنوز آنلاین باشند، اما ویژگی‌های مبتنی بر ابر آفلاین خواهند بود.

بررسی مسیریابی شبکه یک ویژگی

موقعیت مکانی یک ویژگی (trait) نیز در APIهای Home موجود است. dataSourceLocality نشان می‌دهد که آیا ویژگی از راه دور (از طریق ابر)، محلی (از طریق یک هاب محلی) یا نظیر به نظیر (مستقیم از دستگاهی به دستگاه دیگر، بدون هاب) مسیریابی می‌شود.

مقدار محلی ناشناخته UNSPECIFIED ، برای مثال، زمانی امکان‌پذیر است که یک برنامه در حال بوت شدن است و هنوز به هاب یا سرور برای اتصال دستگاه نرسیده است. این دستگاه‌ها قابل دسترسی نیستند و درخواست‌های تعاملی از دستورات یا رویدادها را با شکست مواجه می‌کنند. این به کلاینت بستگی دارد که چگونه با چنین دستگاه‌هایی برخورد کند.

val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality

بررسی مسیریابی شبکه برای یک دستگاه

همانند اتصال، محلی بودن در سطح نوع دستگاه بررسی می‌شود. حالت برگردانده شده ترکیبی از محلی بودن برای تمام ویژگی‌های آن دستگاه است.

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

حالت MIXED ممکن است در سناریویی مشابه با اتصال PARTIALLY_ONLINE مشاهده شود: برخی از ویژگی‌ها مبتنی بر ابر هستند در حالی که برخی دیگر محلی هستند.

تغییر نام یک دستگاه

برای تغییر نام یک دستگاه، متد setName() را فراخوانی کنید:

mixerDevice.setName("Grendel")

اگر تعداد کاراکترهای نام‌ها از حد مجاز ۶۰ کاراکتر یونیکد بیشتر شود، نام‌ها کوتاه می‌شوند و هیچ خطایی رخ نمی‌دهد. توسعه‌دهندگان مسئول مدیریت نام‌های طولانی هستند و برای مثال، می‌توانند تصمیم بگیرند که آیا می‌خواهند به کاربران اطلاع دهند که نام‌ها کوتاه خواهند شد یا خیر.

لیست API

پس از ایجاد یک نمونه از Home ، APIهای دستگاه زیر از طریق آن قابل دسترسی هستند:

رابط برنامه‌نویسی کاربردی توضیحات
devices() تمام دستگاه‌ها را در تمام ساختارهای حساب گوگل دریافت کنید. یک HomeObjectsFlow برمی‌گرداند که گزینه‌های بازیابی و فیلتر بیشتری را ارائه می‌دهد.

زمانی که HomeDevice را داشته باشید، APIهای زیر از طریق آن قابل دسترسی هستند:

رابط برنامه‌نویسی کاربردی توضیحات
allCandidates() تمام کاندیدهای اتوماسیون برای دستگاه و فرزندانش را برمی‌گرداند.
candidates() تمام کاندیدهای اتوماسیون برای دستگاه را برمی‌گرداند.
connectivityStateChanged آخرین باری که وضعیت دستگاه تغییر کرده است.
events(event) جریانی از یک رویداد خاص را دریافت می‌کند.
events(trait) جریانی از تمام رویدادها را توسط این ویژگی دریافت می‌کند.
events(traits) جریانی از تمام رویدادها را بر اساس این ویژگی‌ها دریافت می‌کند.
getSourceConnectivity(trait) فراداده (metadata) مربوط به یک ویژگی (trait) خاص را دریافت می‌کند. یک SourceConnectivity برمی‌گرداند.
has(trait) بررسی کنید که آیا ویژگی درخواستی فعلی توسط دستگاه پشتیبانی می‌شود یا خیر.
has(type) اگر دستگاه از نوع ارائه شده پشتیبانی کند.
id شناسه سیستم منحصر به فرد دستگاه.
isMatterDevice اگر دستگاه توسط Matter پشتیبانی می‌شود.
name نام دستگاه که توسط کاربر ارائه شده است.
room() اتاقی که دستگاه به آن اختصاص داده شده است. یک Room برمی‌گرداند.
roomId شناسه اتاقی که دستگاه به آن اختصاص داده شده است. یک Id برمی‌گرداند.
sourceConnectivity اتصال منبع دستگاه، که نشان‌دهنده‌ی حالت‌های اتصال تجمیعی و موقعیت مکانی شبکه‌ی ویژگی‌های دستگاه است.
structure() ساختاری که دستگاه به آن اختصاص داده شده است. یک Structure برمی‌گرداند.
structureId شناسه‌ی ساختاری که دستگاه به آن اختصاص داده شده است. یک Id برمی‌گرداند.
type(type) تعریف نوع را به همراه ویژگی‌های (traits) پر شده (در صورت وجود) برای دسترسی مستقیم دریافت کنید. همیشه یک تصویر لحظه‌ای به‌روز از ویژگی‌ها را برمی‌گرداند.
types() لیستی از انواع موجود در دستگاه را دریافت کنید.