يمكن الوصول إلى واجهات برمجة التطبيقات الخاصة بالبنية من خلال واجهات برمجة التطبيقات الخاصة بتطبيق Home على أجهزة iOS.
لاستخدام واجهات برمجة التطبيقات الخاصة بالبنية، عليك أولاً استيراد حزمة GoogleHomeSDK إلى تطبيقك:
import GoogleHomeSDK
معالجة الأخطاء
تُطلق بعض الطرق في واجهات برمجة التطبيقات Home استثناء HomeError، لذا ننصحك باستخدام كتلة do-catch لاكتشاف استثناء HomeError في تلك الطلبات.
عند التعامل مع HomeError، راجِع الحقلَين code وmessage
لمعرفة الخطأ الذي حدث.
ستؤدي أي أخطاء لم تتم معالجتها إلى تعطُّل تطبيقك.
لمزيد من المعلومات، اطّلِع على التعامل مع الأخطاء.
Structure API
يمثّل Home الرسم البياني للمنزل، وهو نقطة الدخول إلى Structure API.
تقدّم هذه السمة مراجع إلى المباني والغرف والأجهزة.
يمثّل Structure بنية في الرسم البياني لمنزلك. تتيح الوصول إلى بيانات وصفية خاصة بالبنية، مثل id وname.
استخدِم structures() للحصول على جميع البُنى في حسابك. يتم عرض البُنى على شكل
Query، ما يتيح لك اختيار
طرق استهلاك البيانات:
| واجهة برمجة التطبيقات | الوصف |
|---|---|
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 نقطة رمز يونيكود (حرفًا)، ولن يتم عرض أي أخطاء. يتحمّل المطوّرون مسؤولية التعامل مع الأسماء الطويلة، ويمكنهم مثلاً تحديد ما إذا كانوا يريدون إبلاغ المستخدمين بأنّه سيتم اقتطاع الأسماء.
مجموعات الأجهزة
تمثّل مجموعة الأجهزة مجموعة من الأجهزة يحدّدها المستخدم ضمن بنية واحدة.
وكما هو الحال مع الغرف المادية، تنتمي مجموعات الأجهزة إلى بنية واحدة. ولكن على عكس الغرف، فإنّ مجموعات الأجهزة هي مجموعات منطقية. يمكن أن ينتمي الجهاز إلى عدة مجموعات أجهزة في الوقت نفسه. يمكن أن تحتوي مجموعات الأجهزة على ما يصل إلى 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)
تغيير اسم مجموعة أجهزة
لإعادة تسمية مجموعة أجهزة، عدِّل الحقل GroupTraitname:
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)