Panduan DSL Android untuk otomatisasi yang kompleks

Automation DSL dapat digunakan untuk membuat otomatisasi yang lebih kompleks daripada yang dibahas dalam panduan DSL - otomatisasi dasar di Android.

Berurutan dengan beberapa tindakan

Berurutan dengan beberapa tindakan

Otomatisasi dapat melakukan lebih dari satu hal. Misalnya, sebagai pengganti satu node action, Anda dapat memiliki beberapa node action, yang berjalan dalam urutan berurutan:

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

Berurutan dengan beberapa tindakan paralel

Berurutan dengan beberapa tindakan paralel

Jika Anda menempatkan beberapa node action dalam node parallel, tindakan akan dieksekusi secara bersamaan.

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

Jika ada node action di node sequential yang muncul setelah node parallel, node tersebut akan menunggu untuk dieksekusi hingga semua node dalam node parallel selesai dieksekusi.

Eksekusi kondisional

Secara default, otomatisasi mengeksekusi node secara berurutan atau paralel. Jika Anda memerlukan logika percabangan kondisional—mengeksekusi tindakan atau jalur yang berbeda berdasarkan kondisi runtime—gunakan pernyataan if-then-else, yang dibuat menggunakan blok DSL alur kontrol kondisional: ifThen, elseIf, dan orElse.

Meskipun node condition standar mengontrol seluruh otomatisasi (jika kondisi bernilai false, otomatisasi akan segera menghentikan eksekusi), blok ifThen memungkinkan alur kontrol percabangan:

  • Node condition: Menghentikan eksekusi seluruh otomatisasi (atau jalur eksekusi saat ini) jika ekspresinya adalah false.
  • ifThen / elseIf / orElse: Mengevaluasi kondisi secara berurutan. Jika kondisi adalah false, eksekusi akan diteruskan ke cabang elseIf berikutnya, cabang penggantian orElse, atau dilanjutkan ke node berikutnya dalam otomatisasi jika tidak ada kondisi yang terpenuhi.

Mengeksekusi tindakan berdasarkan kondisi

Blok ifThen mengevaluasi ekspresi kondisional. Jika ekspresi bernilai true, tindakan atau node DSL yang berada di dalam blok akan dieksekusi. Jika bernilai false, tindakan akan dilewati, dan otomatisasi akan dilanjutkan ke node berikutnya dalam alur berurutan.

Anda dapat menggunakan blok ifThen mandiri jika hanya ingin melakukan tindakan secara kondisional tanpa memblokir atau menghentikan node berikutnya dalam otomatisasi:

// When a door opens, turn on the light only if it is off,
// and always broadcast an announcement.
automation {
  sequential {
    val contactState = starter<_>(
      contactSensor,
      ContactSensorDevice,
      BooleanState,
    )
    val lightState = stateReader<_>(
      light,
      DimmableLightDevice,
      OnOff,
    )

    condition {
      // Door opened (contact sensor open)
      expression = contactState.stateValue equals false
    }

    // Conditionally turn on the light if it's off
    ifThen(lightState.onOff equals false) {
      action(light, DimmableLightDevice) { command(OnOff.on()) }
    }

    // Continue executing subsequent actions in the sequential flow
    action(structure) {
      command(AssistantBroadcast.broadcast("The door was opened."))
    }
  }
}

Mengeksekusi tindakan yang berbeda berdasarkan kondisi

Untuk mengeksekusi satu set tindakan saat kondisi benar dan set tindakan alternatif saat kondisi salah, gabungkan blok .orElse { ... } opsional setelah ifThen(...) { ... }:

// When the door is unlocked, turn on the entryway light if it is off;
// otherwise, broadcast a welcome message.
automation {
  sequential {
    val doorLockEvent = starter<_>(
      doorLock,
      DoorLockDevice,
      LockOperationEvent,
    )
    val lightState = stateReader<_>(
      light,
      DimmableLightDevice,
      OnOff,
    )

    condition {
      expression =
        doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock
    }

    ifThen(lightState.onOff equals false) {
      action(light, DimmableLightDevice) { command(OnOff.on()) }
    }.orElse {
      action(structure) {
        command(AssistantBroadcast.broadcast("Welcome home!"))
      }
    }
  }
}

Menggabungkan beberapa kondisi secara berurutan

Anda dapat menggabungkan satu atau beberapa blok .elseIf(...) { ... } opsional untuk mengevaluasi beberapa kondisi secara berurutan. Cabang pertama yang kondisinya bernilai true akan dieksekusi, dan semua cabang yang tersisa akan dilewati. Jika tidak ada kondisi yang bernilai true, blok .orElse { ... } opsional akan dieksekusi (jika disediakan):

// Adjust climate controls based on room temperature changes.
automation {
  sequential {
    val tempStarter = starter<_>(
      tempSensor,
      TemperatureSensorDevice,
      TemperatureMeasurement,
    )

    // If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
    ifThen(tempStarter.measuredValue greaterThanOrEquals 2800) {
      action(thermostat, ThermostatDevice) {
        command(
          SimplifiedThermostat.setSystemMode(
            SimplifiedThermostatSystemModeEnum.Cool
          )
        )
      }
    }.elseIf(tempStarter.measuredValue lessThan 1800) {
      // If temperature is low (< 18°C / 1800 mC), switch to Heat mode
      action(thermostat, ThermostatDevice) {
        command(
          SimplifiedThermostat.setSystemMode(
            SimplifiedThermostatSystemModeEnum.Heat
          )
        )
      }
    }.orElse {
      // Otherwise, turn on the fan
      action(fan, FanDevice) {
        command(OnOff.on())
      }
    }
  }
}

Alur kondisional bertingkat

Blok kondisional dapat disarangkan di dalam blok ifThen, elseIf, atau orElse lainnya, serta digabungkan dengan node parallel, delayFor, dan stateReader.

Blok ifThen, elseIf, dan orElse mengeksekusi kontennya sebagai alur berurutan. Anda dapat menempatkan node berurutan di dalam setiap cabang, termasuk blok action, stateReader, parallel, delayFor, dan ifThen bertingkat.

Keterlambatan

Anda dapat menambahkan jeda dalam otomatisasi menggunakan kata kunci delayFor, yang menggunakan argumen java.time.Duration yang menunjukkan durasi jeda sebelum melanjutkan eksekusi. Durasi jeda dapat sesingkat lima detik atau selama 24 jam.

Misalnya, untuk mengalihkan lampu empat kali dengan jeda lima detik di antara setiap pengalihan:

sequential {
  action(light, OnOffLightDevice) { command(OnOff.toggle()) }
  delayFor(Duration.ofSeconds(5))
  action(light, OnOffLightDevice) { command(OnOff.toggle()) }
  delayFor(Duration.ofSeconds(5))
  action(light, OnOffLightDevice) { command(OnOff.toggle()) }
  delayFor(Duration.ofSeconds(5))
  action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}

Pencegahan pemicu

Pencegahan pemicu adalah kemampuan yang memungkinkan otomatisasi Anda mengabaikan starter selama jangka waktu tertentu setelah peristiwa pemicu awal. Mis alnya, jika otomatisasi memiliki starter yang dipicu oleh deteksi gerakan, dan jika Anda menentukan durasi pencegahan pemicu selama lima menit, saat starter dipicu, tidak akan dipicu lagi selama lima menit berikutnya. Hal ini mencegah otomatisasi dipicu berulang kali dengan cepat.

Untuk menerapkan pencegahan pemicu ke otomatisasi, gunakan kata kunci suppressFor dengan argumen java.time.Duration yang menunjukkan durasi tunggu sebelum merespons pemicu berikutnya. Durasi pencegahan dapat sesingkat lima detik atau selama 24 jam.

automation {
  sequential {
    val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
    suppressFor(Duration.ofMinutes(30))
    action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}

Perhatikan bahwa pencegahan pemicu memengaruhi semua starters dalam otomatisasi yang mendahului suppressFor.

Membatasi jumlah eksekusi

Anda dapat membatasi jumlah otomatisasi yang diizinkan untuk dijalankan.

Misalnya, Anda mungkin ingin menyiapkan otomatisasi satu kali yang menjalankan penyedot debu saat Anda tidak berada di rumah selama sehari.

Untuk melakukannya, tetapkan kolom metadata otomatisasi maxExecutionCount. Contoh berikut adalah otomatisasi yang hanya dapat dieksekusi satu kali:

automation {
  // The automation can only be executed once.
  maxExecutionCount = 1
  // When the door lock state changes
  sequential {
    val doorLockEvent = starter<_>(doorLock, DoorLockDevice, LockOperationEvent)
    // if the door is unlocked
    condition() {
      expression = (doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock)
    }
    // turn the light on
    action(light, DimmableLightDevice) { command(OnOff.on()) }
  }
}

Otomatisasi akan segera dihapus setelah menyelesaikan eksekusi untuk terakhir kalinya dan maxExecutionCount tercapai. Entri histori otomatisasi tetap berada di tab Google Home app (GHA) Aktivitas, termasuk automation_id.

Menetapkan atribut karakteristik dalam tindakan

Untuk menetapkan nilai atribut karakteristik:

  1. Buat node update dalam node action, termasuk karakteristik yang relevan sebagai argumen ke node update:
    action(deviceReference, deviceType) {
      update(trait) {
    
      }
    }
  2. Dalam node update, untuk setiap atribut yang akan diubah, gunakan fungsi mutator, dan teruskan nilai baru. Untuk membentuk nama fungsi mutator:
    1. Kapitalisasi nama atribut
    2. Awali dengan kata set.
    Misalnya, untuk mengupdate atribut yang disebut defaultMoveRate, Anda akan menggunakan fungsi mutator yang disebut setDefaultMoveRate.

Perhatikan bahwa node update dapat memiliki beberapa fungsi mutator. Berikut adalah contoh saat dua atribut diupdate:

action(device, Fan) {
  update(FanControl) {
    setPercentSetting(50u)
    setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
  }
}