Hướng dẫn này tiếp nối nội dung trong bài viết Truy cập vào thiết bị và siêu dữ liệu của thiết bị trên iOS, đồng thời giới thiệu thêm các ví dụ về quyền kiểm soát và truy cập vào thiết bị.
Để sử dụng các loại thiết bị hoặc đặc điểm cụ thể, chẳng hạn như Matter
OnOffTrait được dùng trong nhiều ví dụ ở đây, bạn phải nhập các loại thiết bị hoặc đặc điểm đó:
import GoogleHomeSDK
import GoogleHomeTypes
Kiểm tra xem một đặc điểm có hỗ trợ một lệnh hay không
Sử dụng hàm supports ở cấp đặc điểm để kiểm tra xem một lệnh có được hỗ trợ cho một thiết bị cụ thể hay không.
Ví dụ: để kiểm tra xem thiết bị có hỗ trợ lệnh toggle của đặc điểm Bật/Tắt hay không:
// Check if the OnOff trait supports the toggle command. if onOffTraitTest.supportsToggleCommand { print("onOffTrait supports toggle command") } else { print("onOffTrait does not support stateful toggle command") }
Gửi lệnh đến thiết bị
Việc gửi lệnh cũng tương tự như việc đọc thuộc tính trạng thái từ một đặc điểm. Để
bật hoặc tắt thiết bị, hãy sử dụng lệnh
OnOffTrait
Toggle, được xác định trong mô hình dữ liệu
hệ sinh thái Google Home là toggle(). Phương thức này thay đổi onOff thành false nếu là true, hoặc thành true nếu là false:
// Calling a command on a trait. do { try await onOffTraitTest.toggle() } catch let _ as HomeError { // Code for handling the exception }
Các lệnh có thể trả về một ngoại lệ nếu phát hiện thấy vấn đề với luồng thực thi. Là nhà phát triển, bạn nên sử dụng khối do-catch để xử lý đúng cách các ngoại lệ này và hiển thị thông tin chi tiết cho người dùng về những trường hợp có thể xử lý lỗi. Các ngoại lệ chưa được xử lý sẽ dừng thời gian chạy của ứng dụng và có thể gây ra sự cố trong ứng dụng.
Ngoài ra, hãy sử dụng lệnh off() hoặc on() để đặt trạng thái một cách rõ ràng:
do { try await onOffTraitTest.off() try await onOffTraitTest.on() } catch let _ as HomeError { // Code for handling the exception }
Sau khi gửi lệnh thay đổi trạng thái, khi lệnh hoàn tất, bạn có thể đọc trạng thái như mô tả trong phần Đọc trạng thái thiết bị để xử lý trạng thái đó trong ứng dụng.
Gửi lệnh có tham số
Một số lệnh có thể sử dụng tham số, chẳng hạn như các lệnh trên
OnOffTrait hoặc
LevelControlTrait:
offWithEffect
// Turn off the light using the DyingLight effect. do { try await onOffTraitTest.offWithEffect( effectIdentifier: Matter.OnOffTrait.EffectIdentifierEnum.dyingLight, effectVariant: 0 ) } catch let _ as HomeError { // Code for handling the exception }
moveToLevel
// Change the brightness of the light to 50% do { try await levelControlTraitTest.moveToLevel( level: UInt8(127), transitionTime: 0, optionsMask: Matter.LevelControlTrait.OptionsBitmap(), optionsOverride: Matter.LevelControlTrait.OptionsBitmap() ) } catch let _ as HomeError { // Code for handling the exception }
Kiểm tra xem một đặc điểm có hỗ trợ một thuộc tính hay không
Một số thiết bị có thể hỗ trợ một đặc điểm Matter, nhưng không hỗ trợ một thuộc tính cụ thể. Ví dụ: một thiết bị Cloud-to-cloud được liên kết với Matter có thể không hỗ trợ mọi thuộc tính của Matter. Để xử lý các trường hợp như thế này, hãy sử dụng thuộc tính isSupported ở cấp đặc điểm để kiểm tra xem thuộc tính có được hỗ trợ cho một thiết bị cụ thể hay không.
Ví dụ: để kiểm tra xem thiết bị có hỗ trợ thuộc tính onOff của đặc điểm Bật/Tắt hay không, hãy làm như sau:
// Check if the OnOff trait supports the onOff attribute. if onOffTrait.attributes.$onOff.isSupported { print("onOffTrait supports onOff state") } else { print("onOffTrait is for a command only device!") }
Một số thuộc tính có thể rỗng trong quy cách Matter hoặc giản đồ Cloud-to-cloud smart home. Đối với các thuộc tính này, bạn có thể xác định xem giá trị nil mà thuộc tính trả về là do thiết bị không báo cáo giá trị đó hay giá trị của thuộc tính thực sự là nil, bằng cách sử dụng isNullable ngoài isSupported:
// Check if a nullable attribute is set or is not supported. if let deviceType = await device.types.get(OnOffLightDeviceType.self) { if let onOffTrait = deviceType.traits[Matter.OnOffTrait.self] { if onOffTrait.attributes.startUpOnOff == nil { if onOffTrait.attributes.$startUpOnOff.isSupported { print( "onOffTrait supports startUpOnOff and it is nil. Check the spec for the contextual meaning." ) } else { print("onOffTrait does not support startUpOnOff!") } } else { print( "onOffTrait supports startUpOnOff and it is set to \(String(describing: onOffTrait.attributes.startUpOnOff))" ) } } }
Cập nhật thuộc tính đặc điểm
Nếu bạn muốn thay đổi giá trị của một thuộc tính nhất định và không có lệnh nào của đặc điểm thực hiện việc này, thì thuộc tính đó có thể hỗ trợ việc đặt giá trị một cách rõ ràng.
Việc có thể thay đổi giá trị của một thuộc tính hay không phụ thuộc vào hai yếu tố:
- Thuộc tính có thể ghi được không?
- Giá trị của thuộc tính có thể thay đổi do tác dụng phụ của việc gửi lệnh đặc điểm không?
Tài liệu tham khảo về các đặc điểm và thuộc tính của đặc điểm cung cấp thông tin này.
Do đó, các tổ hợp thuộc tính quyết định cách thay đổi giá trị của một thuộc tính là:
Chỉ đọc và không bị ảnh hưởng bởi các lệnh khác. Điều này có nghĩa là giá trị của thuộc tính không thay đổi. Ví dụ: thuộc tính
currentPositioncủaSwitchTrait.Chỉ đọc và bị ảnh hưởng bởi các lệnh khác. Điều này có nghĩa là cách duy nhất để thay đổi giá trị của thuộc tính là gửi lệnh. Ví dụ: thuộc tính
currentLevelcủaLevelControlTraitlà chỉ có thể đọc, nhưng giá trị của thuộc tính này có thể thay đổi bằng các lệnh nhưmoveToLevel.Có thể ghi và không bị ảnh hưởng bởi các lệnh khác. Điều này có nghĩa là bạn có thể thay đổi trực tiếp giá trị của thuộc tính bằng cách sử dụng hàm
updatecủa đặc điểm, nhưng không có lệnh nào ảnh hưởng đến giá trị của thuộc tính. Ví dụ: thuộc tínhWrongCodeEntryLimitcủaDoorLockTrait.Có thể ghi và bị ảnh hưởng bởi các lệnh khác. Điều này có nghĩa là bạn có thể thay đổi trực tiếp giá trị của thuộc tính bằng cách sử dụng hàm
updatecủa đặc điểm và giá trị của thuộc tính có thể thay đổi do gửi lệnh. Ví dụ: thuộc tínhoccupiedCoolingSetpointcủaThermostatTraitcó thể được ghi vào nhưng cũng có thể được cập nhật bằng lệnhsetpointRaiseLower.
Ví dụ về cách sử dụng hàm cập nhật để thay đổi giá trị của thuộc tính
Ví dụ này cho thấy cách đặt giá trị của thuộc tính DoorLockTrait.wrongCodeEntryLimit một cách rõ ràng.
Để đặt giá trị thuộc tính, hãy gọi hàm update của đặc điểm và truyền cho hàm đó một hàm cập nhật để đặt giá trị mới. Trước tiên, bạn nên xác minh rằng đặc điểm đó hỗ trợ một thuộc tính.
Ví dụ:
if doorLockTraitTest.attributes.$wrongCodeEntryLimit.isSupported { let _ = try await doorLockTraitTest.update { $0.setWrongCodeEntryLimit(3) } }
Điều khiển một nhóm thiết bị
Ngoài việc kiểm soát chi tiết từng thành viên của một nhóm bằng cách lặp lại
qua các thiết bị thành viên,
bạn có thể kiểm soát
DeviceGroup dưới dạng một
thực thể duy nhất. DeviceGroup tuân thủ giao thức HasParts và hiển thị các phần DeviceType được các thiết bị trong nhóm hỗ trợ:
await group.part(_:)trả về thực thể đầu tiên củaDeviceTypeđược chỉ định nếu nhóm hỗ trợ, hoặcnilnếu không hỗ trợ.try await group.parts(_:)trả về một mảng gồm tất cả các phần cấp cao nhất khớp vớiDeviceTypeđược chỉ định.
Khi bạn gọi một lệnh đặc điểm trên một loại thiết bị thuộc DeviceGroup, SDK sẽ chuyển tiếp lệnh đó đến tất cả thiết bị thành viên có liên quan trong nhóm hỗ trợ chức năng đó, bất kể khả năng kết nối hoặc phương thức truyền tải cơ bản của các thiết bị đó (chẳng hạn như Matter hoặc Cloud-to-cloud).
Thuộc tính đặc điểm của bộ phận nhóm và cách xử lý lỗi
Việc nhắm đến một phần của nhóm sẽ đơn giản hoá các trường hợp phổ biến mà bạn muốn gửi một lệnh không thay đổi (chẳng hạn như bật hoặc tắt đèn, hoặc đặt mức độ sáng) cho một nhóm. Khi làm việc với các đặc điểm và lệnh trên một phần DeviceGroup, hãy lưu ý các hành vi sau:
- Các thuộc tính trạng thái động (chẳng hạn như thuộc tính
onOffcủaOnOffTraithoặc thuộc tínhcurrentLevelcủaLevelControlTrait) thường không được điền sẵn trên đặc điểm của một phần nhóm vì các thiết bị thành viên trong một nhóm có thể ở nhiều trạng thái khác nhau và không thể kết hợp thành một giá trị duy nhất. Tuy nhiên, các lệnh được hỗ trợ (được kiểm tra bằngsupports(_:), chẳng hạn như.moveToLevelWithOnOfftrên đèn có thể điều chỉnh độ sáng) và một số thuộc tính chức năng (chẳng hạn nhưcolorTempPhysicalMinMiredsvàcolorTempPhysicalMaxMiredstrênColorControlTraitcho đèn màu) sẽ được điền sẵn để ứng dụng của bạn có thể định cấu hình các thành phần điều khiển trên giao diện người dùng một cách phù hợp. - Không phải lệnh nào về đặc điểm của thành viên nhóm cũng dùng được trên một phần của nhóm. Cụ thể, các lệnh trả về giá trị sẽ không dùng được.
- Lệnh trên một phần của nhóm không trả về kết quả riêng lẻ cho từng lệnh của thiết bị thành viên cơ bản. Để kiểm tra kết quả của từng lệnh hoặc gọi các lệnh trả về giá trị, hãy lặp lại trực tiếp qua các thiết bị thành viên của nhóm.
- Các lệnh được gửi đến một phần trên
DeviceGroupsẽ hoàn tất sau khi toàn bộ quá trình phân phối trên các thiết bị thành viên kết thúc và tất cả các lệnh thành công hoặc không thành công đều được thu thập. Một lệnh chỉ không thành công (gửi mộtHomeError) nếu lệnh đó không thành công đối với mọi thiết bị thành viên được liên kết hoặc nếu tất cả thiết bị mục tiêu đều không hoạt động, xuất hiện dưới dạng một lỗi lệnh duy nhất khớp với cú pháp gọi lệnh đơn. Nếu có ít nhất một thiết bị thành viên thực thi lệnh, thì lệnh nhóm sẽ hoàn tất mà không gửi lỗi.
Gửi lệnh đến một phần của nhóm
Cách bật tất cả đèn OnOffLightDeviceType trong một nhóm thiết bị:
if let lightPart = await group.part(OnOffLightDeviceType.self),
let onOffTrait = lightPart.matterTraits.onOffTrait,
onOffTrait.supports(.on) {
try await onOffTrait.on()
}
Bạn cũng có thể kiểm tra nhiều loại thiết bị có liên quan (ví dụ: tắt mọi loại thiết bị đèn trong nhóm hỗ trợ OnOffTrait):
func onOffTrait(in group: DeviceGroup) async -> Matter.OnOffTrait? {
if let light = await group.part(OnOffLightDeviceType.self) {
return light.matterTraits.onOffTrait
}
if let light = await group.part(DimmableLightDeviceType.self) {
return light.matterTraits.onOffTrait
}
if let light = await group.part(ColorTemperatureLightDeviceType.self) {
return light.matterTraits.onOffTrait
}
if let light = await group.part(ExtendedColorLightDeviceType.self) {
return light.matterTraits.onOffTrait
}
return nil
}
if let trait = await onOffTrait(in: group) {
try await trait.off()
}
Bạn có thể kiểm tra khả năng hỗ trợ lệnh hoặc đọc giới hạn chức năng trên một phần của nhóm trước khi gửi lệnh (ví dụ: kiểm tra .moveToLevelWithOnOff trên một phần đèn có thể điều chỉnh độ sáng hoặc đọc colorTempPhysicalMinMireds và colorTempPhysicalMaxMireds trên một phần đèn có nhiệt độ màu):
if let dimmableLight = await group.part(DimmableLightDeviceType.self),
let levelTrait = dimmableLight.matterTraits.levelControlTrait,
levelTrait.supports(.moveToLevelWithOnOff) {
try await levelTrait.moveToLevelWithOnOff(
level: 127,
transitionTime: nil,
optionsMask: [],
optionsOverride: []
)
}
if let colorLight = await group.part(ColorTemperatureLightDeviceType.self),
let colorTrait = colorLight.matterTraits.colorControlTrait,
let minMireds = colorTrait.attributes.colorTempPhysicalMinMireds,
let maxMireds = colorTrait.attributes.colorTempPhysicalMaxMireds {
let midMireds = UInt16((UInt32(minMireds) + UInt32(maxMireds)) / 2)
try await colorTrait.moveToColorTemperature(
colorTemperatureMireds: midMireds,
transitionTime: 0,
optionsMask: [],
optionsOverride: []
)
}