Truy cập vào thiết bị và siêu dữ liệu thiết bị cho iOS

Bạn có thể truy cập vào Device API thông qua Home API cho iOS. Nhập các gói sau vào ứng dụng của bạn:

import GoogleHomeSDK
import GoogleHomeTypes

Để biết thêm thông tin, hãy xem bài viết Mô hình dữ liệu trên iOS.

Xử lý lỗi

Một số phương thức trong Home API sẽ gửi HomeError, vì vậy, bạn nên sử dụng khối do-catch để bắt HomeError trên các lệnh gọi đó.

Khi xử lý HomeError, hãy kiểm tra các trường codemessage của đối tượng này để biết điều gì đã xảy ra.

Mọi lỗi chưa được xử lý sẽ khiến ứng dụng của bạn gặp sự cố.

Để biết thêm thông tin, hãy xem phần Xử lý lỗi.

Hãy xem phần Gửi lệnh đến thiết bị để tham khảo ví dụ.

Cuộc gọi mẫu

Lấy danh sách thiết bị

Khi tham chiếu đến đối tượng Home, hãy gọi devices() để nhận Query của các thiết bị có thể truy cập. Gọi phương thức batched() của Query. Phương thức này sẽ phát ra một Set phản ánh trạng thái hiện tại của Home khi có mọi thay đổi về siêu dữ liệu thiết bị. Hoặc gọi Query.list() để chụp nhanh các thiết bị có sẵn. Đây là một phương thức tiện lợi, đăng ký vào luồng batched() và trả về giá trị được phát đầu tiên. Query.stream() tạo ra một luồng phát ra các giá trị mới khi có thay đổi về siêu dữ liệu của thiết bị, chẳng hạn như tên, phòng hoặc cấu trúc của thiết bị. Về nội bộ, thành phần này sử dụng batched() và chỉ phát ra các thuộc tính đã thay đổi.

// Get a list of all devices accessible to the user
let homeDevices = try await self.home.devices().list()

Từ đó, bạn có thể truy cập vào trạng thái của từng thiết bị và gửi các lệnh được hỗ trợ đến thiết bị.

Lấy các loại thiết bị

Để lấy các loại thiết bị được liên kết với một thiết bị, hãy đọc thuộc tính types của thiết bị. Thuộc tính này sẽ trả về một DeviceTypeController.

Gọi DeviceTypeController.subscribe(_:) để đăng ký nhận thông tin cập nhật cho một loại thiết bị cụ thể:

let devices = try await self.home.devices().list()
if let device = devices.first(where: { $0.id == myDeviceId }) {
  var receivedUpdate1 = false
  var receivedUpdate2 = false
  device.types.subscribe(OnOffLightDeviceType.self)
    .assertNoFailure()
    .sink { device in
      if !receivedUpdate1 {
        receivedUpdate1 = true
        Task {
          try await device.matterTraits.onOffTrait?.on()
        }
        return
      }
      if !receivedUpdate2 {
        receivedUpdate2 = true
        return
      }
      fatalError("Received unexpected update")
    }
}

Nếu thiết bị không hỗ trợ loại thiết bị đã chỉ định, thì thiết bị sẽ trả về một Empty Publisher hoàn tất ngay lập tức.

Nếu thiết bị hỗ trợ một loại thiết bị cụ thể, bạn có thể lấy một giá trị nhận dạng cho loại đó bằng cách gọi get():

if let device = devices.first(where: { $0.id == myDeviceId }) {
  let deviceType = await device.types.get(OnOffLightDeviceType.self)
}

Nếu thiết bị không hỗ trợ loại được chỉ định, thì phương thức này sẽ trả về nil.

Gọi DeviceTypeController.subscribeAll() để nhận Publisher của DeviceTypeCollection. Lớp này cho phép bạn kiểm tra xem thiết bị có một loại thiết bị cụ thể hay không:

if let device = devices.first(where: { $0.id == myDeviceId }) {
  device.types.subscribeAll()
    .assertNoFailure()
    .sink { types in
      let lightDeviceType = types[OnOffLightDeviceType.self]
      let fanDeviceType = types[FanDeviceType.self]
    }
}

Nhận một sự kiện của loại thiết bị

Các loại thiết bị là điểm truy cập để đọc các đặc điểm, vì chúng phân tách một thiết bị thành các phần chức năng (chẳng hạn như các điểm cuối trong Matter).

Chúng cũng tính đến các trường hợp xung đột đặc điểm trong trường hợp một thiết bị có 2 loại thiết bị, cả hai loại này đều có thể có cùng một đặc điểm. Ví dụ: nếu một thiết bị vừa là Loa vừa là Đèn có thể điều chỉnh độ sáng, thì thiết bị đó sẽ có 2 đặc điểm Bật/tắt và 2 đặc điểm Điều khiển mức độ.

Một loại xung đột đặc điểm khác có thể xảy ra khi một thiết bị có 2 đặc điểm trùng tên. Ví dụ: onOff có thể đề cập đến một phiên bản của đặc điểm OnOff tiêu chuẩn hoặc có thể đề cập đến một phiên bản của đặc điểm OnOff do nhà sản xuất xác định. Để loại bỏ mọi điểm mơ hồ tiềm ẩn về đặc điểm dự kiến, hãy tham chiếu một đặc điểm thông qua một trong hai bộ sưu tập đặc điểm trên mỗi loại thiết bị.

Đối với các đặc điểm tiêu chuẩn, tức là những đặc điểm tương tự như các cụm tiêu chuẩn Matter, hãy sử dụng matterTraits. Ví dụ: để nhận một đặc điểm cụ thể cho loại thiết bị Đèn có thể điều chỉnh độ sáng:

if let dimmableLightDeviceType =
  await device.types.get(DimmableLightDeviceType.self)
{
  // Accessing standard trait on the type.
  let levelControlTrait =
    dimmableLightDeviceType.matterTraits.levelControlTrait.self
}

Đối với các đặc điểm của Google, hãy sử dụng googleTraits:

if let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) {
  // Accessing Google trait on the type.
  let doorbellPressTrait =
    doorbellDeviceType.googleTraits.doorbellPressTrait.self
}

Để truy cập vào một đặc điểm dành riêng cho nhà sản xuất, hãy tham chiếu đặc điểm đó thông qua thuộc tính traits, nhưng hãy thêm tên gói của nhà sản xuất vào trước:

let deviceType = await device1?.types.get(OnOffLightDeviceType.self)
// Accessing custom trait on the type.
if let spinnerTrait = deviceType?.traits[ExampleOrganization.SpinnerTrait.self] {
  let rpmVal = spinnerTrait.attributes.rpm
}

Đọc trạng thái thiết bị

Hãy xem ví dụ này về cách kiểm tra thuộc tính OnOff trong đặc điểm Bật/tắt của thiết bị:

let lightDevices = devices.filter {
  $0.types.contains(OnOffLightDeviceType.self)
}
let light1 = lightDevices.first
let lightDeviceTypeOptional = await light1?.types.get(OnOffLightDeviceType.self)
if let onOffTrait = lightDeviceTypeOptional?.matterTraits.onOffTrait {
  let onOffVal = onOffTrait.attributes.onOff
}

Lấy danh sách các thiết bị có một đặc điểm cụ thể

Để nhận danh sách các thiết bị có một đặc điểm cụ thể, bạn cần lặp lại các thiết bị, loại thiết bị của từng thiết bị và đặc điểm của từng loại thiết bị. Ví dụ: để lấy danh sách các thiết bị trong nhà có đặc điểm Bật/Tắt:

// Get all light devices that support levelControl
var levelControlDevices: [HomeDevice] = []
var allDevices = try await home.devices().list()
for device in allDevices {
  if let deviceType = await device.types.get(OnOffLightDeviceType.self) {
    if deviceType.traits.contains(Matter.LevelControlTrait.self) {
      levelControlDevices.append(device)
    }
  }
}

Hãy xem Chỉ mục đặc điểm trên iOS để biết danh sách đầy đủ các đặc điểm có trong Home API.

Lấy danh sách các thiết bị có cùng loại thiết bị

Cách lấy danh sách các thiết bị đại diện cho tất cả đèn trong nhà:

// Get a list of devices with similar device types (lights)
let lightDevices =
  try await self.home.devices().list().compactMap {
    $0.types.contains(DimmableLightDeviceType.self)
      || $0.types.contains(OnOffLightDeviceType.self)
      || $0.types.contains(ColorTemperatureLightDeviceType.self)
      || $0.types.contains(ExtendedColorLightDeviceType.self)
  }

Có nhiều loại thiết bị trong Home API có thể đại diện cho một loại thiết bị cốt lõi. Ví dụ: không có loại thiết bị "Đèn". Thay vào đó, có 4 loại thiết bị có thể đại diện cho một đèn, như minh hoạ trong ví dụ trước. Do đó, để có cái nhìn toàn diện về loại thiết bị cấp cao hơn trong nhà, bạn phải thêm nhiều loại thiết bị.

Hãy xem Các loại thiết bị được hỗ trợ trên iOS để biết danh sách đầy đủ các loại thiết bị và đặc điểm của chúng có trong Home API.

Lấy tên nhà cung cấp, mã nhà cung cấp hoặc mã sản phẩm của một thiết bị

Đặc điểm BasicInformationTrait bao gồm những thông tin như Mã nhà cung cấp, Mã sản phẩm, Tên sản phẩm và Số sê-ri của thiết bị:

guard
  let vendorName =
    basicInfoTrait.attributes.vendorName
else {
  fatalError("Failed to get vendorName")
}
guard
  let vendorID =
    basicInfoTrait.attributes.vendorID
else {
  fatalError("Failed to get vendorID")
}
guard
  let productID =
    basicInfoTrait.attributes.productID
else {
  fatalError("Failed to get productID")
}

Tính năng nhận dạng thiết bị từ đám mây đến đám mây dành cho nhà sản xuất thiết bị

Nếu là nhà sản xuất thiết bị và tạo thiết bị Cloud-to-cloud, để xác định thiết bị Cloud-to-cloud thông qua đặc điểm BasicInformation, bạn có thể thêm các trường chuỗi này vào phản hồi SYNC của thiết bị:

  • Liên minh Tiêu chuẩn Kết nối (CSA) đã cấp mã nhận dạng nhà cung cấp: "matterOriginalVendorId": "0xfff1",

  • Giá trị nhận dạng sản phẩm là giá trị nhận dạng riêng biệt của một sản phẩm của nhà cung cấp: "matterOriginalProductId": "0x1234",

  • Giá trị nhận dạng duy nhất của thiết bị, được tạo theo cách dành riêng cho nhà sản xuất: "matterUniqueId": "matter-device-id",

Khi nhập các trường chuỗi này, hãy sử dụng Mã nhận dạng sản phẩm và nhà cung cấp Matter nếu có. Nếu không phải là thành viên CSA và chưa được chỉ định các mã nhận dạng này, bạn có thể để trống các trường matterOriginalVendorIdmatterOriginalProductId, đồng thời cung cấp matterUniqueId làm giá trị nhận dạng.

Ví dụ về phản hồi SYNC cho thấy cách sử dụng các trường này:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "456",
        "type": "action.devices.types.LIGHT",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorSetting",
        ],
        "willReportState": true,
        "deviceInfo": { ... },
        "matterOriginalVendorId": "0xfff1",
        "matterOriginalProductId": "0x1234",
        "matterUniqueId": "matter-device-id",
        "otherDeviceIds": [
          {
            "deviceId": "local-device-id",
          }
        ]
      }
    ]
  }
}

Để biết thêm thông tin, hãy xem tài liệu về Cloud-to-cloud SYNC.

Siêu dữ liệu về thiết bị và đặc điểm

Các thiết bị và đặc điểm trong Home API có siêu dữ liệu liên kết với chúng, điều này có thể giúp quản lý trải nghiệm người dùng trong một ứng dụng.

Mỗi đặc điểm trong Home API đều chứa một thuộc tính sourceConnectivity. Thuộc tính này có thông tin về trạng thái trực tuyến và vị trí của đặc điểm (định tuyến cục bộ hoặc từ xa).

Lấy loại chính của một thiết bị

Một số thiết bị có thể trình bày nhiều loại thiết bị thông qua Home API. Để đảm bảo người dùng thấy các lựa chọn phù hợp trong một ứng dụng (chẳng hạn như chế độ điều khiển thiết bị và các hoạt động tự động hoá được đề xuất) cho thiết bị của họ, bạn nên kiểm tra xem loại thiết bị có phải là loại chính của thiết bị hay không.

if let deviceType =
  await device?.types.get(HumiditySensorDeviceType.self)
{
  if deviceType.metadata.isPrimaryType {
    print("Humidity Sensor is the primary type on this device.")
  } else {
    print("Humidity Sensor isn't the primary type on this device.")
  }
}

Kiểm tra xem một đặc điểm có đang trực tuyến hay không

Đọc thuộc tính connectivityState để kiểm tra khả năng kết nối của một đặc điểm:

let levelControlConnectivity =
  levelControlTrait.metadata.sourceConnectivity
  .connectivityState

Một số đặc điểm, thường là đặc điểm smart home của Google, có thể xuất hiện ở trạng thái ngoại tuyến nếu thiết bị không có kết nối Internet. Nguyên nhân là do các đặc điểm này dựa trên đám mây và không có định tuyến cục bộ.

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.

Kiểm tra định tuyến mạng của một đặc điểm

Địa điểm của một đặc điểm cũng có trong Home API. dataSourceLocality cho biết liệu đặc điểm này được định tuyến từ xa (thông qua đám mây), cục bộ (thông qua một trung tâm cục bộ) hay ngang hàng (trực tiếp từ thiết bị sang thiết bị, không cần trung tâm).

Có thể có giá trị vị trí không xác định unspecified, ví dụ: trong khi một ứng dụng đang khởi động và chưa kết nối với một trung tâm hoặc máy chủ để kết nối thiết bị. Những thiết bị này không thể truy cập và sẽ không thực hiện được các yêu cầu tương tác từ lệnh hoặc sự kiện. Việc xác định cách xử lý các thiết bị như vậy là tuỳ thuộc vào ứng dụng.

let levelControlLocality =
  levelControlTrait.metadata.sourceConnectivity
  .dataSourceLocality

Kiểm tra định tuyến mạng cho một thiết bị

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

let lightLocality =
  dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality

Trạng thái mixed có thể xuất hiện trong một trường hợp tương tự như trạng thái kết nối partiallyOnline: một số đặc điểm dựa trên đám mây trong khi những đặc điểm khác là cục bộ.

Thay đổi tên của thiết bị

Gọi phương thức setName(_:) để thay đổi tên của một thiết bị:

let updatedDevice = try await theDevice.setName("new device name")

Khi thay đổi tên của một thiết bị, cấu trúc HomeDevice ban đầu vẫn giữ nguyên và thay đổi sẽ được phản ánh trong đối tượng HomeDevice được cập nhật đã trả về.

Danh sách API

Sau khi bạn tạo một phiên bản Home, bạn có thể truy cập vào các Device API sau thông qua phiên bản đó:

API Mô tả
device(id:) Trả về một Publisher cho thiết bị đã chỉ định, phát trạng thái thiết bị bất cứ khi nào trạng thái đó thay đổi.
devices() Lấy tất cả thiết bị trong tất cả các cấu trúc trên Tài khoản Google. Trả về một Query<HomeDevice> cung cấp thêm các lựa chọn truy xuất và lọc.

Sau khi bạn có HomeDevice, bạn có thể truy cập vào các API sau thông qua khoá này:

API Mô tả
id Mã nhận dạng duy nhất của hệ thống trên thiết bị.
name Tên do người dùng cung cấp cho thiết bị.
structureID Mã nhận dạng của cấu trúc mà thiết bị được chỉ định. Trả về một String?.
roomID Mã của phòng mà thiết bị được chỉ định. Trả về một String?.
types Nhận một loại cụ thể hoặc tất cả các loại có trên thiết bị.
isMatterDevice Nếu thiết bị được Matter hỗ trợ.
sourceConnectivity Khả năng kết nối nguồn của thiết bị, thể hiện trạng thái kết nối tổng hợp và vị trí mạng của các đặc điểm của thiết bị.