מדריך למכשיר פעמון הדלת ל-iOS

סוג המכשיר "פעמון דלת" מיושם באמצעות שלוש תכונות: PushAvStreamTransportTrait, שמטפלת בהעברת סטרימינג של אודיו ווידאו באמצעות פרוטוקולים מבוססי-דחיפה, WebRtcLiveViewTrait, שמספקת את היכולת לשלוט בשידורים חיים וב-TalkBack, וגם CameraSnapshotTrait, שמספקת תמונות ממוזערות של תצוגה מקדימה שנשמרו במטמון וצילומי תמונות בשידור חי.

לפני שמשתמשים בתכונות או מנסים לעדכן מאפיינים, תמיד צריך לבדוק אם המכשיר תומך במאפיינים ובפקודות. מידע נוסף זמין במאמר שליטה במכשירים ב-iOS.

סוג המכשיר ב-Home APIs תכונות אפליקציה לדוגמה ב-Swift תרחיש לדוגמה

פעמון דלת

GoogleDoorbellDeviceType

home.matter.6006.types.0113

מכשיר שמופעל באמצעות כפתור מחוץ לדלת ומשמיע צליל או מציג אות חזותי, כדי למשוך את תשומת הלב של אדם שנמצא בצד השני של הדלת. פעמוני דלת יכולים לכלול שידורים חיים נגישים, דיבור דו-כיווני או אירועי זיהוי.

תכונות נדרשות
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

פעמון דלת

לקבל מידע בסיסי על מכשיר

   הטמעה באפליקציה לדוגמה ל-iOS   

המאפיין BasicInformation כולל מידע כמו שם הספק, מזהה הספק, מזהה המוצר, שם המוצר (כולל מידע על הדגם) וגרסת התוכנה של המכשיר:

let vendorName = basicInfoTrait.attributes.vendorName!
let vendorID = basicInfoTrait.attributes.vendorID!
let productID = basicInfoTrait.attributes.productID!
let productName = basicInfoTrait.attributes.productName!
let softwareVersion = basicInfoTrait.attributes.softwareVersion!

קבלת מספר סידורי

   הטמעה באפליקציה לדוגמה ל-iOS   

כדי לקבל את המספר הסידורי של המכשיר, משתמשים בפקודה GetSerialNumber של המאפיין ExtendedBasicInformation. בדוגמה הבאה מוצגת שמירה של המספר הסידורי במשתנה בשם serialNumber:

// Assuming extendedBasicInformationTrait: Google.ExtendedBasicInformationTrait
let response = try await extendedBasicInformationTrait.getSerialNumber()
let serialNumber = response.serialNumber

תגובות מהירות אוטומטיות

התכונה "תגובות מהירות" מאפשרת למשתמש לשלוח הודעה מוגדרת מראש למכשיר פעמון הדלת.

התכונה הזו זמינה רק במכשירי פעמון לדלת. רשימת ההודעות המוגדרות מראש זמינה לאפליקציית השותף, שיכולה להציג אותן למשתמש כדי שיבחר מביניהן. המשתמשים לא יכולים לערוך הודעות מוגדרות מראש.

התכונה "תגובות מהירות" מיושמת באמצעות המאפיין PresetMessage.

השמעת הודעה מוגדרת מראש

כדי להשמיע הודעה מוגדרת מראש, צריך להפעיל את ה-method‏ playPresetMessage ולהעביר לה את אחד מערכי המחרוזת שנמצאים במאפיין availablePhraseTypes.


import GoogleHomeSDK
import GoogleHomeTypes

func playDoorbellPresetMessage(device: HomeDevice, phraseTypeString: String) async {
    // 1. Retrieve the GoogleDoorbellDeviceType helper on the device
    guard let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) else {
        print("This device is not a Google Doorbell or is currently uninitialized.")
        return
    }

    // 2. Extract the Google.PresetMessageTrait
    guard let presetMessageTrait = doorbellDeviceType.traits[Google.PresetMessageTrait.self] else {
        print("PresetMessageTrait is not supported on this device.")
        return
    }

    // 3. (Optional) Check available phrase types supported by the device
    if let availablePhrases = presetMessageTrait.attributes.availablePhraseTypes {
        let phraseTypeNames = availablePhrases.map { $0.phraseType }
        print("Supported quick response phrases: \(phraseTypeNames)")
    }

    // 4. Send the playPresetMessage command asynchronously
    do {
        try await presetMessageTrait.playPresetMessage(phraseType: phraseTypeString)
        print("Preset message successfully requested.")
    } catch {
        print("SDK error occurred playing preset message: \(error)")
    }
}

הגדרת השפה שבה מדברים

הגדרת השפה שבה מדברים

מגדירים את השפה המדוברת הפעילה של המכשיר ללוקאל ספציפי (לדוגמה, "en_US") באמצעות השיטה setActiveLocale של המאפיין LocalizationConfiguration.

// Setting the active language
// Assuming localizationConfigurationTrait: Matter.LocalizationConfigurationTrait
let selectedLocale = "en_US"
try await localizationConfigurationTrait.update {
    $0.setActiveLocale(selectedLocale)
}

קבלת הזמן האחרון שבו המכשיר יצר קשר עם הענן

כדי למצוא את הפעם האחרונה שבה המכשיר היה בקשר עם הענן, משתמשים במאפיין lastContactTimestamp של התכונה ExtendedGeneralDiagnostics:

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

הגדרות של סוג התושבת של המצלמה

התכונה Mount מכילה את הגדרות התושבת של המצלמה ואת פרטי הסטטוס. אפשר לקרוא מאפיינים כמו מצב ההרכבה, סוג הזיהוי ושם סוג ההרכבה. בנוסף, אפשר להשתמש במאפיין Mount כדי לשנות את הגדרת ברירת המחדל של סוג נקודת ה-mount.

// 1. Get the Mount trait
guard let mountTrait = deviceType.traits[Google.MountTrait.self] else {
  print("Mount trait not supported or configured on this device.")
  return
}

// 2. Read the current mount state, detection type, and type name
let mountState         = mountTrait.attributes.mountState         // Type: Google.MountTrait.MountStateEnum?
let mountDetectionType = mountTrait.attributes.mountDetectionType // Type: Google.MountTrait.MountDetectionTypeEnum?
let mountTypeName      = mountTrait.attributes.mountTypeName      // Type: String?

// 3. Update the mount type override
try await mountTrait.update { mutableTrait in
  mutableTrait.setMountTypeOverride(.official)
}

בדיקת החיבור של המכשיר

הקישוריות של מכשיר נבדקת בפועל ברמת סוג המכשיר, כי חלק מהמכשירים תומכים בכמה סוגי מכשירים. המצב שמוחזר הוא שילוב של מצבי הקישוריות של כל התכונות במכשיר הזה.

let doorbellConnectivity = doorbellDeviceType.metadata.sourceConnectivity.connectivityState

יכול להיות שיוצג מצב של partiallyOnline במקרה של סוגי מכשירים מעורבים כשאין חיבור לאינטרנט. יכול להיות שתכונות סטנדרטיות של Matter עדיין יהיו אונליין בגלל ניתוב מקומי, אבל תכונות מבוססות-ענן יהיו אופליין.

איך מוצאים את כתובת ה-IP של המכשיר

כדי למצוא את כתובת ה-IP של המכשיר, משתמשים במאפיין networkInterfaces של GeneralDiagnosticsTrait. הכתובות מוחזרות כאובייקטים מסוג Data, שאפשר להמיר למחרוזות IPv4 או IPv6 רגילות באמצעות מסגרת Network:

func getIpAddresses(trait: Matter.GeneralDiagnosticsTrait) -> [String] {
  let interfaces = trait.attributes.networkInterfaces ?? []
  var ipAddresses: [String] = []

  for interface in interfaces {
    for data in interface.iPv4Addresses {
      if let ipv4 = IPv4Address(data) {
        ipAddresses.append(String(describing: ipv4))
      }
    }
    for data in interface.iPv6Addresses {
      if let ipv6 = IPv6Address(data) {
        ipAddresses.append(String(describing: ipv6))
      }
    }
  }

  return ipAddresses
}

התחלת שידור חי

   הטמעה באפליקציה לדוגמה ל-iOS   

כדי להתחיל שידור חי, שולחים את המחרוזת של פרוטוקול תיאור הסשן (SDP) למתודה startLiveView(offerSdp:) של המאפיין WebRtcLiveViewTrait, שמחזירה שלושה ערכים:

  • ה-SDP של הסשן.
  • משך הסשן בשניות.
  • מזהה הסשן, שבו אפשר להשתמש כדי להאריך או לסיים את הסשן.
public func sendOffer(offerSdp: String) async throws
-> (answerSdp: String, mediaSessionId: String, liveViewDuration: TimeInterval)
{
  do {
    // Sending StartLiveView command
    let response = try await liveViewTrait.startLiveView(
      offerSdp: offerSdp
    )
    // Received StartLiveView response
    return (
      answerSdp: response.answerSdp,
      mediaSessionId: response.mediaSessionId,
      liveViewDuration: TimeInterval(response.liveSessionDurationSeconds)
    )
  } catch {
    // Failed to send StartLiveView command
    throw error
  }
}

הארכת שידור חי

   הטמעה באפליקציה לדוגמה ל-iOS   

לשידורים חיים יש משך זמן מוגדר מראש, ואחרי שהוא מסתיים, השידור נגמר. כדי להאריך את משך הזמן של שידור פעיל, שולחים בקשת הארכה באמצעות השיטה extendLiveView(mediaSessionId:optionalArgsProvider:):

public func extendLiveView(mediaSessionId: String) async throws {
  do {
    // Extending live view
    let extendedDuration = try await liveViewTrait.extendLiveView(mediaSessionId: mediaSessionId)
  } catch {
    // Failed to extend live view
    throw error
  }
}

הפעלה והפסקה של TalkBack

   הטמעה באפליקציה לדוגמה ל-iOS   

כדי להפעיל את TalkBack, מפעילים את השיטה startTalkback(mediaSessionId:optionalArgsProvider:) של המאפיין WebRtcLiveViewTrait. כדי להפסיק, משתמשים ב-stopTalkback(mediaSessionId:).

public func toggleTwoWayTalk(isOn: Bool, mediaSessionId: String) async throws {
  do {
    if isOn {
      try await liveViewTrait.startTalkback(mediaSessionId: mediaSessionId)
    } else {
      try await liveViewTrait.stopTalkback(mediaSessionId: mediaSessionId)
    }
  } catch {
    throw HomeError.commandFailed("Failed to toggle twoWayTalk: \(error)")
  }
}

ניהול השידור החי

   הטמעה באפליקציה לדוגמה ל-iOS   

כדאי לשנות את איכות השידור החי כדי לבצע אופטימיזציה של השימוש ברוחב הפס בהתאם להקשר הצפייה של הלקוח (לדוגמה, מעבר לרזולוציה נמוכה יותר כשמציגים משבצת קטנה יותר של תצוגה מקדימה, תצוגת משבצות או מצב תמונה בתוך תמונה).

שינוי האיכות באופן דינמי באמצעות המאפיין WebRtcLiveView מנהל באופן ספציפי את הרזולוציה של סשן השידור החי הפעיל בלקוח מסוים. היא לא זהה להגדרה של רוחב הפס במכשיר עצמו, שמשפיעה על כל הצופים בו-זמנית ועל האיכות של הקלטות הווידאו ההיסטוריות שנשמרו בענן.

בדוגמה הבאה אפשר לראות איך לאחזר ולעדכן את איכות השידור החי במכשיר:

  • אחזור אפשרויות האיכות הנתמכות: קבלת רזולוציות הסטרימינג הזמינות שנתמכות במכשיר. הקוד שולח שאילתה למאפיין WebRtcLiveView כדי לחשוף את איכויות הסטרימינג הנתמכות כרשימה של ערכי QualityHint (כמו .sd,‏ .hd,‏ .fhd,‏ .qhd או .uhd) באמצעות המאפיין supportedQualityHints.

  • שינוי האיכות של השידור החי: אפשר להחיל QualityHint נבחר כדי לשנות את רזולוציית הסטרימינג של השידור החי הפעיל (לדוגמה, מעבר מאיכות רגילה לאיכות גבוהה). הפונקציה updateQualityHint משתמשת ב-method‏ changeLiveViewQuality של המאפיין WebRtcLiveView כדי להחיל את ההגדרה QualityHint שנבחרה על סשן המדיה הפעיל.

public var supportedQualityHints: [Google.WebRtcLiveViewTrait.QualityHint] {
  return liveViewTrait?.attributes.supportedQualityHints ?? []
}

public func updateQualityHint(
  liveViewTrait: Google.WebRtcLiveViewTrait,
  hint: Google.WebRtcLiveViewTrait.QualityHint,
  mediaSessionId: String
) async {
  do {
    _ = try await liveViewTrait.changeLiveViewQuality(
      mediaSessionId: mediaSessionId,
      qualityHint: hint
    )
  } catch {
    // error
  }
}

הפעלה והשבתה של יכולת ההקלטה

כדי להפעיל את יכולת ההקלטה של המצלמה, מעבירים את הערך TransportStatusEnum.Active ל-method‏ setTransportStatus(transportStatus:optionalArgsProvider:) של המאפיין PushAvStreamTransportTrait. כדי להשבית את יכולת ההקלטה, מעבירים את הערך TransportStatusEnum.Inactive. בדוגמה הבאה, אנחנו עוטפים את הקריאות האלה בקריאה אחת שמשתמשת ב-Boolean כדי להחליף את מצב יכולת ההקלטה:

public func toggleIsRecording(isOn: Bool) {
  self.uiState = .loading

  guard let pushAvStreamTransportTrait else {
    // PushAvStreamTransportTrait not found.
    return
  }
  Task {
    do {
      try await pushAvStreamTransportTrait.setTransportStatus(
        transportStatus: isOn ? .active : .inactive)
      if isOn {
        do {
          self.player = try self.createWebRtcPlayer()
        } catch {
          // Failed to initialize WebRtcPlayer
          self.uiState = .disconnected
          return
        }
        await self.player?.initialize()
        self.uiState = .live
      } else {
        self.player = nil
        self.uiState = .off
      }
    } catch {
      // Failed to toggle onOff
    }
  }
}

הפעלה או השבתה של יכולת ההקלטה של המצלמה זהה להפעלה או לכיבוי של הווידאו במצלמה. כשהווידאו במצלמה מופעל, המצלמה מקליטה (למטרות של אירועים וקליפים קשורים).

כשיכולת ההקלטה מושבתת (הווידאו של המצלמה כבוי):

  • המצלמה עדיין יכולה להופיע כפעילה בהתאם לconnectivityState של סוג המכשיר.
  • אי אפשר לגשת לשידור החי, והמצלמה לא מזהה אירועים בענן.

איך בודקים אם אפשרות ההקלטה פועלת

כדי לבדוק אם יכולת ההקלטה של המצלמה מופעלת, בודקים אם יש חיבורים פעילים. בדוגמה הבאה מוגדרות שתי פונקציות שמבצעות את הפעולה הזו:

public func isDeviceRecording() -> Bool {
  guard let pushAvStreamTransportTrait else {
    // PushAvStreamTransportTrait not found.
    return false
  }
  guard
    let hasActiveConnection =
      pushAvStreamTransportTrait
      .attributes
      .currentConnections?
      .contains(where: { $0.transportStatus == .active })
  else {
    return false
  }
  return hasActiveConnection
}

אחזור תמונות מצב מהמצלמה

   הטמעה באפליקציה לדוגמה ל-iOS   

אפשר להשתמש בתכונה CameraSnapshot כדי לאחזר תמונות סטטיות ממצלמה. תמונות המצב האלה שימושיות בכמה תרחישים:

  • כמשבצת זמנית בממשק המשתמש בזמן שהשידור החי ב-WebRTC נטען.
  • כתמונה סטטית של תצוגה מקדימה שמשתדרגת לשידור חי כשהמשתמש לוחץ עליה.
  • כקנבס רקע לציור ולהגדרה של אזורי פעילות בהתאמה אישית.

התכונה CameraSnapshot מציעה שתי דרכים לאחזור תמונות מצב, בהתאם לצורך שלכם בתמונת מצב שנשמרה במטמון לעיבוד מהיר או בתמונת מצב בזמן אמת על פי דרישה.

קבלת תמונת מצב של תצוגה מקדימה שנשמרה במטמון

תמונת מצב של תצוגה מקדימה היא תמונה שנשמרה במטמון, וערכת ה-SDK יכולה לאחזר אותה בלי להפעיל את המצלמה. זו השיטה המהירה ביותר לאחזר תמונה סטטית, והיא אידיאלית לדפי סקירה כללית של מצלמות או לרשתות של לוחות בקרה.

כדי לקבל את תמונת המצב של התצוגה המקדימה, קוראים את מאפיין התכונה preview_image_url:

guard let cameraSnapshotTrait = deviceType.traits[
  Google.CameraSnapshotTrait.self
] else {
  print("CameraSnapshot trait not supported on this device.")
  return
}

if let previewImageUrlString = cameraSnapshotTrait
  .attributes.preview_image_url,
   let url = URL(string: previewImageUrlString) {
  // Load the preview image from the URL
}

בהתאם להגדרות המצלמה ולפעילות, כתובת ה-URL של התצוגה המקדימה מפנה לתמונה שנשמרה במטמון ונוצרה מקטע וידאו אחרון (ה-I-frame הראשון של קטע הווידאו האחרון) או לתמונת מצב שהמצלמה מעלה מדי פעם.

כדי לציין את עדכניות התמונה, הענן של Google Home מטמיע כותרת X-Home-Image-Captured-At בתמונת ה-JPEG או ה-PNG שמוצגת, בפורמט UTC. אפשר לנתח את הכותרת הזו בצד הלקוח כדי להציג את גיל קובץ ה-snapshot באפליקציה.

איך מקבלים תמונת מצב בזמן אמת על פי דרישה

בתהליכים שבהם המשתמשים צריכים את התצוגה החיה הנוכחית של המצלמה, כמו הגדרת אזורי פעילות, אתם יכולים לבקש תמונת מצב בזמן אמת. הפעלת תמונת מצב בשידור חי גורמת למצלמה להתעורר, לצלם פריים חדש ולהעלות אותו לענן.

כדי לבקש תמונת מצב בזמן אמת, משתמשים בפקודה getLiveSnapshot():

do {
  let response = try await cameraSnapshotTrait.getLiveSnapshot()
  let snapshotUrlString = response.snapshot_url

  if let url = URL(string: snapshotUrlString) {
    // Load the live snapshot image from the URL
  }
} catch {
  print("Failed to get live snapshot: \(error)")
}

אימות בקשות של תמונת מצב

   הטמעה באפליקציה לדוגמה ל-iOS   

כל כתובות ה-URL של תמונות המצב מפנות למדיה מאובטחת ודורשות אסימון OAuth 2.0 להיקף של Home APIs v2. כדי להוריד ולעבד את התמונות, צריך להוסיף את טוקן ה-OAuth כטוקן למוכ"ז בכותרת Authorization של בקשת ה-HTTP.

בדוגמה הבאה אפשר לראות איך מגדירים בקשה מאובטחת לאחזור מהרשת כדי להוריד קובץ Snapshot:

import UIKit

func loadSnapshotImage(from url: URL, home: Home) async -> UIImage? {
  do {
    // 1. Retrieve the OAuth access token from the Home APIs SDK
    let (accessToken, _) = try await home.permissions.authorization()

    // 2. Configure the HTTP GET request with the Bearer token
    var request = URLRequest(url: url)
    request.setValue(
      "Bearer \(accessToken)",
      forHTTPHeaderField: "Authorization"
    )

    // 3. Fetch the image data
    let (data, _) = try await URLSession.shared.data(for: request)
    return UIImage(data: data)
  } catch {
    print("Error loading snapshot image: \(error)")
    return nil
  }
}

הגדרות הסוללה

אפשר לשלוט בהגדרות שונות של הסוללה באמצעות ממשקי ה-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"
    }
  ]
}
private func setBatteryUsage(to option: UInt8) async throws {
  _ = try await energyPreferenceTrait.update {
    $0.setCurrentEnergyBalance(option)
  }
}

הפעלה אוטומטית של מצב החיסכון בסוללה

   הטמעה באפליקציה לדוגמה ל-iOS   

כדי להגדיר את התכונה הזו, מעדכנים את המאפיין currentLowPowerModeSensitivity של התכונה EnergyPreference. המאפיין הזה משתמש באינדקס כדי לבחור רמת רגישות, כאשר 0 בדרך כלל מייצג את Disabled ו-1 מייצג את Enabled או Automatic.

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

קבלת מצב הטעינה של הסוללה

   הטמעה באפליקציה לדוגמה ל-iOS   

כדי לקבל את מצב הטעינה הנוכחי של המכשיר (בטעינה, טעון במלואו או לא בטעינה), משתמשים במאפיין batChargeState של התכונה PowerSource.

self.chargingState = powerSourceTrait.attributes.batChargeState

var description: String
switch self.chargingState {
case .isCharging:
  description = "Charging"
case .isAtFullCharge:
  description = "Full"
case .isNotCharging:
  description = "Not Charging"
default:
  description = "Unknown"
}

איך בודקים את רמת הטעינה

כדי לקבל את רמת הטעינה הנוכחית של הסוללה, משתמשים במאפיין batChargeLevel של התכונה PowerSource. הרמה היא OK, Warning (נמוכה) או Critical.

self.batteryLevel = powerSourceTrait.attributes.batChargeLevel

var description: String
switch self.batteryLevel {
case .ok:
  description = "OK"
case .warning:
  description = "Warning"
case .critical:
  description = "Critical"
default:
  description = "Unknown"
}

משיגים את מקור המתח

כדי לקבוע באיזה מקור מתח המכשיר משתמש, צריך להשתמש במאפיינים BatPresent ו-wiredPresent של התכונה PowerSource.

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

בודקים אם צריך להחליף את הסוללה

המאפיין batReplaceability מציין אם הסוללה לא ניתנת להחלפה, ניתנת להחלפה על ידי המשתמש או ניתנת להחלפה במפעל.

אם אפשר להחליף את הסוללה, המאפיין batReplacementNeeded של התכונה PowerSource מציין אם צריך להחליף את הסוללה.

// Get the battery replacement status
var batteryStatus = powerSourceTrait.attributes.batReplacementNeeded

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

כשהמשתמש יכול להחליף את הסוללה, batReplacementDescription מתאר את הסוללה, כולל מידע כמו גורם הצורה, הכימיה והיצרן המועדף.

הגדרות אודיו

אפשר לשלוט בהגדרות אודיו שונות באמצעות ממשקי ה-API של Home.

הפעלה או השבתה של המיקרופון

כדי להפעיל או לכבות את המיקרופון של המכשיר, מעדכנים את המאפיין microphoneMuted של התכונה CameraAvStreamManagementTrait באמצעות הפונקציה המובנית setMicrophoneMuted:

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

איך מפעילים או משביתים את הקלטת האודיו

כדי להפעיל או להשבית את הקלטת האודיו במכשיר, מעדכנים את המאפיין recordingMicrophoneMuted של התכונה CameraAvStreamManagementTrait באמצעות הפונקציה המובנית setRecordingMicrophoneMuted:

// Turn audio recording on or off for the device
func setAudioRecording(on: Bool) async {
  do {
    _ = try await self.cameraAvStreamManagementTrait?.update {
      $0.setRecordingMicrophoneMuted(!on)
    }
  } catch {
    // Error
  }
}

שינוי עוצמת הקול של הרמקול

כדי לשנות את עוצמת הקול של הרמקול במכשיר, מעדכנים את המאפיין speakerVolumeLevel של התכונה CameraAvStreamManagementTrait באמצעות הפונקציה המובנית setSpeakerVolumeLevel:

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

הגדרות של אזורי פעילות

   הטמעה באפליקציה לדוגמה ל-iOS   

התכונה ZoneManagement מספקת ממשק לניהול אזורי עניין מותאמים אישית (אזורי פעילות) במצלמות ובפעמוני דלת. האזורים האלה משמשים לסינון זיהוי האירועים (כמו תנועה של אדם או רכב) לאזורים ספציפיים בשדה הראייה של המכשיר.

המשתמש מגדיר את אזורי הפעילות באפליקציה של השותף, וכך הוא יכול לשרטט אזורים מעל חלקים ספציפיים בשדה הראייה של המצלמה. האזורים האלה שמוגדרים על ידי המשתמש מתורגמים למבנים שבהם התכונה הזו משתמשת. מידע נוסף על אופן הפעולה של אזורי הפעילות זמין במאמר הגדרה ושימוש באזורי פעילות.

בדרך כלל מגדירים אזורי פעילות באמצעות קואורדינטות קרטזיות דו-ממדיות. המאפיין מספק את TwoDCartesianVertexStruct לקודקודים ואת TwoDCartesianZoneStruct להגדרת האזור (שם, קודקודים, צבע ושימוש).

בדיקת אזורי הפעילות

כדי להציג אזורי פעילות, בודקים את המאפיין zones של התכונה ZoneManagement.

let zoneManagementTrait: Google.ZoneManagementTrait

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

הוספת אזור פעילות

כדי ליצור אזור חדש, משתמשים בפקודה createTwoDCartesianZone. הפקודה הזו מקבלת TwoDCartesianZoneStruct, שמגדיר את השם, הקודקודים, הצבע והשימוש של האזור.

בדוגמה הבאה מוסבר איך ליצור אזור בשם "Front Porch" עם ארבעה קודקודים, בצבע ורוד סלמון (‎#F439A0), שמשמש לזיהוי תנועה.

import GoogleHomeSDK
import GoogleHomeTypes

func createFrontPorchZone(trait: Google.ZoneManagementTrait) async {
  // 1. Define the vertices for the zone (2D Cartesian coordinates)
  // Values are UInt16, typically scaled to the device's twoDCartesianMax.
  let vertices = [
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 260, y = 422),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1049, y = 0),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048, y = 0),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 2048, y = 950),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 1630, y = 1349),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 880, y = 2048),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 0, y = 2048),
    Google.ZoneManagementTrait.TwoDCartesianVertexStruct(x = 638, y = 1090)
  ]

  // 2. Define the zone structure using the given SDK struct
  let newZone = Google.ZoneManagementTrait.TwoDCartesianZoneStruct(
    name: "Front Porch",
    use: [.motion], // ZoneUseEnum.motion
    vertices: vertices,
    // Color is a hex string (for example, Salmon/Pink)
    color: "#F439A0"
  )

  do {
    // 3. Execute the raw command to add the zone to the device
    // This returns the created zone's ID (UInt16).
    var newZoneID = try await trait.createTwoDCartesianZone(zone: newZone)
  } catch {
    // Error
  }
}

עדכון של אזור פעילות

כדי לעדכן אזור קיים, משתמשים בפקודה updateTwoDCartesianZone. כדי להריץ את הפקודה הזו, צריך את zoneId ואת TwoDCartesianZoneStruct המעודכן.

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

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

מחיקת אזור פעילות

כדי להסיר אזור, משתמשים בפקודה removeZone עם הערך הספציפי של zoneId.

let zoneManagementTrait: Google.ZoneManagementTrait
let zoneID: UInt16

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

טריגרים לאירועים של זיהוי צליל

המאפיין AvStreamAnalysis מספק ממשק לניהול טריגרים לזיהוי אירועים במצלמות ובפעמוני דלת. טריגרים שמבוססים על ראייה (כמו אנשים או כלי רכב) יכולים להיות ספציפיים לאזור, אבל טריגרים שקשורים לצלילים הם בדרך כלל הגדרות ברמת המכשיר.

אלה סוגי הטריגרים שזמינים לזיהוי צלילים באמצעות EventTriggerTypeEnum:

מצב הערך של הטיפוס בן המנייה (enum) תיאור
צליל Sound זיהוי צלילים כללי.
מישהו מדבר PersonTalking מזהה דיבור.
נביחות של כלב DogBark מזהה נביחות של כלבים.
זכוכית נשברת GlassBreak מזהה צליל של זכוכית נשברת.
גלאי עשן SmokeAlarm זיהוי של גלאי עשן, בדרך כלל לפי דפוס הצליל T3 (שלושה צפצופים קצרים ואחריהם הפסקה).
גלאי פחמן חד-חמצני CoAlarm זיהוי אזעקות של פחמן חד-חמצני (CO), שבדרך כלל מזוהות לפי דפוס הצליל T4 (ארבעה צפצופים קצרים ואחריהם הפסקה).

איך בודקים את סטטוס זיהוי הצלילים

כדי להציג למשתמש את המצב הנוכחי של זיהוי הצלילים, צריך לבדוק במה המכשיר תומך ומה מופעל על ידי החומרה של המכשיר. שני המאפיינים שצריך לבדוק הם:

בפיתוח ל-iOS, בדרך כלל ניגשים למאפיין AvStreamAnalysis מהמכשיר כדי לקרוא את המאפיינים האלה.

// Example struct to store event triggers
public struct EventTrigger: Equatable {
  public var id: Google.AvStreamAnalysisTrait.EventTriggerTypeEnum
  public var enabled: Bool
}

let avStreamAnalysisTrait: Google.AvStreamAnalysisTrait

let possibleEventTriggers = avStreamAnalysisTrait.attributes.supportedEventTriggers ?? []
let enabledEventTriggers = avStreamAnalysisTrait.attributes.enabledEventTriggers ?? []

let eventTriggers [EventTrigger] = []
for trigger in possibleEventTriggers {
  self.eventTriggers.append(
    EventTrigger(
      id: trigger,
      enabled: enabledEventTriggers.contains(trigger)
    )
  )
}

עדכון קבוצת הטריגרים המופעלים

כדי לעדכן את קבוצת הטריגרים המופעלים, משתמשים בפקודה SetOrUpdateEventDetectionTriggers, שמקבלת רשימה של מבני EventTriggerEnablement.

// Example struct to store event triggers
public struct EventTrigger: Equatable {
  public var id: Google.AvStreamAnalysisTrait.EventTriggerTypeEnum
  public var enabled: Bool
}

let avStreamAnalysisTrait: Google.AvStreamAnalysisTrait
let eventTriggers: [EventTrigger]

let enabledEventTriggers = eventTriggers.map {
  Google.AvStreamAnalysisTrait.EventTriggerEnablement(
    eventTriggerType: $0.id,
    enablementStatus: $0.enabled ? .enabled : .disabled
  )
}

try await avStreamAnalysisTrait.setOrUpdateEventDetectionTriggers(
  eventTriggerEnablements: enabledEventTriggers
)

מצבי הקלטה

   הטמעה באפליקציה לדוגמה ל-iOS   

התכונה RecordingMode מספקת ממשק לניהול ההתנהגות של הקלטת וידאו ותמונות במצלמות ובפעמוני דלת. המשתמשים יכולים לבחור בין הקלטה רציפה, הקלטה בזמן אירוע (EBR) או השבתה של ההקלטה לחלוטין (צפייה בזמן אמת בלבד).

השדה RecordingModeEnum מגדיר את אסטרטגיות ההקלטה הזמינות:

מצב הערך של הטיפוס בן המנייה (enum) תיאור
מושבת Disabled ההקלטה מושבתת לגמרי. משמש בעיקר מכשירים מדור קודם.
‫CVR (הקלטת וידאו רציפה) Cvr הווידאו מוקלט 24 שעות ביממה, 7 ימים בשבוע. נדרש מינוי (לדוגמה, Google Home Premium.
EBR (הקלטה בזמן אירוע) Ebr ההקלטה מופעלת על ידי אירועים (אדם, תנועה). אורך הסרטון תלוי במשך האירוע ובמינוי.
ETR (הקלטה שמופעלת על ידי אירוע) Etr הקלטה של קטע מקדים קצר (לדוגמה, 10 שניות) שמופעלת על ידי אירועים.
Live View LiveView ההקלטה מושבתת, אבל המשתמשים עדיין יכולים לגשת לשידור החי.
תמונות סטילס Images כשמתרחשים אירועים, המצלמה מצלמת תמונות במקום סרטונים.

בדיקת מצבי ההקלטה

כדי להציג את הגדרות ההקלטה הנוכחיות, בודקים את המאפיינים של התכונה RecordingMode:

// Example struct to store recording modes.
public struct RecordingMode: Hashable {
  public let id: UInt8
  public let mode: Google.RecordingModeTrait.RecordingModeEnum
}

let recordingModeTrait: Google.RecordingModeTrait

if let availableRecordingModes = recordingModeTrait.attributes.availableRecordingModes,
   let supportedRecordingModes = recordingModeTrait.attributes.supportedRecordingModes,
   let selectedRecordingMode = recordingModeTrait.attributes.selectedRecordingMode {

  var recordingModes: [RecordingMode] = []

  for recordingModeId in availableRecordingModes {
    guard Int(recordingModeId) < supportedRecordingModes.count,
          Int(recordingModeId) >= 0 else {
      // Out of bounds error
    }

    recordingModes.append(
      RecordingMode(
        id: recordingModeId,
        mode: supportedRecordingModes[Int(recordingModeId)].recordingMode,
      )
    )
  }
}

שינוי מצב ההקלטה

לפני העדכון, צריך לוודא שהאינדקס שנבחר מהמאפיין supportedRecordingModes קיים במאפיין availableRecordingModes.

כדי לעדכן את המצב שנבחר, משתמשים בפונקציה setSelectedRecordingMode ומעבירים את האינדקס של המצב שנבחר:

let recordingModeTrait: Google.RecordingModeTrait
let recordingModeID: UInt8

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

הגדרות אחרות

אפשר לשלוט בהגדרות שונות אחרות באמצעות ממשקי ה-API של Home.

הפעלה או השבתה של ראיית לילה

כדי להפעיל או להשבית את ראיית הלילה במצלמה, משתמשים ב-TriStateAutoEnum כדי לעדכן את המאפיין nightVision של התכונה CameraAvStreamManagementTrait באמצעות הפונקציה המובנית setNightVision:

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

שינוי הבהירות של נורית הסטטוס

כדי לשנות את הבהירות של נורית הסטטוס, משתמשים בפקודה ThreeLevelAutoEnum כדי לעדכן את המאפיין statusLightBrightness של התכונה CameraAvStreamManagementTrait באמצעות הפונקציה המובנית setStatusLightBrightness:

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

שינוי אזור התצוגה של המצלמה

אזור התצוגה של המצלמה זהה לתכונה "הגדלה וחיתוך" שמתוארת במאמר התמיכה הגדלה ושיפור של סרטונים במצלמת Nest.

אזור התצוגה מוגדר ב-ViewportStruct שמכיל ארבעה ערכים, שמשמשים כקואורדינטות של אזור התצוגה. הקואורדינטות מוגדרות כך:

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

הערכים של ViewportStruct נקבעים לפי ממשק המשתמש של האפליקציה והטמעת המצלמה. ברמה הבסיסית ביותר, כדי להגדיר את אזור התצוגה של סרטון המצלמה, מעדכנים את המאפיין viewport של התכונה CameraAvStreamManagementTrait באמצעות ViewportStruct, בעזרת הפונקציה המובנית setViewport.

func setCrop(x1: UInt16, y1: UInt16, x2: UInt16, y2: UInt16) {

  let viewport = Google.CameraAvStreamManagementTrait.ViewportStruct(
    x1: x1,
    y1: y1,
    x2: x2,
    y2: y2
  )

  Task {
    do {
      try await cameraAvStreamManagementTrait.update {
        $0.setViewport(viewport)
      }
    } catch {
      // Error
    }
  }

}

יצירת TransportOptionsStruct

כדי להשתמש בחלק מההגדרות, צריך לשנות מאפיינים ב-TransportOptionsStruct, שמועבר לאפשרויות ההעברה של חיבור הסטרימינג. ב-Swift, צריך ליצור את המבנה הזה לפני שמעדכנים מאפיינים כלשהם.

אפשר להשתמש בפונקציית העזר הזו כדי ליצור את המבנה לשימוש עם השינויים הבאים בהגדרות:

func getTransportOptions(
  transportOptions: Google.PushAvStreamTransportTrait.TransportOptionsStruct,
  wakeUpSensitivity: UInt8?,
  maxEventLength: UInt32?
) async throws
  -> Google.PushAvStreamTransportTrait.TransportOptionsStruct
{

  var newMotionTimeControl:
    Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct? = nil
  if let maxEventLength {
    guard let motionTimeControl = transportOptions.triggerOptions.motionTimeControl else {
      throw HomeError.failedPrecondition(
        // Error - cannot update max event length without motion time control
    }
    newMotionTimeControl =
      Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct(
        initialDuration: motionTimeControl.initialDuration,
        augmentationDuration: motionTimeControl.augmentationDuration,
        maxDuration: maxEventLength,
        blindDuration: motionTimeControl.blindDuration
      )
  }

  return Google.PushAvStreamTransportTrait.TransportOptionsStruct(
    streamUsage: .recording,
    videoStreamID: nil,
    audioStreamID: nil,
    tlsEndpointID: transportOptions.tlsEndpointID,
    url: transportOptions.url,
    triggerOptions: Google.PushAvStreamTransportTrait.TransportTriggerOptionsStruct(
      triggerType: .motion,
      motionZones: nil,
      motionSensitivity: wakeUpSensitivity,
      motionTimeControl: newMotionTimeControl,
      maxPreRollLen: nil
    ),
    ingestMethod: .cmafIngest,
    containerOptions: Google.PushAvStreamTransportTrait.ContainerOptionsStruct(
      containerType: .cmaf,
      cmafContainerOptions: nil
    ),
    expiryTime: nil
  )
}

private func getRecordingConnection() async throws
  -> Google.PushAvStreamTransportTrait.TransportConfigurationStruct?
{
  guard let pushAvStreamTransportTrait else {
    // Error - PushAvStreamTransport trait not available
    return nil
  }

  let connections = try await pushAvStreamTransportTrait.findTransport().transportConfigurations

  for connection in connections {
    guard let transportOptions = connection.transportOptions,
      transportOptions.streamUsage == .recording
    else {
      continue
    }

    return connection
  }

  return nil
}

הפעלה או השבתה של ניתוח נתונים

כל מכשיר יכול להצטרף בנפרד לשליחת נתוני ניתוח מפורטים לענן של Google Home (ראו Cloud Monitoring לממשקי Home API).

כדי להפעיל ניתוח נתונים במכשיר, מגדירים את המאפיין analyticsEnabled של ExtendedGeneralDiagnosticsTrait לערך true. כשמגדירים את analyticsEnabled, מאפיין אחר, logUploadEnabled, מוגדר באופן אוטומטי ל-true, מה שמאפשר להעלות את קובצי היומן של ניתוח הנתונים לענן של Google Home.

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

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

הגדרות של העברה והקלטה

בקטע הזה מפורטות הגדרות שקשורות לאיכות הסטרימינג מהמצלמה ולהפעלת אירועים. ההגדרות האלה מנוהלות על ידי המאפיין PushAvStreamTransport.

קריאת הגדרות התחבורה

בקטע הזה מוסבר איך לאחזר את ההגדרות הנוכחיות ממצלמה או מפעמון דלת. הוא מאחזר את המאפיין PushAvStreamTransport, מוצא את החיבור הספציפי שמשמש להקלטה, ואז מחלץ את הערכים הנוכחיים של איכות רוחב הפס, הרגישות של יציאה ממצב שינה ואורך האירוע המקסימלי.

// Assuming access to
// var pushAvStreamTransportTrait: Google.PushAvStreamTransportTrait
let connections = try await pushAvStreamTransportTrait.findTransport().transportConfigurations

// Locate the connection designated for recording
let recordingConnection = connections.first { connection in
    guard let transportOptions = connection.transportOptions else { return false }
    return transportOptions.streamUsage == .recording
}

let options = recordingConnection?.transportOptions

// 1. Bandwidth Quality (Video Stream ID)
let videoStreamId = options?.videoStreamID

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

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

עדכון הגדרות התחבורה

בקטע הזה מוסבר איך לשנות את הגדרות ההעברה. הוא יוצר TransportOptionsStruct חדש שמכיל את הערכים החדשים, ואז משתמש בפקודה modifyPushTransport כדי לשלוח את ההגדרות המעודכנות האלה בחזרה למכשיר, ולהחיל אותן על החיבור להקלטה שנמצא בשלב הקודם.

כדי לשנות את ההגדרות האלה, משתמשים בפקודה modifyPushTransport עם TransportOptionsStruct.

// Example: Updating to Max Quality and 30s duration
let currentOptions = recordingConnection!.transportOptions!
let newOptions = Google.PushAvStreamTransportTrait.TransportOptionsStruct(
    streamUsage: .recording,
    videoStreamID: 2, // Max Quality
    tlsEndpointID: currentOptions.tlsEndpointID,
    url: currentOptions.url,
    triggerOptions: Google.PushAvStreamTransportTrait.TransportTriggerOptionsStruct(
        triggerType: .motion,
        motionSensitivity: 5, // Medium
        motionTimeControl: Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct(
            initialDuration: currentOptions.triggerOptions.motionTimeControl?.initialDuration ?? 10,
            augmentationDuration: currentOptions.triggerOptions.motionTimeControl?.augmentationDuration ?? 5,
            maxDuration: 30,
            blindDuration: currentOptions.triggerOptions.motionTimeControl?.blindDuration ?? 0
        )
    ),
    ingestMethod: currentOptions.ingestMethod,
    containerOptions: currentOptions.containerOptions
)

try await pushAvStreamTransportTrait.modifyPushTransport(
    connectionID: recordingConnection!.connectionID,
    transportOptions: newOptions
)

בדיקת איכות רוחב הפס

המאפיין videoStreamId של TransportOptionsStruct תואם להגדרות ספציפיות של שידור וידאו.

כדי לקבל את שידורי הווידאו הנתמכים, עיינו במאפיין allocatedVideoStreams, שהוא רשימה של VideoStreamStructs. מה-trait‏ CameraAvStreamManagement של המכשיר.

שינוי הרגישות של יציאה ממצב שינה במכשיר

המאפיין motionSensitivity של TransportTriggerOptionsStruct תואם לערכים הבאים:

תווית ערך (UInt8)
נמוכה 1
בינונית 5
גבוהה 10

שינוי משך הזמן המקסימלי של האירוע

המאפיין maxDuration של TransportMotionTriggerTimeControlStruct תואם למשכי הזמן הבאים של UInt32 (בשניות):

  • ‫10, ‏ 15, ‏ 30, ‏ 60, ‏ 120, ‏ 180

הגדרות הצלצול

אפשר לשלוט בהגדרות שונות של צלצול הפעמון באמצעות ממשקי ה-API של Home.

שינוי צליל הפעמון

כדי לשנות את צליל הפעמון, קודם צריך לקבל את רשימת הצלילים שמותקנים במכשיר באמצעות המאפיין installedChimeSounds של התכונה ChimeTrait:

doorbellChimeTrait.attributes.installedChimeSounds?.compactMap { chimeSound in
  return chimeSound.chimeID, chimeSound.name
}

לאחר מכן, מעדכנים את המאפיין selectedChime של התכונה ChimeTrait באמצעות הפונקציה המובנית setSelectedChime:

func setDoorbellChime(chimeID: UInt8) async {
  do {
    _ = try await doorbellChimeTrait.update {
      $0.setSelectedChime(chimeID)
    }
  } catch {
    // Error
  }
}

שימוש בפעמון חיצוני

   הטמעה באפליקציה לדוגמה ל-iOS   

אפשר להגדיר את פעמון הדלת כך שישתמש בפעמון חיצוני, כמו פעמון מכני שמותקן בתוך הבית. כדי למנוע נזק פוטנציאלי לפעמון החיצוני, צריך להגדיר את זה במהלך ההתקנה של פעמון הדלת.

כדי לציין את סוג הפעמון החיצוני שמותקן, משתמשים ב-ExternalChimeType כדי לעדכן את המאפיין externalChime של התכונה ChimeTrait באמצעות הפונקציה המובנית setExternalChime:

// Indicate the external chime is mechanical
func setExternalChime(to value: Google.ChimeTrait.ExternalChimeType) async {
  do {
    _ = try await doorbellChimeTrait.update {
      $0.setExternalChime(value)
    }
  } catch {
    // Error
  }
}

שינוי משך הצלצול החיצוני

אפשר להגדיר את משך הזמן בשניות שבו הפעמון החיצוני מצלצל באמצעות ממשקי ה-API של Home. אם הפעמון החיצוני תומך במשך צלצול, המשתמש יכול להגדיר אותו.

הערך שמוגדר כאן תלוי במפרט של מנגנון הצלצול החיצוני עצמו, ובמשך הצלצול המומלץ שלו.

כדי לשנות את משך הצלצול החיצוני, מעדכנים את המאפיין externalChimeDurationSeconds של התכונה ChimeTrait באמצעות הפונקציה המובנית setExternalChimeDurationSeconds:

// Change the external chime duration
func setExternalChimeDuration(to value: UInt16) async {
  do {
    _ = try await doorbellChimeTrait.update {
      $0.setExternalChimeDuration(value)
    }
  } catch {
    // Error
  }
}

הפעלת ערכת נושא של צליל

   הטמעה באפליקציה לדוגמה ל-iOS   

בחלק מפעמוני הדלת יש צלילים שזמינים למשתמשים רק לזמן מוגבל. לדוגמה, צלילים ספציפיים לחגים. הצלילים האלה נקראים ערכות נושא של צלצולים.

כדי לראות אילו ערכות נושא של צלצולים זמינות למשתמש, יוצרים מסנן של חלון זמן ומשתמשים בו כדי לסנן את התוצאות של הפקודה getAvailableThemes מהתכונה ChimeThemes. תופיע רשימה של העיצובים הזמינים, כולל שמות העיצובים.

בדוגמה הבאה אפשר לראות איך מסננים את הרשימה. עיצוב נחשב לפעיל אם השעה הנוכחית היא בין שעת ההתחלה לשעת הסיום שלו (הערכים startTimeSeconds ו-endTimeSeconds, בהתאמה). אם לא מוגדרת שעת התחלה, המדיניות נחשבת כפעילה מתחילת הזמן. אם לא מגדירים שעת סיום, הוא ממשיך לפעול ללא הגבלת זמן. אם שניהם חסרים, העיצוב תמיד פעיל.

let chimeThemes = try await chimeThemeTrait.getAvailableThemes().themes

if !chimeThemes.isEmpty {
  var chimeThemeSettings = []
  for chimeTheme in chimeThemes {
    let currentDateTime = UInt64(Date().timeIntervalSince1970)

    // Only show chime themes that are active.
    if chimeTheme.startTimeSeconds ?? 0 &lt;= currentDateTime
      &amp;&amp; chimeTheme.endTimeSeconds ?? UInt64.max &gt;= currentDateTime
    {
      self.chimeThemeSettings.append(chimeTheme.name)
    }
  }
}

אחרי שבוחרים את שם העיצוב הרצוי, למשל Christmas, אפשר לבחור אותו באמצעות הפונקציה setSelectedTimeboxedThemeName() במאפיין ChimeThemes ChimeThemes.

private func setChimeTheme(to value: String) async throws {
  _ = try await chimeThemeTrait.update {
    $0.setSelectedTimeboxedThemeName(value)
  }
}

הגדרות של הכרזה על הגעת אורחים

אתם יכולים לשלוח שאילתות ולנהל את ההגדרות של ההכרזה על הגעת אורחים בפעמוני דלת באמצעות המאפיין VisitorAnnouncement של Home APIs. התכונה הזו קובעת אם תושמע הודעה על נוכחות של מבקר ברמקולים או במסכים החכמים של Google כשמישהו מצלצל בפעמון הדלת.

בדוגמה הבאה אפשר לראות איך בודקים אם ההכרזה על הגעת אורחים מופעלת, ואיך מעדכנים את ההגדרה הזו:

let visitorAnnouncementsEnabled: Bool = visitorAnnouncementTrait.attributes.visitorAnnouncementsEnabled

let value: Bool
_ = try await self.visitorAnnouncementTrait?.update {
  $0.setVisitorAnnouncementsEnabled(value)
}

הוצאת מכשיר משימוש

כדי להסיר פעמון דלת ממבנה, צריך להתקשר אל device.decommission(). כשמוציאים את המצלמה משימוש, מוצג למשתמש מסך אישור בניהול Google, שבו מופיעה אזהרה שכל הנתונים של היסטוריית הווידאו המלאה, היסטוריית האירועים, הקליפים וספריית הפנים המוכרות יימחקו באופן סופי בכל המבנה.

הוראות מפורטות ודוגמאות לקוד מופיעות במאמר הסרת מכשיר.