Controlar dispositivos no iOS

Este guia é uma continuação de Acessar dispositivos e metadados de dispositivos no iOS e apresenta outros exemplos de controle e acesso a dispositivos.

Para usar tipos ou características de dispositivos específicos, como o Matter OnOffTrait usado em muitos dos exemplos aqui, eles precisam ser importados:

import GoogleHomeSDK
import GoogleHomeTypes

Verificar se uma característica oferece suporte a um comando

Use a função supports no nível da característica para verificar se um comando é compatível com um dispositivo específico.

Por exemplo, para verificar o suporte de um dispositivo ao comando da característica "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")
}

Enviar um comando para um dispositivo

O envio de um comando é semelhante à leitura de um atributo de estado de uma característica. Para ativar ou desativar o dispositivo, use o OnOffTrait comando "Toggle", que é definido no modelo de dados do ecossistema do Google Home como toggle(). Esse método muda onOff para false se for true, ou para true se for false:

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

Os comandos podem retornar uma exceção se um problema for detectado no fluxo de execução. Como desenvolvedor, você precisa usar um bloco do-catch para processar essas exceções corretamente e mostrar informações detalhadas aos usuários em casos em que os erros são acionáveis. Exceções não processadas vão interromper o tempo de execução do app e podem resultar em falhas.

Como alternativa, use os comandos off() ou on() para definir o estado explicitamente:

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

Depois de enviar um comando para mudar o estado, quando ele for concluído, você poderá ler o estado conforme descrito em Ler o estado de um dispositivo para processá-lo no app.

Enviar um comando com parâmetros

Alguns comandos podem usar parâmetros, como os de OnOffTrait ou 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
}

Verificar se uma característica oferece suporte a um atributo

Alguns dispositivos podem oferecer suporte a uma Matter característica, mas não a um atributo específico. Por exemplo, um dispositivo Cloud-to-cloud que foi mapeado para Matter pode não oferecer suporte a todos os atributos Matter. Para processar casos como esses, use a propriedade isSupported no nível da característica para verificar se o atributo é compatível com um dispositivo específico.

Por exemplo, para verificar o suporte de um dispositivo ao atributo da característica "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!")
}

Alguns atributos podem ser anuláveis na especificação Matter ou no esquema Cloud-to-cloud smart home. Para esses atributos, você pode determinar se um nil retornado pelo atributo é devido ao dispositivo não informar esse valor ou se o valor do atributo é realmente nil, usando isNullable além de 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))"
      )
    }
  }
}

Atualizar atributos de características

Se você quiser mudar o valor de um determinado atributo e nenhum dos comandos da característica fizer isso, o atributo poderá oferecer suporte à definição explícita do valor.

Se o valor de um atributo pode ser alterado, isso depende de dois fatores:

  • O atributo é gravável?
  • O valor do atributo pode mudar como um efeito colateral do envio de um comando de característica?

A documentação de referência para características e atributos fornece essas informações.

Portanto, as combinações de propriedades que ditam como o valor de um atributo pode ser alterado são:

  • Somente leitura e não afetado por outros comandos. Isso significa que o valor do atributo não muda. Por exemplo, o currentPosition atributo do SwitchTrait.

  • Somente leitura e afetado por outros comandos. Isso significa que a única maneira de o valor do atributo mudar é como resultado do envio de um comando. Por exemplo, o currentLevel atributo do LevelControlTrait é somente leitura, mas o valor dele pode ser alterado por comandos como moveToLevel.

  • Gravável e não afetado por outros comandos. Isso significa que você pode mudar diretamente o valor do atributo usando a função update da característica, mas não há comandos que afetem o valor do atributo. Por exemplo, o WrongCodeEntryLimit atributo do DoorLockTrait.

  • Gravável e afetado por outros comandos. Isso significa que você pode mudar diretamente o valor do atributo usando a função update da característica, e o valor do atributo pode mudar como resultado do envio de um comando. Por exemplo, o occupiedCoolingSetpoint atributo do ThermostatTrait pode ser gravado, mas também atualizado com o setpointRaiseLower comando.

Exemplo de como usar a função de atualização para mudar o valor de um atributo

Este exemplo mostra como definir explicitamente o valor do DoorLockTrait.wrongCodeEntryLimit atributo.

Para definir um valor de atributo, chame a função updateda característica e transmita uma função de atualização que defina o novo valor. É recomendável primeiro verificar se a característica oferece suporte a um atributo.

Por exemplo:

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