Structure API ใน iOS

คุณเข้าถึง Structure API ได้ผ่าน Home API สำหรับ iOS

หากต้องการใช้ Structure API ให้นำเข้าแพ็กเกจ GoogleHomeSDK ไปยังแอปก่อน

import GoogleHomeSDK

การจัดการข้อผิดพลาด

เมธอดบางอย่างใน Home API จะส่งHomeError ดังนั้นเราขอแนะนำให้คุณใช้บล็อก do-catch เพื่อตรวจหาHomeError ในการเรียกเหล่านั้น

เมื่อจัดการ HomeError ให้ตรวจสอบฟิลด์ code และ message เพื่อดูว่าเกิดข้อผิดพลาดใดขึ้น

ข้อผิดพลาดที่ไม่ได้จัดการจะทำให้แอปขัดข้อง

ดูข้อมูลเพิ่มเติมได้ที่ การจัดการข้อผิดพลาด

Structure API

Home แสดงกราฟบ้านและเป็นจุดแรกเข้าของ Structure API โดยจะมีการอ้างอิงถึงโครงสร้าง ห้อง และอุปกรณ์

Structure แสดงถึงโครงสร้างในกราฟบ้าน โดยจะให้สิทธิ์เข้าถึง ข้อมูลเมตาของโครงสร้าง เช่น id และ name

ใช้ structures() เพื่อ รับโครงสร้างทั้งหมดในบัญชี ระบบจะแสดงโครงสร้างในรูปแบบของ Query ซึ่งมีตัวเลือก ในการใช้ข้อมูลดังนี้

API คำอธิบาย
stream() แสดงผล Publisher ที่ปล่อยออบเจ็กต์แต่ละรายการแยกกันเมื่อมีการเปลี่ยนแปลง
batched() แสดงผล Publisher ที่ปล่อยผลลัพธ์ปัจจุบันเป็น Set ของออบเจ็กต์ Set ที่ปล่อยออกมาแต่ละรายการแสดงสถานะปัจจุบันของกราฟออบเจ็กต์
list() แสดงผลลัพธ์ปัจจุบันเป็น Set ของออบเจ็กต์

การเรียก structures().list() อาจไม่แสดงผลชุดโครงสร้างที่ถูกต้องในทันที หากแอปของคุณตอบสนองและเรียกใช้ stream() เพื่อติดตามการเปลี่ยนแปลงโครงสร้างทั้งหมด เพื่อขับเคลื่อน UI ในที่สุดระบบควรแสดงรายการโครงสร้างที่ถูกต้อง นอกจากนี้ ยังมีสถานการณ์อื่นๆ ที่อาจทำให้ระบบแสดงรายการโครงสร้างว่างเปล่า ได้ เช่น หากโทรศัพท์ของผู้ใช้ขาดการเชื่อมต่อ หรือหาก ผู้ใช้เพิกถอนสิทธิ์เข้าถึงแอปของคุณ คุณควรตรวจสอบว่าแอปของคุณจัดการกรณีเหล่านี้ ได้

@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)

ตัวอย่างการเรียกใช้ Structure

รับชุดโครงสร้าง

การเรียก 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
}

จากนั้นคุณจะเข้าถึงพร็อพเพอร์ตี้ ห้องพัก และอุปกรณ์ของแต่ละโครงสร้างได้

ทำงานกับโครงสร้างหลายแบบ

หากต้องการใช้โครงสร้างมากกว่า 1 รายการ ให้รับการอ้างอิงแยกต่างหากสำหรับแต่ละโครงสร้าง

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 ที่อัปเดตแล้วซึ่งส่งคืน

ชื่อจะถูกตัดทอนหากเกินขีดจำกัดของ Code Point ของ Unicode (อักขระ) ที่ 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)