Automation API dapat diakses melalui Home API untuk Android, tetapi karena titik masuknya 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 antarmuka
HasAutomations
dengan metode khusus otomatisasi berikut:
API | Deskripsi |
---|---|
automations() |
Mencantumkan semua otomatisasi yang termasuk dalam struktur. Hanya otomatisasi yang telah Anda buat melalui Home API yang ditampilkan. |
createAutomation(automation) |
Buat instance otomatisasi untuk struktur. |
deleteAutomation(automationId) |
Menghapus instance otomatisasi menurut 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 serangkaian properti:
- Metadata, seperti nama dan deskripsi.
- Tanda yang menunjukkan, misalnya, apakah otomatisasi dapat dieksekusi atau tidak.
- Daftar node yang berisi logika otomatisasi, yang disebut
grafik otomatisasi, yang diwakili 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 secara default menetapkan flag isActive
ke true
, sehingga
tidak perlu menetapkan flag ini secara eksplisit kecuali jika Anda awalnya ingin
otomatisasi dinonaktifkan. Dalam skenario tersebut, tetapkan tanda ke false
selama
pembuatan.
Antarmuka DraftAutomation
digunakan untuk membangun dan membuat otomatisasi,
dan antarmuka Automation
digunakan untuk pengambilan. Misalnya, berikut adalah
DSL Otomatisasi 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 DSL otomatisasi ditentukan, teruskan ke metode
createAutomation()
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 menerapkan bagian dari otomatisasi hipotetis yang dijelaskan di halaman Mendesain otomatisasi di Android.
Otomatisasi sederhana
Otomatisasi yang menaikkan tirai pada pukul 08.00 dapat diterapkan 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 yang kompleks
Otomatisasi yang memicu lampu berkedip saat gerakan terdeteksi dapat diterapkan 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 entitas
Saat menulis otomatisasi, Anda tidak terbatas pada penentuan perangkat tertentu. Fitur yang disebut filter entitas memungkinkan otomatisasi Anda memilih perangkat saat runtime berdasarkan berbagai kriteria.
Misalnya, menggunakan filter entitas, otomatisasi Anda dapat menargetkan:
- semua perangkat dari jenis perangkat tertentu
- semua perangkat di ruangan tertentu
- semua perangkat dari jenis perangkat tertentu di ruang tertentu
- semua perangkat yang diaktifkan
- semua perangkat yang diaktifkan di ruangan tertentu
Untuk menggunakan filter entitas:
- Di
Structure
atauRoom
, panggilatExecutionTime()
. Tindakan ini akan menampilkanTypedExpression<TypedEntity<StructureType>>
. - Pada objek ini, panggil
getDevicesOfType()
, dengan meneruskanDeviceType
.
Filter entitas 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 merekam status OnOff
semua lampu dalam struktur (khususnya,
Lampu Nyala/Mati) 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 di pembaca status. | Otomatisasi dimulai, tetapi tidak melakukan apa pun. |
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 satu lampu 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
pemicu manual, execute()
memulai otomatisasi dari titik tersebut, dengan mengabaikan semua node yang mendahului
pemicu manual. Jika otomatisasi tidak memiliki pemicu manual, eksekusi
dimulai dari node setelah node pemicu pertama.
Jika operasi execute()
gagal, HomeException
dapat ditampilkan. Lihat Penanganan
error.
Menghentikan otomatisasi
Hentikan otomatisasi yang sedang berjalan menggunakan metode stop()
:
createdAutomation.stop()
Jika operasi stop()
gagal, HomeException
dapat ditampilkan. Lihat Penanganan
error.
Mendapatkan daftar otomatisasi untuk struktur
Otomatisasi ditentukan di tingkat struktur. Kumpulkan di struktur
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 menurut ID
Untuk mendapatkan otomatisasi menurut ID otomatisasi, panggil metode
automations()
pada struktur, dan cocokkan 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
}
}
}
Memperbarui otomatisasi
Untuk memperbarui metadata otomatisasi, panggil metode
update()
dengan meneruskan 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 terhadap error karena saling ketergantungan 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
dapat 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 darinya, atau mengeluarkan perintah ke perangkat tersebut. Misalnya, jika pengguna menghapus
OccupancySensorDevice
dari rumahnya, dan otomatisasi memiliki pemicu yang bergantung pada
OccupancySensorDevice
, pemicu tersebut tidak dapat lagi mengaktifkan otomatisasi.