از DSL خودکارسازی میتوان برای ایجاد خودکارسازیهایی استفاده کرد که پیچیدهتر از موارد بحثشده در راهنمای DSL - خودکارسازیهای پایه در Android هستند.
متوالی با چند کنش
خودکارسازی میتواند بیشاز یک کار انجام دهد. برای مثال، بهجای یک گره action، میتوانید چند گره action داشته باشید که بهصورت متوالی اجرا میشوند:
automation {
sequential {
starter<_>(...)
condition {...}
action {...}
action {...}
action {...}
}
}
متوالی با چند کنش موازی
اگر چند گره action را در یک گره parallel قرار دهید، کنشها بهطور همزمان اجرا میشوند.
automation {
sequential {
starter<_>(...)
condition {...}
parallel {
action {...}
action {...}
action {...}
}
}
}
اگر action گره در گره sequential وجود داشته باشد که بعداز گره parallel قرار گرفته باشد،
این گرهها تا زمانی که اجرای همه گرههای موجود در گره parallel بهپایان نرسد،
برای اجرا منتظر میمانند.
اجرای مشروط
بهطور پیشفرض، خودکارسازی گرهها را بهصورت متوالی یا موازی اجرا میکند. اگر به منطق انشعاب شرطی نیاز دارید (اجرای کنشها یا مسیرهای مختلف براساس شرایط زمان اجرا)، از عبارتهای if-then-else استفاده کنید که بااستفاده از بلوکهای DSL جریان کنترل شرطی ساخته میشوند:
ifThen،
elseIf،
و
orElse.
درحالیکه یک گره استاندارد condition کل خودکارسازی را کنترل میکند (اگر شرط
به false ارزیابی شود، خودکارسازی فوراً اجرا را متوقف میکند)، بلوکهای ifThen
امکان کنترل جریان انشعاب را فراهم میکنند:
- گره
condition: اگر عبارتfalseباشد، اجرای کل خودکارسازی (یا مسیر اجرای فعلی) را متوقف میکند. ifThen/elseIf/orElse: شرایط را بهترتیب ارزیابی میکند. اگر شرطیfalseباشد، اجرا به شاخهelseIfبعدی، شاخه احتیاطیorElseمنتقل میشود، یا اگر هیچ شرطی برآورده نشود، به گرههای بعدی در خودکارسازی ادامه میدهد.
اجرای کنش براساس شرط
بلوک ifThen عبارت شرطی را ارزیابی میکند. اگر عبارت
به true ارزیابی شود، کنشها یا گرههای DSL تودرتو در بلوک
اجرا میشوند. اگر نتیجه ارزیابی false باشد، کنشها نادیده گرفته میشوند و
خودکارسازی به گرههای بعدی در جریان ترتیبی ادامه میدهد.
وقتی میخواهید کنشی را بهطور مشروط انجام دهید بدون اینکه گرههای بعدی را در خودکارسازی مسدود یا متوقف کنید، میتوانید از بلوک مستقل ifThen استفاده کنید:
// 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."))
}
}
}
اجرای کنشهای مختلف براساس یک شرط
برای اجرای یک مجموعه کنش درصورت درست بودن شرط و مجموعه کنشهای جایگزین درصورت نادرست بودن آن، بلوک اختیاری .orElse { ... } را بعداز 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!"))
}
}
}
}
زنجیر کردن چند شرط بهصورت متوالی
میتوانید یک یا چند بلوک اختیاری .elseIf(...) { ... } را بهصورت زنجیرهای اضافه کنید تا چند شرط را بهترتیب ارزیابی کنید. اولین شاخهای که شرط آن به true ارزیابی میشود اجرا میشود و از همه شاخههای باقیمانده صرفنظر میشود. اگر هیچکدام از شرایط
به true ارزیابی نشود، یک بلوک اختیاری .orElse { ... } اجرا میشود (درصورت ارائه):
// 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())
}
}
}
}
جریانهای مشروط تودرتو
بلوکهای شرطی را میتوان در داخل بلوکهای ifThen، elseIf، یا orElse دیگر تودرتو کرد، و همچنین با گرههای parallel، delayFor، و stateReader ترکیب کرد.
بلوکهای ifThen، elseIf، و orElse محتوایشان را بهصورت جریانهای متوالی اجرا میکنند. میتوانید هر گره متوالی را در هر شاخه قرار دهید، ازجمله
بلوکهای action، stateReader، parallel، delayFor، و ifThen تودرتو.
تأخیر
میتوانید بااستفاده از کلیدواژه
delayFor
در خودکارسازیهایتان مکث ایجاد کنید. این کلیدواژه آرگومان
java.time.Duration
را میگیرد که نشاندهنده مدتزمان مکث قبلاز ادامه اجرا است. مدت توقف میتواند از پنج ثانیه تا ۲۴ ساعت باشد.
برای مثال، برای چهار بار روشن و خاموش کردن چراغ با مکث پنج ثانیهای بین هر بار روشن و خاموش کردن:
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()) }
}
راهانداز سرکوب
سرکوب راهانداز قابلیتی است که به خودکارسازی شما اجازه میدهد
starter را برای مدتزمان مشخصی پساز رویداد راهانداز اولیه نادیده بگیرد. برای
مثال، اگر خودکارسازی دارای starter باشد که با تشخیص حرکت راهاندازی میشود،
و اگر مدتزمان توقف راهانداز را پنج دقیقه تعیین کنید، وقتی
starter راهاندازی شود، تا پنج دقیقه بعد دوباره راهاندازی نخواهد شد. این کار
از راهاندازی سریع و مکرر خودکارسازی جلوگیری میکند.
برای اعمال کردن توقف راهانداز در خودکارسازی، از کلیدواژه
suppressFor
با شناسه
java.time.Duration
استفاده کنید که نشاندهنده مدت زمان انتظار قبلاز پاسخ دادن به راهاندازهای بعدی است.
مدتزمان توقف ممکن است کوتاه و در حد پنج ثانیه یا طولانی و تا ۲۴ ساعت باشد.
automation {
sequential {
val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
suppressFor(Duration.ofMinutes(30))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
توجه داشته باشید که توقف موقت راهانداز بر همه starters در خودکارسازیای که
پیشاز suppressFor است تأثیر میگذارد.
محدود کردن تعداد اجراها
میتوانید تعداد دفعاتی را که خودکارسازی مجاز به اجرا است محدود کنید.
برای مثال، شاید بخواهید خودکارسازی یکبارهای راهاندازی کنید که وقتی در طول روز خانه نیستید، جاروبرقی را روشن کند.
برای انجام این کار، فیلد فراداده
maxExecutionCount
خودکارسازی را تنظیم کنید.
مثال زیر خودکارسازیای است که فقط یکبار میتواند اجرا شود:
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()) } } }
خودکارسازی بلافاصله پساز تکمیل اجرا برای آخرین بار و رسیدن به maxExecutionCount حذف میشود. ورودی سابقه خودکارسازی در زبانه Google Home app (GHA) فعالیت باقی میماند، ازجمله automation_id.
تنظیم مشخصههای ویژگی در کنش
برای تنظیم مقدار مشخصه ویژگی:
- یک گره
updateدر گرهactionایجاد کنید، و ویژگی مربوطه را بهعنوان آرگومان به گرهupdateاضافه کنید:action(deviceReference, deviceType) { update(trait) { } } - در گره
update، برای هر مشخصهای که باید اصلاح شود، از تابع جهشدهنده استفاده کنید و مقدار جدید را به آن منتقل کنید. برای تشکیل نام تابع تغییردهنده:- نام مشخصه را با حروف بزرگ بنویسید
- پیشوند آن را با کلمه
setشروع کنید.
defaultMoveRate، از تابع جهشدهندهای بهنامsetDefaultMoveRateاستفاده میکنید.
توجه داشته باشید که یک گره update میتواند چندین تابع جهشدهنده داشته باشد. در اینجا مثالی آورده شده است که در آن دو مشخصه بهروزرسانی شدهاند:
action(device, Fan) {
update(FanControl) {
setPercentSetting(50u)
setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
}
}