Controllare i dispositivi su iOS

Questa guida prosegue da Accedere ai dispositivi e ai metadati dei dispositivi su iOS e presenta ulteriori esempi di controllo e accesso ai dispositivi.

Per utilizzare tipi o tratti di dispositivi specifici, come Matter OnOffTrait utilizzato in molti degli esempi riportati di seguito, è necessario importarli:

import GoogleHomeSDK
import GoogleHomeTypes

Verificare se un tratto supporta un comando

Utilizza la funzione supports a livello di tratto per verificare se un comando è supportato per un determinato dispositivo.

Ad esempio, per verificare se un dispositivo supporta il comando toggle del tratto On/Off:

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

Invio di un comando a un dispositivo

L'invio di un comando è simile alla lettura di un attributo stato da un tratto. Per accendere o spegnere il dispositivo, utilizza il comando di attivazione/disattivazione OnOffTrait, definito nel modello di dati dell'ecosistema Google Home come toggle(). Questo metodo cambia onOff in false se è true o in true se è false:

// Calling a command on a trait.
do {
  try await onOffTraitTest.toggle()
} catch let error as HomeError {
  // Code for handling the exception
}

I comandi potrebbero restituire un'eccezione se viene rilevato un problema con il flusso di esecuzione. In qualità di sviluppatore, devi utilizzare un blocco do-catch per gestire correttamente queste eccezioni e mostrare agli utenti informazioni dettagliate nei casi in cui gli errori sono risolvibili. Le eccezioni non gestite interrompono il runtime dell'app e possono causare arresti anomali dell'app.

In alternativa, utilizza i comandi off() o on() per impostare in modo esplicito lo stato:

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

Dopo aver inviato un comando per modificare lo stato, al termine puoi leggere lo stato come descritto in Leggere lo stato di un dispositivo per gestirlo nella tua app.

Inviare un comando con parametri

Alcuni comandi possono utilizzare parametri, come quelli su OnOffTrait o LevelControlTrait:

offWithEffect

// Turn off the light using the DyingLight effect.
do {
  try await onOffTraitTest.offWithEffect(
    effectIdentifier: Matter.OnOffTrait.EffectIdentifierEnum.dyingLight,
    effectVariant: 0
  )
} catch let error 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 error as HomeError {
  // Code for handling the exception
}

Controllare se un tratto supporta un attributo

Alcuni dispositivi potrebbero supportare una caratteristica Matter, ma non un attributo specifico. Ad esempio, un dispositivo Cloud-to-cloud mappato a Matter potrebbe non supportare tutti gli attributi Matter. Per gestire casi come questi, utilizza la proprietà isSupported a livello di tratto per verificare se l'attributo è supportato per un determinato dispositivo.

Ad esempio, per verificare se un dispositivo supporta l'attributo onOff del tratto On/Off:

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

Alcuni attributi sono nullable nella specifica Matter o nello schema Cloud-to-cloud smart home. Per questi attributi, puoi determinare se un valore nil restituito dall'attributo è dovuto al fatto che il dispositivo non lo segnali o se il valore dell'attributo è effettivamente nil utilizzando isNullable oltre a 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 \(onOffTrait.attributes.startUpOnOff)"
      )
    }
  }
}

Aggiorna gli attributi dei tratti

Se vuoi modificare il valore di un determinato attributo e nessuno dei comandi del tratto lo fa, l'attributo potrebbe supportare l'impostazione esplicita del valore.

La possibilità di modificare il valore di un attributo dipende da due fattori:

  • L'attributo è scrivibile?
  • Il valore dell'attributo può cambiare come effetto collaterale dell'invio di un comando trait?

La documentazione di riferimento per le caratteristiche e i relativi attributi fornisce queste informazioni.

Pertanto, le combinazioni di proprietà che determinano in che modo il valore di un attributo può essere modificato sono:

  • Di sola lettura e non interessate da altri comandi. Ciò significa che il valore dell'attributo non cambia. Ad esempio, l'attributo currentPosition del tag SwitchTrait.

  • Di sola lettura e interessato da altri comandi. Ciò significa che l'unico modo in cui il valore dell'attributo può cambiare è a seguito dell'invio di un comando. Ad esempio, l'attributo currentLevel di LevelControlTrait è di sola lettura, ma il suo valore può essere modificato da comandi come moveToLevel.

  • Scrivibili e non interessati da altri comandi. Ciò significa che puoi modificare direttamente il valore dell'attributo utilizzando la funzione update del tratto, ma non esistono comandi che influiscano sul valore dell'attributo. Ad esempio, l'attributo WrongCodeEntryLimit del tag DoorLockTrait.

  • Scrivibili e influenziati da altri comandi. Ciò significa che puoi cambiare direttamente il valore dell'attributo utilizzando la funzione update del tratto e il valore dell'attributo può cambiare in seguito all'invio di un comando. Ad esempio, l'attributo occupiedCoolingSetpoint di ThermostatTrait può essere scritto, ma anche aggiornato con il comando setpointRaiseLower.

Esempio di utilizzo della funzione di aggiornamento per modificare il valore di un attributo

Questo esempio mostra come impostare esplicitamente il valore dell'attributo DoorLockTrait.wrongCodeEntryLimit.

Per impostare un valore dell'attributo, chiama la funzione update del tratto e passa una funzione di aggiornamento che imposta il nuovo valore. È buona prassi prima verificare che la caratteristica supporti un attributo.

Ad esempio:

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