Guida al dispositivo campanello per iOS

Il tipo di dispositivo Campanello viene implementato utilizzando tre tratti: PushAvStreamTransportTrait, che gestisce il trasporto di stream audio e video utilizzando protocolli basati su push, WebRtcLiveViewTrait, che offre la possibilità di controllare i live streaming e il talkback, e CameraSnapshotTrait, che fornisce snapshot di anteprima memorizzati nella cache e acquisizioni di snapshot in diretta.

Controlla sempre il supporto di attributi e comandi per un dispositivo prima di utilizzare qualsiasi funzionalità o di tentare di aggiornare gli attributi. Per saperne di più, consulta Controlla i dispositivi su iOS.

Tipo di dispositivo delle API Home Tratti App di esempio Swift Caso d'uso

Campanello

GoogleDoorbellDeviceType

home.matter.6006.types.0113

Un dispositivo attivato da un pulsante all'esterno di una porta che emette un segnale acustico e/o visivo, utilizzato per attirare l'attenzione di una persona che si trova dall'altra parte della porta. I campanelli possono includere live streaming accessibili, talkback bidirezionale o eventi di rilevamento.

Tratti richiesti
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

Campanello

Ricevi informazioni di base su un dispositivo

   Implementato nell'app di esempio per iOS   

Il tratto BasicInformation include informazioni come il nome del fornitore, l'ID fornitore, l'ID prodotto, il nome del prodotto (incluse le informazioni sul modello) e la versione software di un dispositivo:

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!

Recupera il numero di serie

   Implementato nell'app di esempio per iOS   

Per ottenere il numero di serie del dispositivo, utilizza il comando GetSerialNumber del tratto ExtendedBasicInformation. L'esempio mostra il salvataggio del numero di serie in una variabile denominata serialNumber:

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

Risposte rapide

La funzionalità Risposte rapide consente all'utente di inviare un messaggio predefinito a un campanello.

Questa funzionalità è disponibile solo sui campanelli. L'elenco dei messaggi predefiniti è disponibile per l'app partner, che può presentarli all'utente per la scelta. I messaggi predefiniti non sono modificabili dall'utente.

Le risposte rapide vengono implementate tramite il tratto PresetMessage.

Riproduci un messaggio preimpostato

Per riprodurre un messaggio preimpostato, chiama il metodo playPresetMessage, passandogli uno dei valori di stringa trovati nella proprietà availablePhraseTypes.


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)")
    }
}

Imposta la lingua parlata

Imposta la lingua parlata

Imposta la lingua parlata attiva di un dispositivo su impostazioni internazionali specifiche (ad esempio "en_US") utilizzando il metodo setActiveLocale del tratto LocalizationConfiguration.

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

Ottieni l'ora più recente del contatto del dispositivo con il cloud

Per trovare l'ora più recente in cui il dispositivo ha avuto contatto con il cloud, utilizza l'attributo lastContactTimestamp del tratto ExtendedGeneralDiagnostics:

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

Impostazioni del tipo di supporto per videocamera

Il tratto Mount contiene le impostazioni e le informazioni sullo stato del supporto della videocamera. Puoi leggere attributi come lo stato di montaggio, il tipo di rilevamento e il nome del tipo di montaggio. Inoltre, puoi utilizzare la caratteristica Mount per eseguire l'override della configurazione predefinita del tipo di montaggio.

// 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)
}

Controlla la connettività di un dispositivo

La connettività di un dispositivo viene effettivamente controllata a livello di tipo di dispositivo, perché alcuni dispositivi supportano più tipi di dispositivi. Lo stato restituito è una combinazione degli stati di connettività per tutti i trait di quel dispositivo.

let doorbellConnectivity = doorbellDeviceType.metadata.sourceConnectivity.connectivityState

In caso di tipi di dispositivi misti, potrebbe essere osservato uno stato di partiallyOnline quando non è presente una connessione a internet. I tratti standard Matter potrebbero essere ancora online grazie al routing locale, ma i tratti basati su cloud saranno offline.

Recupera l'indirizzo IP del dispositivo

Per trovare l'indirizzo IP del dispositivo, utilizza l'attributo networkInterfaces di GeneralDiagnosticsTrait. Gli indirizzi vengono restituiti come oggetti Data, che puoi formattare in stringhe IPv4 o IPv6 standard utilizzando il framework Network:

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
}

Avvia un live streaming

   Implementato nell'app di esempio per iOS   

Per avviare un live streaming, invia la stringa SDP (Session Description Protocol) al metodo startLiveView(offerSdp:) del tratto WebRtcLiveViewTrait, che restituisce tre valori:

  • L'SDP per la sessione.
  • La durata della sessione in secondi.
  • L'ID sessione, che può essere utilizzato per estendere o terminare la sessione.
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
  }
}

Estendi un live streaming

   Implementato nell'app di esempio per iOS   

I live streaming hanno una durata preimpostata, dopo la quale scadono. Per allungare la durata di uno stream attivo, invia una richiesta di estensione utilizzando il metodo 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
  }
}

Avvia e interrompi TalkBack

   Implementato nell'app di esempio per iOS   

Per avviare la comunicazione bidirezionale, chiama il metodo startTalkback(mediaSessionId:optionalArgsProvider:) del tratto WebRtcLiveViewTrait. Per interrompere, utilizza 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)")
  }
}

Gestisci il live streaming

   Implementato nell'app di esempio per iOS   

La regolazione della qualità del live streaming è utile per ottimizzare l'utilizzo della larghezza di banda in base al contesto di visualizzazione del client (ad esempio, passando a una risoluzione inferiore quando viene visualizzato un riquadro di anteprima più piccolo, una visualizzazione griglia o una modalità Picture in picture).

La modifica dinamica della qualità tramite il tratto WebRtcLiveView gestisce in modo specifico la risoluzione della sessione di live streaming attiva su un determinato client. Non è la stessa cosa che configurare un'impostazione di utilizzo della larghezza di banda a livello di dispositivo direttamente sul dispositivo, che influirebbe su tutti gli spettatori simultanei e sulla qualità delle registrazioni video storiche salvate sul cloud.

L'esempio seguente mostra come recuperare e aggiornare la qualità del livestream per un dispositivo:

  • Recuperare le opzioni di qualità supportate: ottieni le risoluzioni di streaming disponibili supportate dal dispositivo. Il codice esegue una query sul tratto WebRtcLiveView per esporre le qualità dello stream supportate come un elenco di valori QualityHint (ad esempio .sd, .hd, .fhd, .qhd o .uhd) utilizzando la proprietà supportedQualityHints.

  • Modifica la qualità del live streaming: applica un QualityHint selezionato per modificare la risoluzione di streaming del live streaming attivo (ad esempio, passando dalla definizione standard all'alta definizione). La funzione updateQualityHint utilizza il metodo changeLiveViewQuality del tratto WebRtcLiveView per applicare la configurazione QualityHint selezionata alla sessione multimediale attiva.

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
  }
}

Attivare e disattivare la funzionalità di registrazione

Per attivare la funzionalità di registrazione della videocamera, passa TransportStatusEnum.Active al metodo setTransportStatus(transportStatus:optionalArgsProvider:) del tratto PushAvStreamTransportTrait. Per disattivare la funzionalità di registrazione, passa TransportStatusEnum.Inactive. Nell'esempio seguente, inseriamo queste chiamate in un'unica chiamata che utilizza un Boolean per attivare/disattivare la funzionalità di registrazione:

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
    }
  }
}

L'attivazione o la disattivazione della funzionalità di registrazione della videocamera equivale all'attivazione o alla disattivazione del video della videocamera. Quando il video di una videocamera è attivo, la videocamera sta registrando (ai fini degli eventi e dei clip correlati).

Quando la funzionalità di registrazione è disattivata (il video della videocamera è disattivato):

Controlla se la funzionalità di registrazione è attiva

Per determinare se la funzionalità di registrazione di una videocamera è attiva, controlla se sono attive connessioni. L'esempio seguente definisce due funzioni per farlo:

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
}

Recupera istantanee della videocamera

   Implementato nell'app di esempio per iOS   

Utilizza il tratto CameraSnapshot per recuperare istantanee di immagini statiche da una videocamera. Questi snapshot sono utili in diversi scenari:

  • Come riquadro segnaposto nell'interfaccia utente durante il caricamento di un live streaming WebRTC.
  • Come immagine di anteprima statica che si aggiorna a un live streaming in seguito all'interazione dell'utente.
  • Come sfondo per disegnare e configurare zone attive personalizzate.

Il tratto CameraSnapshot offre due modi per recuperare gli snapshot, a seconda che tu abbia bisogno di uno snapshot memorizzato nella cache per un rendering rapido o di uno snapshot in tempo reale on demand.

Ottieni uno snapshot di anteprima memorizzato nella cache

Un'istantanea di anteprima è un'immagine memorizzata nella cache che l'SDK può recuperare senza riattivare la videocamera. Questo è il metodo più rapido per recuperare un'immagine statica ed è ideale per le pagine Panoramica della videocamera o le griglie della dashboard.

Per ottenere l'istantanea dell'anteprima, leggi l'attributo della caratteristica 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
}

A seconda della configurazione e dell'attività della videocamera, l'URL di anteprima rimanda a un'immagine memorizzata nella cache generata da un filmato recente (il primo I-frame dell'ultimo frammento video) o a un'istantanea caricata periodicamente dalla videocamera.

Per indicare l'aggiornamento dell'immagine, il cloud di Google Home incorpora un'intestazione X-Home-Image-Captured-At nell'immagine JPEG/PNG pubblicata, formattata in UTC. Puoi analizzare questa intestazione sul lato client per visualizzare l'età dello snapshot in un'app.

Ottieni un'istantanea in diretta on demand

Per i percorsi dell'utente che richiedono la visione in diretta attuale della videocamera, ad esempio la configurazione delle zone attive, puoi richiedere un'istantanea in diretta. L'attivazione di un'istantanea in tempo reale indica alla videocamera di riattivarsi, acquisire un nuovo fotogramma e caricarlo sul cloud.

Per richiedere uno snapshot in tempo reale, utilizza il comando 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)")
}

Autentica le richieste di snapshot

   Implementato nell'app di esempio per iOS   

Tutti gli URL degli snapshot rimandano a contenuti multimediali protetti e richiedono un token OAuth 2.0 per l'ambito delle API Home v2. Per scaricare ed eseguire il rendering delle immagini, il token OAuth deve essere inserito come token di connessione nell'intestazione Authorization della richiesta HTTP.

L'esempio seguente mostra come configurare una richiesta di rete sicura per scaricare uno snapshot:

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
  }
}

Impostazioni batteria

Tramite le API Home è possibile controllare varie impostazioni della batteria.

Imposta la preferenza di utilizzo della batteria

L'impostazione del bilanciamento energetico ti consente di configurare il compromesso tra durata della batteria e prestazioni di un dispositivo. Puoi creare diversi profili della batteria, come "Estesa", "Bilanciata" e "Prestazioni", e passare da uno all'altro.

Questa funzionalità viene implementata aggiornando l'attributo currentEnergyBalance del tratto EnergyPreference. L'attributo accetta un indice intero che corrisponde a un profilo specifico definito nell'elenco energyBalances del dispositivo (ad esempio, 0 per EXTENDED, 1 per BALANCED e 2 per PERFORMANCE).

Un valore null per currentEnergyBalance indica che il dispositivo utilizza un profilo personalizzato. Questo è uno stato di sola lettura.

Di seguito è riportato un esempio di struttura che verrà utilizzata dall'attributo currentEnergyBalance, seguito dallo snippet di codice effettivo che utilizza l'attributo.

// 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)
  }
}

Attiva il risparmio energetico automatico

   Implementato nell'app di esempio per iOS   

Per configurare questa funzionalità, aggiorna l'attributo currentLowPowerModeSensitivity del tratto EnergyPreference. Questo attributo utilizza un indice per selezionare un livello di sensibilità, dove 0 in genere rappresenta Disabled e 1 rappresenta Enabled o Automatic.

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

Recupera lo stato di ricarica della batteria

   Implementato nell'app di esempio per iOS   

Per ottenere lo stato di ricarica attuale del dispositivo (in carica, completamente carico o non in carica), utilizza l'attributo batChargeState del tratto PowerSource.

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"
}

Controllare il livello batteria

Per ottenere il livello batteria attuale, utilizza l'attributo batChargeLevel del tratto PowerSource. Il livello è OK, Warning (basso) o 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"
}

Procurati la fonte di alimentazione

Per determinare la fonte di alimentazione utilizzata dal dispositivo, utilizza gli attributi BatPresent e wiredPresent del tratto PowerSource.

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

Controlla se la batteria deve essere sostituita

L'attributo batReplaceability indica se la batteria non è sostituibile, se è sostituibile dall'utente o se è sostituibile in fabbrica.

Se la batteria è sostituibile, l'attributo batReplacementNeeded del tratto PowerSource indica se la batteria deve essere sostituita.

// Get the battery replacement status
var batteryStatus = powerSourceTrait.attributes.batReplacementNeeded

if batteryStatus {
  print("Replace the battery.")
}

Quando la batteria è sostituibile dall'utente, batReplacementDescription descrive la batteria, incluse informazioni come fattore di forma, chimica e produttore preferito.

Impostazioni audio

Tramite le API Home è possibile controllare varie impostazioni audio.

Attiva o disattiva il microfono

Per attivare o disattivare il microfono del dispositivo, aggiorna l'attributo microphoneMuted del tratto CameraAvStreamManagementTrait utilizzando la funzione setMicrophoneMuted integrata:

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

Attiva o disattiva la registrazione audio

Per attivare o disattivare la registrazione audio per il dispositivo, aggiorna l'attributo recordingMicrophoneMuted del tratto CameraAvStreamManagementTrait utilizzando la funzione setRecordingMicrophoneMuted integrata:

// 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
  }
}

Regola il volume dello speaker

Per regolare il volume dell'altoparlante del dispositivo, aggiorna l'attributo speakerVolumeLevel del tratto CameraAvStreamManagementTrait utilizzando la funzione setSpeakerVolumeLevel integrata:

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

Impostazioni della zona attiva

   Implementato nell'app di esempio per iOS   

Il tratto ZoneManagement fornisce un'interfaccia per la gestione di zone di interesse personalizzate (zone attive) sui dispositivi con videocamera e campanello. Queste zone vengono utilizzate per filtrare il rilevamento di eventi (ad esempio il movimento di persone o veicoli) in aree specifiche all'interno del campo visivo del dispositivo.

Le zone attive vengono configurate dall'utente all'interno di un'applicazione partner, consentendogli di disegnare zone su aree specifiche nel campo visivo della videocamera. Queste zone definite dall'utente vengono poi tradotte nelle strutture utilizzate da questo tratto. Per maggiori informazioni sul funzionamento delle zone attive, consulta Configura e usa le zone attive.

Le zone attive vengono in genere definite utilizzando coordinate cartesiane 2D. Il tratto fornisce TwoDCartesianVertexStruct per i vertici e TwoDCartesianZoneStruct per la definizione della zona (nome, vertici, colore e utilizzo).

Controlla le zone attive

Per visualizzare le zone attive, controlla l'attributo zones del tratto ZoneManagement.

let zoneManagementTrait: Google.ZoneManagementTrait

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

Aggiungi una zona attiva

Per creare una nuova zona, utilizza il comando createTwoDCartesianZone. Questo comando accetta un TwoDCartesianZoneStruct, che definisce il nome, i vertici, il colore e l'utilizzo della zona.

L'esempio seguente mostra come creare una zona denominata "Front Porch" con quattro vertici, di colore salmone (#F439A0) e utilizzata per il rilevamento dei movimenti.

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
  }
}

Aggiorna una zona attiva

Per aggiornare una zona esistente, utilizza il comando updateTwoDCartesianZone. Questo comando richiede zoneId e TwoDCartesianZoneStruct aggiornato.

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

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

Elimina una zona attiva

Per rimuovere una zona, utilizza il comando removeZone con il zoneId specifico.

let zoneManagementTrait: Google.ZoneManagementTrait
let zoneID: UInt16

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

Trigger di eventi sonori

Il tratto AvStreamAnalysis fornisce un'interfaccia per la gestione dei trigger di rilevamento degli eventi sui dispositivi con videocamera e campanello. Mentre gli attivatori basati sulla visione (come persone o veicoli) possono essere specifici per una zona, gli attivatori relativi ai suoni sono in genere configurazioni a livello di dispositivo.

I seguenti tipi di attivatori sono disponibili per il rilevamento dei suoni con EventTriggerTypeEnum:

Modalità Valore enum Descrizione
Suono Sound Rilevamento dei suoni generici.
Persona che parla PersonTalking Rileva il parlato.
Cane che abbaia DogBark Rileva le vocalizzazioni dei cani.
Rottura di vetri GlassBreak Rileva il rumore di vetri infranti.
Allarme fumo SmokeAlarm Rileva gli allarmi fumo, spesso riconosciuti dal pattern acustico T3 (tre brevi segnali acustici seguiti da una pausa).
Allarme CO CoAlarm Rileva gli allarmi di monossido di carbonio (CO), generalmente riconosciuti dal segnale acustico T4 (quattro brevi segnali acustici seguiti da una pausa).

Controlla lo stato del rilevamento dei suoni

Per mostrare all'utente lo stato attuale del rilevamento dei suoni, devi controllare cosa supporta il dispositivo e cosa è attivato dall'hardware del dispositivo. I due attributi da controllare sono:

Nello sviluppo per iOS, in genere accedi alla caratteristica AvStreamAnalysis dal dispositivo per leggere questi attributi.

// 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)
    )
  )
}

Aggiorna l'insieme di trigger attivati

Per aggiornare l'insieme di trigger abilitati, utilizza il comando SetOrUpdateEventDetectionTriggers, che accetta un elenco di strutture EventTriggerEnablement.

// 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
)

Modalità di registrazione

   Implementato nell'app di esempio per iOS   

Il tratto RecordingMode fornisce un'interfaccia per gestire il comportamento di registrazione di video e immagini sui dispositivi con videocamera e campanello. Consente agli utenti di scegliere tra registrazione continua, registrazione basata sugli eventi o disattivazione completa della registrazione (solo Visione in diretta).

RecordingModeEnum definisce le strategie di registrazione disponibili:

Modalità Valore enum Descrizione
Disabilitata Disabled La registrazione è completamente disattivata. Utilizzato principalmente dai dispositivi legacy.
CVR (registrazione video continua) Cvr Il video viene registrato 24 ore su 24, 7 giorni su 7. Richiede un abbonamento (ad esempio, Google Home Premium.
EBR (registrazione basata sugli eventi) Ebr La registrazione viene attivata da eventi (persona, movimento). La durata del video dipende dalla durata dell'evento e dall'abbonamento.
ETR (Registrazione attivata da eventi) Etr Breve registrazione di anteprima (ad esempio, 10 secondi) attivata da eventi.
Live View LiveView La registrazione è disattivata, ma gli utenti possono comunque accedere al live streaming.
Immagini fisse Images Quando si verificano eventi, vengono registrate istantanee anziché video.

Controlla le modalità di registrazione

Per visualizzare la configurazione di registrazione corrente, controlla gli attributi del tratto 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,
      )
    )
  }
}

Cambia la modalità di registrazione

Prima di eseguire l'aggiornamento, assicurati che l'indice scelto dall'attributo supportedRecordingModes sia presente nell'attributo availableRecordingModes.

Per aggiornare la modalità selezionata, utilizza la funzione setSelectedRecordingMode, passando l'indice della modalità scelta:

let recordingModeTrait: Google.RecordingModeTrait
let recordingModeID: UInt8

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

Altre impostazioni

Tramite le API Home è possibile controllare varie altre impostazioni.

Attiva o disattiva la visione notturna

Per attivare o disattivare la visione notturna della videocamera, utilizza TriStateAutoEnum per aggiornare l'attributo nightVision del tratto CameraAvStreamManagementTrait utilizzando la funzione setNightVision integrata:

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

Modifica la luminosità del LED di stato

Per modificare la luminosità del LED di stato, utilizza ThreeLevelAutoEnum per aggiornare l'attributo statusLightBrightness del tratto CameraAvStreamManagementTrait utilizzando la funzione integrata setStatusLightBrightness:

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

Modifica l'area visibile della videocamera

L'area visibile della videocamera è la stessa della funzionalità Zoom e ritaglio descritta nell'articolo di assistenza Aumenta lo zoom e migliora la qualità del video della videocamera Nest.

L'area visibile è definita in un ViewportStruct che contiene quattro valori, che vengono utilizzati come coordinate dell'area visibile. Le coordinate sono definite come segue:

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

La determinazione dei valori per ViewportStruct dipende dall'interfaccia utente e dall'implementazione della fotocamera di un'app. A un livello molto di base, per impostare l'area visibile del video della videocamera, aggiorna l'attributo viewport del tratto CameraAvStreamManagementTrait con un ViewportStruct, utilizzando la funzione setViewport integrata.

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
    }
  }

}

Genera un TransportOptionsStruct

Alcune impostazioni richiedono modifiche alle proprietà in un TransportOptionsStruct, che viene poi passato alle opzioni di trasporto di una connessione di streaming. Per Swift, questa struttura deve essere generata prima di aggiornare qualsiasi proprietà.

Utilizza questa funzione helper per generare la struttura da utilizzare con le seguenti modifiche alle impostazioni:

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
}

Attiva o disattiva l'analisi

Ogni dispositivo può attivare singolarmente l'invio di dati di analisi dettagliati al cloud di Google Home (consulta Cloud Monitoring per le API Home).

Per attivare l'analisi per un dispositivo, imposta la proprietà analyticsEnabled di ExtendedGeneralDiagnosticsTrait su true. Quando imposti analyticsEnabled, un'altra proprietà, logUploadEnabled, viene impostata automaticamente su true, il che consente di caricare i file di log di analisi sul cloud di Google Home.

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

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

Configurazioni di trasporto e registrazione

Questa sezione riguarda le impostazioni relative alla qualità dello streaming della videocamera e all'attivazione degli eventi. Queste impostazioni sono gestite dal tratto PushAvStreamTransport.

Leggi le impostazioni di trasporto

Questa sezione mostra come recuperare la configurazione corrente da un dispositivo videocamera o campanello. Recupera il tratto PushAvStreamTransport, trova la connessione specifica utilizzata per la registrazione, quindi estrae i valori attuali per la qualità della larghezza di banda, la sensibilità riattivazione e la durata massima dell'evento.

// 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

Aggiorna le impostazioni di trasporto

Questa sezione mostra come modificare le impostazioni di trasporto. Crea un nuovo TransportOptionsStruct contenente i nuovi valori e poi utilizza il comando modifyPushTransport per inviare queste impostazioni aggiornate al dispositivo, applicandole alla connessione di registrazione trovata nel passaggio precedente.

Per modificare queste impostazioni, utilizza il comando modifyPushTransport con un TransportOptionsStruct.

// 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
)

Determina la qualità della larghezza di banda

La proprietà videoStreamId di TransportOptionsStruct corrisponde a una configurazione specifica dello stream video.

Per ottenere gli stream video supportati, consulta l'attributo allocatedVideoStreams, che è un elenco di VideoStreamStructs. dal tratto CameraAvStreamManagement del dispositivo.

Regola la sensibilità riattivazione del dispositivo

La proprietà motionSensitivity di TransportTriggerOptionsStruct corrisponde ai seguenti valori:

Etichetta Valore (UInt8)
Bassa 1
Media 5
Alto 10

Regola la durata massima degli eventi

La proprietà maxDuration di TransportMotionTriggerTimeControlStruct corrisponde alle seguenti durate di UInt32 (in secondi):

  • 10, 15, 30, 60, 120, 180

Impostazioni del cicalino

Tramite le API Home è possibile controllare varie impostazioni del cicalino del campanello.

Modifica il suono del cicalino

Per modificare il suono del cicalino del campanello, recupera prima l'elenco dei suoni del cicalino installati sul dispositivo utilizzando l'attributo installedChimeSounds del tratto ChimeTrait:

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

Quindi, aggiorna l'attributo selectedChime del tratto ChimeTrait utilizzando la funzione setSelectedChime integrata:

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

Utilizza un cicalino esterno

   Implementato nell'app di esempio per iOS   

Il campanello può essere configurato per utilizzare un cicalino esterno, ad esempio un campanello meccanico installato all'interno della casa. Questa impostazione deve essere configurata durante l'installazione del campanello per evitare potenziali danni al cicalino esterno.

Per indicare il tipo di cicalino esterno installato, utilizza ExternalChimeType per aggiornare l'attributo externalChime del tratto ChimeTrait utilizzando la funzione setExternalChime integrata:

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

Modifica la durata del cicalino esterno

La durata, in secondi, del suono di un cicalino esterno può essere configurata tramite le API Home. Se il cicalino esterno supporta una durata del suono, l'utente potrebbe voler configurare questa impostazione.

Il valore impostato qui dipende dalle specifiche del cicalino esterno stesso e dalla durata del suono consigliata.

Per modificare la durata del cicalino esterno, aggiorna l'attributo externalChimeDurationSeconds del tratto ChimeTrait utilizzando la funzione integrata setExternalChimeDurationSeconds:

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

Attiva un tema del suono

   Implementato nell'app di esempio per iOS   

Alcuni campanelli potrebbero avere suonerie disponibili per gli utenti solo per un periodo di tempo limitato. Ad esempio, suonerie specifiche per le festività. Questi sono chiamati temi del cicalino.

Per vedere quali temi di suoneria sono disponibili per un utente, crea un filtro per intervallo di tempo e utilizzalo per filtrare i risultati del comando getAvailableThemes dal tratto ChimeThemes. Viene restituito un elenco di temi disponibili, inclusi i nomi dei temi.

L'esempio seguente mostra come filtrare l'elenco. Un tema è considerato attivo se l'ora corrente rientra nelle ore di inizio e di fine (rispettivamente i valori startTimeSeconds e endTimeSeconds). Se non viene impostata un'ora di inizio, l'evento viene considerato attivo dall'inizio dei tempi. Se non viene impostata un'ora di fine, la regola rimane attiva a tempo indeterminato. Se mancano entrambi, il tema è sempre attivo.

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)
    }
  }
}

Una volta ottenuto il nome del tema che ti interessa, ad esempio Christmas, puoi selezionarlo utilizzando la funzione setSelectedTimeboxedThemeName() sul tratto ChimeThemes ChimeThemes.

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

Impostazioni degli annunci visite

Puoi eseguire query e gestire le impostazioni degli annunci visite per i campanelli utilizzando il tratto VisitorAnnouncement delle API Home. Questo tratto controlla se la presenza di un visitatore viene annunciata sugli smart speaker o smart display Google quando qualcuno suona il campanello.

L'esempio seguente mostra come verificare se gli annunci visite sono attivati e come aggiornare questa impostazione:

let visitorAnnouncementsEnabled: Bool = visitorAnnouncementTrait.attributes.visitorAnnouncementsEnabled

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

Dismetti un dispositivo

Per rimuovere un campanello da una struttura, chiama device.decommission(). La dismissione mostra all'utente una schermata di conferma gestita da Google che avvisa che tutti i dati registrati della cronologia video 24/7, della cronologia eventi, dei clip e della raccolta di volti riconosciuti verranno eliminati definitivamente in tutta la struttura.

Per istruzioni dettagliate ed esempi di codice, consulta Rimuovi un dispositivo.