אפשר לגשת ל-Structure APIs דרך Home APIs ל-Android. מייבאים את החבילות האלה לאפליקציה:
import com.google.home.Home
import com.google.home.Id
import com.google.home.Structure
טיפול בשגיאות
כל שיטה ב-Home APIs יכולה להפעיל
HomeException, לכן מומלץ להשתמש בבלוק try-catch כדי לתפוס את HomeException בכל הקריאות.
כשמטפלים ב-HomeException, צריך לבדוק את השדות
error.code ו-
error.message כדי להבין מה השתבש. יכול להיות שיהיו גם קודי שגיאות משניים, אז צריך להפעיל את השיטה
getSubErrorCodes() ולבדוק את התוצאה.
כל חריגה שלא תטופל תגרום לקריסת האפליקציה.
מידע נוסף מופיע במאמר טיפול בשגיאות.
שיחות לדוגמה
איך מקבלים רשימה של מבנים
אחרי ההפעלה, קריאה ל-structures() מחזירה Flow של מבנים שנגישים לכם:
// Get a flow of all structures accessible to the user val allStructuresFlow: HomeObjectsFlow<Structure> = home.structures() // Calling list() on a HomeObjectsFlow returns the first Set of elements. val allStructures: Set<Structure> = allStructuresFlow.list()
structures() API הוא תהליך שלא בהכרח מחזיר מיד רשימה תקינה של מבנים. אם האפליקציה שלכם היא ריאקטיבית ונרשמת לתהליך הזה כדי להפעיל את ממשק המשתמש, בסופו של דבר אמורה לחזור רשימה תקינה של מבנים.
יש מצבים אחרים שבהם יכולה לחזור רשימת מבנים ריקה, למשל אם הטלפון של המשתמש מאבד את הקישוריות או אם המשתמש ביטל את ההרשאות לאפליקציה. חשוב לטפל במקרים האלה באפליקציה.
לחלופין, אם נדרש תכנות אימפרטיבי במקום תכנות ריאקטיבי, אפשר להשתמש באופרטור של זרימת טרמינל:
val everyStructure = withTimeout(5000) { home.structures().first { it.isNotEmpty() } }
הקריאה הזו ממתינה לרשימה תקינה של מבנים שתגיע דרך התהליך, ואם הרשימה לא מתקבלת תוך פרק הזמן שהוגדר באפליקציה, הזמן הקצוב לתפוגה נגמר.
קבלת מאפייני מבנה
אחרי שקיבלתם את רשימת המבנים, אתם יכולים לגשת למאפיינים שלהם:
// Get a flow on a structure. Flow emits new values on structure metadata changes: name. val structureFlow: Flow<Structure> = home.structures().itemFlow(myStructureId) // Get a snapshot of the structure. val structure: Structure = structureFlow.first() // Get structure properties println("id ${structure.id}") println("name ${structure.name}")
חיפוש מבנה לפי שם
אם אתם יודעים את השם של המבנה, אתם יכולים לגשת אליו גם באמצעות המאפיין name:
val myHome = home.structures().list().first { it.name == "My home" }
משם אפשר לגשת לנכסים, לחדרים ולמכשירים בכל מבנה.
עבודה עם כמה מבנים
כדי להשתמש ביותר ממבנה אחד, צריך לקבל הפניה נפרדת לכל מבנה:
var structure1: Structure? = null var structure2: Structure? = null try { structure1 = home.structures().list().firstOrNull { it.name == "Main House" } } catch (e: HomeException) { // Code for handling the exception } try { structure2 = home.structures().list().firstOrNull { it.name == "Guest Cottage" } } catch (e: HomeException) { // Code for handling the exception }
קבלת רשימה של חדרים
אחרי שקיבלתם את המבנה, אתם יכולים לקבל רשימה של חדרים ולגשת למאפיינים שלהם:
val allRoomsFlow: HomeObjectsFlow<Room> = structure.rooms() val allRooms: Set<Room> = allRoomsFlow.list() val room: Room = allRooms.first() println("id ${room.id}") println("name ${room.name}")
יצירת חדר
כדי ליצור חדר חדש:
val testName = "Test Room Name" val newRoom: Room = structure.createRoom(testName)
מחיקת חדר
אפשר גם למחוק חדר:
val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull() structure.deleteRoom(roomToDelete!!)
אפשר גם למחוק חדר רק באמצעות מזהה:
val roomToDelete1 = allRooms.filter { it.id == testRoomId }.firstOrNull() structure.deleteRoom(roomToDelete1!!)
אם מוחקים חדר עם מכשירים, המכשירים עדיין יהיו במבנה אבל לא יהיו מוקצים יותר לחדר.
העברת מכשירים לחדר אחר
אחרי שיוצרים מבנה, אפשר להעביר מכשירים לחדר אחר באותו מבנה:
val room2 = structure.rooms().get(Id("room_id_other_structure")) val device1 = structure.devices().get(Id("device_id1")) structure.moveDevicesToRoom(room2!!, listOf(device1!!))
אם יש לכם רק את מזהי המכשירים והחדרים, אתם יכולים להעביר מכשירים גם בדרך הבאה:
structure.moveDevicesToRoom(Id("room_id_other_structure"), listOf(Id("device_id1")))
שינוי השם של חדר
כדי לשנות את השם של החדר, קוראים ל-method setName():
livingRoom.setName("Living Room")
שמות ארוכים יותר ממגבלת 60 מיקומי התווים (code point) של Unicode ייחתכו, ולא יוצגו שגיאות. המפתחים אחראים לטיפול בשמות ארוכים, ויכולים, למשל, להחליט אם הם רוצים להודיע למשתמשים שהשמות ייחתכו.
איך רואים את סוגי המכשירים שהמשתמש נתן להם הרשאות
בסביבת Google Home, ברוב סוגי המכשירים המשתמשים יכולים לתת הרשאות לכל המכשירים מאותו סוג בבת אחת. בסוגי מכשירים רגישים או מוגבלים, כמו מנעולים, מצלמות או פעמוני דלת, המשתמשים צריכים לתת הרשאה לכל מכשיר בנפרד.
כדי לבדוק אם משתמש נתן הרשאת גישה לסוג מכשיר רגיש או מוגבל, משתמשים בפונקציה consentedDeviceTypes() ברמת המבנה:
import com.google.home.Structure
import com.google.home.DeviceType
import com.google.home.DeviceTypeFactory
import com.google.home.consentedDeviceTypes // Extension function from the SDK
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
/**
* Example of how an app may monitor which device types have been granted access by a user.
*/
fun monitorDeviceConsent(structure: Structure, myScope: CoroutineScope) {
// Obtain the flow of consented device type factories
val consentedTypesFlow: Flow<Set<DeviceTypeFactory<out DeviceType>>> =
structure.consentedDeviceTypes()
myScope.launch {
consentedTypesFlow.collect { consentedSet ->
// Check if the user has consented to share a specific restricted
// type, such as a Doorbell or Camera.
val hasCameraAccess = consentedSet.any {
it.toString() == "matter.google.type.GoogleDoorbellDevice"
}
if (hasCameraAccess) {
// Enable features that require camera access
} else {
// Inform the user or disable camera-specific features
}
}
}
}
קבוצות מכשירים
קבוצת מכשירים מייצגת אוסף של מכשירים שהמשתמש הגדיר במבנה אחד. החברות בקבוצה נשמרת בשירותי Google וגלויה לחברים אחרים במבנה ולאפליקציות אחרות שיש להן גישה למבנה.
כמו חדרים פיזיים, קבוצות מכשירים שייכות למבנה אחד. אבל בניגוד לחדרים, קבוצות של מכשירים הן קבוצות לוגיות. מכשיר יכול להשתייך לכמה קבוצות מכשירים בו-זמנית. קבוצות מכשירים יכולות להכיל עד 100 מכשירים.
קבוצות מכשירים מיוצגות על ידי הישותDeviceGroup, שהיא שונה מ-HomeDevice. כדי לשלוח שאילתות לקבוצות מכשירים ולקיים איתן אינטראקציה, צריך לכלול את DeviceGroup ברשימת entityTypes כשמאתחלים את FactoryRegistry, יחד עם התכונות Group, GroupManagement ו-GroupMembership.
אתם יכולים לבצע פעולות במכשירים בקבוצה על ידי איטרציה ישירה על המכשירים שחברים בה (ראו ביצוע פעולות במכשירים שחברים בקבוצה) או על ידי טירגוט של חלק מסוג המכשיר ב-DeviceGroup (ראו שליטה בקבוצת מכשירים).
איך מקבלים רשימה של קבוצות מכשירים
כדי לראות את כל קבוצות המכשירים במבנה, צריך להפעיל את home.entities(DeviceGroup) ולסנן לפי מזהה המבנה:
home.entities(DeviceGroup).collect { allGroups ->
val structureGroups = allGroups.filter { it.structureId == structure.id }
for (group in structureGroups) {
val groupName = group.trait(Group)?.Name
println("Found group: $groupName with ID: ${group.id.id}")
}
}
אינטראקציה עם מכשירים של חברי הקבוצה
חזרה על מכשירים שחברים בקבוצה באמצעות group.devices() מאפשרת לכם שליטה מפורטת על חברים ספציפיים, מאפשרת לכם לשלוח פקודות באצווה בבקשה אחת, ומאפשרת לכם לצבור או לכתוב מאפיינים בין חברים.
לדוגמה, כדי לשלוח בקשת Batch אחת עם פקודות למאפיין בכל הגורמים התואמים בקבוצה:
val members = group.devices(enableMultipartDevices = true).first()
val onOffTraits = members.mapNotNull { device ->
device.partOrNull(OnOffLightDevice).first()?.standardTraits?.onOff
}
val responses = home.sendBatchedCommands {
onOffTraits.map { onOff ->
add(onOff.onBatchable())
}
}
for (response in responses) {
response.getOrThrow()
}
אפשר גם לעדכן מאפיין בכל המכשירים החברים התואמים בקבוצה (לדוגמה, הגדרת onTransitionTime ל-1u בכל החברים ב-DimmableLightDevice) ולהמתין להשלמה במסגרת המועד האחרון:
val members = group.devices(enableMultipartDevices = true).first()
withTimeout(5.seconds) {
members.map { device ->
async {
val light = device.partOrNull(DimmableLightDevice).first()
val levelControl = light?.standardTraits?.levelControl
if (
levelControl?.supports(
LevelControl.Attribute.onTransitionTime
) == true
) {
levelControl.update { setOnTransitionTime(1u) }
}
}
}.awaitAll()
}
כדי לצבור מאפיין של חברים בקבוצה, למשל למצוא את הערך המינימלי של colorTempPhysicalMaxMireds בכל המנורות עם טמפרטורת צבע בקבוצה:
val members = group.devices(enableMultipartDevices = true).first()
val minMaxMireds: UShort? = members.mapNotNull { device ->
val light = device.partOrNull(ColorTemperatureLightDevice).first()
light?.standardTraits?.colorControl?.colorTempPhysicalMaxMireds
}.minOrNull()
יצירת קבוצת מכשירים
משתמשים ב-GroupManagement במבנה כדי ליצור קבוצת מכשירים:
val groupManagement = structure.trait(GroupManagementTrait)
val response = groupManagement?.createUserDefinedGroup(
name = "Living room lights",
memberDeviceObjectIds = listOf(light1.id.id, light2.id.id)
)
ניהול החברות בקבוצה
כדי להוסיף חברים לקבוצה קיימת:
structure.trait(GroupManagementTrait)?.addGroupMembers(
groupObjectId = group.id.id,
memberDeviceObjectIds = listOf(light3.id.id)
)
כדי להסיר חברים מהקבוצה:
structure.trait(GroupManagementTrait)?.removeGroupMembers(
groupObjectId = group.id.id,
memberDeviceObjectIds = listOf(light1.id.id)
)
שינוי השם של קבוצת מכשירים
כדי לשנות את השם של קבוצת מכשירים, מעדכנים את מאפיין השם ב-GroupTrait של הקבוצה:
group.trait(GroupTrait)?.update {
name = "Movie corner"
}
מחיקה של קבוצת מכשירים
כדי למחוק קבוצת מכשירים ממבנה:
structure.trait(GroupManagementTrait)?.deleteGroup(
groupObjectId = group.id.id
)
פעולות אוטומטיות
נקודת הכניסה ל-Automation API היא דרך מבנה. מידע נוסף על Automations ב-Home APIs זמין במאמר סקירה כללית על Automation API ב-Android.