אפשר לגשת לממשקי 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, יש לכם אפשרות להגדיר את הפרמטר enableMultipartDevices של השיטה devices() לערך true כדי שממשק ה-API ייצג כל מכשיר מרובה חלקים כמכשיר יחיד. מידע נוסף זמין במאמר בנושא מכשירים מרובי חלקים ב-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()!!
מידע נוסף על פונקציית ה-Flow של Kotlin זמין במאמר distinctUntilChanged.
ביטול תוקף של סטטוס במינוי לתכונה
ממשק TraitStateInvalidation מאפשר לבטל מצב שאוחזר באמצעות מינויים למכשיר היעד, במקרים שבהם המצב לא מדווח בצורה נכונה.
דוגמאות למקרים שבהם יכול להיות שהמצב לא ידווח בצורה נכונה: שימוש במאפיינים בMatterמאפיינים עם איכות 'C' או בגלל הטמעה במכשיר שגורמת לבעיה באופן בלתי צפוי.
ה-API הזה מבצע קריאה מאולצת של המצב הנוכחי של המאפיין ומחזיר את התוצאה באמצעות תהליכי העבודה הקיימים של המאפיין.
מקבלים את המאפיין, ואז מריצים forceRead על המאפיין:
val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()
קבלת רשימה של סוגי traits של מכשירים
סוגי המכשירים צריכים לשמש כנקודת כניסה לקריאת מאפיינים, כי הם מפרקים את המכשיר לחלקים פונקציונליים (כמו נקודות קצה ב-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. לדוגמה, כדי לקבל רשימה של מכשירים בבית שיש להם את המאפיין On/Off:
// Get all devices that support OnOff val onOffDevices: Flow<List<HomeDevice>> = home.devices().map { devices -> devices.filter { it.has(OnOff) } }
רשימה מלאה של המאפיינים שזמינים בממשקי ה-API של Home מופיעה בממשק 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. במקום זאת, יש ארבעה סוגים שונים של מכשירים שיכולים לייצג אור, כמו שרואים בדוגמה הקודמת. לכן, כדי לקבל תצוגה מקיפה של סוג מכשיר ברמה גבוהה יותר בבית, צריך לכלול כמה סוגי מכשירים בזרימות מסוננות.
בממשק DeviceType מופיעה רשימה מלאה של סוגי המכשירים שזמינים בממשקי ה-API של Home.
איך מאתרים את מזהה הספק או מזהה המוצר של מכשיר
מאפיין 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",
כשמזינים את השדות האלה של מחרוזות, כדאי להשתמש Matter
במזהי הספק והמוצר, אם יש לכם כאלה. אם אתם לא חברים ב-Alliance ולא הוקצו לכם המזהים האלה, אתם יכולים להשאיר את השדות 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 נקודות קוד של Unicode (תווים), ולא יוצגו שגיאות. המפתחים אחראים לטיפול בשמות ארוכים. לדוגמה, הם יכולים להחליט אם הם רוצים להודיע למשתמשים שהשמות יקוצרו.
בדיקת החברות של מכשיר בקבוצה
מכשיר פיזי יכול להשתייך לקבוצת מכשירים אחת או יותר. כדי לראות לאילו קבוצות מכשיר שייך, בודקים את המאפיין GroupMembership במכשיר:
val groupIds = device.trait(GroupMembershipTrait)?.groupObjectIds.orEmpty()
for (groupId in groupIds) {
println("HomeAPI", "Device belongs to group: $groupId")
}
לחלופין, אפשר לראות את כל המכשירים של חברי המועדון ששייכים לDeviceGroup
על ידי הפעלת התהליך devices() בDeviceGroup:
group.devices(enableMultipartDevices = true).collect { members ->
println("HomeAPI", "Group contains ${members.size} devices")
}