راهنمای دستگاه دوربین برای Android

نوع دستگاه «دوربین» بااستفاده از سه مشخصه پیاده‌سازی می‌شود: PushAvStreamTransport، که انتقال جاری‌سازی صوتی و ویدیویی را بااستفاده از پروتکل‌های مبتنی بر ارسال مدیریت می‌کند، WebRtcLiveView، که امکان کنترل کردن جاری‌سازی‌های زنده و پاسخ‌گویی را فراهم می‌کند، و CameraSnapshot، که عکس‌های آنی پیش‌نمایش ذخیره‌شده در حافظه نهان و عکس‌های آنی زنده را ارائه می‌دهد.

همیشه قبل‌از استفاده از هر ویژگی یا تلاش برای به‌روزرسانی مشخصه‌ها، پشتیبانی از مشخصه و فرمان را برای دستگاه بررسی کنید. برای اطلاعات بیشتر، به کنترل دستگاه‌ها در Android مراجعه کنید.

نوع دستگاه Home APIs ویژگی‌ها برنامه نمونه Kotlin مورد استفاده

دوربین

GoogleCameraDevice

home.matter.6006.types.0158

دستگاهی که تصاویر ثابت یا ویدیو ضبط می‌کند. دوربین‌ها ممکن است دارای جاری‌سازی زنده دردسترس، مکالمه دوطرفه، یا رویدادهای تشخیص باشند.

ویژگی‌های الزامی
     google PushAvStreamTransport
     google WebRtcLiveView

دوربین

دریافت اطلاعات پایه درباره دستگاه

   در برنامه نمونه برای Android پیاده‌سازی شده است   

ویژگی BasicInformation شامل اطلاعاتی مثل نام فروشنده، شناسه فروشنده، شناسه محصول، نام محصول (شامل اطلاعات مدل)، و نسخه نرم‌افزار دستگاه است:

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

دریافت شماره سریال

برای دریافت شماره سریال دستگاه، از فرمان GetSerialNumber ویژگی ExtendedBasicInformation استفاده کنید. مثال زیر ذخیره کردن شماره سریال را در متغیری به‌نام serialNumber نشان می‌دهد:

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

دریافت آخرین زمان تماس ابری دستگاه

برای پیدا کردن آخرین باری که دستگاه با فضای ابری تماس داشته است، از مشخصه lastContactTimestamp ویژگی ExtendedGeneralDiagnostics استفاده کنید:

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 cameraConnectivity = cameraDevice.metadata.sourceConnectivity.connectivityState

درصورت وجود انواع دستگاه‌های ترکیبی، وقتی اتصال اینترنت وجود نداشته باشد، ممکن است وضعیت PARTIALLY_ONLINE در پرونده مشاهده شود. ویژگی‌های استاندارد Matter ممکن است به‌دلیل مسیریابی محلی همچنان آنلاین باشند، اما ویژگی‌های مبتنی بر ابر آفلاین خواهند بود.

دریافت نشانی IP دستگاه

برای پیدا کردن نشانی IP دستگاه، از مشخصه networkInterfaces ویژگی GeneralDiagnostics استفاده کنید. نشانی‌ها به‌صورت آرایه‌های بایتی برگردانده می‌شوند که می‌توانید آن‌ها را به رشته‌های استاندارد 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()

شروع کردن جاری‌سازی زنده

   در برنامه نمونه برای Android پیاده‌سازی شده است   

برای شروع جاری‌سازی زنده، رشته «پروتکل شرح جلسه» (SDP) را به روش startLiveView() مشخصه WebRtcLiveView ارسال کنید که WebRtcLiveViewTrait.StartLiveViewCommand.Response حاوی سه مقدار را برمی‌گرداند:

  • «پروتکل شرح جلسه» برای جلسه.
  • مدت جلسه برحسب ثانیه.
  • شناسه جلسه که ممکن است برای تمدید یا پایان دادن به جلسه استفاده شود.
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)

تمدید کردن جاری‌سازی زنده

   در برنامه نمونه برای Android پیاده‌سازی شده است   

جاری‌سازی‌های زنده مدت زمان ازپیش تعیین‌شده‌ای دارند که پس‌از آن منقضی می‌شوند. برای طولانی‌تر کردن مدت جاری‌سازی فعال، بااستفاده از روش 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

   در برنامه نمونه برای Android پیاده‌سازی شده است   

برای شروع پاسخ صوتی، روش startTalkback() مشخصه WebRtcLiveView را فراخوانی کنید. برای توقف، از 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)
  }
}

مدیریت جاری‌سازی زنده

تنظیم کیفیت جاری‌سازی زنده برای بهینه‌سازی استفاده از پهنای باند براساس بافتار مشاهده مشتری مفید است (برای مثال، جابه‌جایی به وضوح پایین‌تر هنگام نمایش کاشی پیش‌نمایش کوچک‌تر، نمای جدولی، یا حالت تصویردرتصویر).

تغییر پویای کیفیت بااستفاده از ویژگی WebRtcLiveView به‌طور خاص وضوح جلسه جاری‌سازی زنده فعال را در یک کارخواه خاص مدیریت می‌کند. این تنظیمات با پیکربندی تنظیمات استفاده از پهنای باند در سراسر دستگاه به‌طور مستقیم در دستگاه یکسان نیست، که بر همه بینندگان هم‌زمان و کیفیت ضبط‌های ویدیویی تاریخی ذخیره‌شده در فضای ابری تأثیر می‌گذارد.

مثال زیر نحوه بازیابی و به‌روزرسانی کیفیت جاری‌سازی زنده را برای دستگاه نشان می‌دهد:

  • بازیابی گزینه‌های کیفیت پشتیبانی‌شده: دریافت وضوح‌های جاری‌سازی دردسترس که دستگاه از آن‌ها پشتیبانی می‌کند. کد، ویژگی supportedQualityHints مشخصه WebRtcLiveView را در جریان نوع دستگاه پُرسمان می‌کند و کیفیت‌های پشتیبانی‌شده را به‌عنوان StateFlow حاوی فهرستی از مقادیر QualityHint (مانند QUALITY_HINT_SD، QUALITY_HINT_HD، QUALITY_HINT_FHD، QUALITY_HINT_QHD، یا QUALITY_HINT_UHD) نشان می‌دهد.

  • تغییر کیفیت جاری‌سازی زنده: برای تغییر وضوح جاری‌سازی زنده فعال، QualityHint انتخاب‌شده را اعمال کنید (برای مثال، تغییر از «وضوح استاندارد» به «وضوح بالا»). تابع changeQuality ویژگی جاری‌سازی زنده دستگاه را حل می‌کند و changeLiveViewQuality را با mediaSessionId فعال و پیکربندی QualityHint انتخاب‌شده فراخوانی می‌کند.

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

فعال و غیرفعال کردن قابلیت ضبط

برای فعال کردن قابلیت ضبط دوربین، TransportStatusEnum.Active را به روش setTransportStatus() ویژگی PushAvStreamTransport منتقل کنید. برای غیرفعال کردن قابلیت ضبط، آن را 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
    }
}

بازیابی عکس‌های آنی دوربین

   در برنامه نمونه برای Android پیاده‌سازی شده است   

از ویژگی CameraSnapshot برای بازیابی عکس‌های آنی تصویر ثابت از دوربین استفاده کنید. این عکس‌های آنی برای چندین سناریو مفید هستند:

  • به‌عنوان کاشی جای‌بان در میانای کاربر درحین بار شدن جاری‌سازی زنده WebRTC.
  • به‌عنوان تصویر پیش‌نمایش ثابت که با تعامل کاربر به جاری‌سازی زنده ارتقا می‌یابد.
  • به‌عنوان بوم پس‌زمینه برای ترسیم و پیکربندی مناطق فعالیت سفارشی.

ویژگی CameraSnapshot دو روش برای واکشی عکس‌های آنی ارائه می‌دهد، بسته به اینکه آیا برای رندر سریع به عکس آنی ذخیره‌شده در حافظه نهان نیاز دارید یا به عکس آنی زنده درخواستی.

دریافت عکس آنی پیش‌نمایش ذخیره‌شده در حافظه نهان

عکس آنی پیش‌نمایش تصویری ذخیره‌شده در حافظه نهان است که کیت توسعه نرم‌افزار می‌تواند بدون فعال کردن دوربین آن را بازیابی کند. این سریع‌ترین روش برای واکشی تصویر ثابت است و برای صفحه‌های نمای کلی دوربین یا شبکه‌های داشبورد ایده‌آل است.

برای دریافت عکس آنی پیش‌نمایش، مشخصه ویژگی preview_image_url را بخوانید:

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

بسته به پیکربندی و فعالیت دوربین، نشانی وب پیش‌نمایش به تصویر ذخینه‌شده‌ای اشاره می‌کند که از فیلم ویدیویی اخیر (اولین قاب I از آخرین قطعه ویدیو) یا عکس آنی‌ای که به‌طور دوره‌ای توسط دوربین بارگذاری شده است تولید شده است.

برای نشان دادن تازگی تصویر، فضای ابری Google Home یک سرصفحه X-Home-Image-Captured-At را در تصویر JPEG/PNG ارائه‌شده جاسازی می‌کند که در قالب UTC است. می‌توانید این سرصفحه را در سمت کارخواه تجزیه کنید تا سن عکس آنی را در برنامه نمایش دهید.

دریافت عکس آنی زنده درخواستی

برای مسیرهای کاربر که به نمای زنده فعلی دوربین نیاز دارند (مثلاً راه‌اندازی «مناطق فعالیت»)، می‌توانید عکس آنی زنده درخواست کنید. راه‌اندازی عکس آنی زنده به دوربین دستور می‌دهد که بیدار شود، قاب جدیدی را ضبط کند، و آن را در فضای ابری بارگذاری کند.

برای درخواست عکس آنی زنده، از فرمان getLiveSnapshot() استفاده کنید:

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

اصالت‌سنجی کردن درخواست‌های عکس آنی

   در برنامه نمونه برای Android پیاده‌سازی شده است   

همه نشانی‌های وب عکس آنی به رسانه ایمن اشاره می‌کنند و به کد OAuth 2.0 برای دامنه Home APIs v2 نیاز دارند. برای بارگیری و ارائه تصاویر، کد OAuth باید به‌عنوان کد «دارنده» در سرصفحه Authorization درخواست HTTP شما تزریق شود.

مثال زیر نحوه پیکربندی درخواست شبکه امن برای بارگیری عکس آنی را نشان می‌دهد:

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

تنظیمات باتری

تنظیمات مختلف باتری را می‌توان ازطریق Home API کنترل کرد.

تنظیم اولویت مصرف باتری

تنظیم توازن انرژی به شما امکان می‌دهد توازن بین عمر باتری و عملکرد دستگاه را پیکربندی کنید. می‌توانید نمایه‌های باتری مختلفی مثل «طولانی»، «متعادل»، و «عملکرد» ایجاد کنید و بین آن‌ها جابه‌جا شوید.

این ویژگی با به‌روزرسانی مشخصه currentEnergyBalance در ویژگی EnergyPreference پیاده‌سازی می‌شود. این مشخصه نمایه عدد صحیحی را می‌پذیرد که با نمایه خاصی که در فهرست energyBalances دستگاه تعریف شده است مطابقت دارد (برای مثال، 0 برای EXTENDED، 1 برای BALANCED، و 2 برای PERFORMANCE).

مقدار null برای currentEnergyBalance نشان می‌دهد دستگاه از نمایه سفارشی استفاده می‌کند. این حالت فقط خواندنی است.

در زیر نمونه‌ای از ساختاری که مشخصه 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)

روشن کردن «بهینه‌سازی باتری» خودکار

برای پیکربندی این ویژگی، مشخصه currentLowPowerModeSensitivity از ویژگی EnergyPreference را به‌روز کنید. این مشخصه از نمایه‌ای برای انتخاب سطح حساسیت استفاده می‌کند، که در آن 0 معمولاً نشان‌دهنده Disabled است و 1 نشان‌دهنده Enabled یا 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) }
}

دریافت وضعیت شارژ باتری

برای دریافت وضعیت شارژ فعلی دستگاه (درحال شارژ، شارژ کامل، یا عدم شارژ)، از مشخصه batChargeState ویژگی PowerSource استفاده کنید.

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

دریافت سطح باتری

برای دریافت سطح باتری فعلی، از مشخصه batChargeLevel ویژگی PowerSource استفاده کنید. سطح آن 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"
}

دریافت منبع برق

برای تعیین منبع برقی که دستگاه استفاده می‌کند، از مشخصه‌های BatPresent و wiredPresent در ویژگی PowerSource استفاده کنید.

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

بررسی کنید که آیا باتری نیاز به تعویض دارد یا نه

مشخصه batReplaceability نشان می‌دهد که باتری غیرقابل‌تعویض است، توسط کاربر قابل‌تعویض است، یا توسط کارخانه قابل‌تعویض است.

مشخصه batReplacementNeeded از ویژگی PowerSource به شما می‌گوید که آیا باتری باید تعویض شود یا نه.

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

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

وقتی باتری قابل‌تعویض توسط کاربر باشد، batReplacementDescription باتری را توصیف می‌کند، ازجمله اطلاعاتی مانند ضریب شکل، شیمی، و سازنده ترجیحی.

تنظیمات صوتی

تنظیمات صوتی مختلف را می‌توان ازطریق Home API کنترل کرد.

روشن یا خاموش کردن میکروفون

برای روشن یا خاموش کردن میکروفون دستگاه، مشخصه microphoneMuted ویژگی CameraAvStreamManagement را بااستفاده از تابع Kotlin داخلی setMicrophoneMuted به‌روز کنید:

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

روشن یا خاموش کردن ضبط صدا

برای روشن یا خاموش کردن ضبط صدا برای دستگاه، مشخصه recordingMicrophoneMuted ویژگی CameraAvStreamManagement را بااستفاده از تابع Kotlin setRecordingMicrophoneMuted داخلی به‌روز کنید:

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

تنظیم میزان صدای بلندگو

برای تنظیم میزان صدای بلندگوی دستگاه، مشخصه speakerVolumeLevel از ویژگی CameraAvStreamManagement را بااستفاده از تابع Kotlin داخلی setSpeakerVolumeLevel به‌روز کنید:

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

تنظیمات منطقه فعالیت

   در برنامه نمونه برای Android پیاده‌سازی شده است   

ویژگی ZoneManagement واسطی برای مدیریت مناطق موردعلاقه سفارشی (مناطق فعالیت) در دستگاه‌های دوربین و زنگ در ارائه می‌دهد. از این مناطق برای فیلتر کردن تشخیص رویداد (مثل حرکت فرد یا خودرو) در مناطق خاصی در میدان دید دستگاه استفاده می‌شود.

مناطق فعالیت توسط کاربر در برنامه شریک پیکربندی می‌شوند، و به آن‌ها اجازه می‌دهند تا مناطقی را روی نواحی خاصی در میدان دید دوربین ترسیم کنند. سپس این مناطق تعریف‌شده توسط کاربر به ساختارهای مورداستفاده این مشخصه ترجمه می‌شوند. برای اطلاعات بیشتر درباره نحوه عملکرد مناطق فعالیت، به راه‌اندازی و استفاده از «مناطق فعالیت» مراجعه کنید.

مناطق فعالیت معمولاً بااستفاده از مختصات دکارتی دوبعدی تعریف می‌شوند. این ویژگی TwoDCartesianVertexStruct را برای رئوس و TwoDCartesianZoneStruct را برای تعریف منطقه (نام، رئوس، رنگ، و کاربرد) ارائه می‌دهد.

بررسی مناطق فعالیت

برای نمایش مناطق فعالیت، مشخصه zones از ویژگی ZoneManagement را بررسی کنید.

// 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 را می‌گیرد، که نام، رئوس، رنگ، و کاربرد منطقه را تعریف می‌کند.

مثال زیر نشان می‌دهد که چگونه منطقه‌ای به‌نام «ایوان جلو» با چهار رأس، رنگ سالمون (#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)
}

حذف منطقه فعالیت

برای برداشتن منطقه، از فرمان removeZone با zoneId خاص استفاده کنید.

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 (سه بوق کوتاه و سپس یک مکث) شناخته می‌شود.
هشدار مونوکسیدکربن CoAlarm هشدارهای کربن مونوکسید (CO) را تشخیص می‌دهد، معمولاً با الگوی شنیداری T4 (چهار بوق کوتاه و سپس مکث) تشخیص داده می‌شود.

بررسی وضعیت تشخیص صدا

برای نمایش وضعیت فعلی تشخیص صدا به کاربر، باید بررسی کنید دستگاه از چه چیزی پشتیبانی می‌کند و چه چیزی توسط سخت‌افزار دستگاه فعال شده است. دو مشخصه‌ای که باید بررسی شود عبارت‌اند از:

در توسعه Android بااستفاده از Kotlin Flows، معمولاً ویژگی AvStreamAnalysis را از HomeDevice مشاهده می‌کنید.

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

به‌روزرسانی مجموعه راه‌اندازهای فعال‌شده

برای به‌روزرسانی مجموعه راه‌اندازهای فعال‌شده، از فرمان SetOrUpdateEventDetectionTriggers استفاده کنید که فهرستی از ساختارهای EventTriggerEnablement را می‌گیرد.

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

حالت‌های ضبط

   در برنامه نمونه برای Android پیاده‌سازی شده است   

مشخصه RecordingMode میانایی برای مدیریت رفتار ضبط ویدیو و تصویر در دستگاه‌های دوربین و زنگ در ارائه می‌دهد. این ویژگی به کاربران امکان می‌دهد بین ضبط پیوسته، ضبط مبتنی بر رویداد، یا غیرفعال کردن کامل ضبط (فقط «نمای زنده») انتخاب کنند.

RecordingModeEnum استراتژی‌های ضبط دردسترس را تعریف می‌کند:

حالت مقدار Enum شرح
غیرفعال Disabled ضبط کاملاً غیرفعال است. عمدتاً توسط دستگاه‌های قدیمی استفاده می‌شود.
CVR (ضبط ویدیو پیوسته) Cvr ویدیو به‌صورت شبانه‌روزی ضبط می‌شود. به اشتراک نیاز دارد (برای مثال، Google Home Premium.
EBR (ضبط درصورت رویداد) Ebr ضبط با رویدادها (شخص، حرکت) راه‌اندازی می‌شود. طول ویدیو به مدت رویداد و اشتراک بستگی دارد.
ETR (ضبط با راه‌انداز رویداد) Etr ضبط پیش‌نمایش کوتاه (برای مثال، ۱۰ ثانیه) که با رویدادها راه‌اندازی می‌شود.
نمای زنده 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 کنترل کرد.

تغییر جهت تصویر

جهت تصویر دوربین (ویدیو) را می‌توان چرخاند. ویدیو فقط ۱۸۰ درجه می‌تواند بچرخد.

برای تغییر جهت تصویر دوربین، ویژگی imageRotation مشخصه CameraAvStreamManagement را بااستفاده از تابع Kotlin setImageRotation داخلی به‌روز کنید:

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

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

روشن یا خاموش کردن دید در شب

برای روشن یا خاموش کردن دید در شب برای دوربین، از TriStateAutoEnum برای به‌روزرسانی nightVision ویژگی CameraAvStreamManagement بااستفاده از setNightVision تابع Kotlin داخلی استفاده کنید:

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

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

تغییر روشنایی LED وضعیت

برای تغییر دادن روشنایی LED وضعیت، از ThreeLevelAutoEnum برای به‌روزرسانی مشخصه statusLightBrightness از ویژگی CameraAvStreamManagement بااستفاده از تابع Kotlin داخلی setStatusLightBrightness استفاده کنید:

// 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 به رابط کاربری برنامه و پیاده‌سازی دوربین بستگی دارد. در سطح بسیار ابتدایی، برای تنظیم نمای دوربین ویدیو، viewport ویژگی CameraAvStreamManagement را با ViewportStruct، بااستفاده از تابع Kotlin داخلی setViewport به‌روز کنید:

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

فعال یا غیرفعال کردن Analytics

هر دستگاه می‌تواند به‌طور جداگانه برای ارسال داده‌های تحلیلی دقیق به فضای ابری Google Home موافقت کند (به پایش ابری برای Home APIs مراجعه کنید).

برای فعال کردن تجزیه‌وتحلیل برای دستگاه، ویژگی analyticsEnabled ExtendedGeneralDiagnosticsTrait را روی true تنظیم کنید. وقتی analyticsEnabled را تنظیم می‌کنید، دارایی دیگری، logUploadEnabled، به‌طور خودکار روی true تنظیم می‌شود که اجازه می‌دهد فایل‌های گزارش تجزیه‌وتحلیل در فضای ابری Google Home بارگذاری شود.

// 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 برای ارسال این تنظیمات به‌روزشده به دستگاه استفاده می‌کند و آن‌ها را روی اتصال ضبط که در مرحله قبل پیدا شده است اعمال می‌کند.

برای اصلاح این تنظیمات، از فرمان modifyPushTransport با TransportOptionsStruct استفاده کنید.

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

تعیین کیفیت پهنای باند

مشخصه videoStreamId TransportOptionsStruct با پیکربندی خاصی از جاری‌سازی ویدیو مطابقت دارد.

برای دریافت جاری‌سازی‌های ویدیویی پشتیبانی‌شده، به مشخصه allocatedVideoStreams مراجعه کنید که فهرستی از VideoStreamStructs است. از ویژگی CameraAvStreamManagement برای دستگاه.

تنظیم حساسیت بیدار شدن دستگاه

ویژگی motionSensitivity TransportTriggerOptionsStruct با مقادیر زیر مطابقت دارد:

برچسب مقدار (UByte)
پایین ‫۱ واحد
متوسط ‫۵ واحد
زیاد ‫۱۰ واحد

تنظیم حداکثر طول رویداد

maxDuration ویژگی TransportMotionTriggerTimeControlStruct با مدت‌های زیر (به ثانیه) مطابقت دارد:

  • ‫10u، 15u، 30u، 60u، 120u، 180u

ازکار انداختن دستگاه

برای برداشتن دوربین از ساختمان، با device.decommissionDevice() تماس بگیرید. ازکارانداختن باعث می‌شود کاربر با صفحه تأیید مدیریت‌شده توسط Google مواجه شود که هشدار می‌دهد تمام سابقه ویدیویی ۲۴ساعته، سابقه رویداد، کلیپ‌ها، و داده‌های کتابخانه چهره آشنا در سراسر ساختار برای همیشه حذف خواهند شد.

برای دستورالعمل‌های دقیق و نمونه‌های کد، به برداشتن دستگاه مراجعه کنید.