Structure API ใน Android

คุณสามารถเข้าถึง Structure API ผ่าน Home API สำหรับ Android นำเข้าแพ็กเกจเหล่านี้ไปยังแอปของคุณ

import com.google.home.Home
import com.google.home.Id
import com.google.home.Structure

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

เมธอดใดก็ตามใน Home API สามารถแสดง 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 เป็นขั้นตอนที่อาจไม่แสดงรายการโครงสร้างที่ถูกต้องในทันที หากแอปของคุณเป็นแบบรีแอ็กทีฟและสมัครใช้บริการโฟลว์นั้นเพื่อขับเคลื่อน UI ระบบควรแสดงรายการโครงสร้างที่ถูกต้องในที่สุด ยังมีสถานการณ์อื่นๆ ที่อาจส่งคืนรายการบ้านที่ว่างเปล่า เช่น หากโทรศัพท์ของผู้ใช้ขาดการเชื่อมต่อ หรือหากผู้ใช้เพิกถอนสิทธิ์ของแอป คุณควรตรวจสอบว่าได้จัดการกรณีเหล่านี้ในแอปแล้ว

หรือหากจำเป็นต้องใช้การเขียนโปรแกรมแบบบังคับแทนการเขียนโปรแกรมแบบรีแอ็กทีฟ คุณสามารถใช้โอเปอเรเตอร์ Terminal Flow ได้ดังนี้

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" }

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

ทำงานกับบ้านหลายหลัง

หากต้องการใช้บ้านมากกว่า 1 หลัง ให้รับข้อมูลอ้างอิงแยกต่างหากสำหรับบ้านแต่ละหลัง ดังนี้

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

เปลี่ยนชื่อห้อง

เรียกใช้เมธอด setName() เพื่อเปลี่ยนชื่อห้อง ดังนี้

livingRoom.setName("Living Room")

ระบบจะตัดชื่อให้สั้นลงหากเกินขีดจำกัด Code Point (อักขระ) ของ Unicode ที่ 60 รายการ และจะไม่แสดงข้อผิดพลาด นักพัฒนาแอปมีหน้าที่รับผิดชอบในการจัดการชื่อที่ยาว และสามารถตัดสินใจได้ว่าต้องการแจ้งให้ผู้ใช้ทราบหรือไม่ว่าชื่อจะถูกตัดให้สั้นลง

ในระบบนิเวศของ 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() ช่วยให้คุณควบคุมสมาชิกแต่ละรายได้อย่างละเอียด ช่วยให้คุณรวมคำสั่งเป็นกลุ่มในคำขอเดียว และช่วยให้คุณรวมหรือเขียนแอตทริบิวต์ในสมาชิกได้

ตัวอย่างเช่น หากต้องการส่งคำขอแบบกลุ่มรายการเดียวที่มีคำสั่งสำหรับลักษณะหนึ่งๆ ไปยังสมาชิกที่เข้ากันได้ทั้งหมดของกลุ่ม ให้ทำดังนี้

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 คือผ่านบ้าน ดูข้อมูลเพิ่มเติมเกี่ยวกับการทำงานอัตโนมัติใน Home API ได้ที่ภาพรวมของ Automation API ใน Android