Android 카메라 기기 가이드

카메라 기기 유형은 푸시 기반 프로토콜을 사용하여 오디오 및 동영상 스트림 전송을 처리하는 PushAvStreamTransport와 라이브 스트림 및 토크백을 제어하는 기능을 제공하는 WebRtcLiveView의 두 가지 특성을 사용하여 구현됩니다.

기능을 사용하거나 속성을 업데이트하려고 시도하기 전에 항상 기기의 속성 및 명령어 지원을 확인하세요. 자세한 내용은 Android에서 기기 제어를 참고하세요.

Home API 기기 유형 특성 Kotlin 샘플 앱 사용 사례

카메라

GoogleCameraDevice

home.matter.6006.types.0158

정지 이미지나 동영상을 캡처하는 기기 카메라에는 액세스 가능한 라이브 스트림, 양방향 대화 또는 감지 활동이 포함될 수 있습니다.

필수 특성
     google PushAvStreamTransport
     google WebRtcLiveView

카메라

기기에 관한 기본 정보 가져오기

BasicInformation 특성에는 공급업체 이름, 공급업체 ID, 제품 ID, 제품 이름 (모델 정보 포함), 기기의 소프트웨어 버전과 같은 정보가 포함됩니다.

// Get device basic information. All general information traits are on the RootNodeDevice type.
    device.type(RootNodeDevice).first().standardTraits.basicInformation?.let { basicInformation ->
        println("vendorName ${basicInformation.vendorName}")
        println("vendorId ${basicInformation.vendorId}")
        println("productId ${basicInformation.productId}")
        println("productName ${basicInformation.productName}")
        println("softwareVersion ${basicInformation.softwareVersion}")
    }

일련번호 가져오기

기기의 일련번호를 가져오려면 ExtendedBasicInformation 특성의 GetSerialNumber 명령어를 사용합니다. 이 예에서는 일련번호를 serialNumber라는 변수에 저장하는 방법을 보여줍니다.

val basicInfo: ExtendedBasicInformation = device.getTrait(ExtendedBasicInformation)
val serialNumber = basicInfo.getSerialNumber().serialNumber

기기 클라우드 접촉의 가장 최근 시간 가져오기

기기가 클라우드와 접촉한 가장 최근 시간을 찾으려면 ExtendedGeneralDiagnostics 트레이트의 lastContactTimestamp 속성을 사용하세요.

fun getLastContactTimeStamp(trait: ExtendedGeneralDiagnostics): java.time.Instant {
  val timestamp = trait.lastContactTimestamp
  return Instant.ofEpochSecond(timestamp.toLong())
}

카메라 마운트 유형 설정

Mount 특성에는 카메라 장착 설정과 상태 정보가 포함됩니다. 마운트 상태, 감지 유형, 마운트 유형 이름과 같은 속성을 읽을 수 있습니다. 또한 Mount 트레이트를 사용하여 기본 마운트 유형 구성을 재정의할 수 있습니다.

// Get the Mount trait
val mountTrait: Mount = device.getTrait(Mount)

// Read the current mount state and detection type
val mountState = mountTrait.mountState
val mountDetectionType = mountTrait.mountDetectionType

// Read the current mount type name
val mountTypeName = mountTrait.mountTypeName

// Update the mount type override
mountTrait.update {
  setMountTypeOverride(MountTrait.MountTypeOverrideEnum.Official)
}

기기의 연결 확인

일부 기기는 여러 기기 유형을 지원하므로 기기의 연결은 실제로 기기 유형 수준에서 확인됩니다. 반환된 상태는 해당 기기의 모든 특성의 연결 상태를 조합한 것입니다.

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

인터넷 연결이 없는 경우 기기 유형이 혼합된 경우 PARTIALLY_ONLINE 상태가 관찰될 수 있습니다. Matter 표준 특성은 로컬 라우팅으로 인해 온라인 상태일 수 있지만 클라우드 기반 특성은 오프라인 상태입니다.

기기의 IP 주소 가져오기

기기의 IP 주소를 찾으려면 GeneralDiagnostics 트레이트의 networkInterfaces 속성을 사용합니다. 주소는 바이트 배열로 반환되며, 이를 표준 IPv4 또는 IPv6 문자열로 형식화할 수 있습니다.

val ipAddresses =
  trait.networkInterfaces?.flatMap { networkInterface ->
    (networkInterface.ipv4Addresses + networkInterface.ipv6Addresses).mapNotNull { bytes ->
      try {
        java.net.InetAddress.getByAddress(bytes).hostAddress
      } catch (e: java.net.UnknownHostException) {
        null
      }
    }
  } ?: emptyList()

라이브 스트림 시작

라이브 스트림을 시작하려면 세션 설명 프로토콜 (SDP) 문자열을 WebRtcLiveView 특성의 startLiveView() 메서드로 전송합니다. 이 메서드는 다음 세 값을 포함하는 WebRtcLiveViewTrait.StartLiveViewCommand.Response를 반환합니다.

  • 세션의 SDP입니다.
  • 세션 시간(초)입니다.
  • 세션을 연장하거나 종료하는 데 사용할 수 있는 세션 ID입니다.
suspend fun getWebRtcLiveViewTrait(cameraDevice: HomeDevice) {
 return cameraDevice.type(GoogleCameraDevice).trait(WebRtcLiveView).first {
    it?.metadata?.sourceConnectivity?.connectivityState == ConnectivityState.ONLINE
  }

}

// Start the live view
suspend fun startCameraStream(trait: WebRtcLiveView, offerSdp: String) {
  val response = trait.startLiveView(offerSdp)
  // Response contains three fields (see below)
  return response
}
  ...

// This is used to manage the WebRTC connection
val peerConnection: RTCPeerConnection = ...

   ...

val startResponse = startCameraStream(sdp)
val answerSdp = startResponse?.answerSdp
val sessionDuration = startResponse?.liveSessionDurationSeconds
val mediaSessionId = startResponse?.mediaSessionId

peerConnection.setRemoteDescription(SessionDescription.Type.ANSWER,
                                    answerSdp)

라이브 스트림 연장하기

라이브 스트림에는 만료되는 사전 설정 기간이 있습니다. 활성 스트림의 기간을 늘리려면 WebRtcLiveView.extendLiveView() 메서드를 사용하여 연장 요청을 실행합니다.

// Assuming camera stream has just been started
suspend fun scheduleExtension(trait: WebRtcLiveView, mediaSessionId: String, liveSessionDurationSeconds: UShort ) {
  delay(liveSessionDurationSeconds - BUFFER_SECONDS * 1000)
  val response = trait.extendLiveView(mediaSessionId)
  // returns how long the session will be live for
  return response.liveSessionDurationSeconds
}

TalkBack 시작 및 중지

토크백을 시작하려면 WebRtcLiveView 트레이트의 startTalkback() 메서드를 호출합니다. 중지하려면 stopTalkback()를 사용합니다.

// Make sure camera stream is on
suspend fun setTalkback(isOn: Boolean, trait: WebRtcLiveView, mediaSessionId: String) {
  if(isOn) {
    trait.startTalkback(mediaSessionId)
  } else {
    trait.stopTalkback(mediaSessionId)
  }
}

라이브 스트림 관리

라이브 스트림 품질을 조정하면 클라이언트의 시청 컨텍스트에 따라 대역폭 사용량을 최적화할 수 있습니다 (예: 작은 미리보기 타일, 그리드로 보기 또는 PIP 모드를 표시할 때 해상도를 낮춤).

WebRtcLiveView 특성을 사용하여 품질을 동적으로 변경하면 특정 클라이언트에서 활성 라이브 스트림 세션의 해상도가 특별히 관리됩니다. 기기에서 직접 기기 전체 대역폭 사용량 설정을 구성하는 것과는 다릅니다. 기기 전체 대역폭 사용량 설정은 모든 동시 시청자와 클라우드에 저장된 이전 동영상 녹화의 품질에 영향을 미칩니다.

다음 예에서는 기기의 라이브 스트림 품질을 가져오고 업데이트하는 방법을 보여줍니다.

  • 지원되는 품질 옵션 가져오기: 기기에서 지원하는 사용 가능한 스트리밍 해상도를 가져옵니다. 이 코드는 기기 유형 흐름에서 WebRtcLiveView 특성의 supportedQualityHints 속성을 쿼리하고 지원되는 품질을 QualityHint 값 목록 (예: QUALITY_HINT_SD, QUALITY_HINT_HD, QUALITY_HINT_FHD, QUALITY_HINT_QHD 또는 QUALITY_HINT_UHD)이 포함된 StateFlow로 노출합니다.

  • 라이브 스트림 품질 변경: 선택한 QualityHint을 적용하여 활성 라이브 스트림의 스트리밍 해상도를 변경합니다(예: 표준 화질에서 고화질로 전환). changeQuality 함수는 기기의 라이브 스트리밍 트레이트를 확인하고 활성 mediaSessionId 및 원하는 QualityHint 구성으로 changeLiveViewQuality을 호출합니다.

// Assuming you have a HomeDevice instance 'device'
val availableQualityHints: StateFlow<List> =
    device.type(GoogleCameraDevice)
        .trait(WebRtcLiveView)
        .map { trait -> 
            trait?.supportedQualityHints ?: emptyList() 
        }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())

// Assuming you have a HomeDevice instance 'device'
suspend fun changeQuality(mediaSessionId: String, qualityHint: QualityHint) {
    // Get the trait from the device
    val trait = device.type(GoogleCameraDevice).trait(WebRtcLiveView).first() ?: return
    try {
        trait.changeLiveViewQuality(mediaSessionId, qualityHint)
    } catch (e: Exception) {
        // Handle error
    }
}

녹화 기능 사용 설정 및 중지

카메라의 녹화 기능을 사용 설정하려면 PushAvStreamTransport 특성의 setTransportStatus() 메서드에 TransportStatusEnum.Active를 전달합니다. 녹화 기능을 사용 중지하려면 TransportStatusEnum.Inactive를 전달하세요. 다음 예에서는 Boolean를 사용하여 녹화 기능을 전환하는 단일 호출로 이러한 호출을 래핑합니다.

// Start or stop recording for all connections.
suspend fun setCameraRecording(trait: PushAvStreamTransport, isOn: Boolean) {
  if(isOn) {
    trait.setTransportStatus(TransportStatusEnum.Active)
  } else {
    trait.setTransportStatus(TransportStatusEnum.Inactive)
  }
}

카메라의 녹화 기능을 사용 설정하거나 사용 중지하는 것은 카메라 동영상을 켜거나 끄는 것과 같습니다. 카메라 동영상이 켜져 있으면 활동 및 관련 클립을 위해 녹화됩니다.

녹화 기능이 사용 중지된 경우 (카메라 동영상이 꺼져 있음):

  • 카메라가 기기 유형의 connectivityState에 따라 온라인으로 표시될 수 있습니다.
  • 실시간 스트림에 액세스할 수 없으며 카메라에서 클라우드 활동을 감지하지 못합니다.

녹화 기능이 사용 설정되어 있는지 확인

카메라의 녹화 기능이 사용 설정되어 있는지 확인하려면 활성 연결이 있는지 확인하세요. 다음 예에서는 이를 수행하는 두 함수를 정의합니다.

// Get the on/off state
suspend fun onOffState(pushAvStreamTransport: PushAvStreamTransport) {
  return pushAvStreamTransport
    .currentConnections?.any { it.transportStatus == TransportStatusEnum.Active } ?: false
}

// Check if the camera's recording capability is enabled
fun PushAvStreamTransport.recordModeActive(): Boolean {
  return currentConnections?.any { it.transportStatus == TransportStatusEnum.Active } ?: false
}

또 다른 확인 방법은 술어와 함께 findTransport() 함수를 사용하는 것입니다.

// Fetch the current connections
suspend fun queryRecordModeState(trait: PushAvStreamTransport) {
  return trait.findTransport().let {
      it.transportConfigurations.any { it.transportStatus == TransportStatusEnum.Active
    }
}

배터리 설정

Home API를 통해 다양한 배터리 설정을 제어할 수 있습니다.

배터리 사용량 환경설정 설정

에너지 균형을 설정하면 기기의 배터리 수명과 성능 간의 절충을 구성할 수 있습니다. '확장', '균형', '성능'과 같은 다양한 배터리 프로필을 만들고 프로필 간에 전환할 수 있습니다.

이 기능은 EnergyPreference 특성의 currentEnergyBalance 속성을 업데이트하여 구현됩니다. 이 속성은 기기의 energyBalances 목록에 정의된 특정 프로필에 해당하는 정수 색인을 허용합니다 (예: EXTENDED의 경우 0, BALANCED의 경우 1, PERFORMANCE의 경우 2).

currentEnergyBalancenull 값은 기기에서 맞춤 프로필을 사용하고 있음을 나타냅니다. 읽기 전용 상태입니다.

다음은 currentEnergyBalance 속성이 사용할 구조의 예와 속성을 사용하는 실제 코드 스니펫을 보여줍니다.

// Example energyBalances list
energy_balances: [
  {
    step: 0,
    label: "EXTENDED"
  },
  {
    step: 50,
    label: "BALANCED"
  },
  {
    step: 100,
    label: "PERFORMANCE"
  }
]
// The index parameter must be within the UByte range (0-255).
suspend fun setEnergyBalance(trait: EnergyPreference, index: Int) {
  trait.update { setCurrentEnergyBalance(index.toUByte()) }
}

// Setting the battery usage to more recording ie performance
setEnergyBalance(energyPreference, 2)

자동 절전 모드 사용 설정하기

이 기능을 구성하려면 EnergyPreference 특성의 currentLowPowerModeSensitivity 속성을 업데이트하세요. 이 속성은 색인을 사용하여 민감도 수준을 선택합니다. 여기서 0은 일반적으로 Disabled을 나타내고 1Enabled 또는 Automatic을 나타냅니다.

suspend fun setAutomaticBatterySaver(enable: Boolean, trait: EnergyPreference) {
  // 0 is Disabled, 1 is Enabled
  val value = if (enable) 1.toUByte() else 0.toUByte()
  trait.update { setCurrentLowPowerModeSensitivity(value) }
}

배터리 충전 상태 가져오기

기기의 현재 충전 상태 (충전 중, 완전 충전, 충전 안 됨)를 가져오려면 PowerSource 특성의 batChargeState 속성을 사용하세요.

// Get the battery charging state
val batteryChargeState = powerSource.batChargeState

when (batteryChargeState) {
    PowerSourceTrait.BatChargeStateEnum.IsCharging -> "Charging"
    PowerSourceTrait.BatChargeStateEnum.IsAtFullCharge -> "Full"
    PowerSourceTrait.BatChargeStateEnum.IsNotCharging -> "Not Charging"
    else -> "Unknown"
}

배터리 잔량 가져오기

현재 배터리 잔량을 가져오려면 PowerSource 특성의 batChargeLevel 속성을 사용합니다. 수준은 OK, Warning (낮음) 또는 Critical입니다.

// Get the battery charge level
val batteryLevel = powerSourceTrait.batChargeLevel

when (batteryLevel) {
    PowerSourceTrait.BatChargeLevelEnum.OK -> "OK"
    PowerSourceTrait.BatChargeLevelEnum.Warning -> "Warning"
    PowerSourceTrait.BatChargeLevelEnum.Critical -> "Critical"
    else -> "Unknown"
}

전원 가져오기

기기에서 사용하는 전원 소스를 확인하려면 PowerSource 특성의 BatPresentwiredPresent 속성을 사용하세요.

  val trait: PowerSource
  val isWired = trait.wiredPresent
  val hasBattery = trait.batPresent

오디오 설정

Home API를 통해 다양한 오디오 설정을 제어할 수 있습니다.

마이크 켜거나 끄기

기기의 마이크를 켜거나 끄려면 내장된 setMicrophoneMuted Kotlin 함수를 사용하여 CameraAvStreamManagement 특성의 microphoneMuted 속성을 업데이트합니다.

// Turn the device's microphone on or off
suspend fun turnOffMicrophone(disableMicrophone: Boolean, trait: CameraAvStreamManagement) {
  trait.update { setMicrophoneMuted(disableMicrophone) }
}

오디오 녹음 사용 설정 또는 사용 중지하기

기기의 오디오 녹음을 사용 설정 또는 중지하려면 내장된 setRecordingMicrophoneMuted Kotlin 함수를 사용하여 CameraAvStreamManagement 특성의 recordingMicrophoneMuted 속성을 업데이트합니다.

// Turn audio recording on or off for the device
suspend fun turnOffAudioRecording(disableAudioRecording: Boolean, trait: CameraAvStreamManagement) {
  trait.update { setRecordingMicrophoneMuted(disableAudioRecording) }
}

스피커 볼륨 조정

기기의 스피커 볼륨을 조정하려면 내장된 setSpeakerVolumeLevel Kotlin 함수를 사용하여 CameraAvStreamManagement 특성의 speakerVolumeLevel 속성을 업데이트합니다.

// Adjust the camera speaker volume
suspend fun adjustSpeakerVolume(volume: Int, trait: CameraAvStreamManagement) {
  trait.update { setSpeakerVolumeLevel(volume.toUbyte()) }
}

활동 감지 구역 설정

ZoneManagement 트레이트는 카메라 및 초인종 기기에서 맞춤 관심 영역 (활동 감지 구역)을 관리하는 인터페이스를 제공합니다. 이러한 영역은 기기의 시야 내 특정 영역으로 활동 감지 (예: 사람 또는 차량 움직임)를 필터링하는 데 사용됩니다.

활동 감지 구역은 파트너 애플리케이션 내에서 사용자가 구성하며, 이를 통해 카메라의 시야 내 특정 영역에 구역을 그릴 수 있습니다. 그러면 이러한 사용자 정의 영역이 이 특성에서 사용되는 구조로 변환됩니다. 활동 감지 구역의 작동 방식에 대한 자세한 내용은 활동 감지 구역 설정 및 사용하기를 참고하세요.

활동 영역은 일반적으로 2D 데카르트 좌표를 사용하여 정의됩니다. 이 특성은 꼭짓점의 TwoDCartesianVertexStruct과 영역 정의 (이름, 꼭짓점, 색상, 사용)의 TwoDCartesianZoneStruct을 제공합니다.

활동 감지 구역 확인

활동 감지 구역을 표시하려면 ZoneManagement 트레이트의 zones 속성을 확인하세요.

// 1. Obtain the trait flow from the device
private val zoneManagementFlow: Flow =
  device.type(CAMERA_TYPE).flatMapLatest { it.trait(ZoneManagement) }

// 2. Map the flow to the list of zone structures
val activityZones: Flow<List<ZoneManagementTrait.ZoneInformationStruct>> =
  zoneManagementFlow.map { trait ->
    trait.zones ?: emptyList()
  }

활동 감지 구역 추가

새 영역을 만들려면 createTwoDCartesianZone 명령어를 사용합니다. 이 명령어는 영역의 이름, 꼭짓점, 색상, 사용을 정의하는 TwoDCartesianZoneStruct를 사용합니다.

다음 예에서는 4개의 꼭짓점이 있고, 색상이 연어색 (#F439A0)이며, 움직임 감지에 사용되는 '현관'이라는 영역을 만드는 방법을 보여줍니다.

import com.google.home.google.ZoneManagement
import com.google.home.google.ZoneManagementTrait
import com.google.home.matter.serialization.OptionalValue

/**
 * Creates a custom activity zone named "Front Porch" with a salmon color
 * configured for motion detection.
 */
suspend fun createFrontPorchZone(zoneManagement: ZoneManagement) {
  // 1. Define the vertices for the zone (2D Cartesian coordinates)
  // Values are typically scaled to a maximum defined by the device's twoDCartesianMax attribute.
  val vertices =
    listOf(
      ZoneManagementTrait.TwoDCartesianVertexStruct(x = 260u, y = 422u),
      ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1049u, y = 0u),
      ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048u, y = 0u),
      ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048u, y = 950u),
      ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1630u, y = 1349u),
      ZoneManagementTrait.TwoDCartesianVertexStruct(x = 880u, y = 2048u),
      ZoneManagementTrait.TwoDCartesianVertexStruct(x = 0u, y = 2048u),
      ZoneManagementTrait.TwoDCartesianVertexStruct(x = 638u, y = 1090u)
    )

  // 2. Define the zone structure
  val newZone =
    ZoneManagementTrait.TwoDCartesianZoneStruct(
      name = "Front Porch",
      vertices = vertices,
      // Usage defines what the zone filters (for example, Motion, Person, Vehicle)
      use = listOf(ZoneManagementTrait.ZoneUseEnum.Motion),
      // Color is typically a hex string (for example, Salmon/Pink)
      color = OptionalValue.present("#F439A0")
    )

  try {
    // 3. Execute the command to add the zone to the device
    zoneManagement.createTwoDCartesianZone(newZone)
    println("Successfully created activity zone.")
  } catch (e: Exception) {
    // Handle potential HomeException or Timeout
    println("Failed to create activity zone: ${e.message}")
  }
}

활동 감지 영역 업데이트하기

기존 영역을 업데이트하려면 updateTwoDCartesianZone 명령어를 사용합니다. 이 명령어에는 zoneId와 업데이트된 TwoDCartesianZoneStruct이 필요합니다.

private suspend fun ZoneManagement.updateZone(
  zoneId: UShort,
  zone: ZoneManagementTrait.TwoDCartesianZoneStruct
) {
  // Execute the command to update the zone
  this.updateTwoDCartesianZone(zoneId = zoneId, zone = zone)
}

활동 감지 구역 삭제하기

영역을 삭제하려면 특정 zoneId와 함께 removeZone 명령어를 사용합니다.

private suspend fun ZoneManagement.deleteZone(zoneId: UShort) {
  // Execute the command to remove the zone
  this.removeZone(zoneId = zoneId)
}

소리 이벤트 트리거

AvStreamAnalysis 트레이트는 카메라 및 초인종 기기에서 이벤트 감지 트리거를 관리하는 인터페이스를 제공합니다. 비전 기반 트리거(예: 사람 또는 차량)는 구역별로 설정할 수 있지만 소리 관련 트리거는 일반적으로 기기 수준 구성입니다.

EventTriggerTypeEnum을 사용한 소리 감지에는 다음 트리거 유형을 사용할 수 있습니다.

모드 enum 값 설명
소리 Sound 일반 소리 감지
말소리 PersonTalking 음성을 감지합니다.
개 짖는 소리 DogBark 개 소리를 감지합니다.
유리 깨지는 소리 GlassBreak 유리 깨지는 소리를 감지합니다.
연기 경보 SmokeAlarm 연기 경보를 감지합니다. T3 가청 패턴 (짧은 경고음 3회 후 일시중지)으로 인식되는 경우가 많습니다.
일산화탄소 경보 CoAlarm 일반적으로 T4 청각 패턴 (짧은 경고음 4회 후 일시중지)으로 인식되는 일산화탄소 (CO) 경보를 감지합니다.

소리 감지 상태 확인

사용자에게 소리 감지의 현재 상태를 표시하려면 기기에서 지원하는 기능과 기기 하드웨어에서 사용 설정된 기능을 확인해야 합니다. 확인할 두 가지 속성은 다음과 같습니다.

Kotlin 흐름을 사용하는 Android 개발에서는 일반적으로 HomeDevice에서 AvStreamAnalysis 특성을 관찰합니다.

// Example structure to store the
data class EventTriggerAttribute(val type: EventTriggerTypeEnum, val enabled: Boolean)

// 1. Obtain the trait flow from the device
private val avStreamAnalysisFlow: Flow<AvStreamAnalysis> =
  device.traitFromType(AvStreamAnalysis, CAMERA_TYPES.first { device.has(it) })

// 2. Map the flow to a list of sound event attributes
val soundEventTriggersState: Flow<List<EventTriggerAttribute>> =
  avStreamAnalysisFlow.map { trait ->
    // Get raw lists from the trait attributes
    val supported = trait.supportedEventTriggers ?: emptyList()
    val enabled = trait.enabledEventTriggers ?: emptyList()

    // Define sound-specific triggers to filter for
    val soundTypes = setOf(
      EventTriggerTypeEnum.Sound,
      EventTriggerTypeEnum.PersonTalking,
      EventTriggerTypeEnum.DogBark,
      EventTriggerTypeEnum.GlassBreak,
      EventTriggerTypeEnum.SmokeAlarm,
      EventTriggerTypeEnum.CoAlarm,
    )

    // Filter and associate status
    supported
      .filter { soundTypes.contains(it) }
      .map { type ->
        EventTriggerAttribute(
          type = type,
          enabled = enabled.contains(type)
        )
      }
  }

사용 설정된 트리거 집합 업데이트

사용 설정된 트리거 집합을 업데이트하려면 EventTriggerEnablement 구조 목록을 사용하는 SetOrUpdateEventDetectionTriggers 명령어를 사용합니다.

private suspend fun AvStreamAnalysis.updateEventTriggers(
  eventTriggers: List<EventTriggerAttribute>
) {
  val toUpdate = eventTriggers.map {
    EventTriggerEnablement(
      eventTriggerType = it.type,
      enablementStatus = if (it.enabled) {
        EnablementStatusEnum.Enabled
      } else {
        EnablementStatusEnum.Disabled
      },
    )
  }

  // Execute the command on the device
  setOrUpdateEventDetectionTriggers(toUpdate)
}

녹화 모드

RecordingMode 트레이트는 카메라 및 초인종 기기에서 동영상 및 이미지 녹화 동작을 관리하는 인터페이스를 제공합니다. 사용자는 연속 녹화, 활동 기반 녹화 또는 녹화 완전 사용 중지 (실시간 보기 전용) 중에서 선택할 수 있습니다.

RecordingModeEnum는 사용 가능한 녹화 전략을 정의합니다.

모드 enum 값 설명
사용 중지됨 Disabled 녹화가 완전히 사용 중지됩니다. 주로 기존 기기에서 사용됩니다.
CVR (연속 동영상 녹화) Cvr 동영상은 연중무휴로 녹화됩니다. 구독이 필요합니다(예: Google Home Premium).
EBR (활동 기반 녹화) Ebr 녹화는 이벤트 (사람, 움직임)에 의해 트리거됩니다. 동영상 길이는 이벤트 기간과 구독에 따라 다릅니다.
ETR (이벤트 트리거 녹화) Etr 이벤트에 의해 트리거되는 짧은 미리보기 녹화 (예: 10초)
실시간 보기 LiveView 녹화가 사용 중지되었지만 사용자는 라이브 스트림에 계속 액세스할 수 있습니다.
정지 이미지 Images 이벤트가 발생하면 동영상 대신 스냅샷이 녹화됩니다.

녹화 모드 확인

현재 녹화 구성을 표시하려면 RecordingMode 특성의 속성을 확인하세요.

// 1. Obtain the trait flow from the device
private val recordingModeTraitFlow: Flow =
    device.traitFromType(RecordingMode, CAMERA_TYPES.first { device.has(it) })

// 2. Map the flow to recording mode options
data class RecordingModeOptions(
    val recordingMode: RecordingModeTrait.RecordingModeEnum,
    val index: Int,
    val available: Boolean,
    val readableString: String,
)

private val recordingModeOptions: Flow<List> =
    recordingModeTraitFlow.map { trait ->
        val supported = trait.supportedRecordingModes?.map { it.recordingMode } ?: emptyList()
        val available = trait.availableRecordingModes?.map { it.toInt() } ?: emptyList()

        supported.withIndex().map { (index, mode) ->
            RecordingModeOptions(
                recordingMode = mode,
                index = index,
                available = available.contains(index),
                readableString = mode.toReadableString(),
            )
        }
    }

녹화 모드 변경

업데이트하기 전에 supportedRecordingModes 속성에서 선택한 색인이 availableRecordingModes 속성에 있는지 확인합니다.

선택한 모드를 업데이트하려면 선택한 모드의 색인을 전달하여 setSelectedRecordingMode 함수를 사용합니다.

private suspend fun RecordingMode.updateRecordingMode(index: Int) {
    // Execute the command to update the selected mode
    this.setSelectedRecordingMode(index.toUByte())
}

기타 설정

Home API를 통해 다양한 기타 설정을 제어할 수 있습니다.

이미지 방향 변경

카메라 이미지 (동영상)의 방향을 회전할 수 있습니다. 동영상은 180도만 회전할 수 있습니다.

카메라의 이미지 방향을 변경하려면 내장된 setImageRotation Kotlin 함수를 사용하여 CameraAvStreamManagement 특성의 imageRotation 속성을 업데이트합니다.

// Change the camera's image orientation
val isRotated = false

cameraAvStreamManagement.update { setImageRotation(if (isRotated) 180.toUShort() else 0.toUShort()) }

야간 적외선 조명 사용 또는 사용 중지하기

카메라의 야간 모드를 사용 설정하거나 사용 중지하려면 TriStateAutoEnum를 사용하여 내장 setNightVision Kotlin 함수를 사용하여 CameraAvStreamManagement 특성의 nightVision 속성을 업데이트합니다.

// Turn night vision on
cameraAvStreamManagement.update {
  setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.On)
}

// Turn night vision off
CameraAvStreamManagement.update {
  setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.Off)
}

상태 LED 밝기 변경

상태 LED의 밝기를 변경하려면 ThreeLevelAutoEnum를 사용하여 내장 setStatusLightBrightness Kotlin 함수를 사용하여 CameraAvStreamManagement 특성의 statusLightBrightness 속성을 업데이트합니다.

// Set the LED brightness to high
cameraAvStreamManagement.update {
  setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.High)
}

// Set the LED brightness to low
cameraAvStreamManagement.update {
  setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.Low)
}

카메라 표시 영역 변경

카메라 뷰포트는 Nest 카메라 동영상 확대/축소 및 개선 지원 도움말에 설명된 확대/축소 및 자르기 기능과 동일합니다.

뷰포트는 뷰포트의 좌표로 사용되는 네 개의 값이 포함된 ViewportStruct에 정의됩니다. 좌표는 다음과 같이 정의됩니다.

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

ViewportStruct 값을 결정하는 것은 앱의 UI와 카메라 구현에 따라 다릅니다. 매우 기본적인 수준에서 카메라 동영상의 뷰포트를 설정하려면 내장된 setViewport Kotlin 함수를 사용하여 ViewportStructCameraAvStreamManagement 특성의 viewport 속성을 업데이트합니다.

cameraAvStreamManagement
  .update { setViewport(
    CameraAvStreamManagementTrait.ViewportStruct(
      x1 = horizontalRange.rangeStart.roundToInt().toUShort(),
      x2 = horizontalRange.rangeEnd.roundToInt().toUShort(),
      y1 = verticalRange.rangeStart.roundToInt().toUShort(),
      y2 = verticalRange.rangeEnd.roundToInt().toUShort(),
    )
) }

분석 사용 설정 또는 사용 중지

각 기기는 Google Home 클라우드로 상세 분석 데이터를 전송하도록 개별적으로 선택할 수 있습니다 (Home API용 Cloud Monitoring 참고).

기기의 분석을 사용 설정하려면 ExtendedGeneralDiagnosticsTraitanalyticsEnabled 속성을 true로 설정합니다. analyticsEnabled를 설정하면 분석 로그 파일을 Google Home 클라우드에 업로드할 수 있도록 다른 속성인 logUploadEnabled이 자동으로 true로 설정됩니다.

// Enable analytics
extendedGeneralDiagnostics.update {
  setAnalyticsEnabled(true)
}

// Disable analytics
extendedGeneralDiagnostics.update {
  setAnalyticsEnabled(false)
}

전송 및 녹화 구성

이 섹션에서는 카메라 스트리밍 품질 및 이벤트 트리거와 관련된 설정을 다룹니다. 이러한 설정은 PushAvStreamTransport 트레이트로 관리됩니다.

전송 설정 읽기

이 섹션에서는 카메라 또는 초인종 기기에서 현재 구성을 가져오는 방법을 보여줍니다. PushAvStreamTransport 특성을 가져오고, 녹화에 사용된 특정 연결을 찾은 다음, 대역폭 품질, 카메라 센서 민감도, 최대 활동 길이의 현재 값을 추출합니다.

val trait: PushAvStreamTransport = device.getTrait(PushAvStreamTransport)
val connections = trait.findTransport().transportConfigurations

// Locate the connection designated for recording
val recordingConnection = connections.firstOrNull {
    it.transportOptions.getOrNull()?.streamUsage == StreamUsageEnum.Recording
}

val options = recordingConnection?.transportOptions?.getOrNull()

// 1. Bandwidth Quality (Video Stream ID)
val videoStreamId = options?.videoStreamId?.getOrNull()

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

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

전송 설정 업데이트

이 섹션에서는 전송 설정을 변경하는 방법을 보여줍니다. 새 값을 포함하는 새 TransportOptionsStruct를 만든 다음 modifyPushTransport 명령어를 사용하여 이러한 업데이트된 설정을 기기로 다시 전송하여 이전 단계에서 찾은 녹화 연결에 적용합니다.

이러한 설정을 수정하려면 TransportOptionsStruct와 함께 modifyPushTransport 명령어를 사용합니다.

val toUpdate = TransportOptionsStruct(
    videoStreamId = OptionalValue.present(2u), // e.g., Max Quality
    triggerOptions = TransportTriggerOptionsStruct(
        motionSensitivity = OptionalValue.present(5u), // e.g., Medium
        motionTimeControl = OptionalValue.present(
            TransportMotionTriggerTimeControlStruct(maxDuration = 30u)
        )
    )
)

if (recordingConnection != null) {
    trait.modifyPushTransport(
        connectionId = recordingConnection.connectionId,
        transportOptions = toUpdate
    )
}

대역폭 품질 확인

TransportOptionsStructvideoStreamId 속성은 특정 동영상 스트림 구성에 해당합니다.

지원되는 동영상 스트림을 가져오려면 VideoStreamStructs 목록인 allocatedVideoStreams 속성을 참고하세요. 기기의 CameraAvStreamManagement 특성에서 가져옵니다.

기기 카메라 센서 민감도 조정

TransportTriggerOptionsStructmotionSensitivity 속성은 다음 값에 해당합니다.

라벨 값 (UByte)
낮음 1u
보통 5u
높음 10u

최대 이벤트 길이 조정

TransportMotionTriggerTimeControlStructmaxDuration 속성은 다음 지속 시간 (초)에 해당합니다.

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