راهنمای iOS DSL

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

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

جریان متوالی

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

مثال DSL متوالی

در اینجا یک الگوی DSL اتوماسیون بسیار ابتدایی وجود دارد که از یک جریان ترتیبی متشکل از یک شروع‌کننده، یک شرط و یک عمل استفاده می‌کند:

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {
  starter(...)
  condition {...}
  action {...}
}

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

استارتر

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

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

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

  • دستگاه
  • نوع دستگاهی که ویژگی به آن تعلق دارد
  • صفت
starter(
  thermostat,
  Matter.TemperatureSensorDeviceType.self,
  Matter.TemperatureMeasurementTrait.self
)

پارامتر نوع دستگاه الزامی است زیرا به شما امکان می‌دهد مشخص کنید کدام نوع دستگاه در یک دستگاه، آدرس‌دهی خودکار را انجام می‌دهد. برای مثال، یک دستگاه ممکن است از یک FanDeviceType و یک HeatingCoolingUnitDeviceType تشکیل شده باشد که هر دو حاوی ویژگی OnOffTrait هستند. با مشخص کردن نوع دستگاه، هیچ ابهامی در مورد اینکه کدام بخش از دستگاه، خودکارسازی را آغاز می‌کند، وجود ندارد.

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

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

  • دستگاه
  • نوع دستگاهی که ویژگی به آن تعلق دارد
  • رویداد
starter(
  doorbell,
  Google.GoogleDoorbellDeviceType.self,
  Google.DoorbellPressTrait.DoorbellPressedEvent
)

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

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

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

typealias TimeTrait = Google.TimeTrait

let earlyMorning = starter(
  structure,
  TimeTrait.ScheduledEvent.self
) {
  TimeTrait.ScheduledEvent.clockTime(TimeOfDay(hours: 7, minutes: 0))
}

استارت دستی

استارتر دستی نوع خاصی از استارتر است که به کاربر اجازه می‌دهد اتوماسیون را به صورت دستی اجرا کند.

هنگام اعلام استارت دستی:

  • نوع یا ویژگی دستگاه را مشخص نکنید.
  • یک عنصر رابط کاربری ارائه دهید که Automation.execute() را فراخوانی کند.

هنگام قرار دادن یک استارتر دستی در یک جریان select به همراه یک استارتر دیگر، استارتر دستی بر استارتر دیگر غلبه می‌کند:

select {
  manualStarter()
  starter(
    thermostat,
    Matter.TemperatureSensorDeviceType.self,
    Matter.TemperatureMeasurementTrait.self
  )
}

توجه داشته باشید که هر گره condition که پس از یک شروع‌کننده دستی قرار گیرد، ارزیابی خواهد شد و بسته به عبارت condition ، می‌تواند اجرای اتوماسیون را مسدود کند.

جدا کردن یک استارت دستی از یک استارت مشروط

یک راه برای ساختاردهی اتوماسیون به گونه‌ای که گره‌های condition ، اتوماسیونی را که با یک استارتر دستی فعال شده است، مسدود نکنند، قرار دادن استارتر دیگر در یک جریان ترتیبی جداگانه به همراه condition آن است:

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {

  select {
    sequential {
      starter(...)
      condition {...}
    }
    sequential {
      manualStarter()
    }
  }
  action {...}

}

ارجاع به مقدار یک ویژگی

برای استفاده از مقدار یک ویژگی در یک عبارت، از سینتکس زیر استفاده کنید.

با یک stateReader :

typealias TimeTrait = Google.TimeTrait

let time = stateReader(structure, TimeTrait.self)
time
let currTime = time.currentTime

با یک starter :

typealias LaundryWasherDeviceType = Matter.LaundryWasherDeviceType
typealias OnOffTrait = Google.OnOffTrait

let starterNode = starter(device1, LaundryWasherDeviceType.self, OnOffTrait.self)
starterNode
condition {
  starterNode.onOff.equals(true)
}

گره‌ها و عبارات شرطی

یک گره شرط، نشان‌دهنده‌ی یک نقطه‌ی تصمیم‌گیری است که تعیین می‌کند آیا اتوماسیون ادامه پیدا می‌کند یا خیر. یک اتوماسیون می‌تواند چندین گره condition داشته باشد. اگر عبارت هر گره condition ، false ارزیابی شود، اجرای کل اتوماسیون پایان می‌یابد.

در یک گره condition ، می‌توانید چندین معیار شرط را با استفاده از عملگرهای مختلف ترکیب کنید، تا زمانی که عبارت به یک مقدار بولی واحد ارزیابی شود. اگر مقدار حاصل true باشد، شرط برآورده شده و اتوماسیون اجرای گره بعدی را ادامه می‌دهد. اگر false باشد، اتوماسیون در آن نقطه اجرا را متوقف می‌کند.

عبارات مشابه عبارات در سوئیفت ساخته می‌شوند و ممکن است شامل مقادیر اولیه مانند اعداد، کاراکترها، رشته‌ها و مقادیر بولی و همچنین مقادیر شمارشی باشند. گروه‌بندی زیرعبارات با پرانتز به شما امکان می‌دهد ترتیب ارزیابی آنها را کنترل کنید.

در اینجا مثالی از condition که چندین زیرعبارت را در یک عبارت واحد ترکیب می‌کند، آورده شده است:

condition {
  let exp1 = starterNode.lockState.equals(.unlocked)
  let exp2 = stateReaderNode.lockState.equals(true)
  let exp3 = occupancySensingDevice.occupied.notEquals(0)
  (exp1.and(exp2)).or(exp3)
}

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

typealias OnOffTrait = Matter.OnOffTrait

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

stateReader

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

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

typealias ActivatedCarbonFilterMonitoringTrait = Matter.ActivatedCarbonFilterMonitoringTrait

let filterMonitoringState = stateReader(structure, ActivatedCarbonFilterMonitoringTrait.self)

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

condition {
filterMonitoringState.changeIndication.equals(.warning)
}

با استفاده از عملگرهای مقایسه‌ای و منطقی ، می‌توان از چندین stateReaders در یک گره condition استفاده کرد:

typealias ArmDisarm = Google.ArmDisarmTrait
typealias DoorLockDevice = Matter.DoorLockDeviceType
typealias DoorLock = Matter.DoorLockTrait

let armState = stateReader(doorLock, DoorLockDevice.self, ArmDisarm )
let doorLockState = stateReader(doorLock, DoorLockDevice.self, DoorLock)
armState
doorLockState
condition {
  let exp1 = armState.armState
  let exp2 = doorLockState.lockState
  exp1.and(exp2)
}

مدت زمان شرایط

علاوه بر یک عبارت بولی در یک شرط، می‌توانید یک بازه زمانی مشخص کنید که در طی آن عبارت باید درست باشد تا اتوماسیون اجرا شود. به عنوان مثال، می‌توانید شرطی تعریف کنید که فقط در صورتی اجرا شود که چراغی به مدت ده دقیقه روشن بوده باشد.

condition(for: .seconds(600)) {
lightStateReader.onOff.equals(true)
}

مدت زمان می‌تواند از یک تا 30 دقیقه متغیر باشد.

گره‌های عمل

گره action جایی است که کار اتوماسیون در آن انجام می‌شود. در این مثال، action دستور broadcast() مربوط به AssistantBroadcastTrait را فراخوانی می‌کند:

action(speaker, SpeakerDeviceType.self) {
  Google.AssistantBroadcastTrait.broadcast(msg: "Oven Cycle Complete")
}