אפשר לגשת לממשקי API של מכשירים דרך ממשקי ה-API של Home ל-Android. מייבאים את החבילות האלה לאפליקציה:
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id
כדי להשתמש בסוגים או במאפיינים ספציפיים של מכשירים עם ממשקי Device API, צריך לייבא אותם בנפרד.
לדוגמה, כדי להשתמש בתכונת Matter On/Off ובסוג המכשיר On/Off Plug-in Unit, צריך לייבא את החבילות הבאות לאפליקציה:
import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice
מידע נוסף זמין במאמר בנושא מודל נתונים ב-Android.
טיפול בשגיאות
כל שיטה ב-Home APIs יכולה להחזיר
HomeException, ולכן מומלץ להשתמש בבלוק try-catch כדי לזהות HomeException בכל הקריאות.
כשמטפלים בשגיאה HomeException, צריך לבדוק את השדות
error.code ו-
error.message כדי להבין מה השתבש. יכול להיות שיוחזרו גם קודי שגיאה משניים, לכן צריך לקרוא לשיטה
getSubErrorCodes() ולבדוק את התוצאה.
חריגים שלא טופלו יגרמו לקריסת האפליקציה.
מידע נוסף מופיע במאמר בנושא טיפול בשגיאות.
דוגמה מופיעה במאמר בנושא שליחת פקודה למכשיר.
שיחות לדוגמה
הורדה של רשימת מכשירים
אחרי שיש לכם הפניה למופע Structure, קריאה ל-devices() מחזירה Flow של מכשירים שאפשר לגשת אליהם מהמבנה הזה:
// 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()
משם אפשר לגשת למצבים של כל מכשיר ולשלוח פקודות למכשירים.
בגרסה 1.8 של Home APIs, יש לכם אפשרות להגדיר שה-API ייצג כל מכשיר מרובה חלקים כמכשיר יחיד. כדי לעשות זאת, צריך להגדיר את הפרמטר enableMultipartDevices של השיטה devices() לערך true. מידע נוסף זמין במאמר מכשירים מרובי חלקים ב-Android.
קריאת סטטוס המכשיר
דוגמה לבדיקת מאפיין OnOff ממאפיין ההפעלה/ההשבתה של המכשיר. באמצעות מודל הנתונים של מאפיין Home APIs, שבו המאפיין הזה מזוהה כ-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
מידע נוסף על פונקציית Kotlin flow
ביטול תוקף של סטטוס במינוי לתכונה
TraitStateInvalidation interface
מאפשר לבטל סטטוס שאוחזר באמצעות מינויים
למכשיר היעד במקרים שבהם הסטטוס לא מדווח בצורה נכונה.
דוגמאות למקרים שבהם הסטטוס לא מדווח בצורה נכונה כוללות
שימוש במאפיינים בתכונות Matter עם האיכות C
או בגלל הטמעה של מכשיר שגורמת לבעיה באופן בלתי צפוי.
ה-API הזה מבצע קריאה מאולצת של המצב הנוכחי של התכונה ומחזיר את התוצאה באמצעות תהליכי תכונות קיימים.
מקבלים את המאפיין, ואז מריצים forceRead על המאפיין:
val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()
קבלת רשימה של מאפיינים של סוגי מכשירים
סוגי מכשירים צריכים לשמש כנקודת כניסה לקריאת מאפיינים, כי הם מפרקים מכשיר לחלקים פונקציונליים (כמו נקודות קצה ב-Matter).
הם גם מתחשבים בהתנגשויות של מאפיינים במקרה שלמכשיר יש שני סוגי מכשירים, שלשניהם יכול להיות אותו מאפיין. לדוגמה, אם מכשיר הוא גם רמקול וגם מנורה עם עמעום, יהיו לו שני מאפיינים של הפעלה/השבתה ושני מאפיינים של שליטה ברמה.
כדי לקבל את רשימת המאפיינים הזמינים לסוג המכשיר 'תאורה עם אפשרות עמעום':
// 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 ב-Kotlin כדי לחדד עוד יותר את הקריאות ל-API. לדוגמה, כדי לקבל רשימה של מכשירים בבית שיש להם את המאפיין 'הפעלה/השבתה':
// Get all devices that support OnOff val onOffDevices: Flow<List<HomeDevice>> = home.devices().map { devices -> devices.filter { it.has(OnOff) } }
בממשק של Trait אפשר לראות רשימה מלאה של המאפיינים שזמינים בממשקי ה-API של Home.
קבלת רשימה של מכשירים עם סוגי מכשירים דומים
כדי לקבל רשימה של מכשירים שמייצגים את כל האורות בבית:
// 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 (תאורה). במקום זאת, יש ארבעה סוגים שונים של מכשירים שיכולים לייצג תאורה, כמו שמוצג בדוגמה הקודמת. לכן, כדי לקבל תצוגה מקיפה של סוג מכשיר ברמה גבוהה יותר בבית, צריך לכלול כמה סוגי מכשירים בתהליכי עבודה מסוננים.
רשימה מלאה של סוגי המכשירים שזמינים בממשקי ה-API של 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 שלהם:
Connectivity Standards Alliance (Alliance) מזהה הספק שהונפק:
"matterOriginalVendorId": "0xfff1",מזהה מוצר שמזהה באופן ייחודי מוצר של ספק:
"matterOriginalProductId": "0x1234",מזהה ייחודי של המכשיר, שנוצר באופן ספציפי ליצרן:
"matterUniqueId": "matter-device-id",
כשמזינים את השדות האלה של מחרוזות, צריך להשתמש במזהי הספק והמוצר שלכם, אם יש לכם כאלה. אם אתם לא חברים ב-MatterAlliance ולא הוקצו לכם המזהים האלה, אתם יכולים להשאיר את השדות 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.
מטא-נתונים של מכשירים ומאפיינים
למכשירים ולמאפיינים בממשקי ה-API של Home יש מטא-נתונים שמשויכים אליהם, שיכולים לעזור בניהול חוויית המשתמש באפליקציה.
כל מאפיין בממשקי ה-API של Home מכיל מאפיין sourceConnectivity, שכולל מידע על הסטטוס אונליין של המאפיין ועל המיקום שלו (ניתוב מקומי או מרחוק).
קבלת הסוג הראשי של מכשיר
יכול להיות שבמכשירים מסוימים יוצגו כמה סוגים של מכשירים דרך ממשקי ה-API של Home. כדי לוודא שהמשתמשים רואים באפליקציה את האפשרויות המתאימות למכשירים שלהם (כמו שליטה במכשיר ואוטומציות מוצעות), כדאי לבדוק מהו סוג המכשיר העיקרי של המכשיר.
קודם כל, מקבלים את סוגי המכשירים באמצעות type(), ואז קובעים את הסוגים הראשיים:
val types = device.types().first() val primaryTypes = types.filter { it.metadata.isPrimaryType }
איך בודקים אם מאפיין מסוים זמין באינטרנט
כדי לבדוק את הקישוריות של מאפיין, משתמשים בשיטה connectivityState():
val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState
חלק מהתכונות, בדרך כלל תכונות של Google smart home, עשויות להופיע במצב'אופליין' אם למכשיר אין קישוריות לאינטרנט. הסיבה לכך היא שהתכונות האלה מבוססות על ענן ואין להן ניתוב מקומי.
בדיקת החיבור של מכשיר
הקישוריות של מכשיר נבדקת למעשה ברמת סוג המכשיר, כי חלק מהמכשירים תומכים בכמה סוגים של מכשירים. המצב שמוחזר הוא שילוב של מצבי הקישוריות של כל התכונות במכשיר.
val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState
יכול להיות שתראו את המצב PARTIALLY_ONLINE במקרה של סוגי מכשירים מעורבים כשאין קישוריות לאינטרנט. יכול להיות שמאפיינים רגילים של Matter עדיין יהיו אונליין בגלל ניתוב מקומי, אבל מאפיינים מבוססי-ענן יהיו אופליין.
איך מוצאים את כתובת ה-IP של המכשיר
כדי למצוא את כתובת ה-IP של המכשיר, משתמשים במאפיין networkInterfaces של מאפיין המאפיינים GeneralDiagnostics. הכתובות מוחזרות כמערכי בייטים, שאפשר לעצב אותם כמחרוזות IPv4 או IPv6 רגילות:
val ipAddresses =
trait.networkInterfaces?.flatMap { networkInterface ->
(networkInterface.ipv4Addresses + networkInterface.ipv6Addresses).mapNotNull { bytes ->
try {
java.net.InetAddress.getByAddress(bytes).hostAddress
} catch (e: java.net.UnknownHostException) {
null
}
}
} ?: emptyList()
בדיקת ניתוב הרשת של מאפיין
המיקום של מאפיין זמין גם בממשקי ה-API של Home. הערך
dataSourceLocality מציין אם המאפיין מנותב מרחוק (דרך הענן), באופן מקומי (דרך רכזת מקומית) או ישירות (ממכשיר למכשיר, ללא רכזת).
לדוגמה, יכול להיות שהערך של המיקום יהיה UNSPECIFIED בזמן שאפליקציה מופעלת ועדיין לא הגיעה למרכז או לשרת לצורך קישוריות המכשיר. אי אפשר להגיע למכשירים האלה, ובקשות לאינטראקציה מפקודות או מאירועים ייכשלו. הלקוח קובע איך לטפל במכשירים כאלה.
val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality
בדיקת ניתוב הרשת של מכשיר
בדומה לקישוריות, המקומיות נבדקת ברמת סוג המכשיר. המצב שמוחזר הוא שילוב של המיקום עבור כל התכונות במכשיר הזה.
val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality
במקרה דומה, יכול להיות שתראו מצב של MIXED כמו במקרה של קישוריות PARTIALLY_ONLINE: חלק מהמאפיינים מבוססים על ענן וחלקם מקומיים.
שינוי השם של מכשיר
מבצעים קריאה לשיטה setName()
כדי לשנות את השם של מכשיר:
mixerDevice.setName("Grendel")
שמות ייחתכו אם הם יחרגו ממגבלת 60 מיקומי התווים (code point) ב-Unicode, ולא יוצגו שגיאות. המפתחים אחראים לטפל בשמות ארוכים. לדוגמה, הם יכולים להחליט אם הם רוצים ליידע את המשתמשים שהשמות יקוצרו.