Sterowanie urządzeniami w iOS

Ten przewodnik jest kontynuacją artykułu Dostęp do urządzeń i metadanych urządzeń w iOS. Zawiera dodatkowe przykłady sterowania urządzeniami i dostępu do nich.

Aby używać określonych typów urządzeń lub cech, takich jak Matter OnOffTrait używana w wielu przykładach, musisz je zaimportować:

import GoogleHomeSDK
import GoogleHomeTypes

Sprawdzanie, czy cecha obsługuje polecenie

Aby sprawdzić, czy polecenie jest obsługiwane przez dane urządzenie, użyj funkcji supports na poziomie cechy.

Aby na przykład sprawdzić, czy urządzenie obsługuje polecenie cechy On/Off: toggle

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

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 OnOffTrait polecenia Toggle, które jest zdefiniowane w modelu danych ekosystemu Google Home 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.
do {
  try await onOffTraitTest.toggle()
} catch let _ as HomeError {
  // Code for handling the exception
}

Polecenia mogą zwracać wyjątek, jeśli zostanie wykryty problem z przepływem wykonania. Jako deweloper powinieneś użyć bloku do-catch, aby prawidłowo obsługiwać te wyjątki i wyświetlać użytkownikom szczegółowe informacje w przypadkach, gdy błędy są możliwe do naprawienia. Nieobsłużone wyjątki zatrzymają działanie aplikacji i mogą spowodować jej awarię.

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

do {
  try await onOffTraitTest.off()
  try await onOffTraitTest.on()
} catch let _ as HomeError {
  // Code for handling the exception
}

Po wysłaniu polecenia, które ma zmienić stan, możesz odczytać stan po jego zakończeniu, jak opisano w artykule Odczytywanie stanu urządzenia, aby obsługiwać go w aplikacji.

Wysyłanie polecenia z parametrami

Niektóre polecenia mogą używać parametrów, np. polecenia OnOffTrait lub 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
}

Sprawdzanie, czy cecha obsługuje atrybut

Niektóre urządzenia mogą obsługiwać cechę Matter, ale nie określony atrybut. Na przykład urządzenie Cloud-to-cloud, które zostało zmapowane na Matter, może nie obsługiwać wszystkich Matter atrybutów. Aby obsługiwać takie przypadki, użyj właściwości isSupported na poziomie cechy, aby sprawdzić, czy atrybut jest obsługiwany przez dane urządzenie.

Aby na przykład sprawdzić, czy urządzenie obsługuje atrybut cechy On/Off: onOff

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

Niektóre atrybuty mogą mieć wartość null w specyfikacji Matter lub w schemacie Cloud-to-cloud smart home. W przypadku tych atrybutów możesz określić, czy wartość nil zwrócona przez atrybut jest spowodowana tym, że urządzenie nie zgłasza tej wartości, czy też wartość atrybutu jest rzeczywiście równa nil. Aby to zrobić, użyj właściwości isNullable oprócz 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))"
      )
    }
  }
}

Aktualizowanie atrybutów cechy

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

To, czy wartość atrybutu można zmienić, zależy od 2 czynników:

  • Czy atrybut jest zapisywalny?
  • Czy wartość atrybutu może się zmienić jako efekt uboczny wysłania polecenia cechy?

Te informacje 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 mające wpływu na inne polecenia. Oznacza to, że wartość atrybutu nie zmienia się. Na przykład atrybut currentPosition SwitchTrait.

  • Tylko do odczytu i mające wpływ na inne polecenia. Oznacza to, że wartość atrybutu można zmienić tylko w wyniku wysłania polecenia. Na przykład atrybut currentLevel cechy LevelControlTrait jest tylko do odczytu, ale jego wartość można zmienić za pomocą poleceń takich jak moveToLevel.

  • Zapisywalne i nie mające wpływu na inne polecenia. Oznacza to, że możesz bezpośrednio zmienić wartość atrybutu za pomocą funkcji update cechy, ale nie ma poleceń, które wpłyną na wartość atrybutu. Na przykład atrybut WrongCodeEntryLimit DoorLockTrait.

  • Zapisywalne i mające wpływ na inne polecenia. Oznacza to, że możesz bezpośrednio zmienić wartość atrybutu za pomocą funkcji update cechy, a wartość atrybutu może się zmienić w wyniku wysłania polecenia. Na przykład atrybut occupiedCoolingSetpoint cechy ThermostatTrait można zapisać, ale też zaktualizować za pomocą polecenia setpointRaiseLower command.

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 przekaż jej funkcję aktualizacji, która ustawia nową wartość. Dobrym rozwiązaniem jest najpierw sprawdzenie, czy cecha obsługuje atrybut.

Na przykład:

if doorLockTraitTest.attributes.$wrongCodeEntryLimit.isSupported {
  let _ = try await doorLockTraitTest.update {
    $0.setWrongCodeEntryLimit(3)
  }
}