คู่มือ iOS DSL สําหรับการทำงานอัตโนมัติที่ซับซ้อน

คุณใช้ DSL ของการทำงานอัตโนมัติเพื่อสร้างการทำงานอัตโนมัติที่ซับซ้อนกว่าที่กล่าวถึงในคู่มือ DSL - การทำงานอัตโนมัติพื้นฐานใน iOS ได้

ตามลำดับที่มีการดำเนินการหลายอย่าง

ตามลำดับที่มีการดำเนินการหลายอย่าง

การทำงานอัตโนมัติสามารถทำได้มากกว่า 1 อย่าง ตัวอย่างเช่น คุณสามารถมีโหนด 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(...) { ... } ที่ไม่บังคับอย่างน้อย 1 บล็อกเพื่อประเมินเงื่อนไขหลายรายการตามลำดับได้ ระบบจะดำเนินการกับสาขาแรกที่มีเงื่อนไขที่ประเมินเป็น 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 ที่แสดงระยะเวลาที่ต้องหยุดชั่วคราวก่อนที่จะดำเนินการต่อ ระยะเวลาการหยุดชั่วคราวอาจสั้นเพียง 5 วินาทีหรือนานถึง 24 ชั่วโมง

ตัวอย่างเช่น หากต้องการเปิด/ปิดไฟ 4 ครั้งโดยหยุดชั่วคราว 5 วินาทีระหว่างการเปิด/ปิดแต่ละครั้ง ให้ทำดังนี้

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ที่ทริกเกอร์โดยการตรวจจับการเคลื่อนไหว และคุณระบุระยะเวลาการระงับทริกเกอร์เป็น 5 นาที เมื่อstarterทริกเกอร์ ระบบจะไม่ทริกเกอร์อีกเป็นเวลา 5 นาทีถัดไป ซึ่งจะป้องกันไม่ให้การทำงานอัตโนมัติทริกเกอร์ซ้ำๆ อย่างรวดเร็ว

หากต้องการใช้การระงับทริกเกอร์กับการทำงานอัตโนมัติ ให้ใช้คีย์เวิร์ด suppress(for:) พร้อมอาร์กิวเมนต์ Duration ซึ่งแสดงระยะเวลาที่ต้องรอก่อนตอบสนองต่อทริกเกอร์ที่ตามมา ระยะเวลาการระงับอาจสั้นเพียง 5 วินาทีหรือนานถึง 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 สำหรับแต่ละแอตทริบิวต์ที่จะแก้ไข ให้ใช้ฟังก์ชัน Mutator และส่งค่าใหม่ให้ วิธีสร้างชื่อฟังก์ชัน Mutator
    1. ใช้อักษรตัวพิมพ์ใหญ่สำหรับชื่อแอตทริบิวต์
    2. โดยขึ้นต้นด้วยคำว่า set
    ตัวอย่างเช่น หากต้องการอัปเดตแอตทริบิวต์ชื่อ defaultMoveRate คุณจะต้องใช้ฟังก์ชัน Mutator ชื่อ setDefaultMoveRate

โปรดทราบว่าโหนด update สามารถมีฟังก์ชัน Mutator ได้หลายฟังก์ชัน ตัวอย่างการอัปเดตแอตทริบิวต์ 2 รายการมีดังนี้

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

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