เข้าถึงอุปกรณ์และข้อมูลเมตาของอุปกรณ์สำหรับ 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 ที่แสดงสถานะปัจจุบันของบ้านเมื่อมีการเปลี่ยนแปลงข้อมูลเมตาของอุปกรณ์ ทุกครั้ง หรือโทรหา 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 ลักษณะประกอบด้วยข้อมูล เช่น รหัสผู้ให้บริการ รหัสผลิตภัณฑ์ ชื่อผลิตภัณฑ์ และ หมายเลขซีเรียลของอุปกรณ์

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

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

ตรวจสอบการเชื่อมต่อสำหรับอุปกรณ์

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

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

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

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

หากต้องการค้นหาที่อยู่ IP ของอุปกรณ์ ให้ใช้แอตทริบิวต์ networkInterfaces ของ 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 struct เดิมจะยังคงเหมือนเดิม และการเปลี่ยนแปลงจะแสดงในออบเจ็กต์ HomeDevice ที่อัปเดตแล้วซึ่งส่งคืน

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