מדריך DSL - פעולות אוטומטיות בסיסיות

המדריך הבא יעזור לכם להבין איך אפשר להשתמש בצמתים שונים של Automation DSL כדי ליצור תהליך אוטומציה.

כל ה-DSL של האוטומציה ממוקם בצומת automation יחיד. הצומת automation יוצר את הגבול בין ההקשר החיצוני של שפת Kotlin לבין ההקשר של ה-DSL המוטמע.

תהליך עבודה רצוף

תהליך הפעולות האוטומטיות ברצף הוא סוג ברירת המחדל של תהליך הפעולות האוטומטיות.

דוגמה ל-DSL רצף

הנה תבנית בסיסי מאוד של Automation DSL שמשתמשת בתהליך רצוף שמורכב מגורם מפעיל, תנאי ופעולה:


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 {...}
  }
}

אפשר לשפר את הניתוח על ידי הוספת צמתים נוספים.

מתחילים

צמתים מעוררי תהליך מגדירים את הנסיבות הראשוניות שמפעילות תהליך אוטומציה. לדוגמה, שינוי במצב או בערך. תהליך אוטומציה חייב לכלול לפחות אירוע התחלה אחד, אחרת הוא לא יעמוד בתהליך האימות. כדי להוסיף יותר מ-starter אחד לתהליך אוטומציה, צריך להשתמש בצומת בחירה.

תבנית לתחילת העבודה שמבוססת על מאפיין של תכונה

כשמצהירים על צומת מתחיל שמבוסס על מאפיין של מאפיין, צריך לציין:

  • המכשיר
  • סוג המכשיר שאליו שייך המאפיין
  • המאפיין
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)

הפרמטר של סוג המכשיר נדרש כי הוא מאפשר לכם לציין את סוג המכשיר שבו המערכת האוטומטית מטפלת. לדוגמה, מכשיר יכול להיות מורכב מרכיב FanDevice ומרכיב HeatingCoolingUnitDevice, ושניהם מכילים את המאפיין OnOff. כשמציינים את סוג המכשיר, אין אי-בהירות לגבי החלק במכשיר שמפעיל את האוטומציה.

ערכת התחלה מבוססת-אירוע

כשמגדירים צומת מתחיל שמבוסס על אירוע, צריך לציין:

  • המכשיר
  • סוג המכשיר שאליו שייך המאפיין
  • האירוע
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)

ערכת התחלה שמבוססת על מבנה ואירוע, עם פרמטרים

לחלק מהאירועים יכולים להיות פרמטרים, ולכן צריך לכלול את הפרמטרים האלה גם ב-starter.

לדוגמה, ה-starter הזה משתמש ב-ScheduledTimeEvent של המאפיין Time כדי להפעיל את האוטומציה בשעה 7:00:

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

מפעיל ידני

אירוע התחלה ידני הוא סוג מיוחד של אירוע התחלה שמאפשר למשתמש להפעיל את האוטומציה באופן ידני.

כשמגדירים אירוע התחלה ידני:

  • אין לציין מאפיין או סוג מכשיר.
  • מספקים אלמנט בממשק המשתמש שמפעיל את Automation.execute().

כשמקימים התחלה ידנית בתהליך select יחד עם התחלה אחרת, ההתחלה הידנית מבטלת את ההתחלה האחרת:

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

חשוב לזכור שכל צמתים מסוג condition שמופיעים אחרי התחלה ידנית ייבדקו, ויכול להיות שהם ימנעו את ביצוע האוטומציה, בהתאם לביטוי condition.

הפרדה בין התחלה ידנית לבין התחלה מותנית

אחת מהדרכים לבנות את האוטומציה כך שצמתים של condition לא יחסמו אוטומציה שהופעל באמצעות מפעיל ידני היא להציב את המפעיל השני בתהליך רצוף נפרד, יחד עם ה-condition שלו:

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

הפניה לערך של מאפיין

כדי להשתמש בערך של מאפיין בביטוי, משתמשים בתחביר הבא.

עם stateReader:

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

עם starter:

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

צמתים וביטויים של תנאים

צומת תנאי מייצג נקודת החלטה שקובעת אם האוטומציה תמשיך או לא. לפעולה אוטומטית יכולים להיות כמה צמתים מסוג condition. אם ביטוי של צומת condition מקבל את הערך false, הביצוע של כל האוטומציה מסתיים.

בתוך צומת condition, אפשר לשלב כמה קריטריונים של תנאים באמצעות אופרטורים שונים, כל עוד הביטוי מקבל ערך בוליאני יחיד. אם הערך שמתקבל הוא true, התנאי מתקיים והאוטומציה ממשיכה את הביצוע של הצומת הבא. אם הערך הוא false, המערכת תפסיק להריץ את האוטומציה בשלב הזה.

הביטויים נוצרים באופן דומה לביטויים ב-Kotlin, ויכולים להכיל ערכים פרימיטיביים כמו מספרים, תווים, מחרוזות וערכים בוליאניים, וגם ערכים של Enum. קיבוץ של ביטויים משניים בסוגריים מאפשר לכם לקבוע את הסדר שבו הם ייבדקו.

הנה דוגמה ל-condition שמשלב כמה ביטויים משניים לביטוי אחד:

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)
}

אפשר להפנות לערך של מאפיין שגולשים ניגשים אליו דרך ערכת התחלה:

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

stateReader

הדרך השנייה להפנות לערכים של מאפייני המאפיינים בצומת condition היא באמצעות צומת stateReader.

כדי לעשות זאת, קודם צריך לתעד את ערך מאפיין המאפיין בצומת stateReader. הפונקציה stateReader מקבלת את structure ואת המאפיין כארגומנטים:

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

לאחר מכן, מפנים ל-stateReader בצומת condition:

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

באמצעות אופרטורים להשוואה ואופרטורים לוגיים, אפשר להשתמש במספר stateReaders בצומת condition:

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

משך התנאי

בנוסף לביטוי בוליאני בתנאי, אפשר לציין מסגרת זמן שבמהלכה הביטוי צריך להיות נכון כדי להפעיל את האוטומציה. לדוגמה, אפשר להגדיר תנאי שיופעל רק אם הנורה הייתה מופעלת במשך עשר דקות.

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

משך הזמן יכול לנוע בין דקה ל-30 דקות.

צמתים של פעולות

צומת הפעולה הוא המקום שבו מתבצעת העבודה של האוטומציה. בדוגמה הזו, הפעולה מפעילה את הפקודה broadcast() של המאפיין AssistantBroadcast:

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

ייבוא הצהרות

כשמפתחים תהליכים אוטומטיים, לא תמיד ברור איך לייבא לקוד רכיבים שונים של ממשקי ה-API של Home.

מאפייני המאפיין מיובאים מהאובייקט Companion של המאפיין:

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

מבנים של נתונים שמוגדרים על ידי מאפיין מיובאים ממערך המאפיינים ששמו מסתיים ב-'-Trait':

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

פקודות של מאפיינים מיובאות מהאובייקט Companion של המאפיין:

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