Guia de dispositivos de câmera para iOS

O tipo de dispositivo da câmera é implementado usando duas características: PushAvStreamTransportTrait, que processa o transporte de streams de áudio e vídeo usando protocolos baseados em push, e WebRtcLiveViewTrait, que oferece a capacidade de controlar transmissões ao vivo e o recurso de comunicação bidirecional.

Sempre verifique o suporte de atributos e comandos de um dispositivo antes de usar qualquer recurso ou tentar atualizar atributos. Consulte Controlar dispositivos no iOS para mais informações.

Tipo de dispositivo das APIs do Google Home Características App de exemplo do Swift Caso de uso

Câmera

GoogleCameraDeviceType

home.matter.6006.types.0158

Um dispositivo que captura imagens estáticas ou vídeos. As câmeras podem apresentar transmissões ao vivo acessíveis, comunicação bidirecional ou eventos de detecção.

Características obrigatórias
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

Câmera

Receber informações básicas sobre um dispositivo

A BasicInformation característica inclui informações como nome do fornecedor, ID do fornecedor, ID do produto, nome do produto (inclui informações do modelo), versão do software, e o número de série de um dispositivo:

// [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!
let serialNumber = basicInfoTrait.attributes.serialNumber!
// [END get_device_information]

Receber o horário mais recente de contato do dispositivo com a nuvem

Para encontrar o horário mais recente em que o dispositivo entrou em contato com a nuvem, use o lastContactTimestamp atributo da ExtendedGeneralDiagnostics característica:

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

Verificar a conectividade de um dispositivo

A conectividade de um dispositivo é verificada no nível do tipo de dispositivo, porque alguns dispositivos oferecem suporte a vários tipos. O estado retornado é uma combinação dos estados de conectividade de todas as características desse dispositivo.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

Um estado de partiallyOnline pode ser observado no caso de tipos de dispositivos mistos quando não há conectividade com a Internet. Matter As características padrão do Matter ainda podem estar on-line devido ao roteamento local, mas as características baseadas na nuvem estarão off-line.

Iniciar uma transmissão ao vivo

Para iniciar uma transmissão ao vivo, envie a string do Protocolo de descrição de sessão (SDP, na sigla em inglês) para o WebRtcLiveViewTrait da característica startLiveView(offerSdp:) método, que retorna três valores:

  • O SDP da sessão.
  • A duração da sessão em segundos.
  • O ID da sessão, que pode ser usado para estender ou encerrar a sessão.
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
  }
}

Estender uma transmissão ao vivo

As transmissões ao vivo têm uma duração predefinida após a qual expiram. Para aumentar a duração de um stream ativo, emita uma solicitação de extensão usando o extendLiveView(mediaSessionId:optionalArgsProvider:) método:

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

Iniciar e interromper a comunicação bidirecional

Para iniciar a comunicação bidirecional, chame o WebRtcLiveViewTrait método startTalkback(mediaSessionId:optionalArgsProvider:) da característica. Para interromper, use 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)")
  }
}

Ativar e desativar a capacidade de gravação

Para ativar a capacidade de gravação da câmera, transmita TransportStatusEnum.Active para o PushAvStreamTransportTrait da característica setTransportStatus(transportStatus:optionalArgsProvider:) método. Para desativar a capacidade de gravação, transmita-o TransportStatusEnum.Inactive. No exemplo a seguir, envolvemos essas chamadas em uma única chamada que usa um Boolean para alternar a capacidade de gravação:

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

Ativar ou desativar a capacidade de gravação da câmera é o mesmo que ligar ou desligar o vídeo da câmera. Quando o vídeo de uma câmera está ativado, ele está gravando (para fins de eventos e clipes relacionados).

Quando a capacidade de gravação está desativada (o vídeo da câmera está desligado):

Verificar se a capacidade de gravação está ativada

Para determinar se a capacidade de gravação de uma câmera está ativada, verifique se há conexões ativas. O exemplo a seguir define duas funções para fazer isso:

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
}

Configurações da bateria

Várias configurações de bateria podem ser controladas pelas APIs do Google Home.

Definir a preferência de uso da bateria

Ao definir o equilíbrio de energia, você pode configurar a compensação entre a duração da bateria e o desempenho de um dispositivo. É possível criar diferentes perfis de bateria, como "Estendido", "Equilibrado" e "Desempenho", e alternar entre eles.

Esse recurso é implementado atualizando o currentEnergyBalance atributo da EnergyPreference característica. O atributo aceita um índice inteiro que corresponde a um perfil específico definido na lista energyBalances do dispositivo (por exemplo, 0 para EXTENDED, 1 para BALANCED e 2 para PERFORMANCE).

Um valor null para currentEnergyBalance indica que o dispositivo está usando um perfil personalizado. Esse é um estado somente leitura.

O exemplo a seguir mostra uma estrutura que o atributo currentEnergyBalance vai usar, seguido pelo snippet de código real que usa o atributo.

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

Ativar a economia de bateria automática

Para configurar esse recurso, atualize o currentLowPowerModeSensitivity atributo da EnergyPreference característica. Esse atributo usa um índice para selecionar um nível de sensibilidade, em que 0 normalmente representa Disabled e 1 representa Enabled ou Automatic.

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

Receber o estado de carregamento da bateria

Para receber o estado de carregamento atual do dispositivo (carregando, totalmente carregado ou não carregando), use o batChargeState atributo da PowerSource característica.

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

Receber o nível de bateria

Para receber o nível de bateria atual, use o batChargeLevel atributo da PowerSource característica. O nível é OK, Warning (baixo) ou 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"
}

Receber a fonte de energia

Para determinar a fonte de energia que o dispositivo está usando, use os BatPresent e wiredPresent atributos da PowerSource característica.

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

Configurações de áudio

Várias configurações de áudio podem ser controladas pelas APIs do Google Home.

Ativar ou desativar o microfone

Para ativar ou desativar o microfone do dispositivo, atualize o microphoneMuted atributo da característica CameraAvStreamManagementTrait usando a função setMicrophoneMuted integrada:

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

Ativar ou desativar a gravação de áudio

Para ativar ou desativar a gravação de áudio do dispositivo, atualize o recordingMicrophoneMuted atributo da característica CameraAvStreamManagementTrait usando a função setRecordingMicrophoneMuted integrada:

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

Ajustar o volume do alto-falante

Para ajustar o volume do alto-falante do dispositivo, atualize o speakerVolumeLevel atributo da característica CameraAvStreamManagementTrait usando a função setSpeakerVolumeLevel integrada:

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

Configurações da zona de atividade

A característica ZoneManagement fornece uma interface para gerenciar regiões de interesse personalizadas (zonas de atividade) em dispositivos de câmera e campainha. Essas zonas são usadas para filtrar a detecção de eventos (como movimento de pessoas ou veículos) para áreas específicas no campo de visão do dispositivo.

As zonas de atividade são configuradas pelo usuário em um aplicativo parceiro, permitindo que ele desenhe zonas em áreas específicas no campo de visão da câmera. Essas zonas definidas pelo usuário são convertidas nas estruturas usadas por essa característica. Para mais informações sobre como as zonas de atividade funcionam, consulte Configurar e usar as Zonas de Atividade.

As zonas de atividade são normalmente definidas usando coordenadas cartesianas 2D. A característica fornece o TwoDCartesianVertexStruct para vértices e o TwoDCartesianZoneStruct para a definição de zona (nome, vértices, cor e uso).

Verificar zonas de atividade

Para mostrar as zonas de atividade, verifique o zones atributo da característica ZoneManagement.

let zoneManagementTrait: Google.ZoneManagementTrait

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

Adicionar uma zona de atividade

Para criar uma nova zona, use o createTwoDCartesianZone comando. Esse comando usa um TwoDCartesianZoneStruct, que define o nome, os vértices, a cor e o uso da zona.

O exemplo a seguir mostra como criar uma zona chamada "Varanda da frente" com quatro vértices, colorida em salmão (#F439A0) e usada para detecção de movimento.

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

Atualizar uma zona de atividade

Para atualizar uma zona atual, use o updateTwoDCartesianZone comando. Esse comando exige o zoneId e o atualizado TwoDCartesianZoneStruct.

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

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

Excluir uma zona de atividade

Para remover uma zona, use o removeZone comando com o zoneId específico.

let zoneManagementTrait: Google.ZoneManagementTrait
let zoneID: UInt16

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

Acionadores de eventos de som

A característica AvStreamAnalysis fornece uma interface para gerenciar acionadores de detecção de eventos em dispositivos de câmera e campainha. Embora os acionadores baseados em visão (como pessoas ou veículos) possam ser específicos da zona, os acionadores relacionados ao som são normalmente configurações no nível do dispositivo.

Os seguintes tipos de acionadores estão disponíveis para detecção de som com o EventTriggerTypeEnum:

Modo Valor de tipo enumerado Descrição
Som Sound Detecção de som geral.
Pessoa falando PersonTalking Detecta fala.
Latido DogBark Detecta vocalizações caninas.
Vidro quebrando GlassBreak Detecta o som de vidro quebrando.
Detector de fumaça SmokeAlarm Detecta alarmes de fumaça, geralmente reconhecidos pelo padrão audível T3 (três bips curtos seguidos de uma pausa).
Alarme de monóxido de carbono CoAlarm Detecta alarmes de monóxido de carbono (CO), normalmente reconhecidos pelo padrão audível T4 (quatro bips curtos seguidos de uma pausa).

Verificar o status da detecção de som

Para mostrar o estado atual da detecção de som ao usuário, verifique o que o dispositivo oferece suporte e o que está ativado pelo hardware do dispositivo. Os dois atributos a serem verificados são:

No desenvolvimento para iOS, normalmente você acessa a característica AvStreamAnalysis do dispositivo para ler esses atributos.

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

Atualizar o conjunto de acionadores ativados

Para atualizar o conjunto de acionadores ativados, use o SetOrUpdateEventDetectionTriggers comando, que usa uma lista de EventTriggerEnablement estruturas.

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

Modos de gravação

A característica RecordingMode fornece uma interface para gerenciar o comportamento de gravação de vídeo e imagem em dispositivos de câmera e campainha. Ela permite que os usuários escolham entre gravação contínua, gravação baseada em eventos ou desativação completa da gravação (somente visualização ao vivo).

O RecordingModeEnum define as estratégias de gravação disponíveis:

Modo Valor de tipo enumerado Descrição
Desativada Disabled A gravação está completamente desativada. Usado principalmente por dispositivos legados.
CVR (gravação contínua de vídeo) Cvr O vídeo é gravado 24 horas por dia, 7 dias por semana. Requer uma assinatura (por exemplo, Google Home Premium.
EBR (gravação baseada em eventos) Ebr A gravação é acionada por eventos (pessoa, movimento). A duração do vídeo depende da duração do evento e da assinatura.
ETR (gravação acionada por eventos) Etr Gravação de prévia curta (por exemplo, 10 segundos) acionada por eventos.
Visualização ao vivo LiveView A gravação está desativada, mas os usuários ainda podem acessar a transmissão ao vivo.
Imagens estáticas Images Os instantâneos são gravados em vez de vídeos quando ocorrem eventos.

Verificar modos de gravação

Para mostrar a configuração de gravação atual, verifique os atributos da característica 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,
      )
    )
  }
}

Mudar o modo de gravação

Antes de atualizar, verifique se o índice escolhido do atributo supportedRecordingModes está presente no atributo availableRecordingModes.

Para atualizar o modo selecionado, use a função setSelectedRecordingMode, transmitindo o índice do modo escolhido:

let recordingModeTrait: Google.RecordingModeTrait
let recordingModeID: UInt8

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

Outras configurações

Várias outras configurações podem ser controladas pelas APIs do Google Home.

Mudar a orientação da imagem

A orientação da imagem da câmera (vídeo) pode ser girada. O vídeo só pode ser girado em 180 graus.

Para mudar a orientação da imagem da câmera, atualize o imageRotation atributo da característica CameraAvStreamManagementTrait usando a função setImageRotation integrada:

// Change the camera's image orientation
// Value must be 0 or 180
func setImageRotation(to value: UInt16) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setImageRotation(value)
    }
  } catch {
    // Error
  }
}

Ativar ou desativar a visão noturna

Para ativar ou desativar a visão noturna da câmera, use TriStateAutoEnum para atualizar o nightVision atributo da característica CameraAvStreamManagementTrait usando a função setNightVision integrada:

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

Mudar o brilho do LED de status

Para mudar o brilho do LED de status, use ThreeLevelAutoEnum para atualizar o atributo statusLightBrightness da característica CameraAvStreamManagementTrait usando a função setStatusLightBrightness integrada:

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

Mudar a janela de visualização da câmera

A janela de visualização da câmera é a mesma que o recurso de zoom e corte descrito no Zoom e modo Enhance no vídeo da câmera Nest artigo de suporte.

A janela de visualização é definida em um ViewportStruct que contém quatro valores, que são usados como as coordenadas da janela de visualização. As coordenadas são definidas como:

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

A determinação dos valores do ViewportStruct depende da interface do app e da implementação da câmera. Em um nível muito básico, para definir a janela de visualização do vídeo da câmera, atualize o viewport atributo da característica CameraAvStreamManagementTrait com um ViewportStruct, usando a função setViewport integrada.

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

}

Gerar um TransportOptionsStruct

Algumas configurações exigem modificações nas propriedades de um TransportOptionsStruct, que é transmitido para as opções de transporte de uma conexão de streaming. Para Swift, essa estrutura precisa ser gerada antes de atualizar qualquer propriedade.

Use esta função auxiliar para gerar a estrutura para uso com as seguintes mudanças de configuração:

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
}

Ajustar a sensibilidade de ativação do dispositivo

A sensibilidade de ativação do dispositivo é usada para conservar a bateria, diminuindo o alcance em que o dispositivo pode detectar atividades e aumentando o tempo de ativação após detectar essa atividade.

Nas APIs do Google Home, isso pode ser definido usando a propriedade motionSensitivity do triggerOptions no transportOptions do dispositivo. Essas opções são definidas na característica PushAvStreamTransportTrait para cada dispositivo.

A sensibilidade de ativação só pode ser definida com os seguintes valores:

  • 1 = baixa
  • 5 = média
  • 10 = alta

O processo de atualização é encontrar a configuração de transporte para streams de gravação ativos usando o findTransport comando e modificar a configuração com o novo valor de sensibilidade usando o modifyPushTransport comando.

O comando modifyPushTransport exige que o TransportOptionsStruct completo seja transmitido. Portanto, primeiro copie os valores atuais da configuração. Consulte Gerar um TransportOptionsStruct para uma função auxiliar para fazer isso.

func setWakeUpSensitivity(to value: UInt8) async {
  do {
    let connection = try await getRecordingConnection()
    guard let connection,
      let transportOptions = connection.transportOptions
    else {
      // Error - Transport options not available
      return
    }

    guard transportOptions.triggerOptions.motionSensitivity != nil else {
      // Error - Motion sensitivity not available to be updated for this device
      return
    }

    try await pushAvStreamTransportTrait.modifyPushTransport(
      connectionID: connection.connectionID,
      transportOptions: self.getTransportOptions(
        transportOptions: transportOptions,
        wakeUpSensitivity: value,
        maxEventLength: nil
      )
    )

  } catch {
    // Error
  }
}

Ajustar a duração máxima de eventos

A duração máxima de eventos é o período de tempo em que a câmera vai gravar um clipe para um evento. Nas APIs do Google Home, isso pode ser configurado, por dispositivo, com as mesmas durações que no Google Home app (GHA), em intervalos de segundos:

  • 10 segundos
  • 15 segundos
  • 30 segundos
  • 60 segundos (1 minuto)
  • 120 segundos (2 minutos)
  • 180 segundos (3 minutos)

Nas APIs do Google Home, isso pode ser definido usando a propriedade motionTimeControl do triggerOptions no transportOptions do dispositivo. Essas opções são definidas na característica PushAvStreamTransportTrait para cada dispositivo.

O processo de atualização é encontrar a configuração de transporte para streams de gravação ativos usando o findTransport comando e modificar a configuração com o novo valor de duração do evento usando o modifyPushTransport comando.

O comando modifyPushTransport exige que o TransportOptionsStruct completo seja transmitido. Portanto, primeiro copie os valores atuais da configuração. Consulte Gerar um TransportOptionsStruct para uma função auxiliar para fazer isso.

func setMaxEventLength(to value: UInt32) async {
  do {
    let connection = try await getRecordingConnection()
    guard let connection,
      let transportOptions = connection.transportOptions
    else {
      // Error - Transport options not available
      return
    }

    guard transportOptions.triggerOptions.motionTimeControl != nil else {
      // Error - Motion time control not available to be updated for this device
      return
    }

    try await pushAvStreamTransportTrait.modifyPushTransport(
      connectionID: connection.connectionID,
      transportOptions: self.getTransportOptions(
        transportOptions: transportOptions,
        wakeUpSensitivity: nil,
        maxEventLength: value
      )
    )

  } catch {
    // Error
  }
}

Ativar ou desativar a análise

Cada dispositivo pode ativar individualmente o envio de dados de análise detalhados para a nuvem do Google Home (consulte Cloud Monitoring para APIs do Google Home).

Para ativar a análise de um dispositivo, defina a analyticsEnabled) propriedade da ExtendedGeneralDiagnosticsTrait como true. Quando você define analyticsEnabled, outra propriedade, logUploadEnabled, é definida automaticamente como true, o que permite que os arquivos de registro de análise sejam enviados para a nuvem do Google Home.

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

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