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

نوع دستگاه Doorbell با استفاده از دو ویژگی پیاده‌سازی می‌شود: PushAvStreamTransport که انتقال جریان صوتی و تصویری را با استفاده از پروتکل‌های مبتنی بر فشار مدیریت می‌کند، و WebRtcLiveView که امکان کنترل پخش زنده و talkback را فراهم می‌کند.

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

نوع دستگاه APIهای خانگی صفات نمونه برنامه کاتلین مورد استفاده

زنگ در

Google Doorbell Device

home.matter.6006.types.0113

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

ویژگی‌های مورد نیاز
گوگل PushAvStreamTransport
گوگل وب‌آر‌تی‌سی لایو ویو

زنگ در

دریافت اطلاعات اولیه در مورد یک دستگاه

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

ویژگی 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

پاسخ‌های سریع

ویژگی پاسخ‌های سریع به کاربر این امکان را می‌دهد که یک پیام از پیش تعریف‌شده را به دستگاه زنگ در ارسال کند.

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

پاسخ‌های سریع از طریق ویژگی PresetMessage پیاده‌سازی می‌شوند.

پخش یک پیام از پیش تنظیم شده

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

import com.google.home.HomeDevice
import com.google.home.HomeException
import com.google.home.google.GoogleDoorbellDevice
import com.google.home.google.PresetMessage
import kotlinx.coroutines.flow.first

suspend fun playDoorbellPresetMessage(device: HomeDevice, phraseTypeString: String) {
    try {
        // 1. Retrieve the first snapshot of the doorbell device type
        val doorbellDevice = device.type(GoogleDoorbellDevice).first()

        // 2. Extract the PresetMessage trait
        val presetMessageTrait = doorbellDevice.trait(PresetMessage)
        if (presetMessageTrait == null) {
            println("PresetMessage trait is not supported on this doorbell device.")
            return
        }

        // 3. (Optional) Check available phrase types supported by the device
        val availablePhrases = presetMessageTrait.availablePhraseTypes
        if (availablePhrases != null) {
            val phraseTypesList = availablePhrases.map { it.phraseType }
            println("Supported quick response phrases: $phraseTypesList")
        }

        // 4. Send the playPresetMessage command to the doorbell
        presetMessageTrait.playPresetMessage(phraseType = phraseTypeString)
        println("Preset message command sent successfully.")

    } catch (e: HomeException) {
        println("Home API error occurred: ${e.message}")
    } catch (e: Exception) {
        println("Unexpected failure: ${e.message}")
    }
}

تنظیم زبان گفتاری

زبان گفتاری فعال یک دستگاه را با استفاده از متد setActiveLocale از ویژگی LocalizationConfiguration ، روی یک زبان خاص (مثلاً "en_US") تنظیم کنید.

import java.util.Locale

// Convert underscore format (en_US) to Java Locale
fun String.toLocale(): Locale = Locale.forLanguageTag(this.replace('_', '-'))

// Setting the active language
val trait: LocalizationConfiguration = device.getTrait(LocalizationConfiguration)
val selectedLocale = "en_US" // Target locale string
trait.update {
    setActiveLocale(selectedLocale)
}

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

برای یافتن آخرین زمانی که دستگاه با فضای ابری تماس داشته است، از ویژگی 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 lightConnectivity = dimmableLightDevice.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()

شروع پخش زنده

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

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

  • SDP برای جلسه.
  • مدت زمان جلسه بر حسب ثانیه.
  • شناسه جلسه، که ممکن است برای تمدید یا خاتمه جلسه استفاده شود.
suspend fun getWebRtcLiveViewTrait(cameraDevice: HomeDevice) {
 return cameraDevice.type(GoogleDoorbellDevice).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، متد 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)
  }
}

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

برای فعال کردن قابلیت ضبط دوربین، 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
    }
}

بازیابی تصاویر دوربین

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

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

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

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

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

برای دریافت پیش‌نمایش تصویر، ویژگی ویژگی 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
}

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

برای نشان دادن تازگی تصویر، فضای ابری گوگل هوم یک هدر 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}")
}

درخواست‌های اسنپ‌شات را تأیید کنید

همه URLهای snapshot به رسانه امن اشاره می‌کنند و برای محدوده Home APIs v2 به یک توکن OAuth 2.0 نیاز دارند. برای دانلود و رندر تصاویر، توکن OAuth باید به عنوان یک توکن Bearer در هدر Authorization درخواست HTTP شما تزریق شود.

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

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

مدیریت پخش زنده

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

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

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

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

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

// Assuming you have a HomeDevice instance 'device'
val availableQualityHints: StateFlow<List> =
    device.type(GoogleDoorbellDevice)
        .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(GoogleDoorbellDevice).trait(WebRtcLiveView).first() ?: return
    try {
        trait.changeLiveViewQuality(mediaSessionId, qualityHint)
    } catch (e: Exception) {
        // Handle error
    }
}

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

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

تنظیم اولویت استفاده از باتری

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

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

تنظیمات صوتی

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

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

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

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

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

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

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

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

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

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

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

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

ویژگی 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 در دسترس هستند:

حالت مقدار شمارشی توضیحات
صدا Sound تشخیص عمومی صدا
شخص در حال صحبت کردن PersonTalking گفتار را تشخیص می‌دهد.
پارس سگ DogBark صداهای سگ را تشخیص می‌دهد.
شکست شیشه GlassBreak صدای شکستن شیشه را تشخیص می‌دهد.
دزدگیر دود SmokeAlarm آلارم‌های دود را تشخیص می‌دهد، که اغلب با الگوی صوتی T3 (سه بوق کوتاه و به دنبال آن یک مکث) شناخته می‌شوند.
هشدار CO CoAlarm آلارم‌های مونوکسید کربن (CO) را تشخیص می‌دهد، که معمولاً با الگوی صوتی T4 (چهار بوق کوتاه و به دنبال آن مکث) شناخته می‌شوند.

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

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

در توسعه اندروید با استفاده از 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)
}

حالت‌های ضبط

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

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

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

حالت مقدار شمارشی توضیحات
معلول 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())
}

تنظیمات دیگر

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

فعال یا غیرفعال کردن دید در شب

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

// 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 با استفاده از تابع داخلی 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 با بزرگنمایی و بهبود، توضیح داده شده است.

نمای دید (viewport) در یک ViewportStruct تعریف شده است که شامل چهار مقدار است که به عنوان مختصات نمای دید استفاده می‌شوند. این مختصات به صورت زیر تعریف می‌شوند:

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

تعیین مقادیر ViewportStruct به رابط کاربری برنامه و پیاده‌سازی دوربین بستگی دارد. در سطح بسیار ابتدایی، برای تنظیم نمای ویدیوی دوربین، ویژگی viewport از ویژگی CameraAvStreamManagement را با ViewportStruct به‌روزرسانی کنید، و از تابع داخلی 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(),
    )
) }

فعال یا غیرفعال کردن تجزیه و تحلیل

هر دستگاه می‌تواند به صورت جداگانه ارسال داده‌های تحلیلی دقیق به فضای ابری گوگل هوم را انتخاب کند (به بخش نظارت ابری برای APIهای خانگی مراجعه کنید).

برای فعال کردن تجزیه و تحلیل برای یک دستگاه، ویژگی 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 با مقادیر زیر مطابقت دارد:

برچسب مقدار (یوبایت)
کم ۱ یو
متوسط 5u
بالا 10u

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

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

  • ۱۰ واحد ، ۱۵ واحد ، ۳۰ واحد ، ۶۰ واحد ، ۱۲۰ واحد ، ۱۸۰ واحد

تنظیمات زنگ

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

صدای زنگ را تغییر دهید

برای تغییر صدای زنگ در، ابتدا لیست صداهای زنگی که روی دستگاه نصب شده‌اند را با استفاده از ویژگی installedChimeSounds از ویژگی Chime دریافت کنید:

// Get a list of chimes and identify the currently selected one
private val doorbellChimeTraitFlow: Flow =
    device.traitFromType(Chime, GoogleDoorbellDevice)
val chimeSounds = doorbellChimeTraitFlow.first().installedChimeSounds ?: emptyList()

سپس، با استفاده از تابع داخلی setSelectedChime در کاتلین، ویژگی selectedChime از Chime trait را به‌روزرسانی کنید:

// Set the chime using the chimeId from the installed list
chimeSounds.firstOrNull { it.name == name }?.let { setSelectedChime(it.chimeId) }

از زنگ خارجی استفاده کنید

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

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

برای نشان دادن نوع زنگ خارجی نصب شده، ExternalChimeType برای به‌روزرسانی ویژگی externalChime از Chime trait با استفاده از تابع داخلی setExternalChime کاتلین استفاده کنید:

// Indicate the external chime is mechanical
chime.update {
  setExternalChime(ChimeTrait.ExternalChimeType.Mechanical)
}

مدت زمان زنگ خارجی را تغییر دهید

مدت زمان زنگ زدن یک زنگ خارجی (بر حسب ثانیه) را می‌توان از طریق APIهای Home پیکربندی کرد. اگر زنگ خارجی از مدت زمان زنگ پشتیبانی می‌کند، کاربر می‌تواند آن را پیکربندی کند.

مقدار تعیین‌شده در اینجا به مشخصات خود زنگ خارجی و مدت زمان پیشنهادی زنگ آن بستگی دارد.

برای تغییر مدت زمان زنگ خارجی، ویژگی externalChimeDurationSeconds از Chime trait را با استفاده از تابع داخلی setExternalChimeDurationSeconds در کاتلین به‌روزرسانی کنید:

// Change the external chime duration
chime.update {
  setExternalChimeDurationSeconds(newDuration.toUShort())
}

فعال کردن تم زنگوله

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

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

برای دیدن اینکه کدام تم‌های chime برای یک کاربر در دسترس هستند، یک فیلتر timebox ایجاد کنید و از آن برای فیلتر کردن نتایج دستور getAvailableThemes() از ویژگی ChimeThemes استفاده کنید. این دستور لیستی از تم‌های موجود، از جمله نام تم‌ها را برمی‌گرداند.

مثال زیر نحوه فیلتر کردن لیست را نشان می‌دهد. یک قالب در صورتی فعال در نظر گرفته می‌شود که زمان فعلی در محدوده زمان شروع و پایان آن (به ترتیب مقادیر startTimeSeconds و endTimeSeconds ) باشد. اگر زمان شروع تنظیم نشده باشد، از ابتدای زمان فعال در نظر گرفته می‌شود. اگر زمان پایان تنظیم نشده باشد، به طور نامحدود فعال خواهد بود. اگر هر دو وجود نداشته باشند، قالب همیشه فعال است.

// Get themes from the ChimeThemes trait
fun List<ChimeThemesTrait.ThemeStruct>.filterTimeboxedThemes():
    List<ChimeThemesTrait.ThemeStruct> {
  val now = timeSource.instant().epochSecond.toULong()
  return filter { chimeStruct: ChimeThemesTrait.ThemeStruct ->
    val startTime: ULong = chimeStruct.startTimeSeconds.getOrNull() ?: 0UL
    val endTime: ULong = chimeStruct.endTimeSeconds.getOrNull() ?: MAX_VALUE
    startTime <= now && now <= endTime
  }
}

val availableThemes =
  doorbellChimeThemesTraitFlow
    .first()
    .getAvailableThemes()
    .themes
    .filterTimeboxedThemes()

وقتی نام تم مورد نظر خود، مانند Christmas ، را پیدا کردید، می‌توانید آن را با استفاده از تابع setSelectedTimeboxedThemeName() در ویژگی ChimeThemes انتخاب کنید:

// Select a theme using the ChimeThemes trait
val themeToSelect = "Christmas"
if (themeToSelect in availableThemeNames) {
  doorbellChimeThemesTraitFlow.first().setSelectedTimeboxedThemeName(themeToSelect)
}

تنظیمات اعلان بازدیدکنندگان

شما می‌توانید با استفاده از ویژگی VisitorAnnouncement در APIهای Home، تنظیمات اعلام حضور بازدیدکنندگان برای زنگ در را جستجو و مدیریت کنید. این ویژگی کنترل می‌کند که آیا حضور بازدیدکننده در بلندگوهای هوشمند گوگل اعلام شود یا وقتی کسی زنگ در را به صدا در می‌آورد، نمایش داده شود.

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

// Read the current visitor announcements state
val isEnabled = visitorAnnouncementTrait.visitorAnnouncementsEnabled

// Toggle the visitor announcements setting
visitorAnnouncementTrait.update {
    setVisitorAnnouncementsEnabled(true)
}