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

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

import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id

Để sử dụng các loại hoặc đặc điểm thiết bị cụ thể với Device API, bạn phải nhập từng loại hoặc đặc điểm đó.

Ví dụ: để sử dụng đặc điểm Bật/Tắt Matter và loại thiết bị Đơn vị bổ trợ Bật/Tắt , hãy nhập các gói sau vào ứng dụng của bạn:

import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice

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

Xử lý lỗi

Mọi phương thức trong Home API đều có thể gửi HomeException, vì vậy, bạn nên sử dụng khối try-catch để nắm bắt HomeException trên tất cả các lệnh gọi.

Khi xử lý HomeException, hãy kiểm tra các trường error.code error.message để tìm hiểu điều gì đã xảy ra. Cũng có thể có các mã lỗi phụ nữa, vì vậy, hãy gọi phương thức getSubErrorCodes() và kiểm tra kết quả.

Mọi ngoại lệ không đượ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 Xử lý lỗi.

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

Lệnh gọi mẫu

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

Sau khi có tham chiếu đến thực thể Structure, lệnh gọi devices() sẽ trả về Flow của các thiết bị mà bạn có thể truy cập từ cấu trúc đó:

// Get a flow of all devices accessible to the user
val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allDevices: Set<HomeDevice> = allDevicesFlow.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 lệnh đến các thiết bị.

Với bản phát hành 1.8 của Home API, bạn có thể chọn để API đại diện cho từng thiết bị nhiều phần dưới dạng một thiết bị bằng cách đặt tham số enableMultipartDevices của phương thức devices() thành true. Hãy xem bài viết Thiết bị nhiều phần trên Android để biết thêm thông tin.

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

Hãy xem ví dụ về cách kiểm tra thuộc tính OnOff từ đặc điểm Bật/Tắt của thiết bị. Khi sử dụng mô hình dữ liệu đặc điểm Home API, trong đó đặc điểm này được xác định là OnOff, bạn có thể truy xuất dữ liệu đặc điểm thông qua lớp standardTraits của loại thiết bị:

// Assuming we have a device.
val deviceFlow = home.devices().itemFlow(myDeviceId)

val device = deviceFlow.first()

// Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger
// on the specific trait changes and not the whole type.
val onOffTraitFlow: Flow<OnOff?> =
  device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged()

val onOffTrait: OnOff = onOffTraitFlow.first()!!

Hãy xem distinctUntilChanged để tìm hiểu thêm về hàm luồng Kotlin.

Vô hiệu hoá trạng thái trong gói thuê bao đặc điểm

Giao diện TraitStateInvalidation cung cấp khả năng vô hiệu hoá trạng thái được truy xuất thông qua gói thuê bao cho thiết bị mục tiêu trong trường hợp trạng thái không được báo cáo chính xác. Ví dụ về trường hợp trạng thái có thể không được báo cáo chính xác bao gồm việc sử dụng các thuộc tính trong đặc điểm Matter có chất lượng "C" hoặc do quá trình triển khai thiết bị bất ngờ gây ra vấn đề.

API này phát hành lệnh đọc bắt buộc về trạng thái đặc điểm hiện tại và trả về kết quả thông qua các luồng đặc điểm hiện có.

Lấy đặc điểm, sau đó chạy forceRead trên đặc điểm đó:

val onOffTrait = device.?type(DimmableLightDevice)?.map{it.trait(OnOff)}.first()
onOffTrait.forceRead()

Lấy danh sách các đặc điểm loại thiết bị

Bạn nên sử dụng các loại thiết bị làm điểm truy cập để đọc đặc điểm, vì các loại thiết bị này phân tách một thiết bị thành các phần chức năng (như điểm cuối trong Matter).

Các loại thiết bị này cũng tính đến các 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 thiết bị 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.

Cách lấy danh sách các đặc điểm hiện có cho loại thiết bị Đèn có thể điều chỉnh độ sáng:

// Get all types available on this device. Requires the types to be part of the registry during
// SDK initialization.
val typesFlow: Flow<Set<DeviceType>> = device.types()

// Get a snapshot of all types.
val types: Set<DeviceType> = typesFlow.first()

// Get the DimmableLightDevice instance from the set of types.
val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull()

// Get all traits in the type + traits registered
val allTraits: Set<Trait> = dimmableLightDevice!!.traits()

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 có cùng tên. Ví dụ: onOff có thể tham chiếu đến một thực thể của đặc điểm OnOff tiêu chuẩn hoặc có thể tham chiếu đến một thực thể của đặc điểm OnOff do nhà sản xuất xác định. Để loại bỏ mọi sự mơ hồ tiềm ẩn về đặc điểm dự định, thực thể Trait được tham chiếu thông qua một thiết bị phải được đặt trước bằng một không gian tên đủ điều kiện. Đối với các đặc điểm tiêu chuẩn (tức là những đặc điểm tương tự như Matter các cụm tiêu chuẩn), hãy sử dụng standardTraits. Đối với các đặc điểm của Google, hãy sử dụng googleTraits:

// Accessing standard traits on the type.
val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff
val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl

Để 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 trực tiếp đến đặc điểm đó:

// Accessing a custom trait on the type.
val customTrait = dimmableLightDevice.trait(MyCustomTrait)

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

Bạn có thể sử dụng hàm filter trong Kotlin để tinh chỉnh thêm các lệnh gọi API. Ví dụ: để lấy danh sách các thiết bị trong nhà đều có đặc điểm Bật/Tắt:

// Get all devices that support OnOff
val onOffDevices: Flow<List<HomeDevice>> =
  home.devices().map { devices -> devices.filter { it.has(OnOff) } }

Hãy xem giao diện Trait để 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ó loại thiết bị tương tự

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)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }

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 chiếc đèn, như 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 đưa nhiều loại thiết bị vào các luồng đã lọc.

Hãy xem giao diện DeviceType để biết danh sách đầy đủ các loại thiết bị có trong Home API.

Lấy Mã nhà cung cấp hoặc Mã sản phẩm cho một thiết bị

Đặc điểm BasicInformation bao gồm các 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 một thiết bị:

// Get device basic information. All general information traits are on the RootNodeDevice type.
val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!!
println("vendorName ${basicInformation.vendorName}")
println("vendorId ${basicInformation.vendorId}")
println("productId ${basicInformation.productId}")

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

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

  • Connectivity Standards Alliance (Alliance) đã cấp mã nhà cung cấp: "matterOriginalVendorId": "0xfff1",

  • Giá trị nhận dạng sản phẩm giúp xác định duy nhất một sản phẩm của nhà cung cấp: "matterOriginalProductId": "0x1234",

  • Giá trị nhận dạng duy nhất cho 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ã Matter nhà cung cấp và Mã sản phẩm nếu bạn có. Nếu bạn không phải là Alliance thành viên và chưa được chỉ định các mã này, bạn có thể để trống các trường matterOriginalVendorIdmatterOriginalProductId rồ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 Cloud-to-cloud SYNC tài liệu.

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 được liên kết với chúng, 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 sourceConnectivity thuộc tính, 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 được cung cấp các lựa chọn phù hợp trong một ứng dụng (chẳng hạn như tính năng điều khiển thiết bị và tự động hoá được đề xuất) cho thiết bị của họ, bạn nên kiểm tra loại thiết bị chính của một thiết bị.

Trước tiên, hãy lấy(các) loại thiết bị bằng cách sử dụng type(), sau đó xác định(các) loại chính:

val types = device.types().first()
val primaryTypes = types.filter { it.metadata.isPrimaryType }

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

Sử dụng phương thức connectivityState() để kiểm tra khả năng kết nối của một đặc điểm:

val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState

Một số đặc điểm (thường là đặc điểm smart home của Google) có thể hiển thị 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ó tính năng định tuyến cục bộ.

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

Khả năng kết nối của một 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ị đó.

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

Bạn có thể quan sát thấy trạng thái PARTIALLY_ONLINE trong trường hợp các loại thiết bị hỗn hợp khi không có kết nối Internet. Matter Các đặc điểm tiêu chuẩn vẫn có thể trực tuyến do tính năng đị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 tính năng định tuyến mạng của một đặc điểm

Vị trí của một đặc điểm cũng có trong Home API. dataSourceLocality cho biết liệu đặc điểm đượ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ị đến thiết bị, không có trung tâm).

Giá trị vị trí không xác định UNSPECIFIED có thể xảy ra, ví dụ: 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ị. Không thể truy cập vào các thiết bị này 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. Khách hàng có trách nhiệm xác định cách xử lý các thiết bị như vậy.

val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality

Kiểm tra tính năng định tuyến mạng của một thiết bị

Giống như khả năng kết nối, vị trí đượ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ị đó.

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

Bạn có thể quan sát thấy trạng thái MIXED trong một tình huống tương tự như khả năng kết nối PARTIALLY_ONLINE: 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 một thiết bị

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

mixerDevice.setName("Grendel")

Tên sẽ bị cắt bớt nếu vượt quá giới hạn 60 điểm mã Unicode (ký tự) và sẽ không có lỗi nào được gửi. Nhà phát triển chịu trách nhiệm xử lý tên dài và ví dụ: có thể quyết định xem họ có muốn thông báo cho người dùng rằng tên sẽ bị cắt bớt hay không.