Android'deki Structure API'leri

Structure API'lere Android için Home API'leri üzerinden erişilebilir. Bu paketleri uygulamanıza aktarın:

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

Hata işleme

Home API'lerindeki tüm yöntemler HomeException hatası verebilir. Bu nedenle, tüm çağrılarda HomeException hatasını yakalamak için try-catch bloğu kullanmanızı öneririz.

HomeException ile işlem yaparken neyin yanlış gittiğini öğrenmek için error.code ve error.message alanlarını kontrol edin. Alt hata kodları da olabilir. Bu nedenle getSubErrorCodes() yöntemini çağırıp sonucu kontrol edin.

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

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

Örnek aramalar

Yapıların listesini alma

Başlatıldıktan sonra structures() çağrısı, erişebileceğiniz yapıların akışını döndürür:

// 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'si, geçerli bir yapı listesini hemen döndürmeyebilen bir akıştır. Uygulamanız reaktifse ve kullanıcı arayüzünü yönlendirmek için bu akışa abone oluyorsa 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 telefonunun bağlantısı kesilirse veya kullanıcı uygulamanızın izinlerini iptal ederse. Uygulamanızda bu durumları ele aldığınızdan emin olmanız gerekir.

Alternatif olarak, reaktif programlama yerine zorunlu programlama kesinlikle gerekliyse bir terminal akış operatörü kullanılabilir:

val everyStructure = withTimeout(5000) { home.structures().first { it.isNotEmpty() } }

Bu çağrı, akış üzerinden geçerli bir yapı listesinin gelmesini bekler ve liste, uygulama tarafından belirlenen zaman aşımı süresi içinde alınmazsa zaman aşımına uğrar.

Yapı özelliklerini alma

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

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

Yapıları ada göre bulma

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

val myHome = home.structures().list().first { it.name == "My home" }

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

Odaların listesini alma

Yapıyı oluşturduktan sonra odaların listesini alabilir ve özelliklerine erişebilirsiniz:

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

Oda oluştur

Yeni oda oluşturmak için:

val testName = "Test Room Name"
val newRoom: Room = structure.createRoom(testName)

Oda silme

Alternatif olarak, bir odayı silebilirsiniz:

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

Yalnızca kimlik kullanarak da oda silebilirsiniz:

val roomToDelete1 = allRooms.filter { it.id == testRoomId }.firstOrNull()
structure.deleteRoom(roomToDelete1!!)

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

Cihazları farklı bir odaya taşıma

Bir yapı oluşturduktan sonra cihazları bu yapı içindeki farklı bir odaya taşıyabilirsiniz:

val room2 = structure.rooms().get(Id("room_id_other_structure"))
    val device1 = structure.devices().get(Id("device_id1"))
    structure.moveDevicesToRoom(room2!!, listOf(device1!!))

Yalnızca cihaz ve oda kimlikleriniz varsa cihazları şu şekilde de taşıyabilirsiniz:

structure.moveDevicesToRoom(Id("room_id_other_structure"), listOf(Id("device_id1")))

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

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

livingRoom.setName("Living Room")

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.

Google Home ekosisteminde kullanıcılar, çoğu cihaz türü için o türdeki tüm cihazlara aynı anda izin verebilir. Kilit, kamera veya kapı zili gibi hassas ya da kısıtlanmış cihaz türleri için kullanıcıların her birine ayrı ayrı izin vermesi gerekir.

Bir kullanıcının hassas veya kısıtlanmış bir cihaz türüne erişim izni verip vermediğini belirlemek için yapı düzeyindeki consentedDeviceTypes() işlevini kullanın:

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

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ını sorgulamak ve onlarla etkileşimde bulunmak için FactoryRegistry öğenizi başlatırken entityTypes listesine DeviceGroup özelliğini, Group, GroupManagement ve GroupMembership ö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

Bir yapıdaki tüm cihaz gruplarını gözlemlemek için home.entities(DeviceGroup) yöntemini çağırın ve yapının kimliğine göre filtreleyin:

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

Grup üyesi cihazlarla etkileşim kurma

group.devices() ile bir grubun üye cihazları üzerinde iterasyon yapmak, her bir üye üzerinde ayrıntılı kontrol sahibi olmanızı, komutları tek bir istekte toplu olarak çalıştırmanızı ve üyeler arasında özellikleri birleştirmenizi veya yazmanızı sağlar.

Örneğin, bir grubun tüm uyumlu üyeleri genelinde bir özelliğe yönelik komutlar içeren tek bir toplu istek göndermek için:

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

Ayrıca, bir gruptaki tüm eşleşen üye cihazlarda bir özelliği güncelleyebilir (ör. tüm DimmableLightDevice üyelerinde onTransitionTime özelliğini 1u olarak ayarlayabilirsiniz) ve işlemin belirli bir süre içinde tamamlanmasını bekleyebilirsiniz:

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

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

val members = group.devices(enableMultipartDevices = true).first()
val minMaxMireds: UShort? = members.mapNotNull { device ->
  val light = device.partOrNull(ColorTemperatureLightDevice).first()
  light?.standardTraits?.colorControl?.colorTempPhysicalMaxMireds
}.minOrNull()

Cihaz grubu oluşturma

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

val groupManagement = structure.trait(GroupManagementTrait)
val response = groupManagement?.createUserDefinedGroup(
  name = "Living room lights",
  memberDeviceObjectIds = listOf(light1.id.id, light2.id.id)
)

Grup üyeliğini yönetme

Mevcut bir gruba üye eklemek için:

structure.trait(GroupManagementTrait)?.addGroupMembers(
  groupObjectId = group.id.id,
  memberDeviceObjectIds = listOf(light3.id.id)
)

Gruptan üye kaldırmak için:

structure.trait(GroupManagementTrait)?.removeGroupMembers(
  groupObjectId = group.id.id,
  memberDeviceObjectIds = listOf(light1.id.id)
)

Cihaz grubunun adını değiştirme

Bir cihaz grubunu yeniden adlandırmak için grubun GroupTrait öğesindeki ad özelliğini güncelleyin:

group.trait(GroupTrait)?.update {
  name = "Movie corner"
}

Cihaz grubunu silme

Bir yapıdan cihaz grubunu silmek için:

structure.trait(GroupManagementTrait)?.deleteGroup(
  groupObjectId = group.id.id
)

Otomasyonlar

Automation API'nin giriş noktası bir yapı üzerinden gerçekleşir. Home API'lerindeki otomasyonlar hakkında daha fazla bilgi edinmek için Android'de Automation API'ye genel bakış başlıklı makaleyi inceleyin.