การทำงานอัตโนมัติแบบหลายอุปกรณ์ใน iOS

การทำงานอัตโนมัติอาจอ้างอิงอุปกรณ์หลายส่วนในลักษณะเดียวกับการทำงานอัตโนมัติที่ไม่ได้ใช้อุปกรณ์หลายส่วน

ขั้นแรก ให้รับส่วนประกอบตามปกติ ดูวิธีใช้อุปกรณ์ หลายส่วนได้ที่ อุปกรณ์หลายส่วน

จากนั้นสร้าง AutomationPartPath, สำหรับแต่ละส่วนที่ต้องการใช้ในการทำงานอัตโนมัติ ซึ่งจะช่วยให้คุณอ้างอิงส่วนดังกล่าวในตัวเริ่ม เงื่อนไข และ การดำเนินการของการทำงานอัตโนมัติได้

//  Obtain a reference to the device:
let multipartDevices = try await self.home.devices(enableMultipartDevices: true).list()

let light = multipartDevices.first(where: {
  $0.parts.contains(OnOffLightDeviceType.self) && $0.structureID == structure.id
})

let lightDeviceType = await light.parts.get(OnOffLightDeviceType.self)

let lightPartPath = light.automationPart(lightDeviceType)

อีกสิ่งที่ควรทราบคือการดำเนินการของการทำงานอัตโนมัติมักจะใช้อุปกรณ์และประเภทอุปกรณ์เป็นพารามิเตอร์ อย่างไรก็ตาม การดำเนินการของการทำงานอัตโนมัติที่อ้างอิงอุปกรณ์ส่วนประกอบ (อีกครั้งโดยใช้ AutomationPartPath) จะต้องใช้ AutomationPartPath เท่านั้น เนื่องจาก AutomationPartPath มีการอ้างอิงประเภทอุปกรณ์ อยู่แล้วนอกเหนือจากการอ้างอิงอุปกรณ์ส่วนประกอบ

ตัวอย่างเช่น ใน Automation API ระบบอาจถือว่าประเภทอุปกรณ์ Refrigerator เป็นอุปกรณ์หลายส่วน ซึ่งประกอบด้วย RefrigeratorDevice รูทที่สามารถมีตู้ย่อยหลายตู้ เช่น ตู้แช่แข็งหรือตู้มาตรฐานประเภท TemperatureControlledCabinetDevice

หากต้องการสร้างการทำงานอัตโนมัติของตู้เย็น คุณจะต้องโต้ตอบกับลักษณะการทำงานมาตรฐาน 2 อย่าง Matter เป็นหลัก ดังนี้

  • RefrigeratorAlarm: แสดงการแจ้งเตือนสถานะประตูผ่านแอตทริบิวต์ doorOpen ของช่อง state
  • RefrigeratorAndTemperatureControlledCabinetMode: อนุญาตให้อ่านและสั่งการโหมดต่างๆ เช่น การเรียกใช้คำสั่งอย่าง changeToMode เพื่อเปลี่ยนไปใช้โหมดต่างๆ เช่น LowEnergy, RapidCool หรือ LowNoise

การทำงานอัตโนมัติตัวอย่างนี้จะทริกเกอร์เมื่อเปิดประตูตู้เย็น หากเปิดประตูทิ้งไว้นานกว่า 2 นาที การทำงานอัตโนมัติจะออกอากาศการแจ้งเตือนด้วยเสียงในลำโพงอัจฉริยะ กระพริบไฟในครัว และส่งการแจ้งเตือนแบบพุช โปรดทราบว่าการทำงานอัตโนมัตินี้จะส่งผลต่อช่องแช่เย็นของอุปกรณ์เท่านั้น โดยไม่สนใจช่องแช่แข็ง (หากมี)

import GoogleHomeSDK
import GoogleHomeTypes

typealias RefrigeratorAlarmTrait = Matter.RefrigeratorAlarmTrait
typealias OnOffTrait = Matter.OnOffTrait

// Fetch devices using the multipart device model.
let multipartDevices = try await self.home.devices(enableMultipartDevices: true).list()

// Obtain a reference to the refrigerator device.
guard let refrigeratorDevice = multipartDevices.first {
    $0.types.contains(TemperatureControlledCabinetDeviceType.self) &&
    $0.traits.contains(Matter.RefrigeratorAndTemperatureControlledCabinetModeTrait.self) &&
    $0.traits.contains(Matter.RefrigeratorAlarmTrait.self)
  }

let refrigeratorDeviceType = await refrigeratorDevice.parts.get(RefrigeratorDeviceType.self).first

// Get all temperature-controlled cabinet parts of the refrigerator
let cabinets = refrigeratorDeviceType.parts(type: TemperatureControlledCabinetDeviceType.self)

// Find the cabinet part with the 'refrigerator' semantic tag
let refrigeratorCabinet = cabinets.first {
  $0.metadata.tags.contains(SemanticTag.Refrigerator.refrigerator)
}
var cabinetPartPath = refrigeratorDevice.automationPart(refrigeratorCabinet)

let structure = home.structures().list().first

let speaker = multipartDevices.first(where: {
        $0.types.contains(SpeakerDeviceType.self) && $0.structureID == structure.id
      })

let refrigeratorDoorAlert = automation(
  name: "Refrigerator Door Open Alert",
  description: "Warn when the refrigerator door has been open for over 2 min."
) {
  // 1. Starter: Monitor the refrigerator door alarm trait
  let alarmStarter = starter(
    cabinetPartPath,
    RefrigeratorAlarmTrait.self
  )

  alarmStarter

  // 2. Condition: Ensure the 'doorOpen' alarm remains active for 120 seconds
  condition(for: .seconds(120)) {
    alarmStarter.state.doorOpen.equals(true)
  }

  // 3. Actions: Execute parallel reactions
  parallel {
    // Broadcast warning to household speakers
    action(speaker, SpeakerDeviceType.self) {
      Google.AssistantBroadcastTrait.broadcast(msg: "The refrigerator door has been left open!")
    }

    // Push a notification alerts to home members' mobile devices
    action(structure) {
      Google.NotificationTrait.sendNotifications(
        title: "Fridge Alert",
        body: "The refrigerator door has been open for over 2 min.",
        optInMemberEmailsArray: ["222larabrown@gmail.com"]
      )
    }
  }
}

ตัวอย่างต่อไปนี้จะเปลี่ยนตู้เย็นเป็นโหมดประหยัดพลังงานเมื่อตรวจพบว่าไม่มีใครอยู่บ้าน

import GoogleHomeSDK
import GoogleHomeTypes

typealias AreaPresenceStateTrait = Google.AreaPresenceStateTrait
typealias RefrigeratorAndTemperatureControlledCabinetModeTrait = Matter.RefrigeratorAndTemperatureControlledCabinetModeTrait

let structure = home.structures().list().first()

// Fetch devices using the multipart device model.
let devices = try await self.home.devices(enableMultipartDevices: true).list()

// Obtain a reference to the refrigerator device.
guard let refrigeratorDevice = multipartDevices.first {
    $0.types.contains(TemperatureControlledCabinetDeviceType.self) &&
    $0.traits.contains(Matter.RefrigeratorAndTemperatureControlledCabinetModeTrait.self) &&
    $0.traits.contains(Matter.RefrigeratorAlarmTrait.self)
  }

let refrigeratorDeviceType = await refrigeratorDevice.parts.get(RefrigeratorDeviceType.self)

// Get all temperature-controlled cabinet parts of the refrigerator
let cabinets = refrigeratorDeviceType.parts(type: TemperatureControlledCabinetDeviceType.self)

// Find the cabinet part with the 'refrigerator' semantic tag
let refrigeratorCabinet = cabinets.first {
  $0.metadata.tags.contains(SemanticTag.Refrigerator.refrigerator)
}

let cabinetPartPath = refrigeratorDevice.automationPart(refrigeratorCabinet)

let refrigeratorEcoMode = automation(
  name: "Refrigerator Eco Mode",
  description: "Automatically changes refrigerator to low energy mode when house is vacant."
) {
  // 1. Starter: Monitor household presence changes
  let presenceStarter = starter(structure, AreaPresenceStateTrait.self)

  presenceStarter

  // 2. Condition: Verify presence state transitions to vacant
  condition {
    presenceStarter.presenceState.equals(.presenceStateVacant)
  }
  // 3. Action: Set refrigerator cabinet Mode to 'Low Energy' (commonly option index 1)
  action(cabinetPartPath) {
    RefrigeratorAndTemperatureControlledCabinetModeTrait.changeToMode(newMode: 1)
  }
}