Sterowanie urządzeniami

Sprawdzanie, czy cecha obsługuje polecenie

Możesz też sprawdzić, czy zespół pomocy nie ma poleceń dotyczących cech. Aby sprawdzić, czy polecenie jest obsługiwane na danym urządzeniu, użyj też funkcji supports na poziomie atrybutu.

Aby na przykład sprawdzić, czy urządzenie obsługuje polecenie toggle atrybutu Włącz/Wyłącz:

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

Wysyłanie polecenia do urządzenia

Wysyłanie polecenia jest podobne do odczytywania atrybutu stanu z cechy. Aby włączyć lub wyłączyć urządzenie, użyj polecenia przełącznika OnOff w ramach funkcji, która w modelu danych ekosystemu Google Home jest zdefiniowana jako toggle(). Ta metoda zmienia wartość onOff na false, jeśli jest ona równa true, lub na true, jeśli jest równa false:

// Calling a command on a trait.
try {
  onOffTrait.toggle()
} catch (e: HomeException) {
  // Code for handling the exception
}

Wszystkie polecenia dotyczące cech to funkcje suspend, które są wykonywane tylko wtedy, gdy interfejs API zwróci odpowiedź (np. potwierdzenie zmiany stanu urządzenia). W przypadku wykrycia problemu w przepływie wykonywania poleceń może zostać zwrócony wyjątek. Jako deweloper powinieneś używać bloku try-catch, aby odpowiednio obsługiwać te wyjątki, oraz wyświetlać użytkownikom szczegółowe informacje o przypadkach, w których błędy można naprawić. Nieprzetworzone wyjątki zatrzymają działanie aplikacji i mogą spowodować jej awarię.

Możesz też użyć poleceń off() lub on(), aby jednoznacznie ustawić stan:

onOffTrait.off()
onOffTrait.on()

Po wysłaniu polecenia zmiany stanu możesz odczytać stan urządzenia, korzystając z opisu w sekcji Odczyt stanu urządzenia, aby obsłużyć go w aplikacji. Możesz też użyć przepływów opisanych w sekcji Obserwowanie stanu, która jest preferowaną metodą.

Wysyłanie polecenia z parametrami

Niektóre polecenia mogą używać parametrów, takich jak te na stronie OnOff lub LevelControlwłaściwości:

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(),
)

Niektóre polecenia mają argumenty opcjonalne, które występują po wymaganych argumentach.

Na przykład polecenie step dotyczące atrybutu FanControl ma 2 argumenty opcjonalne:

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 }

Sprawdzanie, czy cecha obsługuje atrybut

Niektóre urządzenia mogą obsługiwać cechę Matter, ale nie konkretny atrybut. Na przykład urządzenie Cloud-to-cloud, które zostało zmapowane na Matter, może nie obsługiwać wszystkich atrybutów Matter. Aby obsłużyć takie przypadki, użyj funkcji supports na poziomie atrybutu i enumeracji Attribute atrybutu, aby sprawdzić, czy atrybut jest obsługiwany na danym urządzeniu.

Aby na przykład sprawdzić, czy urządzenie obsługuje atrybut onOff cechy Włączanie/wyłączanie:

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

Niektóre atrybuty mogą być puste w specyfikacji Matter lub w schemacie Cloud-to-cloud smart home. W przypadku tych atrybutów możesz określić, czy zwrócony przez nie null jest spowodowany tym, że urządzenie nie przekazuje tej wartości, czy też wartość atrybutu jest rzeczywiście null, używając isNullable zamiast supports:

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

Aktualizowanie atrybutów cech

Jeśli chcesz zmienić wartość danego atrybutu, a żaden z poleceń atrybutu tego nie robi, atrybut może obsługiwać jawne ustawianie wartości.

Możliwość zmiany wartości atrybutu zależy od 2 czynników:

  • Czy atrybut jest zapisywalny?
  • Czy wartość atrybutu może się zmienić w efekcie ubocznym wysłania polecenia dotyczącego cech?

Informacje te znajdziesz w dokumentacji referencyjnej dotyczącej cech i ich atrybutów.

Dlatego kombinacje właściwości, które określają, jak można zmienić wartość atrybutu, to:

  • Tylko do odczytu i nie podlega innym poleceniom. Oznacza to, że wartość atrybutu się nie zmienia. Na przykład atrybut currentPosition cechy Switch.

  • Tylko do odczytu i ulegające wpływowi innych poleceń. Oznacza to, że wartość atrybutu może się zmienić tylko w wyniku wysłania polecenia. Na przykład atrybut currentLevel atrybutu LevelControl Matter jest tylko do odczytu, ale jego wartość może być modyfikowana przez polecenia takie jak moveToLevel.

  • Do zapisu i nie podlegające innym poleceniom. Oznacza to, że możesz bezpośrednio zmienić wartość atrybutu, używając funkcji update cechy, ale nie ma żadnych poleceń, które mogłyby wpłynąć na wartość atrybutu. Na przykład atrybut WrongCodeEntryLimit cechy DoorLock.

  • Dostęp do zapisu i modyfikacji przez inne polecenia. Oznacza to, że możesz bezpośrednio zmienić wartość atrybutu za pomocą funkcji update atrybutu, a wartość atrybutu może się zmienić w wyniku wysłania polecenia. Na przykład atrybut occupiedCoolingSetpoint cechy Thermostat można zapisać, ale też zaktualizować za pomocą polecenia setpointRaiseLower.

Przykład użycia funkcji update do zmiany wartości atrybutu

Ten przykład pokazuje, jak jawnie ustawić wartość atrybutu DoorLockTrait.WrongCodeEntryLimit.

Aby ustawić wartość atrybutu, wywołaj funkcję update cechy i podaj jej funkcję modyfikującą, która ustawia nową wartość. Warto najpierw sprawdzić, czy cecha obsługuje dany atrybut.

Na przykład:

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