Bir özelliğin komut destekleyip desteklemediğini kontrol etme
Bir özellik komutu için de destek kontrol edilebilir. Bir komutun belirli bir cihazda desteklenip desteklenmediğini kontrol etmek için özellik düzeyindeki supports
işlevini de kullanın.
Örneğin, bir cihazın Açma/Kapama özelliği toggle
komutunu destekleyip desteklemediğini kontrol etmek için:
// Check if the OnOff trait supports the toggle command. if (onOffTrait.supports(OnOff.Command.Toggle)) { println("onOffTrait supports toggle command") } else { println("onOffTrait does not support stateful toggle command") }
Cihaza komut gönderme
Komut göndermek, bir özellikten durum özelliği okumaya benzer. Cihazı açmak veya kapatmak için Google Home ekosistem veri modelinde toggle()
olarak tanımlanan OnOff
özelliğiyle ilişkili Toggle komutunu kullanın. Bu yöntem, onOff
değeri true
ise false
olarak, false
ise true
olarak değiştirir:
// Calling a command on a trait. try { onOffTrait.toggle() } catch (e: HomeException) { // Code for handling the exception }
Tüm özellik komutları suspend
işlevleridir ve yalnızca API tarafından bir yanıt döndürüldüğünde (ör. cihaz durumunun değiştiği onaylandığında) tamamlanır.
Yürütme akışında bir sorun algılanırsa komutlar istisna döndürebilir. Geliştirici olarak, bu istisnaları düzgün şekilde işlemek ve hataların düzeltilebildiği durumlarda kullanıcılara ayrıntılı bilgi sunmak için bir try-catch
bloğu kullanmanız gerekir. İşlenmeyen istisnalar, uygulama çalışma zamanını durdurur ve uygulamanızda kilitlenmelere neden olabilir.
Alternatif olarak, durumu açıkça ayarlamak için off()
veya on()
komutlarını kullanın:
onOffTrait.off() onOffTrait.on()
Durumu değiştirmek için bir komut gönderdikten sonra, komut tamamlandığında Cihaz durumunu okuma bölümünde açıklandığı şekilde durumu okuyarak uygulamanızda işleyebilirsiniz. Alternatif olarak, tercih edilen yöntem olan Durumu gözlemleme bölümünde açıklandığı şekilde akışları kullanın.
Parametrelerle komut gönderme
Bazı komutlar, OnOff
veya LevelControl
özelliklerindeki gibi parametreler kullanabilir:
offWithEffect
// Turn off the light using the DyingLight effect. onOffTrait.offWithEffect( effectIdentifier = OnOffTrait.EffectIdentifierEnum.DyingLight, effectVariant = 0u, )
moveToLevel
// Change the brightness of the light to 50% levelControlTrait.moveToLevel( level = 127u.toUByte(), transitionTime = null, optionsMask = LevelControlTrait.OptionsBitmap(), optionsOverride = LevelControlTrait.OptionsBitmap(), )
Bazı komutlarda, zorunlu bağımsız değişkenlerden sonra gelen isteğe bağlı bağımsız değişkenler bulunur.
Örneğin, FanControl
trait
için step
komutunun iki isteğe bağlı bağımsız değişkeni vardır:
val fanControlTraitFlow: Flow<FanControl?> = device.type(FanDevice).map { it.standardTraits.fanControl }.distinctUntilChanged() val fanControl = fanControlTraitFlow.firstOrNull() // Calling a command with optional parameters not set. fanControl?.step(direction = FanControlTrait.StepDirectionEnum.Increase) // Calling a command with optional parameters. fanControl?.step(direction = FanControlTrait.StepDirectionEnum.Increase) { wrap = true }
Bir özelliğin, bir özelliği destekleyip desteklemediğini kontrol etme
Bazı cihazlar Matter özelliğini destekleyebilir ancak belirli bir özelliği desteklemeyebilir. Örneğin, Cloud-to-cloud cihazı Matter ile eşlenmişse her Matter özelliğini desteklemeyebilir. Bu gibi durumları ele almak için özelliğin belirli bir cihazda desteklenip desteklenmediğini kontrol etmek üzere özellik düzeyinde supports
işlevini ve özelliğin Attribute
enum'unu kullanın.
Örneğin, bir cihazın On/Off özelliği için onOff
özelliğini destekleyip desteklemediğini kontrol etmek için:
// Check if the OnOff trait supports the onOff attribute. if (onOffTrait.supports(OnOff.Attribute.onOff)) { println("onOffTrait supports onOff state") } else { println("onOffTrait is for a command only device!") }
Bazı özellikler, Matter spesifikasyonunda veya Cloud-to-cloud smart home şemasında boş değer atanabilir. Bu özellikler için, özellik tarafından döndürülen null değerinin, cihazın bu değeri bildirmemesinden mi yoksa özelliğin değerinin gerçekten null
olmasından mı kaynaklandığını belirleyebilirsiniz. Bunun için supports
'e ek olarak isNullable
'ı kullanın:
// Check if a nullable attribute is set or is not supported. if (onOffTrait.supports(OnOff.Attribute.startUpOnOff)) { // The device supports startupOnOff, it is safe to expect this value in the trait. if (OnOff.Attribute.startUpOnOff.isNullable && onOffTrait.startUpOnOff == null) { // This value is nullable and set to null. Check the specification as to // what null in this case means println("onOffTrait supports startUpOnOff and it is null") } else { // This value is nullable and set to a value. println("onOffTrait supports startUpOnOff and it is set to ${onOffTrait.startUpOnOff}") } } else { println("onOffTrait does not support startUpOnOff!") }
Özellikleri güncelleme
Belirli bir özelliğin değerini değiştirmek istiyorsanız ve özelliğin komutlarından hiçbiri bunu yapmıyorsa özellik, değerinin açıkça ayarlanmasını destekleyebilir.
Bir özelliğin değerinin değiştirilip değiştirilemeyeceği iki faktöre bağlıdır:
- Özellik yazılabilir mi?
- Özelliğin değeri, bir özellik komutu göndermenin yan etkisi olarak değişebilir mi?
Özellikler ve bunların nitelikleriyle ilgili referans belgelerinde bu bilgiler yer alır.
Bu nedenle, bir özelliğin değerinin nasıl değiştirileceğini belirleyen özellik kombinasyonları şunlardır:
Salt okunur ve diğer komutlardan etkilenmez. Bu, özelliğin değerinin değişmediği anlamına gelir. Örneğin,
Switch
özelliğinincurrentPosition
özelliği.Salt okunur ve diğer komutlardan etkilenir. Bu, özelliğin değerinin yalnızca bir komut gönderilmesi sonucunda değişebileceği anlamına gelir. Örneğin,
LevelControl
Matter özelliğinincurrentLevel
özelliği salt okunurdur ancak değerimoveToLevel
gibi komutlarla değiştirilebilir.Yazılabilir ve diğer komutlardan etkilenmez. Bu, özelliğin
update
işlevini kullanarak özelliğin değerini doğrudan değiştirebileceğiniz ancak özelliğin değerini etkileyecek herhangi bir komut olmadığı anlamına gelir. Örneğin,DoorLock
özelliğininWrongCodeEntryLimit
özelliği.Yazılabilir ve diğer komutlardan etkilenir. Bu, özelliğin
update
işlevini kullanarak özelliğin değerini doğrudan değiştirebileceğiniz ve komut gönderilmesi sonucunda özelliğin değerinin değişebileceği anlamına gelir. Örneğin,speedSetting
özelliğiFanControlTrait
doğrudan yazılabilir ancakstep
komutu kullanılarak da değiştirilebilir.
Bir özelliğin değerini değiştirmek için güncelleme işlevini kullanma örneği
Bu örnekte, DoorLockTrait.WrongCodeEntryLimit
özelliğinin değerinin nasıl açıkça ayarlanacağı gösterilmektedir.
Bir özellik değerini ayarlamak için özelliğin update
işlevini çağırın ve yeni değeri ayarlayan bir mutator işlevi iletin.
Öncelikle özelliğin bir özelliği desteklediğini doğrulamanız iyi bir uygulamadır.
Örneğin:
val doorLockDevice = home.devices().list().first { device -> device.has(DoorLock) } val traitFlow: Flow<DoorLock?> = doorLockDevice.type(DoorLockDevice).map { it.standardTraits.doorLock }.distinctUntilChanged() val doorLockTrait: DoorLock = traitFlow.first()!! if (doorLockTrait.supports(DoorLock.Attribute.wrongCodeEntryLimit)) { val unused = doorLockTrait.update { setWrongCodeEntryLimit(3u) } }
Aynı anda birden fazla komut gönderme
Toplu İşleme API'si, bir istemcinin tek bir yükte birden fazla Home API'si cihaz komutu göndermesine olanak tanır. Komutlar tek bir yükte gruplandırılır ve paralel düğüm kullanılarak bir Home API otomasyonu oluşturmaya benzer şekilde paralel olarak yürütülür. Örneğin, Güneş doğmadan önce jaluzileri aç. Ancak Batching API, Automation API'den daha karmaşık ve gelişmiş davranışlara olanak tanır. Örneğin, çalışma zamanında cihazları herhangi bir ölçüte göre dinamik olarak seçme özelliği.
Tek bir toplu işlemdeki komutlar, birden fazla cihazda, birden fazla odada ve birden fazla yapıda birden fazla özelliği hedefleyebilir.
Komutları toplu olarak göndermek, cihazların işlemleri aynı anda gerçekleştirmesine olanak tanır. Bu, komutlar ayrı isteklerde sırayla gönderildiğinde mümkün değildir. Toplu komutlar kullanılarak elde edilen davranış, geliştiricinin bir grup cihazın durumunu önceden belirlenmiş bir toplu duruma eşleşecek şekilde ayarlamasına olanak tanır.
Batching API'yi kullanma
Toplu İşleme API'si aracılığıyla komut çağırmayla ilgili üç temel adım vardır:
Home.sendBatchedCommands()
yöntemini çağırın.sendBatchedCommands()
bloğunun gövdesinde, toplu işleme dahil edilecek komutları belirtin.- Gönderilen komutların başarılı olup olmadığını görmek için sonuçlarını kontrol edin.
sendBatchedCommands() yöntemini çağırın.
Home.sendBatchedCommands()
yöntemini çağırın. Bu yöntem, arka planda özel bir toplu işlem bağlamında lambda ifadesi oluşturur.
home.sendBatchedCommands() {
Toplu komutları belirtme
sendBatchedCommands()
bloğunun gövdesinde batchable
commands öğesini doldurun. Toplu işlenebilir komutlar, toplu iş bağlamında kullanılabilen ve Batchable
soneki eklenerek adlandırılan mevcut Cihaz API'si komutlarının "gölge" sürümleridir. Örneğin, LevelControl
özelliğinin
moveToLevel()
komutunun moveToLevelBatchable()
adlı bir karşılığı vardır.
Örnek:
val response1 = add(command1)
val response2 = add(command2)
Tüm komutlar toplu iş bağlamına eklendikten ve yürütme bağlamdan çıktıktan sonra toplu iş otomatik olarak gönderilir.
Yanıtlar DeferredResponse<T>
nesnelerinde yakalanır.
DeferredResponse<T>
örnekleri, Collection
gibi herhangi bir türdeki bir nesnede veya sizin tanımladığınız bir veri sınıfında toplanabilir. Yanıtları birleştirmek için seçtiğiniz nesne türü, sendBatchedCommands()
tarafından döndürülür. Örneğin, toplu işlem bağlamı bir Pair
içinde iki DeferredResponse
örneği döndürebilir:
val (response1, response2) = homeClient.sendBatchedComamnds {
val response1 = add(someCommandBatched(...))
val response2 = add(someOtherCommandBatched(...))
Pair(response1, response2)
}
Alternatif olarak, toplu işlem bağlamı özel bir veri sınıfındaki DeferredResponse
örneklerini döndürebilir:
// Custom data class
data class SpecialResponseHolder(
val response1: DeferredResponse<String>,
val response2: DeferredResponse<Int>,
val other: OtherResponses
)
data class OtherResponses(...)
Her yanıtı kontrol edin
sendBatchedCommands()
bloğunun dışında, ilgili komutun başarılı mı yoksa başarısız mı olduğunu belirlemek için yanıtları kontrol edin. Bu işlem, DeferredResponse.getOrThrow()
çağrılarak yapılır. Bu çağrı:
- Yürütülen komutun sonucunu döndürür,
- veya toplu işlem kapsamı tamamlanmamışsa ya da komut başarısız olmuşsa hata verir.
Sonuçları yalnızca lambda kapsamının dışında kontrol etmeniz gerekir. sendBatchedCommands()
Örnek
Örneğin, herkes uyuduğunda evdeki tüm cihazları geceye hazırlayan bir "iyi geceler" sahnesi oluşturmak için Batching API'yi kullanan bir uygulama geliştirmek istediğinizi varsayalım. Bu uygulama, ışıkları kapatmalı ve ön ile arka kapıyı kilitlemelidir.
Bu göreve yaklaşmanın bir yolu şudur:
val lightDevices: List<OnOffLightDevice>
val doorlockDevices: List<DoorLockDevice>
// Send all the commands
val responses: List<DeferredResponse<Unit>> = home.sendBatchedCommands {
// For each light device, send a Batchable command to turn it on
val lightResponses: List<DeferredResponse<Unit>> = lightDevices.map { lightDevice ->
add(lightDevice.standardTraits.onOff.onBatchable())
}
// For each doorlock device, send a Batchable command to lock it
val doorLockResponse: List<DeferredResponse<Unit>> = doorlockDevices.map { doorlockDevice ->
add(doorlockDevice.standardTraits.doorLock.lockDoorBatchable())
}
lightResponses + doorLockResponses
}
// Check that all responses were successful
for (response in responses) {
response.getOrThrow()
}