Automation API dapat diakses melalui Home API untuk Android, tetapi karena titik entri-nya melalui struktur, izin harus diberikan terlebih dahulu pada struktur sebelum dapat digunakan.
Setelah izin diberikan untuk struktur, impor paket ini ke aplikasi Anda:
import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id
import com.google.home.Structure
Struktur berisi
HasAutomations
antarmuka dengan metode khusus otomatisasi berikut:
| API | Deskripsi |
|---|---|
automations() |
Mencantumkan semua otomatisasi yang termasuk dalam struktur. Hanya otomatisasi yang Anda buat melalui Home API yang ditampilkan. |
createAutomation(automation) |
Membuat instance otomatisasi untuk struktur. |
deleteAutomation(automationId) |
Menghapus instance otomatisasi berdasarkan ID-nya. |
Membuat otomatisasi
Setelah membuat instance Home dan menerima izin dari pengguna, dapatkan struktur dan perangkat:
val structure = homeManager.structures().list().single()
val device = homeManager.devices().get(Id("myDevice"))!!
Kemudian, tentukan logika otomatisasi Anda menggunakan Automation DSL. Di Home API, otomatisasi direpresentasikan oleh antarmuka Automation. Antarmuka ini berisi kumpulan properti:
- Metadata, seperti nama dan deskripsi.
- Flag yang menunjukkan, misalnya, apakah otomatisasi dapat dieksekusi atau tidak.
- Daftar node yang berisi logika otomatisasi, yang disebut grafik otomatisasi, yang direpresentasikan oleh properti
automationGraph.
automationGraph, secara default, berjenis SequentialFlow, yang merupakan class yang berisi daftar node yang dieksekusi dalam urutan berurutan. Setiap node mewakili elemen otomatisasi, seperti pemicu, kondisi, atau tindakan.
Tetapkan name dan description untuk otomatisasi.
Pembuatan otomatisasi menetapkan flag isActive ke true secara default, sehingga Anda tidak perlu menetapkan flag ini secara eksplisit kecuali jika Anda awalnya ingin otomatisasi dinonaktifkan. Dalam skenario tersebut, tetapkan flag ke false selama pembuatan.
Antarmuka DraftAutomation digunakan untuk membuat dan membuat otomatisasi,
dan antarmuka Automation digunakan untuk pengambilan. Misalnya, berikut adalah Automation DSL untuk otomatisasi yang mengaktifkan perangkat saat perangkat lain diaktifkan:
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()) }
}
}
Setelah Automation DSL ditentukan, teruskan ke
createAutomation()
metode untuk membuat instance DraftAutomation:
val createdAutomation = structure.createAutomation(automation)
Dari sini, Anda dapat menggunakan semua metode otomatisasi lainnya pada otomatisasi, seperti execute(), stop(), dan update().
Error validasi
Jika pembuatan otomatisasi tidak lulus validasi, pesan peringatan atau error akan memberikan informasi tentang masalah tersebut. Untuk mengetahui informasi selengkapnya, lihat referensi
ValidationIssueType.
Contoh kode
Di sini, kami menyajikan beberapa contoh kode yang dapat digunakan untuk mengimplementasikan bagian dari otomatisasi hipotetis yang dijelaskan di halaman Mendesain otomatisasi di Android.
Otomatisasi sederhana
Otomatisasi yang menaikkan tirai pada pukul 08.00 dapat diimplementasikan seperti ini:
// 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.
}
Otomatisasi kompleks
Otomatisasi yang memicu lampu berkedip saat gerakan terdeteksi dapat diimplementasikan seperti ini:
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())}
}
}
}
}
Memilih perangkat secara dinamis dengan filter entity
Saat menulis otomatisasi, Anda tidak terbatas untuk menentukan perangkat tertentu. Fitur yang disebut filter entity memungkinkan otomatisasi Anda memilih perangkat saat runtime berdasarkan berbagai kriteria.
Misalnya, menggunakan filter entity, otomatisasi Anda dapat menargetkan:
- semua perangkat dari jenis perangkat tertentu
- semua perangkat di ruangan tertentu
- semua perangkat dari jenis perangkat tertentu di ruangan tertentu
- semua perangkat yang diaktifkan
- semua perangkat yang diaktifkan di ruangan tertentu
Untuk menggunakan filter entity:
- Di
StructureatauRoom, panggilatExecutionTime(). Tindakan ini akan menampilkanTypedExpression<TypedEntity<StructureType>>. - Pada objek ini, panggil
getDevicesOfType(), dan teruskanDeviceType.
Filter entity dapat digunakan dalam pemicu, pembaca status, dan tindakan.
Misalnya, agar Lampu On/Off memicu otomatisasi dari pemicu:
// If any light is turned on or off val starter = starter( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, )
Untuk mengambil status OnOff semua lampu dalam struktur (khususnya, lampu On/Off) di pembaca status:
// Build a Map<Entity, OnOff> val onOffStateOfAllLights = stateReader( entityExpression = structure.atExecutionTime().getDevicesOfType(OnOffLightDevice), trait = OnOff, )
Untuk mendapatkan lampu di ruangan tertentu dan menggunakannya dalam kondisi:
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 } }
Saat runtime:
| Skenario | Hasil |
|---|---|
| Tidak ada perangkat yang memenuhi kriteria dalam pemicu. | Otomatisasi tidak dipicu. |
| Tidak ada perangkat yang memenuhi kriteria dalam pembaca status. | Otomatisasi dimulai, tetapi akan terus berlanjut berdasarkan node kondisi. |
| Tidak ada perangkat yang memenuhi kriteria dalam tindakan. | Otomatisasi dimulai, tetapi tindakan tidak melakukan apa pun. |
Contoh berikut adalah otomatisasi yang mematikan semua lampu kecuali lampu lorong setiap kali lampu individual dimatikan:
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()) } } }
Menjalankan otomatisasi
Jalankan otomatisasi yang dibuat menggunakan metode
execute():
createdAutomation.execute()
Jika otomatisasi memiliki a
pemicu manual, execute()
memulai otomatisasi dari titik tersebut, dengan mengabaikan semua node yang mendahului
pemicu manual. Jika otomatisasi tidak memiliki pemicu manual, eksekusi akan dimulai dari node yang mengikuti node pemicu pertama.
Jika operasi execute() gagal, HomeException mungkin akan ditampilkan. Lihat Penanganan error.
Menghentikan otomatisasi
Hentikan otomatisasi yang sedang berjalan menggunakan metode stop():
createdAutomation.stop()
Jika operasi stop() gagal, HomeException mungkin akan ditampilkan. Lihat Penanganan error.
Mendapatkan daftar otomatisasi untuk struktur
Otomatisasi ditentukan di tingkat struktur. Kumpulkan struktur's
automations()
untuk mengakses Flow otomatisasi:
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"))
}
}
Atau, tetapkan ke Collection lokal:
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()
Mendapatkan otomatisasi berdasarkan ID
Untuk mendapatkan otomatisasi berdasarkan ID otomatisasi, panggil metode
automations()
pada struktur, dan cocokkan berdasarkan ID:
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()
Respons:
// 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")
]))
Mendapatkan otomatisasi berdasarkan nama
Metode
filter()
di Kotlin dapat digunakan untuk lebih menyempurnakan panggilan API. Untuk mendapatkan otomatisasi berdasarkan nama, dapatkan otomatisasi struktur dan filter berdasarkan nama otomatisasi:
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") }
Mendapatkan semua otomatisasi untuk perangkat
Untuk mendapatkan semua otomatisasi yang mereferensikan perangkat tertentu, gunakan pemfilteran bertingkat untuk memindai automationGraph setiap otomatisasi:
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
}
}
}
Mengupdate otomatisasi
Untuk mengupdate metadata otomatisasi, panggil
update()
metodenya, dan teruskan ekspresi lambda yang menetapkan metadata:
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" }
Metode update()
mendukung penggantian grafik otomatisasi sepenuhnya, tetapi tidak mendukung pengeditan grafik per node. Pengeditan per node rentan error karena interdependensi node. Jika Anda ingin mengubah logika otomatisasi, buat grafik baru dan ganti sepenuhnya grafik yang ada.
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")) }
}
}
}
Menghapus otomatisasi
Untuk menghapus otomatisasi, gunakan metode
deleteAutomation()
struktur. Otomatisasi harus dihapus menggunakan ID-nya.
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)
Jika penghapusan gagal, HomeException mungkin akan ditampilkan. Lihat Penanganan error.
Dampak penghapusan perangkat pada otomatisasi
Jika pengguna menghapus perangkat yang digunakan dalam otomatisasi, perangkat yang dihapus tidak dapat memicu pemicu apa pun, dan otomatisasi tidak akan dapat membaca atribut dari perangkat tersebut, atau mengeluarkan perintah ke perangkat tersebut. Misalnya, jika pengguna menghapus
OccupancySensorDevice
dari rumahnya, dan otomatisasi memiliki pemicu yang bergantung pada
the OccupancySensorDevice, pemicu tersebut tidak dapat lagi mengaktifkan otomatisasi.