Otomasyon API'lerine Android için Ev API'leri üzerinden erişilebilir ancak giriş noktaları bir yapı üzerinden olduğundan kullanılabilmeleri için önce yapıda izin verilmesi gerekir.
Bir yapı için izinler verildikten sonra bu paketleri uygulamanıza aktarın:
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id
import com.google.home.Structure
Bir yapı, aşağıdaki otomasyona özgü yöntemleri içeren bir HasAutomations
arayüzü içerir:
API | Açıklama |
---|---|
automations() |
Yapıya ait tüm otomasyonları listeleyin. Yalnızca Home API'leri aracılığıyla oluşturduğunuz otomasyonlar döndürülür. |
createAutomation(automation) |
Bir yapı için otomasyon örneği oluşturun. |
deleteAutomation(automationId) |
Otomasyon örneğini kimliğine göre silin. |
Otomasyon oluşturma
Home örneği oluşturup kullanıcıdan izin aldıktan sonra yapıyı ve cihazları alın:
val structure = homeManager.structures().list().single()
val device = homeManager.devices().get(Id("myDevice"))!!
Ardından, otomasyonunuzun mantığını Otomasyon DSL'yi kullanarak tanımlayın. Home API'lerinde otomasyonlar Automation
arayüzüyle temsil edilir. Bu arayüzde bir dizi özellik bulunur:
- Ad ve açıklama gibi meta veriler
- Örneğin, otomasyonun yürütülüp yürütülemeyeceğini belirten işaretler.
- Otomasyonun mantığını içeren düğümlerin listesi (otomasyon grafiği olarak adlandırılır ve
automationGraph
özelliğiyle gösterilir).
automationGraph
, varsayılan olarak SequentialFlow
türündedir. Bu tür, sıralı olarak yürütülen bir düğüm listesi içeren bir sınıftır. Her düğüm, otomasyonun bir öğesini (ör. başlatıcı, koşul veya işlem) temsil eder.
Otomasyona name
ve description
atayın.
Otomasyon oluşturulduğunda isActive
işareti varsayılan olarak true
olur. Bu nedenle, otomasyonun başlangıçta devre dışı olmasını istemediğiniz sürece bu işareti açıkça ayarlamanız gerekmez. Bu senaryoda, oluşturma sırasında işareti false
olarak ayarlayın.
Otomasyonları oluşturmak ve geliştirmek için DraftAutomation
arayüzü, almak için ise Automation
arayüzü kullanılır. Örneğin, bir cihaz açıldığında başka bir cihazı açan otomasyon için Otomasyon DSL'si aşağıda verilmiştir:
import com.google.home.automation.Action
import com.google.home.automation.Automation
import com.google.home.automation.Condition
import com.google.home.automation.DraftAutomation
import com.google.home.automation.Equals
import com.google.home.automation.Node
import com.google.home.automation.SequentialFlow
import com.google.home.automation.Starter
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.matter.standard.OnOff
import com.google.home.Structure
...
val automation: DraftAutomation = automation {
name = "MyFirstAutomation"
description = "Turn on a device when another device is turned on."
sequential {
val starterNode = starter<_>(device1, OnOffLightDevice, trait=OnOff)
condition() { expression = stateReaderNode.onOff equals true }
action(device2, OnOffLightDevice) { command(OnOff.on()) }
}
}
Otomasyon DSL'si tanımlandıktan sonra DraftAutomation
örneğini oluşturmak için createAutomation()
yöntemine iletin:
val createdAutomation = structure.createAutomation(automation)
Buradan, otomasyonda execute()
, stop()
ve update()
gibi diğer tüm otomasyon yöntemlerini kullanabilirsiniz.
Doğrulamayla ilgili hatalar
Otomasyon oluşturma işlemi doğrulamadan geçmezse bir uyarı veya hata mesajı
sorun hakkında bilgi verir. Daha fazla bilgi için ValidationIssueType
referansına bakın.
Kod örnekleri
Burada, Android'de otomasyon tasarlama sayfasında açıklanan varsayımsal otomasyonların bazı bölümlerini uygulamak için kullanılabilecek örnek kodlar sunuyoruz.
Basit otomasyon
Saat 8:00'de perdeleri açan bir otomasyon şu şekilde uygulanabilir:
// get all the automation node candidates in the structure
val allCandidates = structure.allCandidates().first()
// determine whether a scheduled automation can be constructed
val isSchedulingSupported =
allCandidates.any {
it is EventCandidate &&
it.eventFactory == Time.ScheduledTimeEvent &&
it.unsupportedReasons.isEmpty()
}
// get the blinds present in the structure
val blinds =
allCandidates
.filter {
it is CommandCandidate &&
it.commandDescriptor == WindowCoveringTrait.UpOrOpenCommand &&
it.unsupportedReasons.isEmpty()
}
.map { it.entity }
.filterIsInstance<HomeDevice>()
.filter { it.has(WindowCoveringDevice) }
if (isSchedulingSupported && blinds.isNotEmpty()) {
// Proceed to create automation
val automation: DraftAutomation = automation {
name = "Day time open blinds"
description = "Open all blinds at 8AM everyday"
isActive = true
sequential {
// At 8:00am local time....
val unused =
starter(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(LocalTime.of(8, 0, 0, 0)))
}
// ...open all the blinds
parallel {
for (blind in blinds) {
action(blind, WindowCoveringDevice) { command(WindowCovering.upOrOpen()) }
}
}
}
}
val createdAutomation = structure.createAutomation(automation)
} else if (!isSchedulingSupported) {
// Cannot create automation.
// Set up your address on the structure, then try again.
} else {
// You don't have any WindowCoveringDevices.
// Try again after adding some blinds to your structure.
}
Karmaşık otomasyon
Hareket algılandığında ışıkların yanıp sönmesini tetikleyen bir otomasyon şu şekilde uygulanabilir:
import com.google.home.Home
import com.google.home.HomeClient
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.equals
import com.google.home.automation.parallel
import com.google.home.automation.starter
import com.google.home.google.AssistantBroadcast
import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOff.Companion.toggle
import com.google.home.matter.standard.OnOffLightDevice
import java.time.Duration
// get all the automation node candidates in the structure
val allCandidates = structure.allCandidates().first()
// get the lights present in the structure
val availableLights = allCandidates.filter {
it is CommandCandidate &&
it.commandDescriptor == OnOffTrait.OnCommand
}.map { it.entity }
.filterIsInstance<HomeDevice>()
.filter {it.has(OnOffLightDevice) ||
it.has(ColorTemperatureLightDevice) ||
it.has(DimmableLightDevice) ||
it.has(ExtendedColorLightDevice)}
val selectedLights = ... // user selects one or more lights from availableLights
automation {
isActive = true
sequential {
// If the presence state changes...
val starterNode = starter<_>(structure, AreaPresenceState)
// ...and if the area is occupied...
condition() {
expression = starterNode.presenceState equals PresenceState.PresenceStateOccupied
}
// "blink" the light(s)
parallel {
for(light in selectedLights) {
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(1))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(1))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(1))
action(light, OnOffLightDevice) { command(OnOff.toggle())}
}
}
}
}
Varlık filtreleriyle cihazları dinamik olarak seçme
Otomasyon yazarken belirli cihazları belirtmekle sınırlı kalmazsınız. Varlık filtreleri adlı bir özellik, otomasyonunuzun çalışma zamanında çeşitli ölçütlere göre cihaz seçmesine olanak tanır.
Örneğin, varlık filtrelerini kullanarak otomasyonunuz şunları hedefleyebilir:
- Belirli bir cihaz türündeki tüm cihazlar
- Belirli bir odadaki tüm cihazlar
- belirli bir odadaki belirli bir cihaz türüne ait tüm cihazlar
- açık olan tüm cihazlar
- Belirli bir odada açık olan tüm cihazlar
Öğe filtrelerini kullanmak için:
Structure
veyaRoom
cihazınızdanatExecutionTime()
numarasını arayın. Bu işlevTypedExpression<TypedEntity<StructureType>>
değerini döndürür.- Bu nesnede
getDevicesOfType()
işlevini çağırın veDeviceType
iletin.
Varlık filtreleri başlatıcılarda, durum okuyucularda ve işlemlerde kullanılabilir.
Örneğin, herhangi bir Açık/Kapalı Işık'ın bir başlatıcıdan otomasyon tetiklemesini sağlamak için:
// If any light is turned on or off val starter = starter( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, )
Bir yapıda bulunan tüm ışıkların (özellikle Açık/Kapalı ışıklar) OnOff
durumunu bir durum okuyucuda yakalamak için:
// Build a Map<Entity, OnOff> val onOffStateOfAllLights = stateReader( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, )
Belirli bir odadaki ışıkları almak ve bunları bir koşulda kullanmak için:
val livingRoomLights = stateReader( entityExpression = livingRoom.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, ) // Are any of the lights in the living room on? condition { expression = livingRoomLights.values.any { it.onOff equals true } }
Çalışma zamanında:
Senaryo | Sonuç |
---|---|
Başlatıcıdaki ölçütleri karşılayan cihaz yok. | Otomasyon tetiklenmiyor. |
Eyalet sürücü belgesinde ölçütleri karşılayan cihaz yok. | Otomasyon başlatılıyor ancak herhangi bir işlem yapılmıyor. |
Hiçbir cihaz, bir işlemdeki ölçütleri karşılamıyor. | Otomasyon başlıyor ancak işlem hiçbir şey yapmıyor. |
Aşağıdaki örnek, bir ışık kapatıldığında salon ışığı hariç tüm ışıkları kapatan bir otomasyondur:
val unused = automation { sequential { // If any light is turned on or off val starter = starter( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, ) condition { // Check to see if the triggering light was turned off expression = starter.onOff equals false } // Turn off all lights except the hall light action( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice).filter { it notEquals entity(hallwayLight, OnOffLightDevice) } ) { command(OnOff.on()) } } }
Otomasyon yürütme
execute()
yöntemini kullanarak oluşturulan bir otomasyonu çalıştırma:
createdAutomation.execute()
Otomasyonda manuel başlatıcı varsa execute()
, manuel başlatıcıdan önceki tüm düğümleri yok sayarak otomasyonu bu noktadan başlatır. Otomasyonda manuel başlatıcı yoksa yürütme, ilk başlatıcı düğümünü izleyen düğümden başlar.
execute()
işlemi başarısız olursa HomeException
oluşturulabilir. Hata işleme bölümüne bakın.
Otomasyonu durdurma
stop()
yöntemini kullanarak çalışan bir otomasyonu durdurun:
createdAutomation.stop()
stop()
işlemi başarısız olursa HomeException
oluşturulabilir. Hata işleme bölümüne bakın.
Bir yapı için otomasyon listesi alma
Otomasyonlar yapı düzeyinde tanımlanır. automations()
yapısını kullanarak Flow
otomasyonuna erişin:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
structure.automations().collect {
println("Available automations:")
for (automation in it) {
println(String.format("%S %S", "$automation.id", "$automation.name"))
}
}
Alternatif olarak, yerel bir Collection
'ya atayın:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
var myAutomations: Collection<Automation> = emptyList()
myAutomations = structure.automations()
Kimliğe göre otomasyon alma
Otomasyon kimliğine göre otomasyon almak için yapı üzerinde automations()
yöntemini çağırın ve kimliğe göre eşleştirin:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: DraftAutomation = structure.automations().mapNotNull {
it.firstOrNull
{ automation -> automation.id == Id("automation-id") }
}.firstOrNull()
Yanıt:
// Here's how the automation looks like in the get response.
// Here, it's represented as if calling a println(automation.toString())
Automation(
name = "automation-name",
description = "automation-description",
isActive = true,
id = Id("automation@automation-id"),
automationGraph = SequentialFlow(
nodes = [
Starter(
entity="device@test-device",
type="home.matter.0000.types.0101",
trait="OnOff@6789..."),
Action(
entity="device@test-device",
type="home.matter.0000.types.0101",
trait="OnOff@8765...",
command="on")
]))
Otomasyonu ada göre alma
Kotlin'deki
filter()
yöntemi, API çağrılarını daha da hassaslaştırmak için kullanılabilir. Otomasyonu ada göre almak için yapının otomasyonlarını alın ve otomasyon adına göre filtreleyin:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: DraftAutomation = structure.automations().filter {
it.name.equals("Sunset Blinds") }
Bir cihazla ilgili tüm otomasyonları alma
Belirli bir cihaza referans veren tüm otomasyonları almak için iç içe filtreleme kullanarak her otomasyonun automationGraph
tarayın:
import android.util.Log
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
import com.google.home.automation.Action
import com.google.home.automation.Automation
import com.google.home.automation.Automation.automationGraph
import com.google.home.automation.Node
import com.google.home.automation.ParallelFlow
import com.google.home.automation.SelectFlow
import com.google.home.automation.SequentialFlow
import com.google.home.automation.Starter
import com.google.home.automation.StateReader
...
fun collectDescendants(node: Node): List<Node> {
val d: MutableList<Node> = mutableListOf(node)
val children: List<Node> =
when (node) {
is SequentialFlow -> node.nodes
is ParallelFlow -> node.nodes
is SelectFlow -> node.nodes
else -> emptyList()
}
for (c in children) {
d += collectDescendants(c)
}
return d
}
val myDeviceId = "device@452f78ce8-0143-84a-7e32-1d99ab54c83a"
val structure = homeManager.structures().list().single()
val automations =
structure.automations().first().filter {
automation: Automation ->
collectDescendants(automation.automationGraph!!).any { node: Node ->
when (node) {
is Starter -> node.entity.id.id == myDeviceId
is StateReader -> node.entity.id.id == myDeviceId
is Action -> node.entity.id.id == myDeviceId
else -> false
}
}
}
Otomasyonu güncelleme
Bir otomasyonun meta verilerini güncellemek için update()
yöntemini çağırın ve meta verileri ayarlayan bir lambda ifadesi iletin:
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: DraftAutomation = structure.automations().mapNotNull {
it.firstOrNull
{ automation -> automation.id == Id("automation-id") }
}.firstOrNull()
automation.update { this.name = "Flashing lights 2" }
update()
yöntemi, otomasyon grafiğinin tamamen değiştirilmesini destekler ancak grafikteki her bir düğümün ayrı ayrı düzenlenmesini desteklemez. Düğümler arası bağımlılıklar nedeniyle düğüm başına düzenleme hataya açıktır. Otomasyonun mantığını değiştirmek istiyorsanız yeni bir grafik oluşturun ve mevcut grafiği tamamen değiştirin.
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: Automation = structure.automations().mapNotNull {
it.firstOrNull
{ automation -> automation.id == Id("automation-id") }
}.firstOrNull()
automation.update {
this.automationGraph = sequential {
val laundryWasherCompletionEvent =
starter<_>(laundryWasher, LaundryWasherDevice, OperationCompletionEvent)
condition {
expression =
laundryWasherCompletionEvent.completionErrorCode equals
// UByte 0x00u means NoError
0x00u
}
action(speaker, SpeakerDevice) { command(AssistantBroadcast.broadcast("laundry is done")) }
}
}
}
Otomasyonu silme
Bir otomasyonu silmek için yapının deleteAutomation()
yöntemini kullanın. Otomasyonlar, kimlikleri kullanılarak silinmelidir.
import com.google.home.automation.Automation
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.HomeManager
import com.google.home.Id
import com.google.home.Structure
...
val structure = homeManager.structures().list().single()
val automation: DraftAutomation = structure.automations().first()
structure.deleteAutomation(automation.id)
Silme işlemi başarısız olursa HomeException
istisnası oluşturulabilir. Hata işleme bölümüne bakın.
Cihaz silme işleminin otomasyonlar üzerindeki etkisi
Bir kullanıcı, otomasyonda kullanılan bir cihazı silerse silinen cihaz herhangi bir başlatıcıyı tetikleyemez ve otomasyon, cihazdan özellikleri okuyamaz veya cihaza komut gönderemez. Örneğin, bir kullanıcı evinden OccupancySensorDevice
cihazını silerse ve bir otomasyonda OccupancySensorDevice
cihazına bağlı bir başlatıcı varsa bu başlatıcı artık otomasyonu etkinleştiremez.