Mengakses perangkat dan metadata perangkat untuk iOS

API perangkat dapat diakses melalui Home API untuk iOS. Impor paket berikut ke aplikasi Anda:

import GoogleHomeSDK
import GoogleHomeTypes

Untuk mengetahui informasi selengkapnya, lihat Model data di iOS.

Penanganan error

Beberapa metode di Home API menampilkan HomeError, jadi sebaiknya gunakan blok do-catch untuk menangkap HomeError pada panggilan tersebut.

Saat menangani HomeError, periksa kolom code dan message-nya untuk mengetahui penyebab masalahnya.

Error yang tidak ditangani akan menyebabkan aplikasi Anda error.

Untuk mengetahui informasi selengkapnya, lihat Penanganan error.

Lihat Mengirim perintah ke perangkat untuk mengetahui contohnya.

Contoh panggilan

Mendapatkan daftar perangkat

Dengan referensi ke objek Home, panggil devices() untuk mendapatkan Query perangkat yang dapat diakses. Panggil metode batched() Query, yang memunculkan Set yang mencerminkan status Home saat ini dengan setiap perubahan metadata perangkat. Atau panggil Query.list() untuk mendapatkan snapshot perangkat yang tersedia. Ini adalah metode praktis yang berlangganan ke aliran data batched() dan menampilkan nilai pertama yang dikeluarkan. Query.stream() menghasilkan aliran data yang memunculkan nilai baru pada perubahan metadata perangkat seperti nama, ruangan, atau strukturnya. Secara internal, ini menggunakan batched() dan hanya memunculkan properti yang diubah.

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

Dari sana, Anda dapat mengakses status untuk setiap perangkat dan mengirim perintah ke perangkat.

Dengan rilis 1.8 API Home, Anda memiliki opsi untuk membuat API merepresentasikan setiap perangkat multibagian sebagai satu perangkat dengan menetapkan parameter enableMultipartDevices metode devices() ke true. Lihat Perangkat multibagian di iOS untuk mengetahui informasi selengkapnya.

Mendapatkan jenis perangkat

Untuk mendapatkan jenis perangkat yang terkait dengan perangkat, baca properti types perangkat, yang menampilkan DeviceTypeController.

Panggil DeviceTypeController.subscribe(_:) untuk berlangganan update untuk jenis perangkat tertentu:

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

Jika perangkat tidak mendukung jenis perangkat yang ditentukan, perangkat akan menampilkan Empty Publisher yang langsung selesai.

Jika perangkat mendukung jenis perangkat tertentu, Anda bisa mendapatkan handle untuk jenis tersebut dengan memanggil get():

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

Jika perangkat tidak mendukung jenis yang ditentukan, perangkat akan menampilkan nil.

Panggil DeviceTypeController.subscribeAll() untuk mendapatkan Publisher DeviceTypeCollection. Class ini memungkinkan Anda memeriksa apakah perangkat memiliki jenis perangkat tertentu:

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

Mendapatkan ciri jenis perangkat

Jenis perangkat adalah titik entri untuk membaca karakteristik, karena jenis perangkat menguraikan perangkat menjadi bagian-bagian fungsionalnya (seperti endpoint di Matter).

Fitur ini juga memperhitungkan tabrakan karakteristik jika perangkat memiliki dua jenis perangkat, yang keduanya mungkin memiliki karakteristik yang sama. Misalnya, jika sebuah perangkat adalah Speaker dan Lampu yang Dapat Diredupkan, perangkat tersebut akan memiliki dua karakteristik On/Off dan dua karakteristik Level Control.

Jenis tabrakan karakteristik lainnya dapat terjadi jika perangkat memiliki dua karakteristik dengan nama yang sama. Misalnya, onOff dapat merujuk ke instance trait OnOff standar, atau dapat merujuk ke instance trait OnOff yang ditentukan produsen. Untuk menghilangkan potensi ambiguitas terkait karakteristik mana yang dimaksud, referensikan karakteristik melalui salah satu dari dua koleksi karakteristik di setiap jenis perangkat.

Untuk karakteristik standar, yaitu yang analog dengan cluster standar Matter, gunakan matterTraits. Misalnya, untuk mendapatkan karakteristik tertentu untuk jenis perangkat Lampu yang Dapat Diredupkan:

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

Untuk karakteristik Google, gunakan googleTraits:

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

Untuk mengakses karakteristik khusus produsen, referensikan melalui properti traits, tetapi awali dengan nama paket produsen:

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
}

Membaca status perangkat

Lihat contoh pemeriksaan atribut OnOff dari karakteristik On/Off perangkat ini:

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
}

Mendapatkan daftar perangkat dengan karakteristik tertentu

Untuk mendapatkan daftar perangkat yang memiliki karakteristik tertentu, Anda perlu melakukan iterasi pada perangkat, jenis perangkat setiap perangkat, dan karakteristik setiap jenis perangkat. Misalnya, untuk mendapatkan daftar perangkat di rumah yang semuanya memiliki karakteristik On/Off:

// 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)
    }
  }
}

Lihat Indeks karakteristik di iOS untuk mengetahui daftar lengkap karakteristik yang tersedia di Home API.

Mendapatkan daftar perangkat dengan jenis perangkat yang serupa

Untuk mendapatkan daftar perangkat yang mewakili semua lampu di rumah:

// 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)
  }

Ada beberapa jenis perangkat di Home API yang dapat mewakili jenis perangkat inti. Misalnya, tidak ada jenis perangkat "Lampu". Sebagai gantinya, ada empat jenis perangkat berbeda yang dapat mewakili lampu, seperti yang ditunjukkan dalam contoh sebelumnya. Oleh karena itu, untuk mendapatkan gambaran komprehensif tentang jenis perangkat tingkat yang lebih tinggi di rumah, beberapa jenis perangkat harus disertakan.

Lihat Jenis perangkat yang didukung di iOS untuk mengetahui daftar lengkap jenis perangkat dan karakteristiknya yang tersedia di Home API.

Mendapatkan Nama Vendor, ID Vendor, atau ID Produk untuk perangkat

Karakteristik BasicInformationTrait mencakup informasi seperti ID Vendor, ID Produk, Nama Produk, dan Nomor Seri untuk perangkat:

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

Identifikasi perangkat cloud-to-cloud untuk produsen perangkat

Jika Anda adalah pembuat perangkat dan membuat perangkat Cloud-to-cloud, untuk mengidentifikasi perangkat Cloud-to-cloud Anda melalui sifat BasicInformation, Anda dapat menyertakan kolom string ini dalam respons SYNC:

  • ID vendor yang dikeluarkan Connectivity Standards Alliance (Alliance): "matterOriginalVendorId": "0xfff1",

  • Kode Produk yang secara unik mengidentifikasi produk vendor: "matterOriginalProductId": "0x1234",

  • ID unik untuk perangkat, yang dibuat dengan cara khusus produsen: "matterUniqueId": "matter-device-id",

Saat memasukkan kolom string ini, gunakan Matter ID Vendor dan Produk jika Anda memilikinya. Jika Anda bukan anggota Alliance dan belum diberi ID ini, Anda dapat mengosongkan kolom matterOriginalVendorId dan matterOriginalProductId serta memberikan matterUniqueId sebagai ID.

Contoh respons SYNC menunjukkan penggunaan kolom berikut:

{
  "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",
          }
        ]
      }
    ]
  }
}

Untuk mengetahui informasi selengkapnya, lihat dokumentasi Cloud-to-cloud SYNC.

Metadata perangkat dan karakteristik

Perangkat dan karakteristik di Home API memiliki metadata yang terkait, yang dapat membantu mengelola pengalaman pengguna di aplikasi.

Setiap karakteristik di Home API berisi properti sourceConnectivity, yang memiliki informasi tentang status online dan lokalitas karakteristik (perutean lokal atau jarak jauh).

Mendapatkan jenis utama perangkat

Beberapa perangkat mungkin menampilkan beberapa jenis perangkat melalui Home API. Untuk memastikan pengguna melihat opsi yang sesuai di aplikasi (seperti kontrol perangkat dan otomatisasi yang disarankan) untuk perangkat mereka, sebaiknya periksa apakah jenis perangkat adalah jenis utama perangkat.

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

Memeriksa apakah ciri sedang online

Baca properti connectivityState untuk memeriksa konektivitas karakteristik:

let levelControlConnectivity =
  levelControlTrait.metadata.sourceConnectivity
  .connectivityState

Beberapa karakteristik, biasanya karakteristik smart home Google, mungkin ditampilkan offline jika perangkat tidak memiliki konektivitas internet. Hal ini karena karakteristik ini berbasis cloud dan tidak memiliki perutean lokal.

Memeriksa konektivitas untuk perangkat

Konektivitas untuk perangkat sebenarnya diperiksa di tingkat jenis perangkat karena beberapa perangkat mendukung beberapa jenis perangkat. Status yang ditampilkan adalah kombinasi status konektivitas untuk semua karakteristik di perangkat tersebut.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

Status partiallyOnline dapat diamati dalam kasus jenis perangkat campuran saat tidak ada konektivitas internet. Karakteristik standar Matter mungkin masih online karena perutean lokal, tetapi karakteristik berbasis cloud akan offline.

Mendapatkan alamat IP perangkat

Untuk menemukan alamat IP perangkat, gunakan atribut networkInterfaces dari GeneralDiagnosticsTrait. Alamat ditampilkan sebagai objek Data, yang dapat Anda format ke string IPv4 atau IPv6 standar menggunakan framework 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
}

Memeriksa pemilihan rute jaringan suatu karakteristik

Lokalitas untuk karakteristik juga tersedia di Home API. dataSourceLocality menunjukkan apakah karakteristik dirutekan dari jarak jauh (melalui cloud), secara lokal (melalui hub lokal), atau peer-to-peer (langsung dari perangkat ke perangkat, tanpa hub).

Nilai lokalitas yang tidak diketahui unspecified dapat terjadi, misalnya, saat aplikasi sedang melakukan booting dan belum mencapai hub atau server untuk konektivitas perangkat. Perangkat ini tidak dapat dijangkau dan akan gagal merespons permintaan interaksi dari perintah atau peristiwa. Klien dapat menentukan cara menangani perangkat tersebut.

let levelControlLocality =
  levelControlTrait.metadata.sourceConnectivity
  .dataSourceLocality

Memeriksa pemilihan rute jaringan untuk perangkat

Seperti konektivitas, lokalitas diperiksa di tingkat jenis perangkat. Status yang ditampilkan adalah kombinasi lokalitas untuk semua karakteristik di perangkat tersebut.

let lightLocality =
  dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality

Status mixed dapat diamati dalam skenario yang mirip dengan konektivitas partiallyOnline: beberapa karakteristik berbasis cloud, sementara yang lain bersifat lokal.

Mengubah nama perangkat

Panggil metode setName(_:) untuk mengubah nama perangkat:

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

Saat mengubah nama perangkat, struct HomeDevice asli tetap sama dan perubahan akan ditampilkan dalam objek HomeDevice yang diperbarui dan ditampilkan.

Nama akan dipotong jika melebihi batas 60 poin kode Unicode (karakter) dan tidak akan ada error yang ditampilkan. Developer bertanggung jawab untuk menangani nama yang panjang dan, misalnya, dapat memutuskan apakah mereka ingin memberi tahu pengguna bahwa nama akan dipotong.

Memeriksa keanggotaan grup untuk perangkat

Perangkat fisik dapat menjadi bagian dari satu atau beberapa grup perangkat. Untuk memeriksa grup tempat perangkat berada, periksa GroupMembershipTrait di perangkat:

if let trait = await device.traits.get(Google.GroupMembershipTrait.self) {
  for groupId in trait.attributes.groupObjectIdsArray {
    print("Device belongs to group: \(groupId)")
  }
}

Untuk memeriksa jenis perangkat yang didukung oleh DeviceGroup dan mengirim perintah ke grup sebagai satu entity, lihat Mengontrol grup perangkat.