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

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

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

ประเภทอุปกรณ์ API สำหรับบ้าน ลักษณะ แอปตัวอย่าง Swift กรณีการใช้งาน

กริ่งประตู

GoogleDoorbellDeviceType

home.matter.6006.types.0113

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

ลักษณะที่ต้องระบุ
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

กริ่งประตู

เริ่มไลฟ์สด

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

  • SDP สำหรับเซสชัน
  • ระยะเวลาเซสชันเป็นวินาที
  • รหัสเซสชัน ซึ่งอาจใช้เพื่อขยายหรือสิ้นสุดเซสชัน
public func sendOffer(offerSdp: String) async throws
-> (answerSdp: String, mediaSessionId: String, liveViewDuration: TimeInterval)
{
  do {
    Logger.info("Sending StartLiveView command...")
    let response = try await liveViewTrait.startLiveView(
      offerSdp: offerSdp
    )
    Logger.info("Received StartLiveView response: \(response)")
    return (
      answerSdp: response.answerSdp,
      mediaSessionId: response.mediaSessionId,
      liveViewDuration: TimeInterval(response.liveSessionDurationSeconds)
    )
  } catch {
    Logger.error("Failed to send StartLiveView command: \(error)")
    throw error
  }
}

ขยายเวลาไลฟ์สด

ไลฟ์สดมีระยะเวลาที่กำหนดไว้ล่วงหน้าซึ่งจะหมดอายุหลังจากนั้น หากต้องการขยาย ระยะเวลาของสตรีมที่ใช้งานอยู่ ให้ส่งคำขอขยายเวลาโดยใช้เมธอด extendLiveView(mediaSessionId:optionalArgsProvider:)

public func extendLiveView(mediaSessionId: String) async throws {
  do {
    Logger.info("Extending live view...")
    let extendedDuration = try await liveViewTrait.extendLiveView(mediaSessionId: mediaSessionId)
    Logger.info("Extended live view for \(extendedDuration.liveSessionDurationSeconds) seconds.")
  } catch {
    Logger.error("Failed to extend live view: \(error)")
    throw error
  }
}

เริ่มและหยุด TalkBack

หากต้องการเริ่ม Talkback ให้เรียกใช้เมธอด startTalkback(mediaSessionId:optionalArgsProvider:) ของลักษณะ WebRtcLiveViewTrait หากต้องการหยุด ให้ใช้ stopTalkback(mediaSessionId:)

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

เปิดและปิดใช้ความสามารถในการบันทึก

หากต้องการเปิดใช้ความสามารถในการบันทึกของกล้อง ให้ส่ง TransportStatusEnum.Active ไปยังเมธอด setTransportStatus(transportStatus:optionalArgsProvider:) ของลักษณะ PushAvStreamTransportTrait หากต้องการปิดใช้ความสามารถในการบันทึก ให้ส่ง TransportStatusEnum.Inactive ในตัวอย่างต่อไปนี้ เราจะรวมการเรียกเหล่านี้ไว้ในการเรียกครั้งเดียวที่ใช้ Booleanเพื่อสลับความสามารถในการบันทึก

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

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

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

เมื่อปิดใช้ความสามารถในการบันทึก (วิดีโอจากกล้องปิดอยู่)

  • กล้องอาจยังคงแสดงเป็นออนไลน์ตามconnectivityStateของ ประเภทอุปกรณ์
  • เข้าถึงไลฟ์สดไม่ได้ และกล้องไม่ตรวจพบเหตุการณ์ในระบบคลาวด์

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

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

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

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

คุณควบคุมการตั้งค่าเสียงของกล้องต่างๆ ได้ผ่าน 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
  }
}

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

การตั้งค่ากล้องอื่นๆ อีกมากมายสามารถควบคุมได้ผ่าน 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 ของวิดีโอ กล้อง ให้อัปเดตแอตทริบิวต์ 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
}

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

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

ใน Home API คุณตั้งค่านี้ได้โดยใช้พร็อพเพอร์ตี้ motionSensitivity ของ triggerOptions ใน transportOptions ของอุปกรณ์ ตัวเลือกเหล่านี้กำหนดไว้ ในPushAvStreamTransportTraitลักษณะของอุปกรณ์แต่ละเครื่อง

คุณตั้งค่าความไวต่อการปลุกได้เฉพาะค่าต่อไปนี้

  • 1 = ต่ำ
  • 5 = ปานกลาง
  • 10 = สูง

กระบวนการอัปเดตคือการค้นหาการกำหนดค่าการรับส่งสำหรับสตรีมการบันทึกที่ใช้งานอยู่โดยใช้คำสั่ง findTransport จากนั้นแก้ไขการกำหนดค่าด้วยค่าความไวใหม่โดยใช้คำสั่ง modifyPushTransport

คำสั่ง modifyPushTransport ต้องส่ง TransportOptionsStruct แบบเต็ม คุณจึงต้องคัดลอกค่าที่มีอยู่จากการกำหนดค่าปัจจุบันก่อน ดูสร้าง TransportOptionsStruct สำหรับ ฟังก์ชันตัวช่วยเพื่อดำเนินการนี้

func setWakeUpSensitivity(to value: UInt8) async {
  do {
    let connection = try await getRecordingConnection()
    guard let connection,
      let transportOptions = connection.transportOptions
    else {
      // Error - Transport options not available
      return
    }

    guard transportOptions.triggerOptions.motionSensitivity != nil else {
      // Error - Motion sensitivity not available to be updated for this device
      return
    }

    try await pushAvStreamTransportTrait.modifyPushTransport(
      connectionID: connection.connectionID,
      transportOptions: self.getTransportOptions(
        transportOptions: transportOptions,
        wakeUpSensitivity: value,
        maxEventLength: nil
      )
    )

  } catch {
    // Error
  }
}

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

ความยาวสูงสุดของเหตุการณ์คือระยะเวลาที่กล้องจะบันทึกคลิปสำหรับเหตุการณ์ คุณกำหนดค่านี้ได้ต่ออุปกรณ์ผ่าน Home API ให้มีความยาวเท่ากับที่กำหนดผ่าน Google Home app (GHA) โดยมีช่วงเวลาเป็นวินาที

  • 10 วินาที
  • 15 วินาที
  • 30 วินาที
  • 60 วินาที (1 นาที)
  • 120 วินาที (2 นาที)
  • 180 วินาที (3 นาที)

ใน Home API คุณตั้งค่านี้ได้โดยใช้พร็อพเพอร์ตี้ motionTimeControl ของ triggerOptions ใน transportOptions ของอุปกรณ์ ตัวเลือกเหล่านี้กำหนดไว้ ในPushAvStreamTransportTraitลักษณะของอุปกรณ์แต่ละเครื่อง

กระบวนการอัปเดตคือการค้นหาการกำหนดค่าการรับส่งสำหรับสตรีมการบันทึกที่ใช้งานอยู่โดยใช้คำสั่ง findTransport จากนั้นแก้ไขการกำหนดค่าด้วยค่าความยาวเหตุการณ์ใหม่โดยใช้คำสั่ง modifyPushTransport

คำสั่ง modifyPushTransport ต้องส่ง TransportOptionsStruct แบบเต็ม คุณจึงต้องคัดลอกค่าที่มีอยู่จากการกำหนดค่าปัจจุบันก่อน ดูสร้าง TransportOptionsStruct สำหรับ ฟังก์ชันตัวช่วยเพื่อดำเนินการนี้

func setMaxEventLength(to value: UInt32) async {
  do {
    let connection = try await getRecordingConnection()
    guard let connection,
      let transportOptions = connection.transportOptions
    else {
      // Error - Transport options not available
      return
    }

    guard transportOptions.triggerOptions.motionTimeControl != nil else {
      // Error - Motion time control not available to be updated for this device
      return
    }

    try await pushAvStreamTransportTrait.modifyPushTransport(
      connectionID: connection.connectionID,
      transportOptions: self.getTransportOptions(
        transportOptions: transportOptions,
        wakeUpSensitivity: nil,
        maxEventLength: value
      )
    )

  } catch {
    // Error
  }
}

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

คุณควบคุมการตั้งค่าเสียงกริ่งประตูต่างๆ ได้ผ่าน 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
  }
}

ใช้กริ่งภายนอก

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

หากต้องการระบุประเภทกริ่งภายนอกที่ติดตั้ง ให้ใช้ 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
  }
}