檢查特徵是否支援指令
您也可以檢查特徵指令的支援情形。另外,請使用特徵層級的 supports
函式,檢查特定裝置是否支援指令。
舉例來說,如要檢查裝置是否支援開/關特徵的 toggle
指令:
// Check if the OnOff trait supports the toggle command. if (onOffTrait.supports(OnOff.Command.Toggle)) { println("onOffTrait supports toggle command") } else { println("onOffTrait does not support stateful toggle command") }
將指令傳送至裝置
傳送指令的做法類似於從特徵讀取狀態屬性。如要開啟或關閉裝置,請使用 OnOff
特徵的切換指令,在 Google Home 生態系統資料模型中定義為 toggle()
。如果 onOff
為 true
,這個方法會將其變更為 false
;如果為 false
,則會變更為 true
:
// Calling a command on a trait. try { onOffTrait.toggle() } catch (e: HomeException) { // Code for handling the exception }
所有特徵指令都是 suspend
函式,只有在 API 傳回回應 (例如確認裝置狀態已變更) 時才會完成。如果執行流程發生問題,指令可能會傳回例外狀況。開發人員應使用 try-catch
區塊妥善處理這些例外狀況,並在錯誤可採取行動的情況下,向使用者顯示詳細資訊。未處理的例外狀況會停止應用程式執行階段,並可能導致應用程式當機。
或者,您也可以使用 off()
或 on()
指令明確設定狀態:
onOffTrait.off() onOffTrait.on()
傳送指令來變更狀態後,在指令完成後,您可以依「讀取裝置狀態」一節的說明讀取狀態,在應用程式中加以處理。或者,您也可以依「觀察狀態」一節的說明使用流程,這是較佳方法。
傳送含有參數的指令
部分指令可能會使用參數,例如 OnOff
或 LevelControl
特徵:
offWithEffect
// Turn off the light using the DyingLight effect. onOffTrait.offWithEffect( effectIdentifier = OnOffTrait.EffectIdentifierEnum.DyingLight, effectVariant = 0u, )
moveToLevel
// Change the brightness of the light to 50% levelControlTrait.moveToLevel( level = 127u.toUByte(), transitionTime = null, optionsMask = LevelControlTrait.OptionsBitmap(), optionsOverride = LevelControlTrait.OptionsBitmap(), )
部分指令具有選用引數,會在必要引數之後出現。
舉例來說,FanControl
特徵的 step
指令有兩個選用引數:
val fanControlTraitFlow: Flow<FanControl?> = device.type(FanDevice).map { it.standardTraits.fanControl }.distinctUntilChanged() val fanControl = fanControlTraitFlow.firstOrNull() // Calling a command with optional parameters not set. fanControl?.step(direction = FanControlTrait.StepDirectionEnum.Increase) // Calling a command with optional parameters. fanControl?.step(direction = FanControlTrait.StepDirectionEnum.Increase) { wrap = true }
檢查特徵是否支援屬性
部分裝置可能支援 Matter 特徵,但不支援特定屬性。舉例來說,已對應至 Matter 的 Cloud-to-cloud 裝置可能不支援所有 Matter 屬性。如要處理這類情況,請使用特徵層級的 supports
函式和特徵的 Attribute
列舉,檢查特定裝置是否支援該屬性。
舉例來說,如要檢查裝置是否支援開/關特徵的 onOff
屬性:
// Check if the OnOff trait supports the onOff attribute. if (onOffTrait.supports(OnOff.Attribute.onOff)) { println("onOffTrait supports onOff state") } else { println("onOffTrait is for a command only device!") }
在 Matter 規格或 Cloud-to-cloud smart home 架構中,部分屬性可為空值。針對這些屬性,您可以使用 isNullable
和 supports
,判斷屬性傳回的 null 是因為裝置未回報該值,還是屬性值實際上是 null
:
// Check if a nullable attribute is set or is not supported. if (onOffTrait.supports(OnOff.Attribute.startUpOnOff)) { // The device supports startupOnOff, it is safe to expect this value in the trait. if (OnOff.Attribute.startUpOnOff.isNullable && onOffTrait.startUpOnOff == null) { // This value is nullable and set to null. Check the specification as to // what null in this case means println("onOffTrait supports startUpOnOff and it is null") } else { // This value is nullable and set to a value. println("onOffTrait supports startUpOnOff and it is set to ${onOffTrait.startUpOnOff}") } } else { println("onOffTrait does not support startUpOnOff!") }
更新特徵屬性
如果您想變更特定屬性的值,但特徵的命令都無法執行此操作,則該屬性可能支援明確設定值。
屬性的值是否可變更,取決於兩個因素:
- 屬性是否可寫入?
- 屬性值是否會因傳送特徵指令而產生副作用?
特徵及其屬性的參考說明文件會提供這項資訊。
因此,決定屬性值變更方式的屬性組合如下:
為唯讀,且不會受到其他指令的影響。也就是說,屬性的值不會變更。例如
Switch
特徵的currentPosition
屬性。唯讀,且會受到其他指令影響。也就是說,屬性值的唯一變更方式是傳送指令。舉例來說,
LevelControl
Matter 特徵的currentLevel
屬性 為唯讀,但其值可透過moveToLevel
等指令變更。可寫入,且不會受到其他指令影響。也就是說,您可以使用特徵的
update
函式直接變更屬性值,但沒有任何指令會影響屬性值。例如DoorLock
特徵的WrongCodeEntryLimit
屬性。可寫入,且會受到其他指令影響。也就是說,您可以使用特徵的
update
函式直接變更屬性值,而屬性值也會隨著傳送指令而變更。舉例來說,Thermostat
特徵的occupiedCoolingSetpoint
屬性可以寫入,但也可以透過setpointRaiseLower
指令更新。
使用更新函式變更屬性值的範例
這個範例說明如何明確設定 DoorLockTrait.WrongCodeEntryLimit
屬性的值。
如要設定屬性值,請呼叫特徵的 update
函式,並傳遞設定新值的修飾函式。建議您先確認特徵是否支援屬性。
例如:
var doorLockDevice = home.devices().list().first { device -> device.has(DoorLock) } val traitFlow: Flow<DoorLock?> = doorLockDevice.type(DoorLockDevice).map { it.standardTraits.doorLock }.distinctUntilChanged() val doorLockTrait: DoorLock = traitFlow.first()!! if (doorLockTrait.supports(DoorLock.Attribute.wrongCodeEntryLimit)) { val unused = doorLockTrait.update { setWrongCodeEntryLimit(3u) } }