راهنمای Android 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، باقی می‌ماند.

تنظیم مشخصه‌های ویژگی در کنش

برای تنظیم مقدار مشخصه ویژگی:

  1. گره update را در گره action ایجاد کنید، ازجمله ویژگی مربوطه به‌عنوان آرگومان گره update:
    action(deviceReference, deviceType) {
      update(trait) {
    
      }
    }
  2. در گره update، برای هر ویژگی که باید اصلاح شود، از تابع جهش‌دهنده استفاده کنید و مقدار جدید را به آن منتقل کنید. برای تشکیل نام تابع جهش‌دهنده:
    1. نام مشخصه را با حروف بزرگ بنویسید
    2. آن را با کلمه set پیشوند کنید.
    برای مثال، برای به‌روزرسانی مشخصه‌ای به‌نام defaultMoveRate، از تابع جهش‌دهنده به‌نام setDefaultMoveRate استفاده می‌کنید.

توجه داشته باشید که یک گره update می‌تواند چندین تابع جهش‌دهنده داشته باشد. در اینجا مثالی از به‌روزرسانی دو مشخصه آورده شده است:

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