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: state フィールドの doorOpen 属性を介してドアのステータス アラームを公開します。
  • RefrigeratorAndTemperatureControlledCabinetMode: 読み取りモードとコマンドモードを許可します。たとえば、changeToMode などのコマンドを実行して、LowEnergyRapidCoolLowNoise などのモードに切り替えます。

この自動化の例では、冷蔵庫のドアが開いたときにトリガーされます。ドアが 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)
  }
}