iOS 向けドアベル デバイスガイド

ドアホン デバイスタイプは、2 つのトレイトを使用して実装されます。PushAvStreamTransportTrait は、プッシュベースのプロトコルを使用して音声と動画のストリーム転送を処理します。WebRtcLiveViewTrait は、ライブ ストリームとトークバックを制御する機能を提供します。

機能を使用したり、属性を更新しようとしたりする前に、デバイスの属性とコマンドのサポートを必ず確認してください。詳しくは、iOSでデバイスを制御するをご覧ください。

Google Home の API のデバイスタイプ トレイト Swift サンプルアプリ ユースケース

ドアホン

GoogleDoorbellDeviceType

home.matter.6006.types.0113

ドアの外側のボタンを押すと、音や視覚的な信号を発するデバイス。ドアの向こう側にいる人の注意を引くために使用されます。ドアホンには、アクセシビリティ対応のライブ配信、双方向のトークバック、検出イベントなどの機能が搭載されている場合があります。

必須のトレイト
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

ドアホン

デバイスに関する基本情報を取得する

BasicInformation トレイトには、ベンダー名、ベンダー ID、プロダクト ID、プロダクト名(モデル情報を含む)、デバイスのソフトウェア バージョンなどの情報が含まれます。

// [START get_device_information]
let vendorName = basicInfoTrait.attributes.vendorName!
let vendorID = basicInfoTrait.attributes.vendorID!
let productID = basicInfoTrait.attributes.productID!
let productName = basicInfoTrait.attributes.productName!
let softwareVersion = basicInfoTrait.attributes.softwareVersion!
// [END get_device_information]

シリアル番号を取得する

デバイスのシリアル番号を取得するには、ExtendedBasicInformation トレイトの GetSerialNumber コマンドを使用します。次の例では、シリアル番号を serialNumber という名前の変数に保存しています。

// Assuming extendedBasicInformationTrait: Google.ExtendedBasicInformationTrait
let response = try await extendedBasicInformationTrait.getSerialNumber()
let serialNumber = response.serialNumber

クイック応答

クイック応答機能を使用すると、ユーザーは事前に定義されたメッセージをドアホン デバイスに送信できます。

この機能はドアホン デバイスでのみ利用できます。事前定義されたメッセージのリストはパートナー アプリで利用でき、ユーザーが選択できるように表示できます。事前定義されたメッセージはユーザーが編集できません。

クイック レスポンスは PresetMessage トレイトを介して実装されます。

プリセットのメッセージを再生する

プリセット メッセージを再生するには、availablePhraseTypes プロパティにある文字列値のいずれかを渡して、playPresetMessage メソッドを呼び出します。


import GoogleHomeSDK
import GoogleHomeTypes

func playDoorbellPresetMessage(device: HomeDevice, phraseTypeString: String) async {
    // 1. Retrieve the GoogleDoorbellDeviceType helper on the device
    guard let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) else {
        print("This device is not a Google Doorbell or is currently uninitialized.")
        return
    }

    // 2. Extract the Google.PresetMessageTrait
    guard let presetMessageTrait = doorbellDeviceType.traits[Google.PresetMessageTrait.self] else {
        print("PresetMessageTrait is not supported on this device.")
        return
    }

    // 3. (Optional) Check available phrase types supported by the device
    if let availablePhrases = presetMessageTrait.attributes.availablePhraseTypes {
        let phraseTypeNames = availablePhrases.map { $0.phraseType }
        print("Supported quick response phrases: \(phraseTypeNames)")
    }

    // 4. Send the playPresetMessage command asynchronously
    do {
        try await presetMessageTrait.playPresetMessage(phraseType: phraseTypeString)
        print("Preset message successfully requested.")
    } catch {
        print("SDK error occurred playing preset message: \(error)")
    }
}

音声言語を設定する

音声言語を設定する

LocalizationConfiguration トレイトの setActiveLocale メソッドを使用して、デバイスのアクティブな音声言語を特定のロケール(「en_US」など)に設定します。

// Setting the active language
// Assuming localizationConfigurationTrait: Matter.LocalizationConfigurationTrait
let selectedLocale = "en_US"
try await localizationConfigurationTrait.update {
    $0.setActiveLocale(selectedLocale)
}

デバイスがクラウドに最後に接続した日時を取得する

デバイスがクラウドと最後に通信した時刻を確認するには、ExtendedGeneralDiagnostics トレイトの lastContactTimestamp 属性を使用します。

if let lastContactTimeStamp = extendedGeneralDiagnosticsTrait.attributes.lastContactTimestamp {
  self.lastContactTime = Date(timeIntervalSince1970: Double(lastConnectedTimeStamp))
}

カメラマウントのタイプの設定

Mount トレイトには、カメラのマウント設定とステータス情報が含まれます。マウント状態、検出タイプ、マウント タイプ名などの属性を読み取ることができます。また、Mount トレイトを使用して、デフォルトのマウントタイプの構成をオーバーライドすることもできます。

// 1. Get the Mount trait
guard let mountTrait = deviceType.traits[Google.MountTrait.self] else {
  print("Mount trait not supported or configured on this device.")
  return
}

// 2. Read the current mount state, detection type, and type name
let mountState         = mountTrait.attributes.mountState         // Type: Google.MountTrait.MountStateEnum?
let mountDetectionType = mountTrait.attributes.mountDetectionType // Type: Google.MountTrait.MountDetectionTypeEnum?
let mountTypeName      = mountTrait.attributes.mountTypeName      // Type: String?

// 3. Update the mount type override
try await mountTrait.update { mutableTrait in
  mutableTrait.setMountTypeOverride(.official)
}

デバイスの接続を確認する

一部のデバイスは複数のデバイスタイプをサポートしているため、デバイスの接続は実際にはデバイスタイプ レベルでチェックされます。返される状態は、そのデバイスのすべてのトレイトの接続状態の組み合わせです。

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

インターネット接続がない場合、デバイスタイプが混在していると partiallyOnline の状態になることがあります。Matter 標準トレイトはローカル ルーティングによりオンラインのままですが、クラウドベースのトレイトはオフラインになります。

デバイスの IP アドレスを取得する

デバイスの IP アドレスを取得するには、GeneralDiagnosticsTraitnetworkInterfaces 属性を使用します。アドレスは Data オブジェクトとして返されます。Network フレームワークを使用して、標準の IPv4 または IPv6 文字列にフォーマットできます。

func getIpAddresses(trait: Matter.GeneralDiagnosticsTrait) -> [String] {
  let interfaces = trait.attributes.networkInterfaces ?? []
  var ipAddresses: [String] = []

  for interface in interfaces {
    for data in interface.iPv4Addresses {
      if let ipv4 = IPv4Address(data) {
        ipAddresses.append(String(describing: ipv4))
      }
    }
    for data in interface.iPv6Addresses {
      if let ipv6 = IPv6Address(data) {
        ipAddresses.append(String(describing: ipv6))
      }
    }
  }

  return ipAddresses
}

ライブ配信を開始する

ライブ配信を開始するには、セッション記述プロトコル(SDP)文字列を WebRtcLiveViewTrait トレイトの startLiveView(offerSdp:) メソッドに送信します。このメソッドは次の 3 つの値を返します。

  • セッションの SDP。
  • セッション継続時間(秒数)。
  • セッションの延長または終了に使用できるセッション ID。
public func sendOffer(offerSdp: String) async throws
-> (answerSdp: String, mediaSessionId: String, liveViewDuration: TimeInterval)
{
  do {
    // Sending StartLiveView command
    let response = try await liveViewTrait.startLiveView(
      offerSdp: offerSdp
    )
    // Received StartLiveView response
    return (
      answerSdp: response.answerSdp,
      mediaSessionId: response.mediaSessionId,
      liveViewDuration: TimeInterval(response.liveSessionDurationSeconds)
    )
  } catch {
    // Failed to send StartLiveView command
    throw error
  }
}

ライブ配信を延長する

ライブ配信には、期限切れになるまでの期間が事前に設定されています。アクティブなストリームの期間を延長するには、extendLiveView(mediaSessionId:optionalArgsProvider:) メソッドを使用して延長リクエストを発行します。

public func extendLiveView(mediaSessionId: String) async throws {
  do {
    // Extending live view
    let extendedDuration = try await liveViewTrait.extendLiveView(mediaSessionId: mediaSessionId)
  } catch {
    // Failed to extend live view
    throw error
  }
}

TalkBack の開始と停止

TalkBack を開始するには、WebRtcLiveViewTrait トレイトの startTalkback(mediaSessionId:optionalArgsProvider:) メソッドを呼び出します。停止するには、stopTalkback(mediaSessionId:) を使用します。

public func toggleTwoWayTalk(isOn: Bool, mediaSessionId: String) async throws {
  do {
    if isOn {
      try await liveViewTrait.startTalkback(mediaSessionId: mediaSessionId)
    } else {
      try await liveViewTrait.stopTalkback(mediaSessionId: mediaSessionId)
    }
  } catch {
    throw HomeError.commandFailed("Failed to toggle twoWayTalk: \(error)")
  }
}

ライブ配信を管理する

ライブ配信の画質を調整すると、クライアントの視聴コンテキストに基づいて帯域幅の使用量を最適化できます(たとえば、小さなプレビュー タイル、ギャラリー表示、ピクチャー イン ピクチャー モードの表示時に解像度を下げることができます)。

WebRtcLiveView トレイトを使用して画質を動的に変更すると、特定のクライアントのアクティブなライブ配信セッションの解像度が特に管理されます。これは、デバイス全体の帯域幅使用量設定をデバイスで直接構成するのとは異なります。後者の場合、すべての同時視聴者と、クラウドに保存された過去の動画録画の画質に影響します。

次の例は、デバイスのライブ配信の品質を取得して更新する方法を示しています。

  • サポートされている画質オプションを取得する: デバイスでサポートされているストリーミング解像度を取得します。このコードは、WebRtcLiveView トレイトをクエリして、supportedQualityHints プロパティを使用してサポートされているストリーム品質を QualityHint 値のリスト(.sd.hd.fhd.qhd.uhd など)として公開します。

  • ライブ配信の画質を変更する: 選択した QualityHint を適用して、アクティブなライブ配信のストリーミング解像度を変更します(標準画質から高画質への切り替えなど)。updateQualityHint 関数は、WebRtcLiveView トレイトの changeLiveViewQuality メソッドを使用して、選択した QualityHint 構成をアクティブなメディア セッションに適用します。

public var supportedQualityHints: [Google.WebRtcLiveViewTrait.QualityHint] {
  return liveViewTrait?.attributes.supportedQualityHints ?? []
}

public func updateQualityHint(
  liveViewTrait: Google.WebRtcLiveViewTrait,
  hint: Google.WebRtcLiveViewTrait.QualityHint,
  mediaSessionId: String
) async {
  do {
    _ = try await liveViewTrait.changeLiveViewQuality(
      mediaSessionId: mediaSessionId,
      qualityHint: hint
    )
  } catch {
    // error
  }
}

録画機能を有効または無効にする

カメラの録画機能を有効にするには、PushAvStreamTransportTrait トレイトの setTransportStatus(transportStatus:optionalArgsProvider:) メソッドに TransportStatusEnum.Active を渡します。録画機能を無効にするには、TransportStatusEnum.Inactive を渡します。次の例では、これらの呼び出しを Boolean を使用して録画機能を切り替える単一の呼び出しでラップしています。

public func toggleIsRecording(isOn: Bool) {
  self.uiState = .loading

  guard let pushAvStreamTransportTrait else {
    // PushAvStreamTransportTrait not found.
    return
  }
  Task {
    do {
      try await pushAvStreamTransportTrait.setTransportStatus(
        transportStatus: isOn ? .active : .inactive)
      if isOn {
        do {
          self.player = try self.createWebRtcPlayer()
        } catch {
          // Failed to initialize WebRtcPlayer
          self.uiState = .disconnected
          return
        }
        await self.player?.initialize()
        self.uiState = .live
      } else {
        self.player = nil
        self.uiState = .off
      }
    } catch {
      // Failed to toggle onOff
    }
  }
}

カメラの録画機能を有効または無効にすることは、カメラの動画のオンとオフを切り替えることと同じです。カメラの動画がオンになっている場合、イベントと関連するクリップの目的で録画が行われます。

録画機能が無効になっている場合(カメラの動画がオフの場合):

  • カメラは、デバイスタイプの connectivityState に従ってオンラインとして表示されることがあります。
  • ライブ ストリームにアクセスできず、カメラでクラウド イベントも検出されません。

録画機能が有効になっているかどうかを確認する

カメラの録画機能が有効になっているかどうかを確認するには、接続がアクティブかどうかを確認します。次の例では、これを行うための 2 つの関数を定義しています。

public func isDeviceRecording() -> Bool {
  guard let pushAvStreamTransportTrait else {
    // PushAvStreamTransportTrait not found.
    return false
  }
  guard
    let hasActiveConnection =
      pushAvStreamTransportTrait
      .attributes
      .currentConnections?
      .contains(where: { $0.transportStatus == .active })
  else {
    return false
  }
  return hasActiveConnection
}

カメラのスナップショットを取得する

CameraSnapshot トレイトを使用して、カメラから静止画像のスナップショットを取得します。これらのスナップショットは、次のような複数のシナリオで役立ちます。

  • WebRTC ライブストリームの読み込み中に UI のプレースホルダ タイルとして。
  • ユーザー操作時にライブ配信にアップグレードされる静的なプレビュー画像として。
  • カスタムのアクティビティ ゾーンを描画して構成するための背景キャンバスとして。

CameraSnapshot トレイトは、高速レンダリング用のキャッシュ保存されたスナップショットが必要か、オンデマンドのライブ スナップショットが必要かに応じて、スナップショットを取得する 2 つの方法を提供します。

キャッシュに保存されたプレビュー スナップショットを取得する

プレビュー スナップショットは、SDK がカメラを起動せずに取得できるキャッシュ保存された画像です。これは静的画像を取得する最も高速な方法であり、カメラの概要ページやダッシュボードのグリッドに最適です。

プレビュー スナップショットを取得するには、preview_image_url トレイト属性を読み取ります。

guard let cameraSnapshotTrait = deviceType.traits[
  Google.CameraSnapshotTrait.self
] else {
  print("CameraSnapshot trait not supported on this device.")
  return
}

if let previewImageUrlString = cameraSnapshotTrait
  .attributes.preview_image_url,
   let url = URL(string: previewImageUrlString) {
  // Load the preview image from the URL
}

カメラの設定とアクティビティに応じて、プレビュー URL は、最近の動画映像から生成されたキャッシュ画像(最新の動画フラグメントの最初の I フレーム)またはカメラによって定期的にアップロードされるスナップショットを指します。

画像の鮮度を示すため、Google Home クラウドは、配信される JPEG/PNG 画像に DateTimeOriginal Exif タグ(ExifInterface#TAG_DATETIME_ORIGINAL)を UTC 形式で埋め込みます。クライアントサイドでこのタグを解析して、アプリでスナップショットの経過時間を表示できます。

オンデマンドのライブ スナップショットを取得する

アクティビティ ゾーンの設定など、カメラの現在のライブビューが必要なユーザー ジャーニーでは、ライブ スナップショットをリクエストできます。ライブ スナップショットをトリガーすると、カメラが起動して新しいフレームをキャプチャし、クラウドにアップロードします。

ライブ スナップショットをリクエストするには、getLiveSnapshot() コマンドを使用します。

do {
  let response = try await cameraSnapshotTrait.getLiveSnapshot()
  let snapshotUrlString = response.snapshot_url

  if let url = URL(string: snapshotUrlString) {
    // Load the live snapshot image from the URL
  }
} catch {
  print("Failed to get live snapshot: \(error)")
}

スナップショット リクエストを認証する

すべてのスナップショット URL は安全なメディアを指しており、Home APIs v2 スコープの OAuth 2.0 トークンが必要です。画像をダウンロードしてレンダリングするには、OAuth トークンを HTTP リクエストの Authorization ヘッダーにベアラー トークンとして挿入する必要があります。

次の例は、スナップショットをダウンロードするための安全なネットワーク リクエストを構成する方法を示しています。

import UIKit

func loadSnapshotImage(from url: URL, home: Home) async -> UIImage? {
  do {
    // 1. Retrieve the OAuth access token from the Home APIs SDK
    let (accessToken, _) = try await home.permissions.authorization()

    // 2. Configure the HTTP GET request with the Bearer token
    var request = URLRequest(url: url)
    request.setValue(
      "Bearer \(accessToken)",
      forHTTPHeaderField: "Authorization"
    )

    // 3. Fetch the image data
    let (data, _) = try await URLSession.shared.data(for: request)
    return UIImage(data: data)
  } catch {
    print("Error loading snapshot image: \(error)")
    return nil
  }
}

バッテリーの設定

さまざまなバッテリー設定は、Home API を介して制御できます。

バッテリー使用量の設定を行う

エネルギー バランスを設定すると、デバイスのバッテリー駆動時間とパフォーマンスのトレードオフを構成できます。「延長」、「バランス」、「パフォーマンス」などのさまざまなバッテリー プロファイルを作成して、切り替えることができます。

この機能は、EnergyPreference トレイトの currentEnergyBalance 属性を更新することで実装されます。この属性は、デバイスの energyBalances リストで定義された特定のプロファイルに対応する整数インデックスを受け入れます(たとえば、EXTENDED の場合は 0BALANCED の場合は 1PERFORMANCE の場合は 2)。

currentEnergyBalancenull 値は、デバイスがカスタム プロファイルを使用していることを示します。読み取り専用の状態です。

以下に、currentEnergyBalance 属性が使用する構造の例と、その属性を使用する実際のコード スニペットを示します。

// Example energyBalances list
{
  "energy_balances": [
    {
      "step": 0,
      "label": "EXTENDED"
    },
    {
      "step": 50,
      "label": "BALANCED"
    },
    {
      "step": 100,
      "label": "PERFORMANCE"
    }
  ]
}
private func setBatteryUsage(to option: UInt8) async throws {
  _ = try await energyPreferenceTrait.update {
    $0.setCurrentEnergyBalance(option)
  }
}

自動バッテリー セーバーをオンにする

この機能を構成するには、EnergyPreference トレイトの currentLowPowerModeSensitivity 属性を更新します。この属性は、インデックスを使用して機密レベルを選択します。通常、0Disabled を表し、1Enabled または Automatic を表します。

private func setAutoBatterySaver(to value: Bool) async throws {
  _ = try await energyPreferenceTrait.update {
    $0.setCurrentLowPowerModeSensitivity(value ? 1 : 0)
  }
}

バッテリーの充電状態を取得する

デバイスの現在の充電状態(充電中、充電完了、充電していない)を取得するには、PowerSource トレイトの batChargeState 属性を使用します。

self.chargingState = powerSourceTrait.attributes.batChargeState

var description: String
switch self.chargingState {
case .isCharging:
  description = "Charging"
case .isAtFullCharge:
  description = "Full"
case .isNotCharging:
  description = "Not Charging"
default:
  description = "Unknown"
}

バッテリー残量を取得する

現在のバッテリー残量を取得するには、PowerSource トレイトの batChargeLevel 属性を使用します。残量は OKWarning(低)、Critical のいずれかです。

self.batteryLevel = powerSourceTrait.attributes.batChargeLevel

var description: String
switch self.batteryLevel {
case .ok:
  description = "OK"
case .warning:
  description = "Warning"
case .critical:
  description = "Critical"
default:
  description = "Unknown"
}

電源を取得する

デバイスが使用している電源を判断するには、PowerSource トレイトの BatPresent 属性と wiredPresent 属性を使用します。

if powerSourceTrait.attributes.wiredPresent ?? false {
  self.powerSourceType = .wired
} else if powerSourceTrait.attributes.batPresent ?? false {
  self.powerSourceType = .battery
} else {
  self.powerSourceType = nil
}

音声設定

さまざまな音声設定は、Home API を介して制御できます。

マイクのオンとオフを切り替える

デバイスのマイクのオンとオフを切り替えるには、組み込みの setMicrophoneMuted 関数を使用して、CameraAvStreamManagementTrait トレイトの microphoneMuted 属性を更新します。

// Turn the device's microphone on or off
func setMicrophone(on: Bool) async {
  do {
    _ = try await self.cameraAvStreamManagementTrait?.update {
      $0.setMicrophoneMuted(!on)
    }
  } catch {
    // Error
  }
}

音声録音のオンとオフを切り替える

デバイスの音声録音のオンとオフを切り替えるには、組み込みの setRecordingMicrophoneMuted 関数を使用して、CameraAvStreamManagementTrait トレイトの recordingMicrophoneMuted 属性を更新します。

// Turn audio recording on or off for the device
func setAudioRecording(on: Bool) async {
  do {
    _ = try await self.cameraAvStreamManagementTrait?.update {
      $0.setRecordingMicrophoneMuted(!on)
    }
  } catch {
    // Error
  }
}

スピーカーの音量を調整する

デバイスのスピーカー音量を調整するには、組み込みの setSpeakerVolumeLevel 関数を使用して CameraAvStreamManagementTrait トレイトの speakerVolumeLevel 属性を更新します。

// Adjust the camera speaker volume
func setSpeakerVolume(to value: UInt8) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setSpeakerVolumeLevel(value)
    }
  } catch {
    // Error
  }
}

アクティビティ エリアの設定

ZoneManagement トレイトは、カメラ デバイスとドアホン デバイスのカスタムの対象領域(アクティビティ エリア)を管理するためのインターフェースを提供します。これらのゾーンは、デバイスの画角内の特定のエリアでイベント検出(人物や車両の動きなど)をフィルタするために使用されます。

アクティビティ エリアは、パートナー アプリケーション内でユーザーが設定します。これにより、カメラの画角内の特定の領域にエリアを描画できます。ユーザーが定義したエリアは、このトレイトで使用される構造に変換されます。アクティビティ エリアの仕組みについて詳しくは、アクティビティ エリアを設定して使用するをご覧ください。

アクティビティ ゾーンは通常、2D の直交座標を使用して定義されます。このトレイトは、頂点の TwoDCartesianVertexStruct と、ゾーン定義(名前、頂点、色、使用状況)の TwoDCartesianZoneStruct を提供します。

アクティビティ エリアを確認する

アクティビティ エリアを表示するには、ZoneManagement トレイトの zones 属性を確認します。

let zoneManagementTrait: Google.ZoneManagementTrait

self.zones = zoneManagementTrait.attributes.zones ?? []

アクティビティ エリアを追加する

新しいゾーンを作成するには、createTwoDCartesianZone コマンドを使用します。このコマンドは、ゾーンの名前、頂点、色、使用状況を定義する TwoDCartesianZoneStruct を取ります。

次の例は、4 つの頂点を持つ「Front Porch」という名前のゾーンを作成し、サーモン色(#F439A0)で塗りつぶして、モーション検知に使用する方法を示しています。

import GoogleHomeSDK
import GoogleHomeTypes

func createFrontPorchZone(trait: Google.ZoneManagementTrait) async {
  // 1. Define the vertices for the zone (2D Cartesian coordinates)
  // Values are UInt16, typically scaled to the device's twoDCartesianMax.
  let vertices = [
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 260, y = 422),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1049, y = 0),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048, y = 0),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048, y = 950),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1630, y = 1349),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 880, y = 2048),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 0, y = 2048),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 638, y = 1090)
  ]

  // 2. Define the zone structure using the given SDK struct
  let newZone = Google.ZoneManagementTrait.TwoDCartesianZoneStruct(
    name: "Front Porch",
    use: [.motion], // ZoneUseEnum.motion
    vertices: vertices,
    // Color is a hex string (for example, Salmon/Pink)
    color: "#F439A0"
  )

  do {
    // 3. Execute the raw command to add the zone to the device
    // This returns the created zone's ID (UInt16).
    var newZoneID = try await trait.createTwoDCartesianZone(zone: newZone)
  } catch {
    // Error
  }
}

アクティビティ エリアを更新する

既存のゾーンを更新するには、updateTwoDCartesianZone コマンドを使用します。このコマンドには、zoneId と更新された TwoDCartesianZoneStruct が必要です。

let zoneManagementTrait: Google.ZoneManagementTrait
let zoneID: UInt16
let zone: Google.ZoneManagementTrait.TwoDCartesianZoneStruct

do {
  _ = try await zoneManagementTrait.updateTwoDCartesianZone(
        zoneID: zoneID, zone: zone)
} catch {
  // Error
}

アクティビティ エリアを削除する

ゾーンを削除するには、特定の zoneId を指定して removeZone コマンドを使用します。

let zoneManagementTrait: Google.ZoneManagementTrait
let zoneID: UInt16

do {
  _ = try await zoneManagementTrait.removeZone(zoneID: zoneID)
} catch {
  // Error
}

サウンド イベント トリガー

AvStreamAnalysis トレイトは、カメラ デバイスとドアホン デバイスでアクティビティ検出トリガーを管理するためのインターフェースを提供します。ビジョンベースのトリガー(人物や車両など)はゾーン固有にできますが、音関連のトリガーは通常デバイスレベルの設定です。

EventTriggerTypeEnum を使用したサウンド検知では、次のトリガータイプを使用できます。

モード 列挙値 説明
サウンド Sound 一般的なサウンド検知。
話し声 PersonTalking 音声を検出します。
犬の鳴き声 DogBark 犬の鳴き声を検出します。
ガラスの割れる音 GlassBreak ガラスの割れる音を検出します。
煙警報 SmokeAlarm 煙警報を検出します。通常、T3 可聴パターン(短いビープ音が 3 回鳴り、一時停止する)で認識されます。
一酸化炭素警報 CoAlarm 一酸化炭素(CO)警報を検出します。通常は、T4 の音声パターン(4 回の短いビープ音の後に一時停止)で認識されます。

サウンド検知のステータスを確認する

サウンド検知の現在の状態をユーザーに表示するには、デバイスがサポートしているものと、デバイスのハードウェアによって有効になっているものを確認する必要があります。確認する 2 つの属性は次のとおりです。

iOS 開発では、通常、デバイスから AvStreamAnalysis トレイトにアクセスしてこれらの属性を読み取ります。

// Example struct to store event triggers
public struct EventTrigger: Equatable {
  public var id: Google.AvStreamAnalysisTrait.EventTriggerTypeEnum
  public var enabled: Bool
}

let avStreamAnalysisTrait: Google.AvStreamAnalysisTrait

let possibleEventTriggers = avStreamAnalysisTrait.attributes.supportedEventTriggers ?? []
let enabledEventTriggers = avStreamAnalysisTrait.attributes.enabledEventTriggers ?? []

let eventTriggers [EventTrigger] = []
for trigger in possibleEventTriggers {
  self.eventTriggers.append(
    EventTrigger(
      id: trigger,
      enabled: enabledEventTriggers.contains(trigger)
    )
  )
}

有効なトリガーのセットを更新する

有効なトリガーのセットを更新するには、EventTriggerEnablement 構造体のリストを受け取る SetOrUpdateEventDetectionTriggers コマンドを使用します。

// Example struct to store event triggers
public struct EventTrigger: Equatable {
  public var id: Google.AvStreamAnalysisTrait.EventTriggerTypeEnum
  public var enabled: Bool
}

let avStreamAnalysisTrait: Google.AvStreamAnalysisTrait
let eventTriggers: [EventTrigger]

let enabledEventTriggers = eventTriggers.map {
  Google.AvStreamAnalysisTrait.EventTriggerEnablement(
    eventTriggerType: $0.id,
    enablementStatus: $0.enabled ? .enabled : .disabled
  )
}

try await avStreamAnalysisTrait.setOrUpdateEventDetectionTriggers(
  eventTriggerEnablements: enabledEventTriggers
)

録画モード

RecordingMode トレイトは、カメラ デバイスとドアホン デバイスの動画と画像の録画動作を管理するためのインターフェースを提供します。連続録画、アクティビティ検出時の録画、録画の完全な無効化(ライブビューのみ)のいずれかを選択できます。

RecordingModeEnum は、使用可能な録音戦略を定義します。

モード 列挙値 説明
無効 Disabled 録画が完全に無効になります。主に以前のデバイスで使用されます。
CVR(連続録画) Cvr 動画は 24 時間 365 日録画されます。定期購入が必要です(Google Home Premium など)。
EBR(アクティビティ検出時の録画) Ebr 録画はイベント(人物、動き)によってトリガーされます。動画の長さは、イベントの長さと定期購入のプランによって異なります。
ETR(イベント トリガー録画) Etr イベントによってトリガーされる短いプレビュー録画(10 秒など)。
ライブビュー LiveView 録画が無効になっているが、ユーザーはライブ配信にアクセスできる。
静止画像 Images アクティビティが発生すると、動画ではなくスナップショットが記録されます。

録画モードを確認する

現在の録画構成を表示するには、RecordingMode トレイトの属性を確認します。

// Example struct to store recording modes.
public struct RecordingMode: Hashable {
  public let id: UInt8
  public let mode: Google.RecordingModeTrait.RecordingModeEnum
}

let recordingModeTrait: Google.RecordingModeTrait

if let availableRecordingModes = recordingModeTrait.attributes.availableRecordingModes,
   let supportedRecordingModes = recordingModeTrait.attributes.supportedRecordingModes,
   let selectedRecordingMode = recordingModeTrait.attributes.selectedRecordingMode {

  var recordingModes: [RecordingMode] = []

  for recordingModeId in availableRecordingModes {
    guard Int(recordingModeId) < supportedRecordingModes.count,
          Int(recordingModeId) >= 0 else {
      // Out of bounds error
    }

    recordingModes.append(
      RecordingMode(
        id: recordingModeId,
        mode: supportedRecordingModes[Int(recordingModeId)].recordingMode,
      )
    )
  }
}

録画モードを変更する

更新する前に、supportedRecordingModes 属性から選択したインデックスが availableRecordingModes 属性に存在することを確認してください。

選択したモードを更新するには、選択したモードのインデックスを渡して setSelectedRecordingMode 関数を使用します。

let recordingModeTrait: Google.RecordingModeTrait
let recordingModeID: UInt8

_ = try await recordingModeTrait.update {
  $0.setSelectedRecordingMode(recordingModeID)
}

その他の設定

その他のさまざまな設定は、Home API を介して制御できます。

ナイトビジョン機能をオンまたはオフにする

カメラのナイト ビジョンをオンまたはオフにするには、TriStateAutoEnum を使用して、組み込みの setNightVision 関数を使用して CameraAvStreamManagementTrait トレイトの nightVision 属性を更新します。

// Turn night vision on or off
func setNightVision(
  to value: Google.CameraAvStreamManagementTrait.TriStateAutoEnum
) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setNightVision(value)
    }
  } catch {
    // Error
  }
}

ステータス LED の明るさを変更する

ステータス LED の明るさを変更するには、ThreeLevelAutoEnum を使用して、組み込みの setStatusLightBrightness 関数を使用して CameraAvStreamManagementTrait トレイトの statusLightBrightness 属性を更新します。

// Set the LED brightness
func setStatusLightBrightness(
  to value: Google.CameraAvStreamManagementTrait.ThreeLevelAutoEnum
) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setStatusLightBrightness(value)
    }
  } catch {
    // Error
  }
}

カメラのビューポートを変更する

カメラのビューポートは、Google Nest カメラの動画でズーム機能や補正機能を使用するのサポート記事で説明されているズームと切り抜き機能と同じです。

ビューポートは、ビューポートの座標として使用される 4 つの値を含む ViewportStruct で定義されます。座標は次のように定義されます。

(x1,y1) -- (x2,y1)
   |          |
(x1,y2) -- (x2,y2)

ViewportStruct の値を決定するのは、アプリの UI とカメラの実装によって異なります。ごく基本的なレベルでは、カメラ動画のビューポートを設定するには、組み込みの setViewport 関数を使用して、CameraAvStreamManagementTrait トレイトの viewport 属性を ViewportStruct で更新します。

func setCrop(x1: UInt16, y1: UInt16, x2: UInt16, y2: UInt16) {

  let viewport = Google.CameraAvStreamManagementTrait.ViewportStruct(
    x1: x1,
    y1: y1,
    x2: x2,
    y2: y2
  )

  Task {
    do {
      try await cameraAvStreamManagementTrait.update {
        $0.setViewport(viewport)
      }
    } catch {
      // Error
    }
  }

}

TransportOptionsStruct を生成する

一部の設定では、TransportOptionsStruct のプロパティを変更する必要があります。このプロパティは、ストリーミング接続のトランスポート オプションに渡されます。Swift の場合、この構造体はプロパティを更新する前に生成する必要があります。

このヘルパー関数を使用して、次の設定変更で使用する構造体を生成します。

func getTransportOptions(
  transportOptions: Google.PushAvStreamTransportTrait.TransportOptionsStruct,
  wakeUpSensitivity: UInt8?,
  maxEventLength: UInt32?
) async throws
  -> Google.PushAvStreamTransportTrait.TransportOptionsStruct
{

  var newMotionTimeControl:
    Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct? = nil
  if let maxEventLength {
    guard let motionTimeControl = transportOptions.triggerOptions.motionTimeControl else {
      throw HomeError.failedPrecondition(
        // Error - cannot update max event length without motion time control
    }
    newMotionTimeControl =
      Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct(
        initialDuration: motionTimeControl.initialDuration,
        augmentationDuration: motionTimeControl.augmentationDuration,
        maxDuration: maxEventLength,
        blindDuration: motionTimeControl.blindDuration
      )
  }

  return Google.PushAvStreamTransportTrait.TransportOptionsStruct(
    streamUsage: .recording,
    videoStreamID: nil,
    audioStreamID: nil,
    tlsEndpointID: transportOptions.tlsEndpointID,
    url: transportOptions.url,
    triggerOptions: Google.PushAvStreamTransportTrait.TransportTriggerOptionsStruct(
      triggerType: .motion,
      motionZones: nil,
      motionSensitivity: wakeUpSensitivity,
      motionTimeControl: newMotionTimeControl,
      maxPreRollLen: nil
    ),
    ingestMethod: .cmafIngest,
    containerOptions: Google.PushAvStreamTransportTrait.ContainerOptionsStruct(
      containerType: .cmaf,
      cmafContainerOptions: nil
    ),
    expiryTime: nil
  )
}

private func getRecordingConnection() async throws
  -> Google.PushAvStreamTransportTrait.TransportConfigurationStruct?
{
  guard let pushAvStreamTransportTrait else {
    // Error - PushAvStreamTransport trait not available
    return nil
  }

  let connections = try await pushAvStreamTransportTrait.findTransport().transportConfigurations

  for connection in connections {
    guard let transportOptions = connection.transportOptions,
      transportOptions.streamUsage == .recording
    else {
      continue
    }

    return connection
  }

  return nil
}

分析を有効または無効にする

各デバイスは、Google Home クラウドに詳細な分析データを送信するかどうかを個別に選択できます(Home API の Cloud Monitoring を参照)。

デバイスの分析を有効にするには、ExtendedGeneralDiagnosticsTraitanalyticsEnabled プロパティを true に設定します。analyticsEnabled を設定すると、別のプロパティ logUploadEnabled が自動的に true に設定され、分析ログファイルを Google Home クラウドにアップロードできるようになります。

// Enable analytics
_ = try await extendedGeneralDiagnosticsTrait.update {
  $0.setAnalyticsEnabled(true)
}

// Disable analytics
_ = try await extendedGeneralDiagnosticsTrait.update {
  $0.setAnalyticsEnabled(false)
}

トランスポートと録画の構成

このセクションでは、カメラのストリーミング品質とイベント トリガーに関連する設定について説明します。これらの設定は、PushAvStreamTransport トレイトによって管理されます。

転送設定を読み取る

このセクションでは、カメラまたはドアホン デバイスから現在の構成を取得する方法について説明します。PushAvStreamTransport トレイトを取得し、録画に使用される特定の接続を見つけて、帯域幅の品質、復帰感度、最大イベント長の現在の値を抽出します。

// Assuming access to
// var pushAvStreamTransportTrait: Google.PushAvStreamTransportTrait
let connections = try await pushAvStreamTransportTrait.findTransport().transportConfigurations

// Locate the connection designated for recording
let recordingConnection = connections.first { connection in
    guard let transportOptions = connection.transportOptions else { return false }
    return transportOptions.streamUsage == .recording
}

let options = recordingConnection?.transportOptions

// 1. Bandwidth Quality (Video Stream ID)
let videoStreamId = options?.videoStreamID

// 2. Wake-up Sensitivity (Motion Sensitivity)
let wakeUpSensitivity = options?.triggerOptions.motionSensitivity

// 3. Max Event Length (Motion Trigger Time Control)
let maxEventLength = options?.triggerOptions.motionTimeControl?.maxDuration

転送設定を更新する

このセクションでは、トランスポート設定を変更する方法について説明します。新しい値を含む新しい TransportOptionsStruct を作成し、modifyPushTransport コマンドを使用して、これらの更新された設定をデバイスに送り返し、前のステップで見つかった録音接続に適用します。

これらの設定を変更するには、TransportOptionsStruct を指定して modifyPushTransport コマンドを使用します。

// Example: Updating to Max Quality and 30s duration
let currentOptions = recordingConnection!.transportOptions!
let newOptions = Google.PushAvStreamTransportTrait.TransportOptionsStruct(
    streamUsage: .recording,
    videoStreamID: 2, // Max Quality
    tlsEndpointID: currentOptions.tlsEndpointID,
    url: currentOptions.url,
    triggerOptions: Google.PushAvStreamTransportTrait.TransportTriggerOptionsStruct(
        triggerType: .motion,
        motionSensitivity: 5, // Medium
        motionTimeControl: Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct(
            initialDuration: currentOptions.triggerOptions.motionTimeControl?.initialDuration ?? 10,
            augmentationDuration: currentOptions.triggerOptions.motionTimeControl?.augmentationDuration ?? 5,
            maxDuration: 30,
            blindDuration: currentOptions.triggerOptions.motionTimeControl?.blindDuration ?? 0
        )
    ),
    ingestMethod: currentOptions.ingestMethod,
    containerOptions: currentOptions.containerOptions
)

try await pushAvStreamTransportTrait.modifyPushTransport(
    connectionID: recordingConnection!.connectionID,
    transportOptions: newOptions
)

帯域幅の品質を判断する

TransportOptionsStructvideoStreamId プロパティは、特定の動画ストリーム構成に対応します。

サポートされている動画ストリームを取得するには、allocatedVideoStreams 属性を参照してください。これは VideoStreamStructs のリストです。デバイスの CameraAvStreamManagement トレイトから取得します。

デバイスの復帰感度を調整する

TransportTriggerOptionsStructmotionSensitivity プロパティは、次の値に対応します。

ラベル 値(UInt8)
1
5
10

最長アクティビティ時間を調整する

TransportMotionTriggerTimeControlStructmaxDuration プロパティは、次の UInt32 の期間(秒単位)に対応しています。

  • 10153060120180

チャイムの設定

ドアホンのチャイムのさまざまな設定は、Home API を介して制御できます。

チャイムの音を変更する

ドアホンのチャイム音を変更するには、まず ChimeTrait トレイトの installedChimeSounds 属性を使用して、デバイスにインストールされているチャイム音のリストを取得します。

doorbellChimeTrait.attributes.installedChimeSounds?.compactMap { chimeSound in
  return chimeSound.chimeID, chimeSound.name
}

次に、組み込みの setSelectedChime 関数を使用して、ChimeTrait トレイトの selectedChime 属性を更新します。

func setDoorbellChime(chimeID: UInt8) async {
  do {
    _ = try await doorbellChimeTrait.update {
      $0.setSelectedChime(chimeID)
    }
  } catch {
    // Error
  }
}

外部チャイムを使用する

ドアホンは、家の中に設置された機械式のベルなどの外部チャイムを使用するように設定できます。外部チャイムの損傷を防ぐため、ドアホンの設置時に設定する必要があります。

外部チャイムのタイプを示すには、ExternalChimeType を使用して、組み込みの setExternalChime 関数を使用して ChimeTrait トレイトの externalChime 属性を更新します。

// Indicate the external chime is mechanical
func setExternalChime(to value: Google.ChimeTrait.ExternalChimeType) async {
  do {
    _ = try await doorbellChimeTrait.update {
      $0.setExternalChime(value)
    }
  } catch {
    // Error
  }
}

外部チャイムの音の長さを変更する

外部チャイムが鳴る時間(秒単位)は、Home API を通じて構成できます。外部チャイムがチャイムの時間をサポートしている場合、ユーザーはこれを構成できます。

ここで設定する値は、外部チャイム自体の仕様と、推奨されるチャイムの継続時間によって異なります。

外部チャイムの継続時間を変更するには、組み込みの setExternalChimeDurationSeconds 関数を使用して、ChimeTrait トレイトの externalChimeDurationSeconds 属性を更新します。

// Change the external chime duration
func setExternalChimeDuration(to value: UInt16) async {
  do {
    _ = try await doorbellChimeTrait.update {
      $0.setExternalChimeDuration(value)
    }
  } catch {
    // Error
  }
}

チャイムのテーマを有効にする

一部のドアホンには、期間限定でユーザーが利用できるチャイムがあります。たとえば、祝日限定のチャイムなどです。これらはチャイムのテーマと呼ばれます。

ユーザーが利用できるチャイム テーマを確認するには、タイムボックス フィルタを作成し、それを使用して ChimeThemes トレイトの getAvailableThemes コマンドの結果をフィルタします。これにより、テーマ名を含む利用可能なテーマのリストが返されます。

次の例は、リストをフィルタする方法を示しています。現在の時刻がテーマの開始時刻と終了時刻(それぞれ startTimeSeconds 値と endTimeSeconds 値)の間にある場合、そのテーマは有効と見なされます。開始時刻が設定されていない場合、最初から有効と見なされます。終了時刻が設定されていない場合、無期限で有効になります。両方ともない場合、テーマは常に有効です。

let chimeThemes = try await chimeThemeTrait.getAvailableThemes().themes

if !chimeThemes.isEmpty {
  var chimeThemeSettings = []
  for chimeTheme in chimeThemes {
    let currentDateTime = UInt64(Date().timeIntervalSince1970)

    // Only show chime themes that are active.
    if chimeTheme.startTimeSeconds ?? 0 &lt;= currentDateTime
      &amp;&amp; chimeTheme.endTimeSeconds ?? UInt64.max &gt;= currentDateTime
    {
      self.chimeThemeSettings.append(chimeTheme.name)
    }
  }
}

Christmas などの目的のテーマの名前を取得したら、ChimeThemes ChimeThemes トレイトの setSelectedTimeboxedThemeName() 関数を使用して選択できます。

private func setChimeTheme(to value: String) async throws {
  _ = try await chimeThemeTrait.update {
    $0.setSelectedTimeboxedThemeName(value)
  }
}

訪問客の通知の設定

ドアホンの訪問者通知設定をクエリして管理するには、Home API の VisitorAnnouncement トレイトを使用します。この特性は、誰かがドアホンを鳴らしたときに、Google スマート スピーカーやスマートディスプレイで訪問者の存在を通知するかどうかを制御します。

次の例は、訪問客の通知が有効になっているかどうかを確認する方法と、この設定を更新する方法を示しています。

let visitorAnnouncementsEnabled: Bool = visitorAnnouncementTrait.attributes.visitorAnnouncementsEnabled

let value: Bool
_ = try await self.visitorAnnouncementTrait?.update {
  $0.setVisitorAnnouncementsEnabled(value)
}