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)

ตัวอย่างการเรียกโครงสร้าง

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

การเรียก 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 ตัว และจะไม่แสดงข้อผิดพลาด นักพัฒนาแอปมีหน้าที่รับผิดชอบในการจัดการชื่อที่ยาว และสามารถตัดสินใจได้ว่าจะแจ้งให้ผู้ใช้ทราบว่าระบบจะตัดชื่อให้สั้นลงหรือไม่