אפשר לגשת אל Structure APIs דרך Home APIs ל-iOS.
כדי לעבוד עם ממשקי ה-API של Structure, קודם צריך לייבא את חבילת GoogleHomeSDK לאפליקציה:
import GoogleHomeSDK
טיפול בשגיאות
חלק מהשיטות ב-Home APIs מחזירות HomeError, ולכן מומלץ להשתמש בבלוק do-catch כדי לזהות HomeError בקריאות האלה.
כשמטפלים בשגיאה HomeError, צריך לבדוק את השדות code ו-message
כדי להבין מה השתבש.
שגיאות שלא טופלו יגרמו לקריסת האפליקציה.
מידע נוסף מופיע במאמר בנושא טיפול בשגיאות.
Structure API
Home מייצג את Home Graph, והוא נקודת הכניסה ל-Structure API.
הוא מספק הפניות למבנים, לחדרים ולמכשירים.
Structure מייצג מבנה בגרף הבית. הוא מספק גישה למטא-נתונים של מבנה כמו id ו-name.
אפשר להשתמש ב-structures() כדי לקבל את כל המבנים בחשבון. המבנים מוחזרים בצורה של Query, שמאפשרת לבחור מבין כמה דרכים לצרוך את הנתונים שלה:
| API | תיאור |
|---|---|
stream() |
הפונקציה מחזירה Publisher שפולטת כל אובייקט בנפרד כשהשינויים מתרחשים. |
batched() |
הפונקציה מחזירה Publisher שפולט את התוצאה הנוכחית כ-Set של אובייקטים. כל Set שמופק מייצג את המצב הנוכחי של גרף האובייקטים. |
list() |
הפונקציה מחזירה את התוצאה הנוכחית כ-Set של אובייקטים. |
יכול להיות שהקריאה structures().list() לא תחזיר מיד קבוצה תקפה של מבנים. אם האפליקציה שלכם היא ריאקטיבית והיא קוראת ל-stream() כדי להירשם לכל השינויים במבנה כדי להפעיל את ממשק המשתמש, בסופו של דבר אמורה לחזור רשימה תקינה של מבנים. יש מצבים אחרים שבהם יכול להיות שיוחזר רשימת מבנים ריקה, למשל אם הטלפון של המשתמש מאבד את הקישוריות או אם המשתמש ביטל את ההרשאות לאפליקציה שלכם. חשוב לטפל במקרים האלה באפליקציה.
@Published public private(set) var structures: [Structure] = []
private var structuresCancellable: AnyCancellable?
self.structuresCancellable = home
.structures()
.batched()
.receive(on: DispatchQueue.main)
.map { Array($0) }
.catch {
// Failed to load structures
return Just([Structure]())
}
.assign(to: \.structures, on: self)
דוגמה לשיחות עם מבנה
קבלת קבוצה של מבנים
התקשרות אל list() ב-Query<Structure> מחזירה את קבוצת הרכיבים האחרונה:
// Get a stream of all structures accessible to the user let allStructuresChanges = self.home.structures() let allStructures = try? await allStructuresChanges.list()
כשמעצבים אפליקציה ריאקטיבית, כדאי להשתמש בקריאות batched() ובקריאות stream()
במקום בקריאות list(), כי הן יוצרות נתונים באופן אוטומטי כשהגרף הביתי משתנה.
קבלת מאפייני מבנה
אחרי שרואים את רשימת המבנים, אפשר לגשת למאפיינים שלהם:
// Get a stream of changes taking place on a structure. let structureChanges = try await home.structures().list().filter { $0.id == structureID } // Get a snapshot of the structure. let structure = structureChanges.first! // Get structure properties print("id \(structure.id) ") print("name \(structure.name) ")
חיפוש מבנה לפי שם
אם אתם יודעים את השם של מבנה, אתם יכולים לגשת אליו גם באמצעות המאפיין name:
do { structure1 = try await home.structures().list().first(where: { $0.name == "Main House" }) } catch let _ as HomeError { // Code for handling the exception }
משם אפשר לגשת לנכסים, לחדרים ולמכשירים של כל מבנה.
עבודה עם כמה מבנים
כדי להשתמש ביותר ממבנה אחד, צריך לקבל הפניה נפרדת לכל מבנה:
var structure1: Structure! var structure2: Structure! do { structure1 = try await home.structures().list().first(where: { $0.name == "Main House" }) } catch let _ as HomeError { // Code for handling the exception } do { structure2 = try await home.structures().list().first(where: { $0.name == "Guest Cottage" }) } catch let _ as HomeError { // Code for handling the exception }
חדרים
חדר מכיל קבוצה של מכשירים. חדר הוא תמיד חלק ממבנה, ומבנה יכול לכלול כמה חדרים. הסרה של חדר ממבנה לא מסירה את המכשירים בחדר מהמבנה. אבל אם החדר נמחק, המכשירים בחדר הזה לא משויכים יותר לחדר.
משתמשים ב-Home.rooms() כדי לאחזר את כל החדרים בחשבון, ואז משתמשים ב-roomID = device.roomID כדי להציג את המכשירים המתאימים בכל חדר.
self.home.rooms().batched()
.combineLatest(self.home.devices().batched())
.receive(on: DispatchQueue.main)
.catch { error in
// Failed to load rooms and devices
return Just((Set<Room>(), Set<HomeDevice>()))
}
.map { rooms, devices in
var devicesByRoom = [Room: [HomeDevice]]()
for room in rooms where room.structureID == currentStructureID {
devicesByRoom[room] = devices.filter { $0.roomID == room.id }
}
return devicesByRoom
}.assign(to: &self.$devicesByRoom)
דוגמאות לשיחות בחדרים
קבלת רשימת חדרים
באמצעות המחלקה Home, אפשר לקבל רשימה של חדרים ולגשת למאפיינים שלהם:
let allRoomsChanges = self.home.rooms() let allRooms = try await allRoomsChanges.list() let room = allRooms.first! XCTAssertTrue(allRooms.contains(room)) print("id \(room.id) ") print("name \(room.name) ")
יצירת חדר
כדי ליצור חדר חדש ב-Structure:
let testName = "Test Room Name" var newRoom: Room! do { newRoom = try await structure.createRoom(name: testName) XCTAssertNotNil(newRoom) } catch let _ as HomeError { // Code for handling the exception }
איך מוחקים חדרים
אפשרות אחרת היא למחוק חדר:
val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull() structure.deleteRoom(roomToDelete!!)
אפשר גם למחוק חדר באמצעות המזהה שלו:
let roomToDelete = allRooms.first(where: { $0.id == room.id }) if let roomToDelete1 = roomToDelete { do { try await structure.deleteRoom(roomToDelete1) } catch let _ as HomeError { // Code for handling the exception } }
אם חדר עם מכשירים נמחק, המכשירים עדיין יהיו במבנה, אבל לא ישויכו יותר לחדר.
העברת מכשירים לחדר אחר
בנוסף, אפשר להעביר מכשיר לחדר אחר באמצעות Structure:
do { try await structure.move(device: light, to: room) } catch let _ as HomeError { // Code for handling the exception }
שינוי השם של חדר
מבצעים קריאה לשיטה setName(_:) כדי לשנות את השם של החדר:
let updatedRoom = try await theRoom.setName("new room name")
כשמשנים את השם של חדר, מבנה הנתונים המקורי Room נשאר זהה והשינוי משתקף באובייקט Room המעודכן שמוחזר.
שמות ייחתכו אם הם יחרגו מהמגבלה של 60 נקודות קוד של Unicode (תווים), ולא יוצגו שגיאות. המפתחים אחראים לטיפול בשמות ארוכים. לדוגמה, הם יכולים להחליט אם הם רוצים להודיע למשתמשים שהשמות יקוצרו.
קבוצות מכשירים
קבוצת מכשירים מייצגת אוסף של מכשירים שהוגדר על ידי המשתמש בתוך מבנה יחיד.
בדומה לחדרים פיזיים, קבוצות מכשירים שייכות למבנה אחד. אבל בניגוד לחדרים, קבוצות מכשירים הן קבוצות לוגיות. מכשיר יכול להשתייך לכמה קבוצות מכשירים בו-זמנית. קבוצות מכשירים יכולות להכיל עד 100 מכשירים.
קבוצות מכשירים מיוצגות על ידי הישות Group, ששונה מ-HomeDevice.
קבלת רשימה של קבוצות מכשירים
כדי לראות את כל קבוצות המכשירים במבנה:
for await groups in structure.deviceGroups.batched() {
for group in groups {
print("Found group: \(group.name) with ID: \(group.id)")
}
}
יצירת קבוצת מכשירים
כדי ליצור קבוצת מכשירים, משתמשים בלחצן GroupManagementTrait במבנה:
let groupsManagementTrait = try await structure.traits(Google.GroupManagementTrait)
let _ = try await groupsManagementTrait.createUserDefinedGroup(withName: "Kitchen Lights",
withDevices: [light1, light2])
ניהול החברות בקבוצה
כדי להוסיף חברים לקבוצה קיימת:
let groupManagementTrait = try await structure.traits(Google.GroupManagementTrait.self)
groupManagementTrait.addGroupMembers(
groupObjectId: group.id,
memberDeviceObjectIds = [light3.id],
)
כדי להסיר חברים מקבוצה:
let groupManagementTrait = try await structure.traits(Google.GroupManagementTrait.self)
_ = try await groupManagementTrait.removeGroupMembers(
groupObjectId: group.id,
memberDeviceObjectIdsArray: Array(removedIDs)
שינוי השם של קבוצת מכשירים
כדי לשנות את השם של קבוצת מכשירים, מעדכנים את השדה GroupTrait's name:
let groupTrait = group.traits.get(Google.GroupTrait.self)
_ = try await groupTrait.update { $0.name = "Movie Corner" }
מחיקת קבוצת מכשירים
כדי למחוק קבוצת מכשירים ממבנה:
let groupManagementTrait = try await structure.traits.get(Google.GroupManagementTrait.self)
_ = try await groupManagementTrait.deleteGroup(groupObjectId: group.id)