Panduan DSL - otomatisasi dasar

Gunakan panduan berikut untuk memahami cara berbagai node DSL Otomatisasi dapat digunakan untuk membuat otomatisasi.

Semua DSL otomatisasi ditempatkan dalam satu node automation. Node automation membentuk batas antara konteks bahasa Kotlin luar dan konteks DSL tersemat.

Alur berurutan

Alur berurutan adalah jenis alur otomatisasi default.

Contoh DSL sekuensial

Berikut adalah template DSL Otomatisasi yang sangat mendasar yang menggunakan alur berurutan yang terdiri dari pemicu, kondisi, dan tindakan:


import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.condition
import com.google.home.automation.sequential
import com.google.home.automation.starter

...

automation {
  sequential {
    starter<_>(...)
    condition {...}
    action {...}
  }
}

Hal ini dapat ditingkatkan dengan menambahkan node tambahan.

Starter

Node pemicu menentukan keadaan awal yang mengaktifkan otomatisasi. Misalnya, perubahan status atau nilai. Otomatisasi harus memiliki minimal satu pemicu, jika tidak, validasi akan gagal. Untuk menambahkan lebih dari satu pemicu ke otomatisasi, Anda harus menggunakan node pilih.

Pemicu berdasarkan atribut sifat

Saat mendeklarasikan node awal yang didasarkan pada atribut sifat, tentukan:

  • perangkat
  • jenis perangkat tempat sifat berada
  • sifat
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)

Parameter jenis perangkat diperlukan karena memungkinkan Anda menentukan jenis perangkat dalam perangkat yang dialamatkan otomatisasi. Misalnya, perangkat mungkin terdiri dari FanDevice dan HeatingCoolingUnitDevice, yang keduanya berisi sifat OnOff. Dengan menentukan jenis perangkat, tidak ada ambiguitas tentang bagian perangkat mana yang memicu otomatisasi.

Pemicu berdasarkan peristiwa

Saat mendeklarasikan node awal yang didasarkan pada peristiwa, tentukan:

  • perangkat
  • jenis perangkat tempat sifat berada
  • peristiwa
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)

Pemicu berdasarkan struktur dan peristiwa, dengan parameter

Beberapa peristiwa dapat memiliki parameter, sehingga parameter ini juga perlu disertakan dalam pemicu.

Misalnya, pemicu ini menggunakan ScheduledTimeEvent dari sifat Time untuk mengaktifkan otomatisasi pada pukul 07.00:

val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
  parameter(Time.ScheduledTimeEvent.clockTime(
    LocalTime.of(7, 0, 0, 0)))
}

Pemicu manual

Pemicu manual adalah jenis pemicu khusus yang memungkinkan pengguna menjalankan otomatisasi secara manual.

Saat mendeklarasikan pemicu manual:

  • Jangan menentukan jenis perangkat atau karakteristik.
  • Berikan elemen UI yang memanggil Automation.execute().

Saat menempatkan pemicu manual dalam alur select bersama dengan pemicu lain, pemicu manual akan menggantikan pemicu lain:

select {
  manualStarter()
  starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}

Perhatikan bahwa setiap node condition yang mengikuti pemicu manual akan dievaluasi, dan dapat memblokir eksekusi otomatisasi, bergantung pada ekspresi condition.

Memisahkan pemicu manual dari kondisional

Salah satu cara untuk menyusun otomatisasi agar node condition tidak memblokir otomatisasi yang diaktifkan dengan pemicu manual adalah dengan menempatkan pemicu lain dalam alur berurutan terpisah beserta condition-nya:

automation_graph {
  sequential {
    select {
      sequential {
        starter<_>(...)
        condition {...}
      }
      sequential {
        manualStarter()
      }
    }
    action {...}
  }
}

Mereferensikan nilai atribut

Untuk menggunakan nilai atribut dalam ekspresi, gunakan sintaksis berikut.

Dengan stateReader:

val time = stateReader<_>(structure, Structure, Time)
val currTime = time.currentTime

Dengan starter:

val starterNode = starter<_>(device1, LaundryWasherDevice, OnOff)
condition() {
  expression = starterNode.onOff equals true
}

Node dan ekspresi kondisi

Node kondisi mewakili titik keputusan yang menentukan apakah otomatisasi berlanjut atau tidak. Otomatisasi dapat memiliki beberapa node condition. Jika ekspresi node condition dievaluasi menjadi false, eksekusi seluruh otomatisasi akan berakhir.

Dalam node condition, Anda dapat menggabungkan beberapa kriteria kondisi menggunakan berbagai operator, selama ekspresi dievaluasi menjadi satu nilai boolean. Jika nilai yang dihasilkan adalah true, kondisi terpenuhi dan otomatisasi melanjutkan eksekusi node berikutnya. Jika false, otomatisasi akan berhenti dieksekusi pada saat itu.

Ekspresi dibentuk mirip dengan ekspresi di Kotlin, dan dapat berisi nilai primitif seperti angka, karakter, string, dan boolean, serta nilai Enum. Dengan mengelompokkan subekspresi menggunakan tanda kurung, Anda dapat mengontrol urutan evaluasinya.

Berikut adalah contoh condition yang menggabungkan beberapa subekspresi menjadi satu ekspresi:

condition() {
  val expr1 = starterNode.lockState equals DlLockState.Unlocked
  val expr2 = stateReaderNode.lockState equals true

  val expr3 = occupancySensingDevice.occupied notEquals 0
  val expr4 = timeStateReaderNode
    .currentTime
    .between(
      timeStateReaderNode.sunsetTime,
      timeStateReaderNode.sunriseTime)
  expression = (expr1 and expr2) or (expr3 and expr4)
}

Anda dapat mereferensikan nilai sifat yang diakses melalui pemicu:

val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }

stateReader

Cara lain untuk mereferensikan nilai atribut sifat di node condition adalah dengan node stateReader.

Untuk melakukannya, tangkap nilai atribut sifat terlebih dahulu di node stateReader. stateReader menggunakan structure dan sifat sebagai argumen:

import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)

Kemudian, referensikan stateReader di node condition:

condition() {
  expression =
    filterMonitoringState.changeIndication
      .equals(ChangeIndicationEnum.Warning)
}

Dengan menggunakan perbandingan dan operator logis, beberapa stateReaders dapat digunakan di node condition:

val armState = stateReader<_>(doorLock, DoorLockDevice, ArmDisarm )
val doorLockState = stateReader<_>(doorLock, DoorLockDevice, DoorLock)
condition() {
  expression =
    (armState.armState equals true)
    and
    (doorLockState.lockState equals true)
}

Durasi kondisi

Selain ekspresi boolean dalam kondisi, Anda dapat menentukan jangka waktu saat ekspresi harus benar untuk menjalankan otomatisasi. Misalnya, Anda dapat menentukan kondisi yang hanya diaktifkan jika lampu telah menyala selama sepuluh menit.

  condition {
    expression(lightStateReader.onOff == true)
    forDuration(Duration.ofMinutes(10))
  }

Durasinya dapat berkisar dari satu hingga 30 menit.

Node tindakan

Node tindakan adalah tempat kerja otomatisasi berlangsung. Dalam contoh ini, tindakan memanggil perintah broadcast() dari sifat AssistantBroadcast:

action(device, SpeakerDevice) {
  command(AssistantBroadcast.broadcast("Intruder detected!"))
}

Pernyataan impor

Saat mengembangkan otomatisasi, cara mengimpor berbagai elemen Home API ke dalam kode Anda tidak selalu jelas.

Atribut sifat diimpor dari objek Companion sifat:

import com.google.home.matter.standard.OnOff.Companion.onOff

Struktur data yang ditentukan oleh sifat diimpor dari class sifat yang namanya diakhiri dengan "-Trait":

import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum

Perintah ciri diimpor dari objek Companion ciri:

import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold