คู่มืออุปกรณ์กริ่งประตูสำหรับ iOS

ประเภทอุปกรณ์กริ่งประตูจะใช้ลักษณะ 3 อย่าง ได้แก่ PushAvStreamTransportTrait ซึ่งจัดการการส่งสตรีมเสียงและวิดีโอโดยใช้โปรโตคอลแบบพุช WebRtcLiveViewTrait ซึ่งให้ความสามารถในการควบคุมไลฟ์สดและ TalkBack และ CameraSnapshotTrait ซึ่งให้ภาพรวมตัวอย่างที่แคชไว้และการจับภาพสแนปชอตแบบสด

ตรวจสอบการรองรับแอตทริบิวต์และคำสั่งสำหรับอุปกรณ์ก่อนใช้ฟีเจอร์หรือพยายามอัปเดตแอตทริบิวต์เสมอ ดูข้อมูลเพิ่มเติมได้ที่ควบคุมอุปกรณ์ในiOS

ประเภทอุปกรณ์ของ Home API ลักษณะเฉพาะ แอปตัวอย่าง Swift กรณีการใช้งาน

กริ่งประตู

GoogleDoorbellDeviceType

home.matter.6006.types.0113

อุปกรณ์ที่ทำงานด้วยปุ่มนอกประตูซึ่งส่งสัญญาณเสียงและ/หรือภาพ ใช้เพื่อดึงดูดความสนใจของบุคคลที่อยู่อีกด้านหนึ่งของประตู กริ่งประตูอาจมีฟีเจอร์ไลฟ์สดที่เข้าถึงได้ การพูดคุยแบบ 2 ทาง หรือเหตุการณ์การตรวจจับ

ลักษณะที่จำเป็น
     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

เล่นข้อความที่ตั้งไว้ล่วงหน้า

หากต้องการเล่นข้อความที่กำหนดล่วงหน้า ให้เรียกใช้เมธอด 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 Trait มีการตั้งค่าตัวยึดกล้องและข้อมูลสถานะ คุณสามารถอ่านแอตทริบิวต์ต่างๆ เช่น สถานะการต่อเชื่อม ประเภทการตรวจจับ และชื่อประเภทการต่อเชื่อม นอกจากนี้ คุณยังใช้ลักษณะ 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   

หากต้องการเริ่มไลฟ์สด ให้ส่งสตริง Session Description Protocol (SDP) ไปยังเมธอด startLiveView(offerSdp:) ของลักษณะ WebRtcLiveViewTrait ซึ่งจะแสดงผล 3 ค่า ได้แก่

  • 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   

หากต้องการเริ่มการพูดตอบ ให้เรียกใช้เมธอด 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 ใช้เมธอด 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 ไปยังเมธอด 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ของประเภทอุปกรณ์
  • คุณจะเข้าถึงไลฟ์สดไม่ได้ และกล้องจะไม่ตรวจจับเหตุการณ์ในระบบคลาวด์

ตรวจสอบว่าเปิดใช้ความสามารถในการบันทึกแล้วหรือไม่

หากต้องการตรวจสอบว่าความสามารถในการบันทึกของกล้องเปิดใช้อยู่หรือไม่ ให้ดูว่ามีการเชื่อมต่อที่ใช้งานอยู่หรือไม่ ตัวอย่างต่อไปนี้จะกำหนด 2 ฟังก์ชันเพื่อดำเนินการนี้

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 เพื่อดึงข้อมูลสแนปชอตรูปภาพนิ่งจากกล้อง ภาพรวมเหล่านี้มีประโยชน์ในหลายสถานการณ์ ดังนี้

  • ปรากฏเป็นการ์ดตัวยึดตำแหน่งใน UI ขณะที่ไลฟ์สด WebRTC กำลังโหลด
  • เป็นภาพตัวอย่างแบบคงที่ซึ่งจะอัปเกรดเป็นไลฟ์สดเมื่อผู้ใช้โต้ตอบ
  • เป็นภาพพื้นหลังสำหรับวาดและกำหนดค่าโซนตรวจจับกิจกรรมที่กำหนดเอง

ลักษณะ CameraSnapshot มี 2 วิธีในการดึงสแนปชอต โดยขึ้นอยู่กับว่าคุณต้องการสแนปชอตที่แคชไว้สำหรับการแสดงผลอย่างรวดเร็วหรือสแนปชอตแบบสดตามต้องการ

ดูภาพรวมตัวอย่างที่แคชไว้

ภาพรวมตัวอย่างคือรูปภาพที่แคชไว้ซึ่ง 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 เพื่อระบุความใหม่ของรูปภาพ คุณสามารถแยกวิเคราะห์ส่วนหัวนี้ในฝั่งไคลเอ็นต์เพื่อแสดงอายุของสแนปชอตในแอปได้

ดูภาพรวมแบบสดตามต้องการ

สำหรับเส้นทางของผู้ใช้ที่ต้องใช้ฟีเจอร์ดูภาพสดของกล้องในปัจจุบัน เช่น การตั้งค่าโซนตรวจจับกิจกรรม คุณสามารถขอสแนปชอตแบบสดได้ การเรียกใช้สแนปชอตแบบเรียลไทม์จะสั่งให้กล้องทำงาน จับภาพเฟรมใหม่ และอัปโหลดไปยังระบบคลาวด์

หากต้องการขอสแนปชอตแบบเรียลไทม์ ให้ใช้คำสั่ง 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 API v2 หากต้องการดาวน์โหลดและแสดงผลรูปภาพ คุณต้องแทรกโทเค็น OAuth เป็นโทเค็นสำหรับผู้ถือในส่วนหัว Authorization ของคำขอ HTTP

ตัวอย่างต่อไปนี้แสดงวิธีกำหนดค่าคำขอเครือข่ายที่ปลอดภัยเพื่อดาวน์โหลดสแนปชอต

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

การตั้งค่าแบตเตอรี่

คุณควบคุมการตั้งค่าแบตเตอรี่ต่างๆ ได้ผ่าน 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"
    }
  ]
}
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 จะอธิบายแบตเตอรี่ รวมถึงข้อมูลต่างๆ เช่น รูปแบบ องค์ประกอบทางเคมี และผู้ผลิตที่แนะนำ

การตั้งค่าเสียง

คุณควบคุมการตั้งค่าเสียงต่างๆ ได้ผ่าน Home API

เปิดหรือปิดไมโครโฟน

หากต้องการเปิดหรือปิดไมโครโฟนของอุปกรณ์ ให้อัปเดตแอตทริบิวต์ 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 มีอินเทอร์เฟซสำหรับจัดการขอบเขตที่สนใจ (โซนตรวจจับกิจกรรม) ที่กำหนดเองในอุปกรณ์กล้องและกริ่งประตู โซนเหล่านี้ใช้เพื่อกรองการตรวจจับเหตุการณ์ (เช่น การเคลื่อนไหวของบุคคลหรือยานพาหนะ) ไปยังพื้นที่เฉพาะภายในขอบเขตการมองเห็นของอุปกรณ์

ผู้ใช้จะกำหนดค่าโซนตรวจจับกิจกรรมภายในแอปพลิเคชันของพาร์ทเนอร์ ซึ่งช่วยให้ผู้ใช้สามารถวาดโซนเหนือพื้นที่ที่เฉพาะเจาะจงในขอบเขตการมองเห็นของกล้องได้ จากนั้นระบบจะแปลโซนที่ผู้ใช้กำหนดเหล่านี้เป็นโครงสร้างที่ลักษณะนี้ใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของโซนตรวจจับกิจกรรมได้ที่ตั้งค่าและใช้โซนตรวจจับกิจกรรม

โดยปกติแล้ว โซนตรวจจับกิจกรรมจะกำหนดโดยใช้พิกัดคาร์ทีเซียน 2 มิติ ลักษณะนี้จะให้ TwoDCartesianVertexStruct สำหรับจุดยอดและ TwoDCartesianZoneStruct สำหรับคำจำกัดความของโซน (ชื่อ จุดยอด สี และการใช้งาน)

ตรวจสอบโซนตรวจจับกิจกรรม

หากต้องการแสดงโซนตรวจจับกิจกรรม ให้ตรวจสอบแอตทริบิวต์ zones ของลักษณะ ZoneManagement

let zoneManagementTrait: Google.ZoneManagementTrait

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

เพิ่มโซนตรวจจับกิจกรรม

หากต้องการสร้างโซนใหม่ ให้ใช้คำสั่ง createTwoDCartesianZone คำสั่งนี้ใช้ TwoDCartesianZoneStruct ซึ่งกำหนดชื่อ จุดยอด สี และการใช้งานของโซน

ตัวอย่างต่อไปนี้แสดงวิธีสร้างโซนชื่อ "ระเบียงหน้าบ้าน" ที่มีจุดยอด 4 จุด สีส้มแซลมอน (#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 (เสียงบี๊บสั้นๆ 3 ครั้งตามด้วยการหยุดชั่วคราว)
สัญญาณเตือนคาร์บอนมอนอกไซด์ CoAlarm ตรวจจับสัญญาณเตือนคาร์บอนมอนอกไซด์ (CO) ซึ่งมักจะจดจำได้จากรูปแบบเสียง T4 (เสียงบี๊บสั้นๆ 4 ครั้งตามด้วยการหยุดชั่วคราว)

ตรวจสอบสถานะการตรวจจับเสียง

หากต้องการแสดงสถานะปัจจุบันของการตรวจจับเสียงให้ผู้ใช้เห็น คุณต้องตรวจสอบว่าอุปกรณ์รองรับอะไรบ้างและฮาร์ดแวร์ของอุปกรณ์เปิดใช้อะไรบ้าง แอตทริบิวต์ 2 รายการที่ต้องตรวจสอบมีดังนี้

ในการพัฒนา 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 มีอินเทอร์เฟซสำหรับจัดการลักษณะการทำงานของการบันทึกวิดีโอและรูปภาพในอุปกรณ์กล้องและกริ่งประตู ซึ่งช่วยให้ผู้ใช้เลือกได้ระหว่างการบันทึกต่อเนื่อง การบันทึกเมื่อเกิดเหตุการณ์ หรือปิดใช้การบันทึกทั้งหมด (ดูภาพสดเท่านั้น)

RecordingModeEnum จะกำหนดกลยุทธ์การบันทึกที่ใช้ได้ ดังนี้

โหมด ค่า enum คำอธิบาย
ปิดใช้แล้ว Disabled การบันทึกปิดใช้อยู่โดยสมบูรณ์ อุปกรณ์รุ่นเก่ามักใช้โปรโตคอลนี้
CVR (การบันทึกวิดีโอต่อเนื่อง) Cvr ระบบจะบันทึกวิดีโอทุกวันตลอด 24 ชั่วโมง ต้องสมัครใช้บริการ (เช่น 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)
}

การตั้งค่าอื่นๆ

คุณควบคุมการตั้งค่าอื่นๆ ได้ผ่าน Home API

เปิดหรือปิดภาพกลางคืน

หากต้องการเปิดหรือปิดภาพกลางคืนของกล้อง ให้ใช้ 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
  }
}

เปลี่ยนความสว่างของไฟ LED แสดงสถานะ

หากต้องการเปลี่ยนความสว่างของไฟ LED แสดงสถานะ ให้ใช้ 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 ซึ่งมีค่า 4 ค่าที่ใช้เป็นพิกัดของวิวพอร์ต พิกัดจะกำหนดเป็นค่าต่อไปนี้

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

การกำหนดค่าสำหรับ ViewportStruct ขึ้นอยู่กับ UI ของแอปและการใช้งานกล้อง ในระดับพื้นฐานที่สุด หากต้องการตั้งค่าวิวพอร์ตของวิดีโอกล้อง ให้อัปเดตแอตทริบิวต์ 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 เป็นรายเครื่อง (ดูการตรวจสอบระบบคลาวด์สำหรับ 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 จากลักษณะ CameraAvStreamManagement ของอุปกรณ์

ปรับความไวในการปลุกระบบของอุปกรณ์

พร็อพเพอร์ตี้ motionSensitivity ของ TransportTriggerOptionsStruct สอดคล้องกับค่าต่อไปนี้

ป้ายกำกับ ค่า (UInt8)
ต่ำ 1
ปานกลาง 5
สูง 10

ปรับระยะเวลาสูงสุดของเหตุการณ์

พร็อพเพอร์ตี้ maxDuration ของ TransportMotionTriggerTimeControlStruct สอดคล้องกับระยะเวลา UInt32 ต่อไปนี้ (เป็นวินาที)

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

การตั้งค่ากริ่ง

คุณควบคุมการตั้งค่ากริ่งประตูต่างๆ ได้ผ่าน Home API

เปลี่ยนเสียงกริ่ง

หากต้องการเปลี่ยนเสียงกริ่งประตู ก่อนอื่นให้ดูรายการเสียงกริ่งที่ติดตั้งในอุปกรณ์โดยใช้แอตทริบิวต์ 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
  }
}

เปลี่ยนระยะเวลาของกริ่งภายนอก

คุณกำหนดค่าระยะเวลา (เป็นวินาที) ที่กริ่งภายนอกจะส่งเสียงได้ผ่าน Home API หากกริ่งภายนอกรองรับระยะเวลาเสียงกริ่ง ผู้ใช้อาจต้องการกำหนดค่านี้

ค่าที่ตั้งไว้ที่นี่จะขึ้นอยู่กับข้อมูลจำเพาะของกริ่งภายนอกและระยะเวลาของเสียงกริ่งที่แนะนำ

หากต้องการเปลี่ยนระยะเวลาของกริ่งภายนอก ให้อัปเดตแอตทริบิวต์ 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   

กริ่งประตูบางรุ่นอาจมีเสียงกริ่งที่ผู้ใช้ใช้ได้ในระยะเวลาที่จำกัดเท่านั้น เช่น เสียงกริ่งเฉพาะสำหรับวันหยุด ซึ่งเรียกว่าธีมเสียงกริ่ง

หากต้องการดูว่าผู้ใช้มีธีมเสียงกริ่งใดบ้าง ให้สร้างตัวกรอง Timebox และใช้เพื่อกรองผลลัพธ์ของคำสั่ง getAvailableThemes จากลักษณะ ChimeThemes ซึ่งจะแสดงรายการธีมที่ใช้ได้ รวมถึงชื่อธีม

ตัวอย่างต่อไปนี้แสดงวิธีกรองรายการ ระบบจะถือว่าธีมทำงานอยู่หากเวลาปัจจุบันอยู่ภายในเวลาเริ่มต้นและเวลาสิ้นสุด (ค่า startTimeSeconds และ endTimeSeconds ตามลำดับ) หากไม่ได้ตั้งค่าเวลาเริ่มต้น ระบบจะถือว่าใช้งานอยู่ตั้งแต่เริ่มต้น หากไม่ได้ตั้งเวลาสิ้นสุด การตั้งค่าจะยังคงทำงานต่อไปเรื่อยๆ หากไม่มีทั้ง 2 รายการ ธีมจะทำงานอยู่เสมอ

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 API ลักษณะนี้จะควบคุมว่าจะประกาศการมาถึงของผู้มาเยือนทางลำโพงอัจฉริยะหรือจอแสดงผลของ Google หรือไม่เมื่อมีคนกดกริ่งประตู

ตัวอย่างต่อไปนี้แสดงวิธีตรวจสอบว่ามีการเปิดใช้การประกาศแจ้งต่อผู้มาเยือนหรือไม่ และวิธีอัปเดตการตั้งค่านี้

let visitorAnnouncementsEnabled: Bool = visitorAnnouncementTrait.attributes.visitorAnnouncementsEnabled

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

เลิกใช้งานอุปกรณ์

หากต้องการนำกริ่งประตูออกจากบ้าน ให้โทรหา device.decommission() การเลิกใช้งานจะแสดงข้อความแจ้งผู้ใช้พร้อมหน้าจอยืนยันที่จัดการโดย Google ซึ่งเตือนว่าระบบจะลบข้อมูลประวัติวิดีโอทุกวันตลอด 24 ชั่วโมง ประวัติเหตุการณ์ คลิป และคลังใบหน้าที่คุ้นเคยที่บันทึกไว้ทั้งหมดในบ้านอย่างถาวร

ดูวิธีการโดยละเอียดและตัวอย่างโค้ดได้ที่นำอุปกรณ์ออก