iOS'te Structure API'leri

Structure API'lerine iOS için Home API'leri üzerinden erişilebilir.

Structure API'leri kullanmak için öncelikle GoogleHomeSDK paketini uygulamanıza aktarın:

import GoogleHomeSDK

Hata işleme

Home API'lerindeki bazı yöntemler HomeError hatası verir. Bu nedenle, bu çağrılarda HomeError hatasını yakalamak için do-catch bloğu kullanmanızı öneririz.

HomeError ile ilgili işlem yaparken neyin yanlış gittiğini öğrenmek için code ve message alanlarını kontrol edin.

İşlenmeyen hatalar uygulamanızın kilitlenmesine neden olur.

Daha fazla bilgi için Hata işleme bölümüne bakın.

Structure API

Home, Home Graph'i temsil eder ve Structure API'nin giriş noktasıdır. Yapılar, odalar ve cihazlar için referanslar sağlar.

Structure, Home Graph'inizdeki bir yapıyı temsil eder. id ve name gibi yapı meta verilerine erişim sağlar.

Hesabınızdaki tüm yapıları almak için structures() kullanın. Yapılar, verilerini kullanmak için çeşitli seçenekler sunan bir Query biçiminde döndürülür:

API Açıklama
stream() Değişiklikler yapıldıkça her nesneyi ayrı ayrı yayınlayan bir Publisher döndürür.
batched() Mevcut sonucu nesnelerin Set olarak yayınlayan bir Publisher döndürür. Yayınlanan her Set, nesne grafiğinin mevcut durumunu temsil eder.
list() Mevcut sonucu nesnelerin Set değeri olarak döndürür.

structures().list() çağrısı, geçerli bir yapı kümesini hemen döndürmeyebilir. Uygulamanız reaktifse ve kullanıcı arayüzünü yönlendirmek için tüm yapı değişikliklerine abone olmak üzere stream() yöntemini çağırıyorsa geçerli bir yapı listesi döndürülmelidir. Boş bir yapı listesinin döndürülebileceği başka durumlar da vardır. Örneğin, kullanıcının telefonu bağlantıyı kaybederse veya kullanıcı uygulamanızın izinlerini iptal ederse. Uygulamanızda bu durumları ele aldığınızdan emin olmanız gerekir.

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

Örnek yapı çağrıları

Bir yapı grubu alma

list() üzerinde Query<Structure> çağrıldığında en son öğe kümesi döndürülür:

// Get a stream of all structures accessible to the user
let allStructuresChanges = self.home.structures()
let allStructures = try? await allStructuresChanges.list()

Tepkisel bir uygulama tasarlarken list() yerine batched() ve stream() çağrılarını kullanmanız gerekir. Çünkü bunlar, ev grafiği değiştiğinde otomatik olarak ürün verileri üretir.

Yapı özelliklerini alma

Yapıların listesini aldıktan sonra bunların özelliklerine erişebilirsiniz:

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

Yapıları ada göre bulma

Bir yapının adını biliyorsanız name özelliğini kullanarak da yapıya erişebilirsiniz:

do {
  structure1 = try await home.structures().list().first(where: { $0.name == "Main House" })
} catch let _ as HomeError {
  // Code for handling the exception
}

Buradan her bir yapının mülklerine, odalarına ve cihazlarına erişilebilir.

Birden fazla yapıyla çalışma

Birden fazla yapı kullanmak için her yapıya ayrı bir referans alın:

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
}

Odalar

Oda, bir grup cihaz içerir. Oda her zaman bir yapının parçasıdır ve bir yapıda birden fazla oda olabilir. Bir odayı yapıdan kaldırdığınızda odadaki cihazlar yapıdan kaldırılmaz. Ancak oda silinirse o odadaki cihazların ataması kaldırılır.

Hesaptaki tüm odaları almak için Home.rooms(), her odadaki ilgili cihazları görüntülemek için roomID = device.roomID kullanın.

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)

Örnek Oda görüşmeleri

Odaların listesini alma

Home sınıfını kullanarak odaların listesini alabilir ve özelliklerine erişebilirsiniz:

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

Oda oluştur

Structure içinde yeni bir oda oluşturmak için:

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
}

Oda silme

Alternatif olarak, bir odayı silebilirsiniz:

val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull()
    structure.deleteRoom(roomToDelete!!)

Bir odayı kimliğini kullanarak da silebilirsiniz:

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

Cihazların bulunduğu bir oda silinirse cihazlar yapıda kalır ancak artık bir odaya atanmaz.

Cihazları farklı bir odaya taşıma

Structure, bir cihazı farklı bir odaya taşımanıza da olanak tanır:

do {
  try await structure.move(device: light, to: room)
} catch let _ as HomeError {
  // Code for handling the exception
}

Odanın adını değiştirme

Bir odanın adını değiştirmek için setName(_:) yöntemini çağırın:

let updatedRoom = try await theRoom.setName("new room name")

Bir odanın adı değiştirilirken orijinal Room yapısı aynı kalır ve değişiklik, döndürülen güncellenmiş Room nesnesine yansıtılır.

Adlar, 60 Unicode kod noktası (karakter) sınırını aşarsa kısaltılır ve hata gösterilmez. Uzun adların işlenmesinden geliştiriciler sorumludur. Örneğin, adların kısaltılacağı konusunda kullanıcıları bilgilendirmek isteyip istemediklerine karar verebilirler.

Cihaz grupları

Cihaz grubu, tek bir yapı içinde kullanıcı tarafından tanımlanan bir cihaz koleksiyonunu temsil eder. Grup üyeliği Google hizmetlerinde saklanır ve yapının diğer üyeleri ile yapıya erişimi olan diğer uygulamalar tarafından görülebilir.

Fiziksel odalar gibi cihaz grupları da tek bir yapıya aittir. Ancak odaların aksine, cihaz grupları mantıksal gruplandırmalardır. Bir cihaz aynı anda birden fazla cihaz grubuna ait olabilir. Cihaz gruplarında en fazla 100 cihaz bulunabilir.

Cihaz grupları, HomeDevice öğesinden farklı olan DeviceGroup varlığıyla temsil edilir. Cihaz gruplarıyla etkileşim kurmak için Home.configure içinde ReferencedAutomationTypes yapılandırırken ilgili cihaz türlerini ve özelliklerini, GroupTrait, GroupManagementTrait ve GroupMembershipTrait özellikleriyle birlikte ekleyin.

Bir gruptaki cihazlarla etkileşim kurmak için doğrudan üye cihazları üzerinde iterasyon yapabilir (Grup üyesi cihazlarla etkileşim kurma bölümüne bakın) veya DeviceGroup üzerinde bir cihaz türü parçasını hedefleyebilirsiniz (Cihaz grubunu kontrol etme bölümüne bakın).

Cihaz gruplarının listesini alma

Evdeki tüm cihaz gruplarını sorgulamak için:

let groups = try await home.entities(DeviceGroup.self).list()
for group in groups {
  let groupTrait = await group.traits.get(Google.GroupTrait.self)
  let name = groupTrait?.attributes.name ?? "Device Group"
  print("Found group: \(name) with ID: \(group.id)")
}

Grup üyesi cihazlarla etkileşim kurma

Bir grubun üye cihazları üzerinde iterasyon yapmak, her bir üye üzerinde ayrıntılı kontrol sağlar, komutları tek bir istekte toplu olarak işlemenize ve üyeler arasında özellikleri birleştirmenize veya yazmanıza olanak tanır.

Öncelikle, hedef grup kimliği için her cihazın GroupMembershipTrait değerini kontrol ederek evdeki cihazları filtreleyin:

let allDevices = try await home.devices().list()
var members: [HomeDevice] = []
for device in allDevices {
  if let membership = await device.traits.get(
    Google.GroupMembershipTrait.self
  ),
  membership.attributes.groupObjectIdsArray.contains(group.id) {
    members.append(device)
  }
}

Bir grubun tüm uyumlu üyeleri için bir özelliğe ait komutları içeren tek bir toplu istek göndermek için:

var onOffTraits: [Matter.OnOffTrait] = []
for device in members {
  if let light = await device.types.get(OnOffLightDeviceType.self),
     let onOff = light.matterTraits.onOffTrait {
    onOffTraits.append(onOff)
  }
}

let traitsToUse = onOffTraits
let responses = try await home.sendBatchedCommands { batcher in
  return try traitsToUse.map { batcher.add(try $0.onBatchable()) }
}

for response in responses {
  try response.getOrThrow()
}

Ayrıca, bir gruptaki tüm eşleşen üye cihazlarda bir özelliği aynı anda güncelleyebilir (örneğin, tüm DimmableLightDeviceType üyelerinde onTransitionTime özelliğini 1 olarak ayarlayabilir) ve işlemin belirli bir süre içinde tamamlanmasını bekleyebilirsiniz:

try await withThrowingTaskGroup(of: Void.self) { taskGroup in
  taskGroup.addTask {
    try await Task.sleep(for: .seconds(5))
    throw CancellationError()
  }

  for device in members {
    taskGroup.addTask {
      guard let light = await device.types.get(DimmableLightDeviceType.self),
            let levelControl = light.matterTraits.levelControlTrait,
            levelControl.attributes.$onTransitionTime.isSupported
      else { return }
      _ = try await levelControl.update {
        $0.setOnTransitionTime(1)
      }
    }
  }

  for _ in 0..<members.count {
    try await taskGroup.next()
  }
  taskGroup.cancelAll()
}

Bir grubun üyeleri arasında bir özelliği toplamak için (ör. gruptaki tüm renk sıcaklığı ışıkları arasında minimum colorTempPhysicalMaxMireds değerini bulmak):

var maxMiredsValues: [UInt16] = []
for device in members {
  if let light = await device.types.get(ColorTemperatureLightDeviceType.self),
     let mireds = light.matterTraits.colorControlTrait?.attributes
       .colorTempPhysicalMaxMireds {
    maxMiredsValues.append(mireds)
  }
}
let minMaxMireds = maxMiredsValues.min()

Cihaz grubu oluşturma

Cihaz grubu oluşturmak için yapıda GroupManagementTrait kullanın:

let groupsManagementTrait =
  try await structure.traits(Google.GroupManagementTrait)
let _ = try await groupsManagementTrait.createUserDefinedGroup(
  withName: "Kitchen Lights",
  withDevices: [light1, light2]
)

Grup üyeliğini yönetme

Mevcut bir gruba üye eklemek için:

let groupManagementTrait =
  try await structure.traits(Google.GroupManagementTrait.self)
groupManagementTrait.addGroupMembers(
  groupObjectId: group.id,
  memberDeviceObjectIds = [light3.id],
)

Gruptan üye kaldırmak için:

let groupManagementTrait =
  try await structure.traits(Google.GroupManagementTrait.self)
_ = try await groupManagementTrait.removeGroupMembers(
  groupObjectId: group.id,
  memberDeviceObjectIdsArray: Array(removedIDs)
)

Cihaz grubunun adını değiştirme

Bir cihaz grubunu yeniden adlandırmak için GroupTrait öğesinin name alanını güncelleyin:

let groupTrait = group.traits.get(Google.GroupTrait.self)
_ = try await groupTrait.update { $0.name = "Movie Corner" }

Cihaz grubunu silme

Bir yapıdan cihaz grubunu silmek için:

let groupManagementTrait =
  try await structure.traits.get(Google.GroupManagementTrait.self)

_ = try await groupManagementTrait.deleteGroup(groupObjectId: group.id)