دليل لغات وصف البيانات (DSL) لنظام التشغيل iOS للإجراءات المبرمَجة المعقدة

يمكن استخدام لغة DSL الخاصة بالتشغيل الآلي لإنشاء عمليات تشغيل آلي أكثر تعقيدًا من تلك الموضّحة في دليل لغة DSL - عمليات التشغيل الآلي الأساسية على أجهزة iOS.

تسلسلي مع إجراءات متعددة

تسلسلي مع إجراءات متعددة

يمكن أن تنفّذ عملية التشغيل الآلي أكثر من إجراء واحد. على سبيل المثال، بدلاً من عقدة action واحدة، يمكنك استخدام عقد action متعددة تعمل بترتيب تسلسلي:

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {

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

}

تسلسلي مع إجراءات متوازية متعددة

تسلسلي مع إجراءات متوازية متعددة

إذا وضعت عُقد action متعددة في عقدة parallel، سيتم تنفيذ الإجراءات بشكل متزامن.

import GoogleHomeSDK
import GoogleHomeTypes

automation (
...
) {

  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.
typealias ContactSensorDevice = Matter.ContactSensorDeviceType
typealias BooleanStateTrait = Matter.BooleanStateTrait
typealias DimmableLightDevice = Matter.DimmableLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait

automation {
  let contactState = starter(
    contactSensor,
    ContactSensorDevice.self,
    BooleanStateTrait.self
  )
  let lightState = stateReader(
    light,
    DimmableLightDevice.self,
    OnOffTrait.self
  )
  contactState
  lightState

  condition {
    // Door opened (contact sensor open)
    contactState.stateValue.equals(false)
  }

  // Conditionally turn on the light if it's off
  ifThen(lightState.onOff.equals(false)) {
    action(light, DimmableLightDevice.self) {
      OnOffTrait.on()
    }
  }

  // Continue executing subsequent actions in the sequential flow
  action(structure) {
    Google.AssistantBroadcastTrait.broadcast(msg: "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.
typealias DoorLockDevice = Matter.DoorLockDeviceType
typealias DoorLockTrait = Matter.DoorLockTrait
typealias DimmableLightDevice = Matter.DimmableLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait

automation {
  let doorLockEvent = starter(
    doorLock,
    DoorLockDevice.self,
    DoorLockTrait.LockOperationEvent.self
  )
  let lightState = stateReader(
    light,
    DimmableLightDevice.self,
    OnOffTrait.self
  )
  doorLockEvent
  lightState

  condition {
    doorLockEvent.lockOperationType.equals(.unlock)
  }

  ifThen(lightState.onOff.equals(false)) {
    action(light, DimmableLightDevice.self) {
      OnOffTrait.on()
    }
  }.orElse {
    action(structure) {
      Google.AssistantBroadcastTrait.broadcast(msg: "Welcome home!")
    }
  }
}

ربط شروط متعددة بالتسلسل

يمكنك ربط كتلة واحدة أو أكثر من كتل .elseIf(...) { ... } الاختيارية لتقييم شروط متعددة بالتسلسل. يتم تنفيذ الفرع الأول الذي يتم تقييم شرطه على أنّه true، ويتم تخطّي جميع الفروع المتبقية. إذا لم يتم تقييم أي من الشروط على أنّه true، يتم تنفيذ كتلة .orElse { ... } اختيارية (إذا تم توفيرها):

// Adjust climate controls based on room temperature changes.
typealias TemperatureSensorDeviceType = Matter.TemperatureSensorDeviceType
typealias TemperatureMeasurementTrait = Matter.TemperatureMeasurementTrait
typealias ThermostatDeviceType = Matter.ThermostatDeviceType
typealias SimplifiedThermostatTrait = Google.SimplifiedThermostatTrait
typealias FanDeviceType = Matter.FanDeviceType
typealias OnOffTrait = Matter.OnOffTrait

automation {
  let tempStarter = starter(
    tempSensor,
    TemperatureSensorDeviceType.self,
    TemperatureMeasurementTrait.self
  )
  tempStarter

  // If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
  ifThen(tempStarter.measuredValue.greaterThanOrEquals(2800)) {
    action(thermostat, ThermostatDeviceType.self) {
      SimplifiedThermostatTrait.setSystemMode(systemMode: .cool)
    }
  }.elseIf(tempStarter.measuredValue.lessThan(1800)) {
    // If temperature is low (< 18°C / 1800 mC), switch to Heat mode
    action(thermostat, ThermostatDeviceType.self) {
      SimplifiedThermostatTrait.setSystemMode(systemMode: .heat)
    }
  }.orElse {
    // Otherwise, turn on the fan
    action(fan, FanDeviceType.self) {
      OnOffTrait.on()
    }
  }
}

المسارات الشرطية المدمجة

يمكن تضمين كتل شرطية داخل كتل أخرى من النوع ifThen أو elseIf أو orElse، كما يمكن دمجها مع العُقد parallel وdelay(for:) وstateReader.

تنفّذ حِزم ifThen وelseIf وorElse محتواها كسلاسل متسلسلة. يمكنك وضع أي عُقد متسلسلة داخل كل فرع، بما في ذلك action وstateReader وparallel وdelay(for:) وكتل ifThen متداخلة.

التأخيرات

يمكنك إدخال فواصل في عمليات التشغيل الآلي باستخدام طريقة delay(for:)، التي تتضمّن وسيطة Duration تمثّل المدة التي يجب إيقاف التنفيذ مؤقتًا قبل مواصلته. يمكن أن تتراوح مدة الإيقاف المؤقت بين خمس ثوانٍ و24 ساعة.

على سبيل المثال، لتبديل حالة المصباح أربع مرات مع إيقاف مؤقت لمدة خمس ثوانٍ بين كل عملية تبديل:

typealias OnOffLightDevice = Matter.OnOffLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait

sequential {
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
  delay(for:.seconds(5))
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
  delay(for:.seconds(5))
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
  delay(for:.seconds(5))
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
}

إيقاف المشغِّل

إيقاف التشغيل هو إحدى الإمكانات التي تتيح لعملية التشغيل الآلي تجاهل starter لفترة زمنية محدّدة بعد حدث التشغيل الأوّلي. على سبيل المثال، إذا كان التشغيل الآلي يتضمّن starter يتم تشغيله عند كشف الحركة، وإذا حدّدت مدة إيقاف التشغيل لمدة خمس دقائق، لن يتم تشغيل starter مرة أخرى خلال الخمس دقائق التالية. يمنع ذلك التشغيل الآلي من التفعيل بشكل متكرر وسريع.

لتطبيق ميزة حظر التشغيل على عملية التشغيل الآلي، استخدِم الكلمة الرئيسية suppress(for:) مع وسيطة Duration تمثّل مدة الانتظار قبل الاستجابة لعمليات التشغيل اللاحقة. قد تكون مدة الحظر قصيرة لا تتجاوز خمس ثوانٍ أو طويلة تصل إلى 24 ساعة.

typealias OccupancySensorDevice = Matter.OccupancySensorDeviceType
typealias OnOffLightDevice = Matter.OnOffLightDeviceType
typealias MotionDetectionTrait = Google.MotionDetectionTrait
typealias OnOffTrait = Matter.OnOffTrait

automation {
  let starterNode = starter(device, OccupancySensorDevice.self, MotionDetectionTrait.self)
  starterNode
  suppress(for: .seconds(30 * 60)) // 30 minutes
  action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
}

يُرجى العِلم أنّ ميزة إيقاف المشغّلات تؤثر في جميع starters في عملية التشغيل الآلي التي تسبق Suppression.

وضع حدّ لعدد عمليات التنفيذ

يمكنك الحدّ من عدد المرات المسموح فيها بتشغيل عملية آلية.

على سبيل المثال، يمكنك إعداد عملية تشغيل آلي لمرة واحدة تشغّل المكنسة الكهربائية أثناء تواجدك خارج المنزل طوال اليوم.

لإجراء ذلك، اضبط حقل البيانات الوصفية maxExecutionCount الخاص بالأتمتة. المثال التالي هو عملية أتمتة يمكن تنفيذها مرة واحدة فقط:

import GoogleHomeSDK
import GoogleHomeTypes

typealias RoboticVacuumCleanerDevice = Matter.RoboticVacuumCleanerDeviceType
typealias RvcRunModeTrait = Matter.RvcRunModeTrait
typealias AreaPresenceStateTrait = Google.AreaPresenceStateTrait

let draftAutomation = automation(
  name: "Vacuum home away",
  description: "Run the vacuum once when everyone is away.",
  maxExecutionCount: 1
) {
  let homeAwayState = starter(structure, AreaPresenceStateTrait.self)
  homeAwayState

  condition {
    homeAwayState.presenceState.equals(.presenceStateVacant)
  }

  action(vacuum, RoboticVacuumCleanerDevice.self) {
    RvcRunModeTrait.changeToMode(newMode: 1)
  }
}

يتم حذف عملية التشغيل الآلي فور اكتمال تنفيذها لآخر مرة والوصول إلى maxExecutionCount. يبقى إدخال سجلّ التشغيل الآلي في علامة التبويب Google Home app (GHA) النشاط، بما في ذلك automation_id.

ضبط سمات السمة في إجراء

لضبط قيمة سمة السلوك، اتّبِع الخطوات التالية:

  1. أنشئ عقدة update ضمن عقدة action، بما في ذلك السمة ذات الصلة كمعلَمة لعقدة update:
    action(deviceReference, deviceType) {
      update(trait) {
    
      }
    }
    
  2. ضمن العقدة update، لكل سمة سيتم تعديلها، استخدِم دالة معدِّلة، ومرِّر إليها القيمة الجديدة. لتكوين اسم دالة المعدِّل، اتّبِع الخطوات التالية:
    1. كتابة اسم السمة بأحرف كبيرة
    2. أضِف البادئة set.
    على سبيل المثال، لتعديل سمة باسم defaultMoveRate، عليك استخدام دالة معدِّلة باسم setDefaultMoveRate.

يُرجى العِلم أنّه يمكن أن تتضمّن عقدة update دوال تغيير متعدّدة. في ما يلي مثال على تعديل سمتَين:

typealias FanDeviceType = Matter.FanDeviceType
typealias FanControlTrait = Matter.FanControlTrait

action(fan, FanDeviceType.self) {
  update(FanControlTrait.self) {
    $0.setFanMode(.on)
  }
}