Android için kamera cihazı kılavuzu

Kamera cihaz türü üç özellik kullanılarak uygulanır: PushAvStreamTransport, push tabanlı protokolleri kullanarak ses ve video akışı aktarımını yönetir, WebRtcLiveView, canlı yayınları ve TalkBack'i kontrol etme olanağı sağlar ve CameraSnapshot, önbelleğe alınmış önizleme anlık görüntüleri ve canlı anlık görüntü yakalama özellikleri sunar.

Herhangi bir özelliği kullanmadan veya özellikleri güncellemeye çalışmadan önce her zaman cihazın özellik ve komut desteğini kontrol edin. Daha fazla bilgi için Androidcihazlarını kontrol etme başlıklı makaleyi inceleyin.

Home API'leri Cihaz Türü Özellikler Kotlin Örnek Uygulaması Kullanım Örneği

Kamera

GoogleCameraDevice

home.matter.6006.types.0158

Fotoğraf veya video çeken cihaz. Kameralarda erişilebilir canlı yayınlar, iki yönlü konuşma veya algılama etkinlikleri bulunabilir.

Gerekli Özellikler
     google PushAvStreamTransport
     google WebRtcLiveView

Kamera

Cihaz hakkında temel bilgileri alma

   Android için örnek uygulamada uygulanır   

BasicInformation özelliği; cihazın tedarikçi adı, tedarikçi kimliği, ürün kimliği, ürün adı (model bilgilerini içerir) ve yazılım sürümü gibi bilgileri içerir:

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

Seri numarasını alma

Cihazın seri numarasını almak için ExtendedBasicInformation özelliğinin GetSerialNumber komutunu kullanın. Örnekte, seri numarasının serialNumber adlı bir değişkene kaydedilmesi gösterilmektedir:

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

Cihazın bulutla en son iletişim kurduğu zamanı alma

Cihazın bulutla en son ne zaman iletişim kurduğunu öğrenmek için ExtendedGeneralDiagnostics özelliğinin lastContactTimestamp özelliğini kullanın:

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

Kamera montaj aparatı türü ayarları

Mount özelliği, kamera montaj ayarlarını ve durum bilgilerini içerir. Bağlantı durumu, algılama türü ve bağlantı türü adı gibi özellikleri okuyabilirsiniz. Ayrıca, varsayılan bağlama türü yapılandırmasını geçersiz kılmak için Mount özelliğini kullanabilirsiniz.

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

Cihazın bağlantısını kontrol etme

Bazı cihazlar birden fazla cihaz türünü desteklediğinden, bir cihazın bağlantısı aslında cihaz türü düzeyinde kontrol edilir. Döndürülen durum, söz konusu cihazdaki tüm özelliklerin bağlantı durumlarının birleşimidir.

val cameraConnectivity = cameraDevice.metadata.sourceConnectivity.connectivityState

İnternet bağlantısı olmadığında karma cihaz türleri için PARTIALLY_ONLINE durumu görülebilir. Yerel yönlendirme nedeniyle Matter standart özellik hâlâ çevrimiçi olabilir ancak bulut tabanlı özellikler çevrimdışı olur.

Cihazın IP adresini alma

Cihazın IP adresini bulmak için GeneralDiagnostics özelliğinin networkInterfaces özelliğini kullanın. Adresler, standart IPv4 veya IPv6 dizeleri olarak biçimlendirebileceğiniz bayt dizileri olarak döndürülür:

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

Canlı yayın başlatma

   Android için örnek uygulamada uygulanır   

Canlı yayın başlatmak için Oturum Açıklama Protokolü (SDP) dizesini WebRtcLiveView özelliğinin startLiveView() yöntemine gönderin. Bu yöntem, üç değer içeren bir WebRtcLiveViewTrait.StartLiveViewCommand.Response döndürür:

  • Oturumun SDP'si.
  • Saniye cinsinden oturum süresi.
  • Oturumu uzatmak veya sonlandırmak için kullanılabilecek oturum kimliği.
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)

Canlı yayını uzatma

   Android için örnek uygulamada uygulanır   

Canlı yayınların önceden ayarlanmış bir süresi vardır ve bu süre dolduğunda yayın sona erer. Etkin bir akışın süresini uzatmak için WebRtcLiveView.extendLiveView() yöntemini kullanarak uzatma isteği gönderin:

// 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'i başlatma ve durdurma

   Android için örnek uygulamada uygulanır   

TalkBack'i başlatmak için WebRtcLiveView özelliğinin startTalkback() yöntemini çağırın. Durdurmak için stopTalkback() tuşlarını kullanın.

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

Canlı yayını yönetme

Canlı yayın kalitesini ayarlamak, istemcinin görüntüleme bağlamına göre bant genişliği kullanımını optimize etmek için kullanışlıdır (ör. daha küçük bir önizleme karosu, tablo görünümü veya pencere içinde pencere modu gösterilirken daha düşük bir çözünürlüğe geçme).

WebRtcLiveView özelliğini kullanarak kaliteyi dinamik olarak değiştirmek, belirli bir istemcideki etkin canlı yayın oturumunun çözünürlüğünü yönetir. Bu, doğrudan cihaz üzerinde cihaz genelinde bant genişliği kullanım ayarı yapılandırmakla aynı şey değildir. Bu ayar, tüm eşzamanlı izleyicileri ve buluta kaydedilen geçmiş video kayıtlarının kalitesini etkiler.

Aşağıdaki örnekte, bir cihazın canlı yayın kalitesinin nasıl alınacağı ve güncelleneceği gösterilmektedir:

  • Desteklenen kalite seçeneklerini alma: Cihazın desteklediği kullanılabilir akış çözünürlüklerini alma Kod, cihaz türü akışında WebRtcLiveView özelliğinin supportedQualityHints özelliğini sorgular ve desteklenen nitelikleri QualityHint değerlerinin (QUALITY_HINT_SD, QUALITY_HINT_HD, QUALITY_HINT_FHD, QUALITY_HINT_QHD veya QUALITY_HINT_UHD gibi) listesini içeren bir StateFlow olarak gösterir.

  • Canlı yayın kalitesini değiştirme: Etkin canlı yayının çözünürlüğünü değiştirmek için seçili bir QualityHint uygulayın (ör. standart çözünürlükten yüksek çözünürlüğe geçiş). changeQuality işlevi, cihazın canlı yayın özelliğini çözer ve etkin mediaSessionId ve seçilen QualityHint yapılandırmasıyla changeLiveViewQuality işlevini çağırır.

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

Kayıt özelliğini etkinleştirme ve devre dışı bırakma

Kameranın kayıt özelliğini etkinleştirmek için PushAvStreamTransport özelliğinin setTransportStatus() yöntemine TransportStatusEnum.Active değerini iletin. Kayıt özelliğini devre dışı bırakmak için TransportStatusEnum.Inactive değerini iletin. Aşağıdaki örnekte, bu çağrıları kayıt özelliğini açıp kapatmak için Boolean kullanan tek bir çağrıda sarmalıyoruz:

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

Kameranın kayıt özelliğini etkinleştirmek veya devre dışı bırakmak, kamera videosunu açmak veya kapatmakla aynıdır. Bir kameranın videosu açık olduğunda kayıt yapar (etkinlikler ve ilgili klipler için).

Kayıt özelliği devre dışı bırakıldığında (kamera videosu kapalıyken):

  • Kamera, connectivityState cihaz türüne göre çevrimiçi olarak görünmeye devam edebilir.
  • Canlı yayına erişilemez ve kamera herhangi bir bulut etkinliği algılamaz.

Kayıt özelliğinin etkin olup olmadığını kontrol etme

Bir kameranın kayıt özelliğinin etkin olup olmadığını belirlemek için herhangi bir bağlantının etkin olup olmadığını kontrol edin. Aşağıdaki örnekte, bu işlemi gerçekleştirmek için iki işlev tanımlanmıştır:

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

Kontrol etmenin bir başka yolu da bir yüklemle findTransport() işlevini kullanmaktır:

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

Kamera anlık görüntülerini alma

   Android için örnek uygulamada uygulanır   

Bir kameradan statik görüntü anlık görüntüleri almak için CameraSnapshot özelliğini kullanın. Bu anlık görüntüler çeşitli senaryolarda kullanışlıdır:

  • WebRTC canlı yayını yüklenirken kullanıcı arayüzünde yer tutucu karo olarak
  • Kullanıcı etkileşimi üzerine canlı yayına yükseltilen statik bir önizleme resmi olarak.
  • Özel Etkinlik Bölgeleri çizmek ve yapılandırmak için arka plan tuvali olarak.

CameraSnapshot özelliği, hızlı oluşturma için önbelleğe alınmış bir anlık görüntüye mi yoksa isteğe bağlı canlı bir anlık görüntüye mi ihtiyacınız olduğuna bağlı olarak anlık görüntüleri getirmenin iki yolunu sunar.

Önbelleğe alınmış önizleme anlık görüntüsü alma

Önizleme anlık görüntüsü, SDK'nın kamerayı uyandırmadan alabileceği önbelleğe alınmış bir resimdir. Bu, statik bir görüntü getirmenin en hızlı yöntemidir ve kamera genel bakış sayfaları veya kontrol paneli ızgaraları için idealdir.

Önizleme anlık görüntüsünü almak için preview_image_url özellik niteliğini okuyun:

// Get a flow of the CameraSnapshot trait
val cameraSnapshotFlow: Flow<CameraSnapshot?> = cameraDevice
  .type(GoogleCameraDevice)
  .trait(CameraSnapshot)

// Get the current trait state
val cameraSnapshot = cameraSnapshotFlow.firstOrNull()
if (cameraSnapshot != null) {
  val previewImageUrl = cameraSnapshot.previewImageUrl
  // Load the preview image from the URL
} else {
  // CameraSnapshot trait not supported on this device
}

Kamera yapılandırmasına ve etkinliğine bağlı olarak önizleme URL'si, son video görüntülerinden (en son video parçasının ilk I-frame'i) oluşturulan önbelleğe alınmış bir resmi veya kamera tarafından düzenli olarak yüklenen bir anlık görüntüyü gösterir.

Google Home bulutu, görüntünün güncelliğini belirtmek için sunulan JPEG/PNG görüntüsüne UTC biçiminde bir X-Home-Image-Captured-At başlığı yerleştirir. Anlık görüntünün yaşını bir uygulamada görüntülemek için bu üstbilgiyi istemci tarafında ayrıştırabilirsiniz.

İstediğiniz zaman canlı anlık görüntü alma

Kameranın mevcut canlı görünümünü gerektiren kullanıcı yolculukları (ör. Etkinlik Bölgeleri'ni ayarlama) için canlı anlık görüntü isteyebilirsiniz. Canlı anlık görüntü tetiklendiğinde kamera uyanır, yeni bir kare yakalar ve bunu buluta yükler.

Canlı anlık görüntü istemek için getLiveSnapshot() komutunu kullanın:

try {
  val response = cameraSnapshot.getLiveSnapshot()
  val snapshotUrl = response.snapshotUrl
  // Load the live snapshot image from the URL
} catch (e: Exception) {
  Log.e("CameraSnapshot", "Failed to get live snapshot: ${e.message}")
}

Anlık görüntü isteklerinin kimliğini doğrulama

   Android için örnek uygulamada uygulanır   

Tüm anlık görüntü URL'leri güvenli medyaya işaret eder ve Home API'leri v2 kapsamı için OAuth 2.0 jetonu gerektirir. Resimleri indirip oluşturmak için OAuth jetonunun, HTTP isteğinizin Authorization üstbilgisine hamiline ait jeton olarak eklenmesi gerekir.

Aşağıdaki örnekte, anlık görüntü indirmek için güvenli bir ağ isteğinin nasıl yapılandırılacağı gösterilmektedir:

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
 * Downloads a snapshot from a URL using an OAuth access token.
 */
suspend fun loadSnapshotImage(urlString: String, oauthToken: String): Bitmap? =
  withContext(Dispatchers.IO) {
    var connection: HttpURLConnection? = null
    try {
      val url = URL(urlString)
      connection = url.openConnection() as HttpURLConnection
      // 1. Configure the HTTP GET request with the Bearer token
      connection.setRequestProperty("Authorization", "Bearer $oauthToken")

      // 2. Fetch the image data
      if (connection.responseCode == HttpURLConnection.HTTP_OK) {
        connection.inputStream.use { inputStream ->
          BitmapFactory.decodeStream(inputStream)
        }
      } else {
        null
      }
    } catch (e: IOException) {
      e.printStackTrace()
      null
    } finally {
      connection?.disconnect()
    }
  }

Pil ayarları

Home API'leri aracılığıyla çeşitli pil ayarları kontrol edilebilir.

Pil kullanımı tercihini ayarlama

Enerji dengesini ayarlayarak bir cihazın pil ömrü ile performansı arasındaki dengeyi yapılandırabilirsiniz. "Genişletilmiş", "Dengeli" ve "Performans" gibi farklı pil profilleri oluşturabilir ve bunlar arasında geçiş yapabilirsiniz.

Bu özellik, EnergyPreference özelliğinin currentEnergyBalance özelliğini güncelleyerek uygulanır. Özellik, cihazın energyBalances listesinde tanımlanan belirli bir profile karşılık gelen bir tam sayı dizini kabul eder (ör. EXTENDED için 0, BALANCED için 1 ve PERFORMANCE için 2).

currentEnergyBalance için null değeri, cihazın özel profil kullandığını gösterir. Bu, salt okunur bir durumdur.

Aşağıda, currentEnergyBalance özelliğinin kullanacağı bir yapı örneği ve ardından özelliği kullanan gerçek kod snippet'i gösterilmektedir.

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

Otomatik pil tasarrufunu açma

Bu özelliği yapılandırmak için EnergyPreference özelliğinin currentLowPowerModeSensitivity özelliğini güncelleyin. Bu özellik, hassasiyet düzeyini seçmek için bir dizin kullanır. 0 genellikle Disabled, 1 ise Enabled veya Automatic anlamına gelir.

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

Pil şarj durumunu alma

Cihazın mevcut şarj durumunu (şarj oluyor, tamamen şarj oldu veya şarj olmuyor) öğrenmek için PowerSource özelliğinin batChargeState özelliğini kullanın.

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

Pil seviyesini öğrenme

Mevcut pil seviyesini öğrenmek için PowerSource özelliğinin batChargeLevel özelliğini kullanın. Seviye OK, Warning (düşük) veya Critical olabilir.

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

Güç kaynağını alma

Cihazın kullandığı güç kaynağını belirlemek için PowerSource özelliğinin BatPresent ve wiredPresent özelliklerini kullanın.

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

Pilin değiştirilmesi gerekip gerekmediğini kontrol etme

batReplaceability özelliği, pilin değiştirilemez, kullanıcı tarafından değiştirilebilir veya fabrika tarafından değiştirilebilir olup olmadığını gösterir.

PowerSource özelliğinin batReplacementNeeded özelliği, pilin değiştirilmesi gerekip gerekmediğini gösterir.

// Get the battery replacement status
val batteryStatus = powerSourceTrait.batReplacementNeeded

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

Pil kullanıcı tarafından değiştirilebiliyorsa batReplacementDescription, form faktörü, kimyasal yapısı ve tercih edilen üretici gibi bilgileri de içerecek şekilde pili tanımlar.

Ses ayarları

Home API'leri aracılığıyla çeşitli ses ayarları kontrol edilebilir.

Mikrofonu açma veya kapatma

Cihazın mikrofonunu açmak veya kapatmak için yerleşik setMicrophoneMuted Kotlin işlevini kullanarak CameraAvStreamManagement özelliğinin microphoneMuted özelliğini güncelleyin:

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

Ses kaydını açma veya kapatma

Cihazda ses kaydını açmak veya kapatmak için yerleşik setRecordingMicrophoneMuted Kotlin işlevini kullanarak CameraAvStreamManagement özelliğinin recordingMicrophoneMuted özelliğini güncelleyin:

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

Hoparlör ses seviyesini ayarlama

Cihazın hoparlör ses seviyesini ayarlamak için yerleşik setSpeakerVolumeLevel Kotlin işlevini kullanarak CameraAvStreamManagement özelliğinin speakerVolumeLevel özelliğini güncelleyin:

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

Etkinlik bölgesi ayarları

   Android için örnek uygulamada uygulanır   

ZoneManagement özelliği, kamera ve kapı zili cihazlarında özel ilgi alanlarını (etkinlik bölgeleri) yönetmek için bir arayüz sağlar. Bu bölgeler, etkinlik algılamayı (ör. kişi veya araç hareketi) cihazın görüş alanındaki belirli alanlara göre filtrelemek için kullanılır.

Etkinlik bölgeleri, kullanıcı tarafından bir iş ortağı uygulamasında yapılandırılır ve kullanıcının kameranın görüş alanındaki belirli alanlar üzerinde bölgeler çizmesine olanak tanır. Kullanıcı tarafından tanımlanan bu bölgeler daha sonra bu özelliğin kullandığı yapılara dönüştürülür. Etkinlik Bölgeleri'nin işleyiş şekli hakkında daha fazla bilgi için Etkinlik Bölgeleri'ni ayarlama ve kullanma başlıklı makaleyi inceleyin.

Etkinlik bölgeleri genellikle 2D Kartezyen koordinatları kullanılarak tanımlanır. Bu özellik, köşeler için TwoDCartesianVertexStruct ve bölge tanımı (ad, köşeler, renk ve kullanım) için TwoDCartesianZoneStruct sağlar.

Etkinlik Bölgeleri'ni kontrol etme

Etkinlik bölgelerini görüntülemek için ZoneManagement özelliğinin zones özelliğini kontrol edin.

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

Etkinlik Bölgesi ekleme

Yeni bir bölge oluşturmak için createTwoDCartesianZone komutunu kullanın. Bu komut, bölgenin adını, köşelerini, rengini ve kullanımını tanımlayan bir TwoDCartesianZoneStruct alır.

Aşağıdaki örnekte, "Ön Veranda" adlı, dört köşeli, somon renginde (#F439A0) ve hareket algılama için kullanılan bir bölgenin nasıl oluşturulacağı gösterilmektedir.

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

Etkinlik Bölgesi'ni güncelleme

Mevcut bir bölgeyi güncellemek için updateTwoDCartesianZone komutunu kullanın. Bu komut için zoneId ve güncellenmiş TwoDCartesianZoneStruct gerekir.

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

Etkinlik Bölgesi'ni silme

Bir bölgeyi kaldırmak için belirli bir zoneId ile removeZone komutunu kullanın.

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

Ses Etkinliği Tetikleyicileri

AvStreamAnalysis özelliği, kamera ve kapı zili cihazlarında olay algılama tetikleyicilerini yönetmek için bir arayüz sağlar. Görüntü tabanlı tetikleyiciler (ör. insanlar veya araçlar) bölgeye özel olabilirken sesle ilgili tetikleyiciler genellikle cihaz düzeyinde yapılandırmalardır.

EventTriggerTypeEnum ile ses algılama için aşağıdaki tetikleyici türleri kullanılabilir:

Mod Enum değeri Açıklama
Ses Sound Genel ses algılama.
Birisi konuşuyor PersonTalking Konuşmayı algılar.
Köpek havlaması DogBark Köpek seslerini algılar.
Cam kırılması GlassBreak Cam kırılma sesini algılar.
Duman alarmı SmokeAlarm Genellikle T3 sesli kalıbıyla (üç kısa bip sesi ve ardından bir duraklama) tanınan duman alarmlarını algılar.
Karbonmonoksit alarmı CoAlarm Genellikle T4 ses deseniyle (dört kısa bip sesi ve ardından bir duraklama) tanınan karbonmonoksit (CO) alarmlarını algılar.

Ses algılama durumunu kontrol etme

Ses algılamanın mevcut durumunu kullanıcıya göstermek için cihazın neleri desteklediğini ve cihaz donanımının neleri etkinleştirdiğini kontrol etmeniz gerekir. Kontrol edilecek iki özellik şunlardır:

Kotlin akışlarını kullanan Android geliştirmede genellikle HomeDevice özelliğinden AvStreamAnalysis özelliğini gözlemlersiniz.

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

Etkin tetikleyici grubunu güncelleme

Etkin tetikleyici grubunu güncellemek için EventTriggerEnablement yapılarının listesini alan SetOrUpdateEventDetectionTriggers komutunu kullanın.

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

Kayıt modları

   Android için örnek uygulamada uygulanır   

RecordingMode özelliği, kamera ve kapı zili cihazlarında video ve görüntü kaydetme davranışını yönetmek için bir arayüz sağlar. Kullanıcılar kesintisiz kayıt, etkinliğe dayalı kayıt veya kaydı tamamen devre dışı bırakma (yalnızca canlı görüntüleme) seçenekleri arasından tercih yapabilir.

RecordingModeEnum, kullanılabilir kayıt stratejilerini tanımlar:

Mod Enum değeri Açıklama
Devre dışı Disabled Kayıt tamamen devre dışı bırakıldıysa. Genellikle eski cihazlar tarafından kullanılır.
CVR (Kesintisiz Video Kaydı) Cvr Video 7/24 kaydedilir. Abonelik gerektirir (ör. Google Home Premium).
EDK (Etkinliğe Dayalı Kayıt) Ebr Kayıt, etkinlikler (kişi, hareket) tarafından tetiklenir. Video uzunluğu, etkinliğin süresine ve aboneliğe bağlıdır.
ETR (Etkinlikle Tetiklenen Kayıt) Etr Etkinlikler tarafından tetiklenen kısa önizleme kaydı (ör. 10 saniye).
Live View LiveView Kayıt devre dışı bırakılır ancak kullanıcılar canlı yayına erişmeye devam edebilir.
Sabit Görüntüler Images Olaylar gerçekleştiğinde video yerine anlık görüntüler kaydedilir.

Kayıt modlarını kontrol etme

Mevcut kayıt yapılandırmasını görüntülemek için RecordingMode özelliğinin niteliklerini kontrol edin:

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

Kayıt modunu değiştirme

Güncellemeden önce, supportedRecordingModes özelliğinden seçilen dizinin availableRecordingModes özelliğinde bulunduğundan emin olun.

Seçilen modu güncellemek için setSelectedRecordingMode işlevini kullanın ve seçilen modun dizinini iletin:

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

Diğer ayarlar

Home API'leri aracılığıyla çeşitli ayarlar kontrol edilebilir.

Resim yönünü değiştirme

Kamera görüntüsünün (video) yönü döndürülebilir. Video yalnızca 180 derece döndürülebilir.

Kameranın görüntü yönünü değiştirmek için yerleşik setImageRotation Kotlin işlevini kullanarak CameraAvStreamManagement özelliğinin imageRotation özelliğini güncelleyin:

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

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

Gece görüşünü açma veya kapatma

Kameranın gece görüşünü açmak veya kapatmak için yerleşik setNightVision Kotlin işlevini kullanarak CameraAvStreamManagement özelliğinin nightVision özelliğini güncellemek için TriStateAutoEnum kullanın:

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

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

Durum LED'inin parlaklığını değiştirme

Durum LED'inin parlaklığını değiştirmek için ThreeLevelAutoEnum komutunu kullanarak yerleşik setStatusLightBrightness Kotlin işleviyle CameraAvStreamManagement özelliğinin statusLightBrightness özelliğini güncelleyin:

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

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

Kamera görüntü alanını değiştirme

Kamera görüntü alanı, Nest kamera videosunu yakınlaştırma ve iyileştirme destek makalesinde açıklanan yakınlaştırma ve kırpma özelliğiyle aynıdır.

Görüntü alanı, görüntü alanının koordinatları olarak kullanılan dört değer içeren bir ViewportStruct içinde tanımlanır. Koordinatlar şu şekilde tanımlanır:

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

ViewportStruct değerlerinin belirlenmesi, uygulamanın kullanıcı arayüzüne ve kamera uygulamasına bağlıdır. Kamera videosunun görüntü alanını ayarlamak için en temel düzeyde, yerleşik setViewport Kotlin işlevini kullanarak CameraAvStreamManagement özelliğinin viewport özelliğini ViewportStruct ile güncelleyin:

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

Analizleri etkinleştirme veya devre dışı bırakma

Her cihaz, Google Home bulutuna ayrıntılı analiz verileri göndermeyi ayrı ayrı etkinleştirebilir (Home API'leri için Cloud Monitoring bölümüne bakın).

Bir cihaz için analizleri etkinleştirmek istiyorsanız ExtendedGeneralDiagnosticsTrait öğesinin analyticsEnabled özelliğini true olarak ayarlayın. analyticsEnabled ayarını yaptığınızda başka bir özellik olan logUploadEnabled otomatik olarak true değerine ayarlanır. Bu sayede analiz günlüğü dosyaları Google Home bulutuna yüklenebilir.

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

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

Aktarım ve kayıt yapılandırmaları

Bu bölümde, kamera görüntü akışı kalitesi ve etkinlik tetiklemeyle ilgili ayarlar ele alınmaktadır. Bu ayarlar PushAvStreamTransport özelliği tarafından yönetilir.

Taşıma ayarlarını okuma

Bu bölümde, bir kamera veya kapı zili cihazından mevcut yapılandırmanın nasıl alınacağı gösterilmektedir. PushAvStreamTransport özelliğini getirir, kayıt için kullanılan belirli bağlantıyı bulur ve ardından bant genişliği kalitesi, uyanma hassasiyeti ve maksimum etkinlik uzunluğu için mevcut değerleri ayıklar.

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

Taşıma ayarlarını güncelleme

Bu bölümde, taşıma ayarlarının nasıl değiştirileceği gösterilmektedir. Yeni değerleri içeren yeni bir TransportOptionsStruct oluşturur ve ardından bu güncellenmiş ayarları cihaza geri göndermek için modifyPushTransport komutunu kullanarak önceki adımda bulunan kayıt bağlantısına uygular.

Bu ayarları değiştirmek için TransportOptionsStruct ile modifyPushTransport komutunu kullanın.

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

Bant genişliği kalitesini belirleme

TransportOptionsStruct öğesinin videoStreamId özelliği, belirli bir video akışı yapılandırmasına karşılık gelir.

Desteklenen video akışlarını almak için VideoStreamStructs listesi olan allocatedVideoStreams özelliğine bakın. özelliğinden alınır.CameraAvStreamManagement

Cihazın uyandırma hassasiyetini ayarlama

TransportTriggerOptionsStruct öğesinin motionSensitivity özelliği aşağıdaki değerlere karşılık gelir:

Şirket Değer (UByte)
Düşük 1u
Orta 5u
Yüksek 10u

Maksimum etkinlik uzunluğunu ayarlama

TransportMotionTriggerTimeControlStruct öğesinin maxDuration özelliği, aşağıdaki sürelere (saniye cinsinden) karşılık gelir:

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

Cihazı kullanımdan kaldırma

Bir kamerayı yapıdan kaldırmak için device.decommissionDevice() yöntemini çağırın. Kullanımdan kaldırma işlemi, kullanıcıya Google tarafından yönetilen bir onay ekranı gösterir. Bu ekranda, kaydedilen tüm 24/7 video geçmişi, olay geçmişi, klipler ve tanıdık yüz kitaplığı verilerinin yapı genelinde kalıcı olarak silineceği uyarısı yer alır.

Ayrıntılı talimatlar ve kod örnekleri için Cihaz kaldırma başlıklı makaleyi inceleyin.