Guia de dispositivos de iluminação

Os dispositivos de iluminação usam atributos padrão de Matter para identificar luminárias, alternar estados de energia e ajustar os níveis de brilho.

O tipo de dispositivo de iluminação mais básico é o OnOffLight, implementado com as características OnOff e Identify e, opcionalmente, as características LevelControl e LightEffects.

Outros tipos de luz oferecem recursos adicionais e são implementados com características diferentes:

Tipo de dispositivo das APIs Home Características App de exemplo em Kotlin Caso de uso

Luz de temperatura da cor

ColorTemperatureLightDevice

home.matter.0000.types.010c

Um dispositivo de iluminação que é capaz de ser ligado ou desligado, com a intensidade da sua luz ajustada e a sua temperatura da cor ajustada.

Atributos obrigatórios
     matter Identify
     matter OnOff
     matter LevelControl
     matter ColorControl

Atributos opcionais
     google LightEffects
     google ExtendedColorControl

ligar e desligar, brilho
Claro

Luz com dimmer

DimmableLightDevice

home.matter.0000.types.0101

Um dispositivo de iluminação que pode ser ligado ou desligado, ter a intensidade da luz ajustada e ser acionado por um sensor de presença vinculado.

Atributos obrigatórios
     matter Identify
     matter OnOff
     matter LevelControl

Atributos opcionais
     google LightEffects

ligar e desligar, brilho
Claro

Luz colorida estendida

ExtendedColorLightDevice

home.matter.0000.types.010d

Um dispositivo de iluminação que pode ser ligado ou desligado, ter a intensidade da luz e a temperatura da cor ajustadas e ser acionado por um sensor de presença vinculado.

Atributos obrigatórios
     matter Identify
     matter OnOff
     matter LevelControl
     matter ColorControl

Atributos opcionais
     google LightEffects
     google ExtendedColorControl

ligar e desligar, brilho
Claro

Luz de ativação/desativação

OnOffLightDevice

home.matter.0000.types.0100

Um dispositivo de iluminação que pode ser ligado ou desligado.

Atributos obrigatórios
     matter Identify
     matter OnOff

Atributos opcionais
     matter LevelControl
     google LightEffects

ligar e desligar, brilho
Claro

Sempre verifique se o dispositivo é compatível com atributos e comandos antes de usar qualquer recurso ou tentar atualizar atributos. Consulte Controlar dispositivos no Android para mais informações.

Pré-requisitos

Antes de trabalhar com dispositivos e curvas de iluminação, verifique se o app inicializa o SDK do Home e inclui as importações necessárias:

import com.google.home.HomeDevice
import com.google.home.Structure
import com.google.home.google.DayOfWeek
import com.google.home.google.ExtendedColorControl
import com.google.home.google.ExtendedColorControlTrait
import com.google.home.google.LightingCurve
import com.google.home.google.LightingCurveTrait
import com.google.home.matter.standard.ColorControl
import com.google.home.matter.standard.ColorControlTrait
import com.google.home.matter.standard.ColorTemperatureLightDevice
import com.google.home.matter.standard.DimmableLightDevice
import com.google.home.matter.standard.ExtendedColorLightDevice
import com.google.home.matter.standard.GeneralDiagnostics
import com.google.home.matter.standard.Identify
import com.google.home.matter.standard.IdentifyTrait
import com.google.home.matter.standard.LevelControl
import com.google.home.matter.standard.LevelControlTrait
import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffLightDevice
import com.google.home.matter.standard.OnOffTrait
import com.google.home.matter.standard.RootNodeDevice
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull

Encontrar dispositivos de iluminação

Para encontrar dispositivos de iluminação em uma estrutura, filtre a lista de dispositivos por tipo, como OnOffLightDevice e DimmableLightDevice .

// Get all On/Off Light devices in the structure
val onOffLights: List<HomeDevice> =
  home.devices().list().filter { it.has(OnOffLightDevice) }

// Get all Dimmable Light devices in the structure
val dimmableLights: List<HomeDevice> =
  home.devices().list().filter { it.has(DimmableLightDevice) }

// Retrieve a specific device type instance to access its traits
val onOffLightDevice: OnOffLightDevice? =
  onOffLights.firstOrNull()?.type(OnOffLightDevice)?.firstOrNull()

val dimmableLightDevice: DimmableLightDevice? =
  dimmableLights.firstOrNull()?.type(DimmableLightDevice)?.firstOrNull()

Também é possível recuperar todos os dispositivos de iluminação de vários tipos em um único filtro:

// Get a list of devices with similar device types (lights)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }

Receber informações básicas sobre um dispositivo

   Implementado no app de exemplo para Android   

O atributo BasicInformation inclui informações como nome do fornecedor, ID do fornecedor, ID do produto, nome do produto (inclui informações do modelo) e versão do software de um dispositivo:

// Get device basic information. All general information traits are on the RootNodeDevice type.
    device.type(RootNodeDevice).first().standardTraits.basicInformation?.let { basicInformation ->
        println("vendorName ${basicInformation.vendorName}")
        println("vendorId ${basicInformation.vendorId}")
        println("productId ${basicInformation.productId}")
        println("productName ${basicInformation.productName}")
        println("softwareVersion ${basicInformation.softwareVersion}")
    }

Identificar um dispositivo de iluminação

Quando um ambiente tem várias luzes, você pode ajudar os usuários a localizar uma luminária física específica acionando um estado de identificação visual, como piscar a luz por alguns segundos. Todos os quatro tipos de dispositivo de iluminação exigem o atributo Identify.

Chame o comando identify com uma duração de identifyTime em segundos para iniciar o estado de identificação. Transmitir 0 interrompe o estado de identificação imediatamente. Também é possível chamar triggerEffect para executar um efeito visual específico, como Blink ou Breathe.

suspend fun identifyLight(lightDevice: DimmableLightDevice) {
  val identifyTrait = lightDevice.standardTraits.identify ?: return

  // Blink the light for 10 seconds so the user can locate it
  if (identifyTrait.supports(Identify.Command.Identify)) {
    identifyTrait.identify(identifyTime = 10u)
  }

  // Or trigger a specific visual identification effect
  if (identifyTrait.supports(Identify.Command.TriggerEffect)) {
    identifyTrait.triggerEffect(
      effectIdentifier = IdentifyTrait.EffectIdentifierEnum.Blink,
      effectVariant = IdentifyTrait.EffectVariantEnum.Default
    )
  }
}

Verificar a conectividade de um dispositivo de iluminação

A conectividade de um dispositivo é verificada no nível do tipo de dispositivo, porque alguns dispositivos são compatíveis com vários tipos. O estado retornado é uma combinação dos estados de conectividade de todos os atributos desse dispositivo.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

Um estado de partiallyOnline pode ser observado no caso de tipos de dispositivos mistos quando não há conectividade com a Internet. Os atributos padrão do Matter ainda podem estar on-line devido ao roteamento local, mas os atributos baseados na nuvem estarão off-line.

Encontrar o endereço IP do dispositivo

Para encontrar o endereço IP do dispositivo, use o atributo networkInterfaces do GeneralDiagnosticsTrait. Os endereços são retornados como objetos Data, que podem ser formatados como strings IPv4 ou IPv6 padrão usando o framework Network:

func getIpAddresses(trait: Matter.GeneralDiagnosticsTrait) -> [String] {
  let interfaces = trait.attributes.networkInterfaces ?? []
  var ipAddresses: [String] = []

  for interface in interfaces {
    for data in interface.iPv4Addresses {
      if let ipv4 = IPv4Address(data) {
        ipAddresses.append(String(describing: ipv4))
      }
    }
    for data in interface.iPv6Addresses {
      if let ipv6 = IPv6Address(data) {
        ipAddresses.append(String(describing: ipv6))
      }
    }
  }

  return ipAddresses
}

Controlar dispositivos de iluminação

Os tipos de dispositivo OnOffLight e DimmableLight usam atributos padrão Matter para identificar acessórios, alternar estados de energia e ajustar os níveis de brilho.

Acender ou apagar uma luz

Use o atributo OnOff para ler o estado de energia atual de um OnOffLight ou DimmableLight e para ligar ou desligar a luz.

Antes de ler o atributo onOff, verifique se o dispositivo é compatível com ele. Alguns dispositivos operam como endpoints somente de comando e não informam o estado.

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

Quando onOff é true, a luz está acesa. Quando onOff é false, a luz está apagada.

Para mudar o estado de energia da luz, verifique se o atributo é compatível com o comando pretendido e chame on(), off() ou 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")
}
// Calling a command on a trait.
try {
  onOffTrait.toggle()
} catch (e: HomeException) {
  // Code for handling the exception
}

Também é possível chamar on() e off() diretamente para definir um estado explícito:

onOffTrait.off()
onOffTrait.on()

Para desligar uma luz com uma transição visual gradual, chame offWithEffect() e especifique um valor EffectIdentifierEnum:

// Turn off the light using the DyingLight effect.
onOffTrait.offWithEffect(
  effectIdentifier = OnOffTrait.EffectIdentifierEnum.DyingLight,
  effectVariant = 0u,
)

Ajustar níveis de brilho

Um DimmableLight requer a característica LevelControl, e um OnOffLight pode oferecer suporte a ela. Use esse atributo para ler e controlar o nível de brilho de uma luz.

O atributo currentLevel informa o nível de brilho atual em uma escala de 0 a 254. Também é possível inspecionar minLevel e maxLevel para determinar o intervalo de brilho válido com suporte do hardware.

Para definir o brilho como um valor específico, chame moveToLevel(). Observe que moveToLevel() só muda o nível atual quando a luz já está acesa, a menos que você configure optionsOverride com executeIfOff. Para ligar automaticamente a luz ao definir um nível de brilho diferente de zero (ou desligá-la ao definir o nível como mínimo), use moveToLevelWithOnOff().

// Change the brightness of the light to 50%
levelControlTrait.moveToLevel(
  level = 127u.toUByte(),
  transitionTime = null,
  optionsMask = LevelControlTrait.OptionsBitmap(),
  optionsOverride = LevelControlTrait.OptionsBitmap(),
)

O exemplo a seguir lê o nível de brilho atual e usa moveToLevelWithOnOff() para definir uma luz regulável para 75% de brilho (190u) em uma transição de 1 segundo (10u décimos de segundo):

suspend fun setLightBrightness(lightDevice: DimmableLightDevice) {
  val levelControl = lightDevice.standardTraits.levelControl ?: return

  // Read the current brightness level (0 to 254)
  val currentLevel: UByte? = levelControl.currentLevel
  println("Current brightness level: $currentLevel")

  // Move to ~75% brightness (190 out of 254) and turn on the light if it is off
  if (levelControl.supports(LevelControl.Command.MoveToLevelWithOnOff)) {
    levelControl.moveToLevelWithOnOff(
      level = 190u,
      transitionTime = 10u,
      optionsMask = LevelControlTrait.OptionsBitmap(),
      optionsOverride = LevelControlTrait.OptionsBitmap()
    )
  }
}

Também é possível aumentar ou diminuir o brilho em relação ao nível atual chamando stepWithOnOff() com StepModeEnum.Up ou StepModeEnum.Down e um stepSize.

Cor do controle

O atributo ColorControl está disponível no ColorTemperatureLightDevice e no ExtendedColorLightDevice.

Esse atributo permite ajustar a temperatura da cor em graus microrecíprocos ou mireds.

val colorControlTrait =
  colorTempLightDevice.standardTraits.colorControl ?: return
// Read the current color temperature and hardware limits in mireds
// (Mireds = 1,000,000 / Kelvin; e.g., 370 mireds ≈ 2700K warm white, 250 mireds = 4000K cool white)
val currentMireds = colorControlTrait.colorTemperatureMireds
val minMireds = colorControlTrait.colorTempPhysicalMinMireds ?: 153u // ~6500K (coolest)
val maxMireds = colorControlTrait.colorTempPhysicalMaxMireds ?: 500u // 2000K (warmest)
// Clamp target (370 mireds ≈ 2700K) to the device's physical bounds
val targetMireds = 370u.toUShort().coerceIn(minMireds, maxMireds)
if (
  colorControlTrait.supports(
    ColorControl.Command.MoveToColorTemperature
  )
) {
  colorControlTrait.moveToColorTemperature(
    colorTemperatureMireds = targetMireds,
    transitionTime = 20u, // 2.0 seconds (in 0.1s units)
    optionsMask = ColorControlTrait.OptionsBitmap(),
    optionsOverride = ColorControlTrait.OptionsBitmap()
  )
}

Também é possível definir a cor usando coordenadas de cromaticidade CIE 1931 e valores de matiz e saturação de 16 bits.

val colorControlTrait =
  extendedColorLightDevice.standardTraits.colorControl ?: return
// 1. Move to CIE 1931 xy chromaticity coordinates (scaled 0..65279)
// Example: x = 0.3127 (20493), y = 0.3290 (21561) for D65 white point
if (colorControlTrait.supports(ColorControl.Command.MoveToColor)) {
  colorControlTrait.moveToColor(
    colorX = 20493u,
    colorY = 21561u,
    transitionTime = 10u, // 1.0 second (in 0.1s units)
    optionsMask = ColorControlTrait.OptionsBitmap(),
    optionsOverride = ColorControlTrait.OptionsBitmap()
  )
}
val currentX = colorControlTrait.currentX
val currentY = colorControlTrait.currentY
// 2. Move to 16-bit Enhanced Hue (0..65534) and 8-bit Saturation (0..254)
if (
  colorControlTrait.supports(
    ColorControl.Command.EnhancedMoveToHueAndSaturation
  )
) {
  colorControlTrait.enhancedMoveToHueAndSaturation(
    enhancedHue = 43690u, // ~240° (Blue) on the 0..65534 scale
    saturation = 254u,    // Full saturation
    transitionTime = 15u, // 1.5 seconds (in 0.1s units)
    optionsMask = ColorControlTrait.OptionsBitmap(),
    optionsOverride = ColorControlTrait.OptionsBitmap()
  )
}
// 3. Start a hardware color loop across the device's hue range
if (colorControlTrait.supports(ColorControl.Command.ColorLoopSet)) {
  colorControlTrait.colorLoopSet(
    updateFlags =
      ColorControlTrait.UpdateFlagsBitmap(
        updateAction = true,
        updateDirection = true,
        updateTime = true,
        updateStartHue = true
      ),
    action =
      ColorControlTrait.ColorLoopActionEnum
        .ActivateFromColorLoopStartEnhancedHue,
    direction = ColorControlTrait.ColorLoopDirectionEnum.Increment,
    time = 30u, // 30 seconds per full cycle
    startHue = 0u,
    optionsMask = ColorControlTrait.OptionsBitmap(),
    optionsOverride = ColorControlTrait.OptionsBitmap()
  )
}

ExtendedColorControl é um atributo opcional do Google em ExtendedColorLightDevice que simplifica o controle de cores ao aceitar nomes de cores, valores RGB ou valores HSV de usar pontos flutuantes unificados que combinam cor e brilho em uma única unidade.

val extendedColorControlTrait =
  extendedColorLightDevice.googleTraits.extendedColorControl ?: return
// 1. Set color by name
if (
  extendedColorControlTrait.supports(
    ExtendedColorControl.Command.MoveToColorName
  )
) {
  extendedColorControlTrait.moveToColorName(colorName = "Lavender")
}
val currentColorName = extendedColorControlTrait.currentName
// 2. Set color using 8-bit RGB values (0..255 per channel)
// Automatically coordinates brightness (LevelControl) and color (ColorControl)
if (
  extendedColorControlTrait.supports(
    ExtendedColorControl.Command.MoveToColorRgb
  )
) {
  extendedColorControlTrait.moveToColorRgb(
    red = 255u,
    green = 128u,
    blue = 0u
  )
}
val currentRed = extendedColorControlTrait.currentRed
val currentGreen = extendedColorControlTrait.currentGreen
val currentBlue = extendedColorControlTrait.currentBlue
// 3. Set color and brightness together using floating-point HSV
// hue: 0.0f..360.0f, saturation: 0.0f..1.0f, value (brightness): 0.0f..1.0f
if (
  extendedColorControlTrait.supports(
    ExtendedColorControl.Command.MoveToColorHsv
  )
) {
  extendedColorControlTrait.moveToColorHsv(
    hue = 210.0f,
    saturation = 0.85f,
    value = 0.75f
  )
}
val currentHue = extendedColorControlTrait.currentHue
val currentSaturation = extendedColorControlTrait.currentSaturation
val currentValue = extendedColorControlTrait.currentValue

Gerenciar curvas de iluminação

Uma curva de iluminação define uma programação automatizada que faz a transição suave do brilho e da temperatura da cor opcional das luzes de destino ao longo do dia. Por exemplo, uma curva de iluminação pode aumentar gradualmente o brilho das luzes pela manhã e diminuí-lo para um tom mais quente à noite. Os tipos de dispositivos de iluminação que só aceitam brilho, como a luz regulável, seguem a curva de brilho e ignoram a temperatura da cor.

A característica LightingCurve é uma característica de estrutura do Google Home platform. Você o acessa em uma instância Structure, em vez de um dispositivo de iluminação individual.

Cada programação no atributo é representada por um LightingCurveSetting, que combina um settingId exclusivo com um LightingCurveConfig. A tabela a seguir descreve os campos de configuração de LightingCurveConfig:

Campo Descrição
curvePointsList Uma sequência de pelo menos dois itens CurvePoint com horários distintos. Cada ponto especifica um time (CurveTimeOfDay com hours de 0 a 23 e minutes de 0 a 59), um brightnessPercent (0 a 100) e um colorTemperature opcional em Kelvin. Se colorTemperature for especificado para qualquer ponto, ele precisará ser um valor positivo para todos os pontos.
roomId O ID do ambiente de destino (por exemplo, room@{uuid}). Aplica a curva de iluminação às luzes compatíveis com ajuste de intensidade e temperatura da cor nesse ambiente. Especifique roomId ou devices.
devices Um objeto TargetDevices que contém uma lista de entradas TargetDevice, cada uma com um id e um ID de type do dispositivo (como home.matter.0000.types.0101 para DimmableLight ou home.matter.0000.types.010c para ColorTemperatureLight). Especifique devices ou roomId.
daysOfWeekList Os dias da semana em que a curva de iluminação é executada (DayOfWeek). Se a lista estiver vazia, a curva de iluminação será executada diariamente.
adaptive Booleano opcional que indica se a curva de iluminação é adaptável, ou seja, se uma luz de destino retoma o nível da curva ativa quando é ligada durante o período de agendamento de horários. Quando o recurso false está ativado, uma mudança manual em uma luz a desativa da curva de iluminação pelo resto do dia. Quando true, uma luz que é desligada e ligada novamente durante o período de agendamento de horários é reativada com a curva de iluminação, fazendo com que ela se ajuste ao brilho e à Temperatura da cor atuais da curva e siga a curva a partir daí.
enabled Booleano opcional que indica se a configuração da curva de iluminação está ativa. O padrão é true ao criar uma nova configuração. Quando enabled é omitido de um comando de atualização, o estado de enabled não muda.

Ler as configurações da curva de iluminação

Para inspecionar as curvas de iluminação configuradas para uma estrutura, recupere o atributo LightingCurve do Structure e leia o atributo lightingCurveSettingsList.

suspend fun readLightingCurves(structure: Structure) {
  val lightingCurve = structure.trait(LightingCurve).firstOrNull() ?: return

  for (setting in lightingCurve.lightingCurveSettingsList) {
    val settingId = setting.settingId
    val config = setting.config
    println("Setting ID: $settingId, enabled: ${config?.enabled}")
    config?.curvePointsList?.forEach { point ->
      println(
        "  Time: ${point.time?.hours}:${point.time?.minutes}, " +
          "Brightness: ${point.brightnessPercent}%, " +
          "ColorTemp: ${point.colorTemperature}K"
      )
    }
  }
}

Criar uma configuração de curva de iluminação

Para criar uma nova programação de curva de iluminação em uma estrutura, construa um LightingCurveConfig com pelo menos duas entradas CurvePoint, luzes de destino (especificadas por roomId ou devices) e os dias ativos da semana. Em seguida, transmita a configuração para createLightingCurveSetting(). O comando retorna o settingId exclusivo atribuído à nova configuração de curva de iluminação.

O exemplo a seguir cria uma curva de iluminação de dia útil para um ambiente. Ela aumenta de 30% de brilho em uma temperatura quente de 2.700 K às 7h para 80% em uma temperatura mais fria de 4.000 K às 9h. Depois, diminui para 20% em uma temperatura muito quente de 2.200 K às 21h:

suspend fun createRoomLightingCurve(
  structure: Structure,
  targetRoomId: String
): String? {
  val lightingCurve = structure.trait(LightingCurve).firstOrNull() ?: return null

  val curvePoints = listOf(
    LightingCurveTrait.CurvePoint(
      time = LightingCurveTrait.CurveTimeOfDay(hours = 7, minutes = 0),
      brightnessPercent = 30,
      colorTemperature = 2700
    ),
    LightingCurveTrait.CurvePoint(
      time = LightingCurveTrait.CurveTimeOfDay(hours = 9, minutes = 0),
      brightnessPercent = 80,
      colorTemperature = 4000
    ),
    LightingCurveTrait.CurvePoint(
      time = LightingCurveTrait.CurveTimeOfDay(hours = 21, minutes = 0),
      brightnessPercent = 20,
      colorTemperature = 2200
    )
  )

  val config = LightingCurveTrait.LightingCurveConfig(
    curvePointsList = curvePoints,
    roomId = targetRoomId,
    daysOfWeekList = listOf(
      DayOfWeek.MONDAY,
      DayOfWeek.TUESDAY,
      DayOfWeek.WEDNESDAY,
      DayOfWeek.THURSDAY,
      DayOfWeek.FRIDAY
    ),
    adaptive = true,
    enabled = true
  )

  // Returns the newly created settingId
  return lightingCurve.createLightingCurveSetting(config = config)
}

Para segmentar dispositivos de iluminação específicos em vez de um ambiente inteiro, forneça o parâmetro devices usando LightingCurveTrait.TargetDevices:

val targetDevices = LightingCurveTrait.TargetDevices(
  devicesList = listOf(
    LightingCurveTrait.TargetDevice(
      id = dimmableLight.id.id,
      type = DimmableLightDevice.TYPE_ID
    )
  )
)

val deviceCurveConfig = LightingCurveTrait.LightingCurveConfig(
  curvePointsList = curvePoints,
  devices = targetDevices,
  daysOfWeekList = listOf(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY),
  adaptive = true,
  enabled = true
)

val settingId = lightingCurve.createLightingCurveSetting(
  config = deviceCurveConfig
)

Atualizar uma configuração de curva de iluminação

Para modificar uma curva de iluminação, como mudar os pontos da curva, atualizar os dias ativos da semana ou ativar e desativar a programação, chame updateLightingCurveSetting() com o settingId de destino e um LightingCurveConfig atualizado.

suspend fun updateLightingCurve(
  structure: Structure,
  settingId: String,
  updatedConfig: LightingCurveTrait.LightingCurveConfig
) {
  val lightingCurve = structure.trait(LightingCurve).firstOrNull() ?: return

  lightingCurve.updateLightingCurveSetting(
    settingId = settingId,
    config = updatedConfig
  )
}

Excluir uma configuração de curva de iluminação

Para remover uma configuração de curva de iluminação de uma estrutura, chame deleteLightingCurveSetting() com o settingId da configuração que você quer excluir.

suspend fun deleteLightingCurve(
  structure: Structure,
  settingId: String
) {
  val lightingCurve = structure.trait(LightingCurve).firstOrNull() ?: return

  lightingCurve.deleteLightingCurveSetting(settingId = settingId)
}