راهنمای DSL اندروید برای اتوماسیون های پیچیده

از Automation DSL می‌توان برای ایجاد اتوماسیون‌هایی پیچیده‌تر از مواردی که در راهنمای DSL - اتوماسیون‌های پایه در اندروید - مورد بحث قرار گرفته است، استفاده کرد.

متوالی با چندین اقدام

متوالی با چندین اقدام

یک اتوماسیون می‌تواند بیش از یک کار انجام دهد. برای مثال، به جای یک گره 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 حذف می‌شود. ورودی تاریخچه اتوماسیون، از جمله automation_id ، در تب Activity Google Home app (GHA) باقی می‌ماند.

ویژگی‌های صفت را در یک عمل تنظیم کنید

برای تنظیم مقدار یک ویژگی صفت:

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

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

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