راهنمای DSL اندروید

از راهنمای زیر برای درک چگونگی استفاده از گره‌های مختلف اتوماسیون DSL برای ساخت یک اتوماسیون استفاده کنید.

تمام DSL اتوماسیون در یک گره automation واحد قرار می‌گیرد. گره automation مرز بین متن زبان Kotlin بیرونی و متن DSL تعبیه‌شده را تشکیل می‌دهد.

جریان متوالی

جریان ترتیبی، نوع پیش‌فرض جریان اتوماسیون است.

مثال DSL متوالی

در اینجا یک الگوی 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 {...}
  }
}

این را می‌توان با اضافه کردن گره‌های اضافی اصلاح کرد.

استارتر

گره‌های آغازگر، شرایط اولیه‌ای را که یک اتوماسیون را فعال می‌کنند، تعریف می‌کنند. برای مثال، تغییر در وضعیت یا مقدار. یک اتوماسیون باید حداقل یک آغازگر داشته باشد، در غیر این صورت اعتبارسنجی آن با شکست مواجه می‌شود. برای اضافه کردن بیش از یک آغازگر به یک اتوماسیون، باید از یک گره select (select node) استفاده کنید.

شروع کننده بر اساس ویژگی صفت

هنگام اعلام یک گره آغازگر که مبتنی بر یک ویژگی trait است، موارد زیر را مشخص کنید:

  • دستگاه
  • نوع دستگاهی که ویژگی به آن تعلق دارد
  • صفت
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)

پارامتر نوع دستگاه الزامی است زیرا به شما امکان می‌دهد مشخص کنید که اتوماسیون به کدام نوع دستگاه در یک دستگاه آدرس‌دهی می‌کند. برای مثال، یک دستگاه ممکن است از یک FanDevice و یک HeatingCoolingUnitDevice تشکیل شده باشد که هر دو حاوی ویژگی OnOff هستند. با مشخص کردن نوع دستگاه، هیچ ابهامی در مورد اینکه کدام بخش از دستگاه، اتوماسیون را فعال می‌کند، وجود ندارد.

شروع کننده بر اساس رویداد

هنگام تعریف یک گره آغازگر که مبتنی بر یک رویداد است، موارد زیر را مشخص کنید:

  • دستگاه
  • نوع دستگاهی که ویژگی به آن تعلق دارد
  • رویداد
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)

شروع کننده بر اساس یک ساختار و رویداد، با پارامترها

برخی رویدادها می‌توانند پارامترهایی داشته باشند، بنابراین این پارامترها نیز باید در آغازگر گنجانده شوند.

برای مثال، این شروع‌کننده از ScheduledTimeEvent مربوط به ویژگی Time برای فعال کردن اتوماسیون در ساعت ۷:۰۰ صبح استفاده می‌کند:

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 باشد، اتوماسیون در آن نقطه اجرا را متوقف می‌کند.

عبارات مشابه عبارات در کاتلین ساخته می‌شوند و ممکن است شامل مقادیر اولیه مانند اعداد، کاراکترها، رشته‌ها و مقادیر بولی و همچنین مقادیر 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)
}

شما می‌توانید مقدار یک ویژگی (trait) که از طریق یک آغازگر (starter) قابل دسترسی است را ارجاع دهید:

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

stateReader

راه دیگر برای ارجاع به مقادیر ویژگی trait در یک گره condition ، استفاده از گره stateReader است.

برای انجام این کار، ابتدا مقدار ویژگی trait را در یک گره stateReader ثبت کنید. یک stateReader structure و trait را به عنوان آرگومان دریافت می‌کند:

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

سپس در گره condition به stateReader ارجاع دهید:

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 دقیقه متغیر باشد.

گره‌های عمل

گره action جایی است که کار اتوماسیون انجام می‌شود. در این مثال، action دستور broadcast() از ویژگی AssistantBroadcast را فراخوانی می‌کند:

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

وارد کردن اظهارات

هنگام توسعه اتوماسیون، همیشه مشخص نیست که چگونه عناصر مختلف API های Home را به کد خود وارد کنید.

ویژگی‌های صفت از شیء Companion مربوط به صفت وارد می‌شوند:

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

ساختارهای داده‌ای که توسط یک trait تعریف می‌شوند، از کلاس trait که نام آن به "-Trait" ختم می‌شود، وارد می‌شوند:

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

دستورات Trait از شیء Companion به trait وارد می‌شوند:

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