เข้าถึงอุปกรณ์และข้อมูลเมตาของอุปกรณ์สำหรับ iOS

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

import GoogleHomeSDK
import GoogleHomeTypes

ดูข้อมูลเพิ่มเติมได้ที่โมเดลข้อมูลใน iOS

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

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

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

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

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

ดูตัวอย่างได้ที่หัวข้อส่งคำสั่งไปยังอุปกรณ์

ตัวอย่างการเรียก

รับรายการอุปกรณ์

ใช้ข้อมูลอ้างอิงถึงออบเจ็กต์ Home แล้วเรียกใช้ devices() เพื่อรับ Query ของอุปกรณ์ที่เข้าถึงได้ เรียกใช้เมธอด Query's batched() ซึ่งจะส่งออก Set ที่แสดงสถานะปัจจุบันของ Home พร้อมการเปลี่ยนแปลงข้อมูลเมตาของอุปกรณ์ทุกรายการ หรือเรียกใช้ Query.list() เพื่อรับ ข้อมูลสแนปช็อตของอุปกรณ์ที่พร้อมใช้งาน ซึ่งเป็นเมธอดที่สะดวกในการสมัครใช้บริการสตรีม batched() และแสดงผลค่าแรกที่ส่งออก Query.stream() จะสร้างสตรีมที่ส่งออกค่าใหม่เมื่อมีการเปลี่ยนแปลงข้อมูลเมตาของอุปกรณ์ เช่น ชื่อ ห้อง หรือโครงสร้าง โดยภายในแล้วจะใช้ batched() และส่งออกเฉพาะพร็อพเพอร์ตี้ที่เปลี่ยนแปลง

// Get a list of all devices accessible to the user
let homeDevices = try await self.home.devices().list()

จากนั้นคุณจะเข้าถึงสถานะของอุปกรณ์แต่ละเครื่องและส่งคำสั่งไปยังอุปกรณ์ได้

ใน Home API เวอร์ชัน 1.8 คุณสามารถเลือกให้ API แสดงอุปกรณ์แบบหลายส่วนเป็นอุปกรณ์เดียวได้โดยตั้งค่าพารามิเตอร์ enableMultipartDevices ของเมธอด devices() เป็น true ดูข้อมูลเพิ่มเติมได้ที่ อุปกรณ์แบบหลายส่วนใน iOS

รับประเภทของอุปกรณ์

หากต้องการรับประเภทอุปกรณ์ที่เชื่อมโยงกับอุปกรณ์ ให้อ่าน พร็อพเพอร์ตี้ types ของอุปกรณ์ ซึ่งจะแสดงผล DeviceTypeController

เรียกใช้ DeviceTypeController.subscribe(_:) เพื่อสมัครใช้บริการรับข้อมูลอัปเดตสำหรับอุปกรณ์บางประเภท

let devices = try await self.home.devices().list()
if let device = devices.first(where: { $0.id == myDeviceId }) {
  var receivedUpdate1 = false
  var receivedUpdate2 = false
  device.types.subscribe(OnOffLightDeviceType.self)
    .assertNoFailure()
    .sink { device in
      if !receivedUpdate1 {
        receivedUpdate1 = true
        Task {
          try await device.matterTraits.onOffTrait?.on()
        }
        return
      }
      if !receivedUpdate2 {
        receivedUpdate2 = true
        return
      }
      fatalError("Received unexpected update")
    }
}

หากอุปกรณ์ไม่รองรับประเภทอุปกรณ์ที่ระบุ ระบบจะแสดงผล Empty Publisher ที่เสร็จสมบูรณ์ทันที

หากอุปกรณ์รองรับประเภทอุปกรณ์ที่เฉพาะเจาะจง คุณจะได้รับแฮนเดิลสำหรับประเภทนั้นโดยการเรียกใช้ get()

if let device = devices.first(where: { $0.id == myDeviceId }) {
  let _ = await device.types.get(OnOffLightDeviceType.self)
}

หากอุปกรณ์ไม่รองรับประเภทที่ระบุ ระบบจะแสดงผล nil

เรียกใช้ DeviceTypeController.subscribeAll() เพื่อรับ Publisher ของ DeviceTypeCollection คลาสนี้ช่วยให้คุณตรวจสอบได้ว่าอุปกรณ์มีประเภทอุปกรณ์ที่เฉพาะเจาะจงหรือไม่

if let device = devices.first(where: { $0.id == myDeviceId }) {
  device.types.subscribeAll()
    .assertNoFailure()
    .sink { types in
      let lightDeviceType = types[OnOffLightDeviceType.self]
      let fanDeviceType = types[FanDeviceType.self]
    }
}

รับลักษณะของประเภทอุปกรณ์

ประเภทอุปกรณ์เป็นจุดเริ่มต้นในการอ่านลักษณะ เนื่องจากประเภทอุปกรณ์จะแยกอุปกรณ์ออกเป็นส่วนการทำงาน (เช่น ปลายทางใน Matter)

นอกจากนี้ยังคำนึงถึงการชนกันของลักษณะในกรณีที่อุปกรณ์มีประเภทอุปกรณ์ 2 ประเภท ซึ่งทั้ง 2 ประเภทอาจมีลักษณะเดียวกัน เช่น หากอุปกรณ์เป็นทั้งลำโพงและไฟหรี่ได้ อุปกรณ์จะมีลักษณะเปิด/ปิด 2 รายการและลักษณะการควบคุมระดับ 2 รายการ

การชนกันของลักษณะอีกประเภทหนึ่งอาจเกิดขึ้นเมื่ออุปกรณ์มีลักษณะ 2 รายการที่มีชื่อเดียวกัน เช่น onOff อาจอ้างอิงถึงอินสแตนซ์ของลักษณะ OnOff มาตรฐาน หรืออาจอ้างอิงถึงอินสแตนซ์ของลักษณะ OnOff ที่ผู้ผลิตกำหนด หากต้องการขจัดความคลุมเครือที่อาจเกิดขึ้นเกี่ยวกับลักษณะที่ต้องการ ให้อ้างอิงลักษณะผ่านคอลเล็กชันลักษณะ 2 รายการในประเภทอุปกรณ์แต่ละประเภท

สำหรับลักษณะมาตรฐาน ซึ่งคล้ายกับ Matter คลัสเตอร์มาตรฐาน ให้ใช้ matterTraits เช่น หากต้องการรับลักษณะที่เฉพาะเจาะจงสำหรับประเภทอุปกรณ์ไฟหรี่ได้ ให้ทำดังนี้

if let dimmableLightDeviceType =
  await device.types.get(DimmableLightDeviceType.self)
{
  // Accessing standard trait on the type.
  let levelControlTrait =
    dimmableLightDeviceType.matterTraits.levelControlTrait.self
}

สำหรับลักษณะของ Google ให้ใช้ googleTraits

if let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) {
  // Accessing Google trait on the type.
  let doorbellPressTrait =
    doorbellDeviceType.traits[Google.DoorbellPressTrait.self]
}

หากต้องการเข้าถึงลักษณะเฉพาะของผู้ผลิต ให้อ้างอิงผ่านพร็อพเพอร์ตี้ traits แต่ให้ใส่ชื่อแพ็กเกจของผู้ผลิตไว้ข้างหน้า

let deviceType = await device1?.types.get(OnOffLightDeviceType.self)
// Accessing custom trait on the type.
if let spinnerTrait = deviceType?.traits[ExampleOrganization.SpinnerTrait.self] {
  let rpmVal = spinnerTrait.attributes.rpm
}

อ่านสถานะอุปกรณ์

ดูตัวอย่างการตรวจสอบแอตทริบิวต์ OnOff จากลักษณะเปิด/ปิดของอุปกรณ์

let lightDevices = devices.filter {
  $0.types.contains(OnOffLightDeviceType.self)
}
let light1 = lightDevices.first
let lightDeviceTypeOptional = await light1?.types.get(OnOffLightDeviceType.self)
if let onOffTrait = lightDeviceTypeOptional?.matterTraits.onOffTrait {
  let onOffVal = onOffTrait.attributes.onOff
}

รับรายการอุปกรณ์ที่มีลักษณะที่เฉพาะเจาะจง

หากต้องการรับรายการอุปกรณ์ที่มีลักษณะที่เฉพาะเจาะจง คุณต้องวนซ้ำอุปกรณ์ ประเภทอุปกรณ์ของอุปกรณ์แต่ละเครื่อง และลักษณะของประเภทอุปกรณ์แต่ละประเภท เช่น หากต้องการรับรายการอุปกรณ์ในบ้านที่มีลักษณะเปิด/ปิดทั้งหมด ให้ทำดังนี้

// Get all light devices that support levelControl
var levelControlDevices: [HomeDevice] = []
let allDevices = try await home.devices().list()
for device in allDevices {
  if let deviceType = await device.types.get(OnOffLightDeviceType.self) {
    if deviceType.traits.contains(Matter.LevelControlTrait.self) {
      levelControlDevices.append(device)
    }
  }
}

ดูรายการลักษณะทั้งหมดที่พร้อมใช้งานใน Home API ได้ที่ ดัชนีลักษณะใน iOS

รับรายการอุปกรณ์ที่มีประเภทอุปกรณ์คล้ายกัน

หากต้องการรับรายการอุปกรณ์ที่แสดงไฟทั้งหมดในบ้าน ให้ทำดังนี้

// Get a list of devices with similar device types (lights)
let lightDevices =
  try await self.home.devices().list().compactMap {
    $0.types.contains(DimmableLightDeviceType.self)
      || $0.types.contains(OnOffLightDeviceType.self)
      || $0.types.contains(ColorTemperatureLightDeviceType.self)
      || $0.types.contains(ExtendedColorLightDeviceType.self)
  }

Home API มีประเภทอุปกรณ์หลายประเภทที่แสดงประเภทอุปกรณ์หลักได้ เช่น ไม่มีประเภทอุปกรณ์ "ไฟ" แต่มีประเภทอุปกรณ์ 4 ประเภทที่แสดงไฟได้ ดังที่แสดงในตัวอย่างก่อนหน้า ดังนั้น หากต้องการดูภาพรวมของอุปกรณ์ประเภทระดับสูงในบ้าน คุณต้องรวมประเภทอุปกรณ์หลายประเภท

ดูรายการประเภทอุปกรณ์ทั้งหมดและลักษณะของประเภทอุปกรณ์ที่พร้อมใช้งานใน Home API ได้ที่ประเภทอุปกรณ์ที่รองรับใน iOS

รับชื่อผู้ให้บริการ รหัสผู้ให้บริการ หรือรหัสสินค้าสำหรับอุปกรณ์

ลักษณะ BasicInformationTrait trait มีข้อมูล เช่น รหัสผู้ให้บริการ รหัสสินค้า ชื่อสินค้า และ หมายเลขซีเรียลของอุปกรณ์

guard
  let vendorName =
    basicInfoTrait.attributes.vendorName
else {
  fatalError("Failed to get vendorName")
}
guard
  let vendorID =
    basicInfoTrait.attributes.vendorID
else {
  fatalError("Failed to get vendorID")
}
guard
  let productID =
    basicInfoTrait.attributes.productID
else {
  fatalError("Failed to get productID")
}

การระบุอุปกรณ์แบบคลาวด์ต่อคลาวด์สำหรับผู้ผลิตอุปกรณ์

หากคุณเป็นผู้ผลิตอุปกรณ์และสร้างอุปกรณ์ Cloud-to-cloud เพื่อระบุอุปกรณ์ Cloud-to-cloud ผ่านลักษณะ BasicInformation คุณสามารถใส่ฟิลด์สตริงต่อไปนี้ในการตอบกลับ SYNC

  • รหัสผู้ให้บริการที่ออกโดย Connectivity Standards Alliance (Alliance) "matterOriginalVendorId": "0xfff1",

  • ตัวระบุสินค้าที่ระบุสินค้าของผู้ให้บริการได้อย่างไม่ซ้ำกัน: "matterOriginalProductId": "0x1234",

  • ตัวระบุที่ไม่ซ้ำกันสำหรับอุปกรณ์ ซึ่งสร้างขึ้นในลักษณะที่เฉพาะเจาะจงของผู้ผลิต: "matterUniqueId": "matter-device-id",

เมื่อป้อนฟิลด์สตริงเหล่านี้ ให้ใช้รหัสMatter ผู้ให้บริการและรหัสสินค้า หากมี หากคุณไม่ได้เป็นสมาชิกของ Alliance และไม่ได้รับรหัสเหล่านี้ คุณสามารถ เว้นฟิลด์ matterOriginalVendorId และ matterOriginalProductId ว่างไว้ แล้วระบุ matterUniqueId เป็นตัวระบุ

ตัวอย่างการตอบกลับ SYNC แสดงการใช้ฟิลด์เหล่านี้

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "456",
        "type": "action.devices.types.LIGHT",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorSetting",
        ],
        "willReportState": true,
        "deviceInfo": { ... },
        "matterOriginalVendorId": "0xfff1",
        "matterOriginalProductId": "0x1234",
        "matterUniqueId": "matter-device-id",
        "otherDeviceIds": [
          {
            "deviceId": "local-device-id",
          }
        ]
      }
    ]
  }
}

ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบ Cloud-to-cloud SYNC

ข้อมูลเมตาของอุปกรณ์และลักษณะ

อุปกรณ์และลักษณะใน Home API มีข้อมูลเมตาที่เชื่อมโยงอยู่ ซึ่งช่วยในการจัดการประสบการณ์ของผู้ใช้ในแอปได้

ลักษณะแต่ละรายการใน Home API มี sourceConnectivity พร็อพเพอร์ตี้ ซึ่งมีข้อมูลเกี่ยวกับสถานะออนไลน์และสถานที่ตั้งของลักษณะ (การกำหนดเส้นทางในเครื่องหรือระยะไกล)

รับประเภทหลักของอุปกรณ์

อุปกรณ์บางเครื่องอาจแสดงประเภทอุปกรณ์หลายประเภทผ่าน Home API การตรวจสอบว่าประเภทอุปกรณ์เป็นประเภทหลักของอุปกรณ์หรือไม่จะเป็นประโยชน์เพื่อให้แน่ใจว่าผู้ใช้จะเห็นตัวเลือกที่เหมาะสมในแอป (เช่น การควบคุมอุปกรณ์และการทำงานอัตโนมัติที่แนะนำ) สำหรับอุปกรณ์ของตน

if let deviceType =
  await device?.types.get(HumiditySensorDeviceType.self)
{
  if deviceType.metadata.isPrimaryType {
    print("Humidity Sensor is the primary type on this device.")
  } else {
    print("Humidity Sensor isn't the primary type on this device.")
  }
}

ตรวจสอบว่าลักษณะออนไลน์อยู่หรือไม่

อ่านพร็อพเพอร์ตี้ connectivityState เพื่อตรวจสอบการเชื่อมต่อของลักษณะ

let levelControlConnectivity =
  levelControlTrait.metadata.sourceConnectivity
  .connectivityState

ลักษณะบางอย่าง โดยปกติแล้วจะเป็นลักษณะ smart home ของ Google อาจแสดงเป็น ออฟไลน์หากอุปกรณ์ไม่มีการเชื่อมต่ออินเทอร์เน็ต เนื่องจากลักษณะเหล่านี้ทำงานบนระบบคลาวด์และไม่มีการกำหนดเส้นทางในเครื่อง

ตรวจสอบการเชื่อมต่อของอุปกรณ์

ระบบจะตรวจสอบการเชื่อมต่อของอุปกรณ์ที่ระดับประเภทอุปกรณ์ เนื่องจากอุปกรณ์บางเครื่องรองรับประเภทอุปกรณ์หลายประเภท สถานะที่แสดงผลเป็นการรวมสถานะการเชื่อมต่อของลักษณะทั้งหมดในอุปกรณ์นั้น

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

คุณอาจเห็นสถานะ partiallyOnline ในกรณีที่อุปกรณ์มีประเภทผสมกันเมื่อไม่มีการเชื่อมต่ออินเทอร์เน็ต Matterลักษณะมาตรฐาน ของ Matter อาจยังคงออนไลน์อยู่เนื่องจากการกำหนดเส้นทางในเครื่อง แต่ลักษณะที่ทำงานบนระบบคลาวด์จะ ออฟไลน์

รับที่อยู่ IP ของอุปกรณ์

หากต้องการค้นหาที่อยู่ IP ของอุปกรณ์ ให้ใช้แอตทริบิวต์ networkInterfaces ของ the GeneralDiagnosticsTrait ระบบจะแสดงผลที่อยู่เป็นออบเจ็กต์ Data ซึ่งคุณสามารถจัดรูปแบบเป็นสตริง IPv4 หรือ IPv6 มาตรฐานได้โดยใช้เฟรมเวิร์ก Network

func getIpAddresses(trait: Matter.GeneralDiagnosticsTrait) -> [String] {
  let interfaces = trait.attributes.networkInterfaces ?? []
  var ipAddresses: [String] = []

  for interface in interfaces {
    for data in interface.iPv4Addresses {
      if let ipv4 = IPv4Address(data) {
        ipAddresses.append(String(describing: ipv4))
      }
    }
    for data in interface.iPv6Addresses {
      if let ipv6 = IPv6Address(data) {
        ipAddresses.append(String(describing: ipv6))
      }
    }
  }

  return ipAddresses
}

ตรวจสอบการกำหนดเส้นทางเครือข่ายของลักษณะ

สถานที่ตั้งของลักษณะยังพร้อมใช้งานใน Home API ด้วย dataSourceLocality จะระบุว่ามีการกำหนดเส้นทางลักษณะจากระยะไกล (ผ่านระบบคลาวด์) ในเครื่อง (ผ่านฮับในเครื่อง) หรือแบบเพียร์ทูเพียร์ (จากอุปกรณ์ไปยังอุปกรณ์โดยตรง ไม่ผ่านฮับ)

ค่าสถานที่ตั้งที่ไม่รู้จัก unspecified อาจเกิดขึ้น เช่น ขณะที่แอปกำลังบูตและยังไม่ได้เชื่อมต่อกับฮับหรือเซิร์ฟเวอร์สำหรับการเชื่อมต่ออุปกรณ์ อุปกรณ์เหล่านี้ไม่สามารถเข้าถึงได้และคำขอการโต้ตอบจากคำสั่งหรือเหตุการณ์จะล้มเหลว ไคลเอ็นต์ต้องเป็นผู้กำหนดวิธีจัดการอุปกรณ์ดังกล่าว

let levelControlLocality =
  levelControlTrait.metadata.sourceConnectivity
  .dataSourceLocality

ตรวจสอบการกำหนดเส้นทางเครือข่ายของอุปกรณ์

เช่นเดียวกับการเชื่อมต่อ ระบบจะตรวจสอบสถานที่ตั้งที่ระดับประเภทอุปกรณ์ สถานะที่แสดงผลเป็นการรวมสถานที่ตั้งของลักษณะทั้งหมดในอุปกรณ์นั้น

let lightLocality =
  dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality

คุณอาจเห็นสถานะ mixed ในสถานการณ์ที่คล้ายกับสถานการณ์การเชื่อมต่อ partiallyOnline นั่นคือ ลักษณะบางอย่างทำงานบนระบบคลาวด์ในขณะที่ลักษณะอื่นๆ ทำงานในเครื่อง

เปลี่ยนชื่ออุปกรณ์

เรียกใช้เมธอด เพื่อเปลี่ยนชื่ออุปกรณ์setName(_:)

let updatedDevice = try await theDevice.setName("new device name")

เมื่อเปลี่ยนชื่ออุปกรณ์ โครงสร้าง HomeDevice เดิมจะยังคงเหมือนเดิม และการเปลี่ยนแปลงจะแสดงในออบเจ็กต์ HomeDevice ที่อัปเดตซึ่งแสดงผล

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