Hướng dẫn sử dụng thiết bị chuông cửa cho iOS

Loại thiết bị Chuông cửa được triển khai bằng 2 đặc điểm: PushAvStreamTransportTrait, xử lý việc truyền luồng âm thanh và video bằng các giao thức dựa trên thông báo đẩy và WebRtcLiveViewTrait, cung cấp khả năng kiểm soát luồng phát trực tiếp và tính năng đàm thoại hai chiều.

Luôn kiểm tra xem thiết bị có hỗ trợ thuộc tính và lệnh hay không trước khi sử dụng bất kỳ tính năng nào hoặc cố gắng cập nhật thuộc tính. Hãy xem bài viết Điều khiển thiết bị trêniOS để biết thêm thông tin.

Loại thiết bị Home API Đặc điểm Ứng dụng mẫu Swift Trường hợp sử dụng

Chuông cửa

GoogleDoorbellDeviceType

home.matter.6006.types.0113

Một thiết bị được kích hoạt bằng nút bên ngoài cửa, tạo ra tín hiệu âm thanh và/hoặc hình ảnh, dùng để yêu cầu sự chú ý của một người ở phía bên kia cửa. Chuông cửa có thể có tính năng phát trực tiếp dễ tiếp cận, đàm thoại hai chiều hoặc phát hiện sự kiện.

Đặc điểm bắt buộc
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

Chuông cửa

Lấy thông tin cơ bản về một thiết bị

Đặc điểm BasicInformation bao gồm những thông tin như tên nhà cung cấp, mã nhận dạng nhà cung cấp, mã nhận dạng sản phẩm, tên sản phẩm (bao gồm cả thông tin về kiểu máy) và phiên bản phần mềm của thiết bị:

// [START get_device_information]
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!
// [END get_device_information]

Lấy số sê-ri

Để lấy số sê-ri của thiết bị, hãy sử dụng lệnh GetSerialNumber của đặc điểm ExtendedBasicInformation. Ví dụ này cho thấy cách lưu số sê-ri vào một biến có tên là serialNumber:

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

Trả lời nhanh

Tính năng Trả lời nhanh cho phép người dùng gửi một tin nhắn được xác định trước đến thiết bị chuông cửa.

Tính năng này chỉ có trên các thiết bị chuông cửa. Ứng dụng đối tác có thể sử dụng danh sách các thông báo được xác định trước và có thể trình bày các thông báo này cho người dùng chọn. Người dùng không thể chỉnh sửa các thông báo được xác định trước.

Tính năng Trả lời nhanh được triển khai thông qua đặc điểm PresetMessage.

Phát một thông báo đặt sẵn

Để phát một thông báo đặt sẵn, hãy gọi phương thức playPresetMessage, truyền vào đó một trong các giá trị chuỗi có trong thuộc tính 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)")
    }
}

Đặt ngôn ngữ nói

Đặt ngôn ngữ nói

Đặt ngôn ngữ nói đang hoạt động của thiết bị thành một ngôn ngữ cụ thể (ví dụ: "en_US") bằng phương thức setActiveLocale của đặc điểm LocalizationConfiguration.

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

Nhận thời gian liên hệ gần đây nhất của thiết bị với đám mây

Để tìm thời gian gần đây nhất mà thiết bị có kết nối với đám mây, hãy sử dụng thuộc tính lastContactTimestamp của đặc điểm ExtendedGeneralDiagnostics:

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

Chế độ cài đặt loại ngàm gắn camera

Đặc điểm Mount chứa thông tin về trạng thái và chế độ cài đặt giá đỡ camera. Bạn có thể đọc các thuộc tính như trạng thái gắn kết, loại phát hiện và tên loại gắn kết. Ngoài ra, bạn có thể sử dụng đặc điểm Mount để ghi đè cấu hình loại giá đỡ mặc định.

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

Kiểm tra khả năng kết nối của thiết bị

Khả năng kết nối của thiết bị thực sự được kiểm tra ở cấp loại thiết bị vì một số thiết bị hỗ trợ nhiều loại thiết bị. Trạng thái được trả về là sự kết hợp của các trạng thái kết nối cho tất cả các đặc điểm trên thiết bị đó.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

Trạng thái partiallyOnline có thể xuất hiện trong trường hợp có nhiều loại thiết bị khi không có kết nối Internet. Các đặc điểm Matter tiêu chuẩn vẫn có thể trực tuyến do định tuyến cục bộ, nhưng các đặc điểm dựa trên đám mây sẽ ngoại tuyến.

Lấy địa chỉ IP của thiết bị

Để tìm địa chỉ IP của thiết bị, hãy sử dụng thuộc tính networkInterfaces của GeneralDiagnosticsTrait. Các địa chỉ được trả về dưới dạng các đối tượng Data mà bạn có thể định dạng thành các chuỗi IPv4 hoặc IPv6 tiêu chuẩn bằng cách sử dụng khung 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
}

Bắt đầu phát trực tiếp

Để bắt đầu một sự kiện phát trực tiếp, hãy gửi chuỗi Giao thức mô tả phiên (SDP) đến phương thức startLiveView(offerSdp:) của đặc điểm WebRtcLiveViewTrait. Phương thức này sẽ trả về 3 giá trị:

  • SDP cho phiên.
  • Thời lượng phiên tính bằng giây.
  • Mã phiên, có thể dùng để kéo dài hoặc kết thúc phiên.
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
  }
}

Kéo dài sự kiện phát trực tiếp

Sự kiện phát trực tiếp có thời lượng đặt sẵn và sẽ hết hạn sau thời lượng đó. Để kéo dài thời lượng của một luồng đang hoạt động, hãy đưa ra yêu cầu gia hạn bằng phương thức 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
  }
}

Bắt đầu và dừng TalkBack

Để bắt đầu TalkBack, hãy gọi phương thức startTalkback(mediaSessionId:optionalArgsProvider:) của đặc điểm WebRtcLiveViewTrait. Để dừng, hãy dùng biểu tượng 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)")
  }
}

Quản lý sự kiện phát trực tiếp

Việc điều chỉnh chất lượng phát trực tiếp rất hữu ích để tối ưu hoá mức sử dụng băng thông dựa trên bối cảnh xem của ứng dụng (ví dụ: chuyển sang độ phân giải thấp hơn khi hiển thị một ô xem trước nhỏ hơn, chế độ xem dạng lưới hoặc chế độ hình trong hình).

Việc thay đổi chất lượng một cách linh hoạt bằng cách sử dụng đặc điểm WebRtcLiveView sẽ quản lý cụ thể độ phân giải của phiên phát trực tiếp đang hoạt động trên một ứng dụng khách cụ thể. Việc này không giống với việc định cấu hình chế độ cài đặt mức sử dụng băng thông trên toàn thiết bị ngay trên thiết bị. Việc này sẽ ảnh hưởng đến tất cả người xem đồng thời và chất lượng của các bản ghi hình video trước đây được lưu vào đám mây.

Ví dụ sau đây minh hoạ cách truy xuất và cập nhật chất lượng sự kiện phát trực tiếp cho một Thiết bị:

  • Truy xuất các lựa chọn chất lượng được hỗ trợ: Lấy độ phân giải phát trực tuyến có sẵn mà thiết bị hỗ trợ. Mã này truy vấn đặc điểm WebRtcLiveView để hiển thị các chất lượng luồng được hỗ trợ dưới dạng danh sách các giá trị QualityHint (chẳng hạn như .sd, .hd, .fhd, .qhd hoặc .uhd) bằng cách sử dụng thuộc tính supportedQualityHints.

  • Thay đổi chất lượng phát trực tiếp: Áp dụng một QualityHint đã chọn để thay đổi độ phân giải phát trực tiếp của sự kiện phát trực tiếp đang hoạt động (ví dụ: chuyển từ Độ phân giải chuẩn sang Độ phân giải cao). Hàm updateQualityHint sử dụng phương thức changeLiveViewQuality của đặc điểm WebRtcLiveView để áp dụng cấu hình QualityHint đã chọn cho phiên đa phương tiện đang hoạt động.

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

Bật và tắt tính năng ghi hình

Để bật khả năng ghi hình của camera, hãy truyền TransportStatusEnum.Active đến phương thức setTransportStatus(transportStatus:optionalArgsProvider:) của đặc điểm PushAvStreamTransportTrait. Để tắt tính năng ghi, hãy truyền TransportStatusEnum.Inactive. Trong ví dụ sau, chúng ta sẽ gói các lệnh gọi này trong một lệnh gọi duy nhất sử dụng Boolean để bật/tắt khả năng ghi:

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

Việc bật hoặc tắt khả năng ghi hình của camera cũng giống như việc bật hoặc tắt video của camera. Khi video của camera đang bật, camera sẽ ghi hình (cho mục đích ghi lại các sự kiện và đoạn video liên quan).

Khi tính năng ghi hình bị tắt (video từ camera ở trạng thái tắt):

  • Camera vẫn có thể hiển thị là đang trực tuyến theo connectivityState của loại thiết bị.
  • Bạn không thể truy cập vào phiên phát trực tiếp và camera cũng không phát hiện thấy bất kỳ sự kiện nào trên đám mây.

Kiểm tra xem bạn đã bật tính năng ghi hình hay chưa

Để xác định xem camera có được bật chế độ ghi hình hay không, hãy kiểm tra xem có kết nối nào đang hoạt động hay không. Ví dụ sau đây xác định 2 hàm để thực hiện việc này:

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
}

Cài đặt pin

Bạn có thể kiểm soát nhiều chế độ cài đặt pin thông qua Home API.

Đặt lựa chọn ưu tiên về mức sử dụng pin

Việc thiết lập mức cân bằng năng lượng cho phép bạn định cấu hình sự cân bằng giữa thời lượng pin và hiệu suất của thiết bị. Bạn có thể tạo các hồ sơ pin khác nhau, chẳng hạn như "Mở rộng", "Cân bằng" và "Hiệu suất", rồi chuyển đổi giữa các hồ sơ này.

Tính năng này được triển khai bằng cách cập nhật thuộc tính currentEnergyBalance của đặc điểm EnergyPreference. Thuộc tính này chấp nhận một chỉ mục số nguyên tương ứng với một hồ sơ cụ thể được xác định trong danh sách energyBalances của thiết bị (ví dụ: 0 cho EXTENDED, 1 cho BALANCED2 cho PERFORMANCE).

Giá trị null cho currentEnergyBalance cho biết thiết bị đang sử dụng một hồ sơ tuỳ chỉnh. Đây là trạng thái chỉ đọc.

Sau đây là ví dụ về cấu trúc mà thuộc tính currentEnergyBalance sẽ sử dụng, theo sau là đoạn mã thực tế sử dụng thuộc tính này.

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

Bật trình tiết kiệm pin tự động

Để định cấu hình tính năng này, hãy cập nhật thuộc tính currentLowPowerModeSensitivity của đặc điểm EnergyPreference. Thuộc tính này dùng một chỉ mục để chọn mức độ nhạy, trong đó 0 thường biểu thị Disabled1 biểu thị Enabled hoặc Automatic.

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

Lấy trạng thái sạc pin

Để biết trạng thái sạc hiện tại của thiết bị (đang sạc, đã sạc đầy hoặc không sạc), hãy sử dụng thuộc tính batChargeState của đặc điểm 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"
}

Nhận mức pin

Để biết mức pin hiện tại, hãy sử dụng thuộc tính batChargeLevel của đặc điểm PowerSource. Cấp độ này có thể là OK, Warning (thấp) hoặc 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"
}

Tìm nguồn điện

Để xác định nguồn điện mà thiết bị đang sử dụng, hãy dùng các thuộc tính BatPresentwiredPresent của đặc điểm PowerSource.

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

Cài đặt âm thanh

Bạn có thể kiểm soát nhiều chế độ cài đặt âm thanh thông qua Home API.

Bật hoặc tắt micrô

Để bật hoặc tắt micrô của thiết bị, hãy cập nhật thuộc tính microphoneMuted của đặc điểm CameraAvStreamManagementTrait bằng hàm setMicrophoneMuted tích hợp:

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

Bật hoặc tắt tính năng ghi âm

Để bật hoặc tắt tính năng ghi âm cho thiết bị, hãy cập nhật thuộc tính recordingMicrophoneMuted của đặc điểm CameraAvStreamManagementTrait bằng cách sử dụng hàm setRecordingMicrophoneMuted tích hợp:

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

Điều chỉnh âm lượng loa

Để điều chỉnh âm lượng của loa cho thiết bị, hãy cập nhật thuộc tính speakerVolumeLevel của đặc điểm CameraAvStreamManagementTrait bằng hàm setSpeakerVolumeLevel tích hợp:

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

Cài đặt khu vực hoạt động

Đặc điểm ZoneManagement cung cấp một giao diện để quản lý các khu vực tuỳ chỉnh mà người dùng quan tâm (khu vực hoạt động) trên các thiết bị camera và chuông cửa. Các vùng này được dùng để lọc thông tin phát hiện sự kiện (chẳng hạn như chuyển động của người hoặc xe) theo các khu vực cụ thể trong trường nhìn của thiết bị.

Người dùng có thể định cấu hình khu vực hoạt động trong một ứng dụng đối tác, cho phép họ vẽ các khu vực trên những vị trí cụ thể trong trường nhìn của camera. Sau đó, các vùng do người dùng xác định này sẽ được chuyển đổi thành các cấu trúc mà đặc điểm này sử dụng. Để biết thêm thông tin về cách hoạt động của vùng hoạt động, hãy xem bài viết Thiết lập và sử dụng vùng hoạt động.

Các vùng hoạt động thường được xác định bằng toạ độ Đề các 2D. Đặc điểm này cung cấp TwoDCartesianVertexStruct cho các đỉnh và TwoDCartesianZoneStruct cho định nghĩa vùng (tên, đỉnh, màu sắc và cách sử dụng).

Kiểm tra khu vực hoạt động

Để hiển thị các vùng hoạt động, hãy kiểm tra thuộc tính zones của đặc điểm ZoneManagement.

let zoneManagementTrait: Google.ZoneManagementTrait

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

Thêm một vùng hoạt động

Để tạo một vùng mới, hãy dùng lệnh createTwoDCartesianZone. Lệnh này lấy TwoDCartesianZoneStruct, xác định tên, đỉnh, màu sắc và cách sử dụng của vùng.

Ví dụ sau đây cho thấy cách tạo một vùng có tên "Hiên nhà" với 4 đỉnh, có màu cá hồi (#F439A0) và được dùng để phát hiện chuyển động.

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

Cập nhật vùng hoạt động

Để cập nhật một vùng hiện có, hãy dùng lệnh updateTwoDCartesianZone. Lệnh này yêu cầu zoneIdTwoDCartesianZoneStruct đã cập nhật.

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

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

Xoá một vùng hoạt động

Để xoá một vùng, hãy dùng lệnh removeZone với zoneId cụ thể.

let zoneManagementTrait: Google.ZoneManagementTrait
let zoneID: UInt16

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

Trình kích hoạt sự kiện âm thanh

Đặc điểm AvStreamAnalysis cung cấp một giao diện để quản lý các điều kiện kích hoạt tính năng phát hiện sự kiện trên thiết bị camera và chuông cửa. Mặc dù các điều kiện kích hoạt dựa trên hình ảnh (chẳng hạn như người hoặc xe) có thể dành riêng cho từng khu vực, nhưng các điều kiện kích hoạt liên quan đến âm thanh thường là cấu hình ở cấp thiết bị.

Sau đây là các loại điều kiện kích hoạt có sẵn cho tính năng phát hiện âm thanh bằng EventTriggerTypeEnum:

Chế độ Giá trị enum Mô tả
Âm thanh Sound Tính năng phát hiện âm thanh chung.
Tiếng người nói PersonTalking Phát hiện lời nói.
Tiếng chó sủa DogBark Phát hiện tiếng sủa của chó.
Tiếng kính vỡ GlassBreak Phát hiện tiếng kính vỡ.
Chuông báo khói SmokeAlarm Phát hiện chuông báo khói, thường được nhận dạng bằng mẫu âm thanh T3 (3 tiếng bíp ngắn, sau đó là một khoảng dừng).
Chuông báo khí CO CoAlarm Phát hiện chuông báo khí cacbon monoxit (CO), thường được nhận dạng bằng mẫu âm thanh T4 (bốn tiếng bíp ngắn, sau đó là một khoảng dừng).

Kiểm tra trạng thái phát hiện âm thanh

Để hiện trạng thái hiện tại của tính năng phát hiện âm thanh cho người dùng, bạn phải kiểm tra xem thiết bị hỗ trợ tính năng nào và phần cứng thiết bị đã bật tính năng nào. Hai thuộc tính cần kiểm tra là:

Trong quá trình phát triển iOS, thường thì bạn sẽ truy cập vào đặc điểm AvStreamAnalysis từ thiết bị để đọc các thuộc tính này.

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

Cập nhật bộ trình kích hoạt đã bật

Để cập nhật tập hợp các điều kiện kích hoạt đã bật, hãy dùng lệnh SetOrUpdateEventDetectionTriggers. Lệnh này sẽ lấy một danh sách các cấu trúc 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
)

Chế độ ghi

Đặc điểm RecordingMode cung cấp một giao diện để quản lý hành vi ghi hình và chụp ảnh trên các thiết bị camera và chuông cửa. Tính năng này cho phép người dùng chọn giữa chế độ ghi hình liên tục, ghi hình theo sự kiện hoặc tắt hoàn toàn chế độ ghi hình (chỉ có trong Chế độ xem trực tiếp).

RecordingModeEnum xác định các chiến lược ghi âm hiện có:

Chế độ Giá trị enum Mô tả
Đã tắt Disabled Tính năng ghi hoàn toàn bị vô hiệu hoá. Chủ yếu được dùng bởi các thiết bị cũ.
CVR (Quay video liên tục) Cvr Video được quay 24/7. Cần có gói thuê bao (ví dụ: Google Home Premium.
EBR (Ghi hình dựa trên sự kiện) Ebr Quá trình ghi hình được kích hoạt bởi các sự kiện (người, chuyển động). Thời lượng video phụ thuộc vào thời lượng sự kiện và gói thuê bao.
ETR (Ghi hình khi có sự kiện kích hoạt) Etr Bản ghi xem trước ngắn (ví dụ: 10 giây) được kích hoạt bởi các sự kiện.
Chế độ xem trực tiếp LiveView Tính năng ghi hình bị tắt, nhưng người dùng vẫn có thể truy cập vào sự kiện phát trực tiếp.
Hình ảnh tĩnh Images Ảnh chụp nhanh sẽ được ghi lại thay vì video khi có sự kiện xảy ra.

Kiểm tra các chế độ ghi

Để hiển thị cấu hình ghi hiện tại, hãy kiểm tra các thuộc tính của đặc điểm 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,
      )
    )
  }
}

Thay đổi chế độ ghi

Trước khi cập nhật, hãy đảm bảo rằng chỉ mục đã chọn từ thuộc tính supportedRecordingModes có trong thuộc tính availableRecordingModes.

Để cập nhật chế độ đã chọn, hãy dùng hàm setSelectedRecordingMode, truyền chỉ mục của chế độ đã chọn:

let recordingModeTrait: Google.RecordingModeTrait
let recordingModeID: UInt8

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

Chế độ cài đặt khác

Bạn có thể kiểm soát nhiều chế độ cài đặt khác thông qua Home API.

Bật hoặc tắt chế độ cảnh đêm

Để bật hoặc tắt chế độ nhìn ban đêm cho camera, hãy dùng TriStateAutoEnum để cập nhật thuộc tính nightVision của đặc điểm CameraAvStreamManagementTrait bằng hàm setNightVision tích hợp:

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

Thay đổi độ sáng của đèn LED trạng thái

Để thay đổi độ sáng của đèn LED trạng thái, hãy dùng ThreeLevelAutoEnum để cập nhật thuộc tính statusLightBrightness của đặc điểm CameraAvStreamManagementTrait bằng hàm setStatusLightBrightness tích hợp:

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

Thay đổi khung nhìn camera

Khung hiển thị camera giống với tính năng Thu phóng và cắt mà bạn có thể xem trong bài viết hỗ trợ Thu phóng và cải thiện video của camera Nest.

Khung hiển thị được xác định trong một ViewportStruct chứa 4 giá trị, được dùng làm toạ độ của khung hiển thị. Toạ độ được xác định như sau:

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

Việc xác định các giá trị cho ViewportStruct phụ thuộc vào giao diện người dùng và cách triển khai camera của ứng dụng. Ở cấp độ rất cơ bản, để đặt khung hiển thị của video từ camera, hãy cập nhật thuộc tính viewport của đặc điểm CameraAvStreamManagementTrait bằng ViewportStruct, sử dụng hàm setViewport tích hợp.

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

}

Tạo TransportOptionsStruct

Một số chế độ cài đặt yêu cầu sửa đổi các thuộc tính trong TransportOptionsStruct, sau đó được truyền vào các lựa chọn truyền tải của một kết nối truyền phát trực tiếp. Đối với Swift, bạn cần tạo cấu trúc này trước khi cập nhật bất kỳ thuộc tính nào.

Sử dụng hàm trợ giúp này để tạo cấu trúc nhằm sử dụng với các thay đổi về chế độ cài đặt sau:

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
}

Bật hoặc tắt tính năng phân tích

Mỗi thiết bị có thể chọn gửi dữ liệu phân tích chi tiết đến đám mây Google Home (xem phần Giám sát đám mây cho API Home).

Để bật tính năng phân tích cho một thiết bị, hãy đặt thuộc tính analyticsEnabled) của ExtendedGeneralDiagnosticsTrait thành true. Khi bạn đặt analyticsEnabled, một thuộc tính khác, logUploadEnabled, sẽ tự động được đặt thành true. Nhờ đó, các tệp nhật ký phân tích có thể được tải lên đám mây Google Home.

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

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

Cấu hình truyền tải và ghi

Phần này trình bày các chế độ cài đặt liên quan đến chất lượng phát trực tiếp của camera và việc kích hoạt sự kiện. Các chế độ cài đặt này do đặc điểm PushAvStreamTransport quản lý.

Đọc chế độ cài đặt về việc vận chuyển

Phần này minh hoạ cách truy xuất cấu hình hiện tại từ một camera hoặc thiết bị chuông cửa. Thao tác này tìm nạp đặc điểm PushAvStreamTransport, tìm thấy kết nối cụ thể được dùng để ghi và sau đó trích xuất các giá trị hiện tại cho chất lượng băng thông, độ nhạy đánh thức và thời lượng tối đa của sự kiện.

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

Cập nhật chế độ cài đặt truyền tải

Phần này hướng dẫn cách thay đổi chế độ cài đặt truyền tải. Thao tác này sẽ tạo một TransportOptionsStruct mới chứa các giá trị mới, sau đó dùng lệnh modifyPushTransport để gửi các chế độ cài đặt đã cập nhật này trở lại thiết bị, áp dụng các chế độ cài đặt này cho kết nối ghi hình được tìm thấy ở bước trước.

Để sửa đổi các chế độ cài đặt này, hãy dùng lệnh modifyPushTransport với 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
)

Xác định chất lượng băng thông

Thuộc tính videoStreamId của TransportOptionsStruct tương ứng với một cấu hình luồng video cụ thể.

Để lấy các luồng video được hỗ trợ, hãy tham khảo thuộc tính allocatedVideoStreams. Đây là danh sách VideoStreamStructs. từ đặc điểm CameraAvStreamManagement của thiết bị.

Điều chỉnh độ nhạy đánh thức thiết bị

Thuộc tính motionSensitivity của TransportTriggerOptionsStruct tương ứng với các giá trị sau:

Hãng nhạc Giá trị (UInt8)
Thấp 1
Trung bình 5
Cao 10

Điều chỉnh thời lượng tối đa của sự kiện

Thuộc tính maxDuration của TransportMotionTriggerTimeControlStruct tương ứng với các khoảng thời gian UInt32 sau đây (tính bằng giây):

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

Cài đặt chuông

Bạn có thể kiểm soát nhiều chế độ cài đặt chuông cửa thông qua Home API.

Thay đổi âm thanh chuông

Để thay đổi âm thanh chuông cửa, trước tiên, hãy lấy danh sách âm thanh chuông cửa đã được cài đặt trên thiết bị bằng cách sử dụng thuộc tính installedChimeSounds của đặc điểm ChimeTrait:

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

Sau đó, hãy cập nhật thuộc tính selectedChime của đặc điểm ChimeTrait bằng hàm setSelectedChime tích hợp:

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

Sử dụng chuông báo bên ngoài

Bạn có thể định cấu hình chuông cửa để sử dụng chuông bên ngoài, chẳng hạn như chuông cơ được lắp đặt bên trong nhà. Bạn nên định cấu hình chế độ này trong quá trình lắp đặt chuông cửa để tránh làm hỏng chuông báo bên ngoài.

Để cho biết loại chuông bên ngoài đã được cài đặt, hãy dùng ExternalChimeType để cập nhật thuộc tính externalChime của đặc điểm ChimeTrait bằng hàm setExternalChime tích hợp sẵn:

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

Thay đổi thời lượng của chuông bên ngoài

Bạn có thể định cấu hình khoảng thời gian (tính bằng giây) mà chuông bên ngoài sẽ đổ chuông thông qua Home API. Nếu chuông bên ngoài hỗ trợ thời lượng đổ chuông, thì người dùng có thể muốn định cấu hình thời lượng này.

Giá trị được đặt ở đây phụ thuộc vào thông số kỹ thuật của chính chuông bên ngoài và thời lượng chuông được đề xuất.

Để thay đổi thời lượng chuông bên ngoài, hãy cập nhật thuộc tính externalChimeDurationSeconds của đặc điểm ChimeTrait bằng hàm setExternalChimeDurationSeconds tích hợp:

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

Bật một chủ đề chuông báo

Một số chuông cửa có thể có chuông báo chỉ dành cho người dùng trong một khoảng thời gian giới hạn. Ví dụ: chuông báo dành riêng cho ngày lễ. Đây được gọi là chủ đề chuông báo.

Để xem những chủ đề chuông báo mà người dùng có thể sử dụng, hãy tạo một bộ lọc timebox và dùng bộ lọc này để lọc kết quả của lệnh getAvailableThemes từ đặc điểm ChimeThemes. Thao tác này sẽ trả về danh sách các giao diện có sẵn, bao gồm cả tên giao diện.

Ví dụ sau đây cho thấy cách lọc danh sách. Một chủ đề được coi là đang hoạt động nếu thời gian hiện tại nằm trong khoảng thời gian bắt đầu và kết thúc của chủ đề đó (tương ứng là giá trị startTimeSecondsendTimeSeconds). Nếu bạn không đặt thời gian bắt đầu, thì quy tắc sẽ được coi là có hiệu lực từ đầu. Nếu bạn không đặt thời gian kết thúc, thì quy tắc sẽ tiếp tục hoạt động vô thời hạn. Nếu thiếu cả hai, giao diện sẽ luôn hoạt động.

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

Sau khi có tên của giao diện bạn muốn, chẳng hạn như Christmas, bạn có thể chọn giao diện đó bằng hàm setSelectedTimeboxedThemeName() trên đặc điểm ChimeThemes ChimeThemes.

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

Cài đặt thông báo có khách

Bạn có thể truy vấn và quản lý chế độ cài đặt thông báo có khách cho chuông cửa bằng đặc điểm VisitorAnnouncement của Home API. Đặc điểm này kiểm soát việc có thông báo sự có mặt của khách trên loa thông minh hoặc màn hình Google khi có người nhấn chuông cửa hay không.

Ví dụ sau đây cho biết cách kiểm tra xem thông báo có khách có được bật hay không và cách cập nhật chế độ cài đặt này:

let visitorAnnouncementsEnabled: Bool = visitorAnnouncementTrait.attributes.visitorAnnouncementsEnabled

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