Guía de dispositivos de iluminación

Los dispositivos de iluminación usan los atributos estándar de Matter para identificar las lámparas, activar o desactivar los estados de encendido y ajustar los niveles de brillo.

El tipo de dispositivo de luz más básico es OnOffLightDeviceType, que se implementa con los atributos OnOffTrait y IdentifyTrait, y, de manera opcional, admite los atributos LevelControlTrait y LightEffectsTrait.

Otros tipos de luces ofrecen capacidades adicionales y se implementan con diferentes rasgos:

Tipo de dispositivo de las APIs de Home Rasgos App de ejemplo de Swift Caso de uso

Luz de temperatura de color

ColorTemperatureLightDeviceType

home.matter.0000.types.010c

Un dispositivo de iluminación que se puede encender o apagar, y cuya intensidad de luz y temperatura de color se pueden ajustar.

Atributos obligatorios
     matter IdentifyTrait
     matter OnOffTrait
     matter LevelControlTrait
     matter ColorControlTrait

Atributos opcionales
     google LightEffectsTrait
     google ExtendedColorControlTrait
Ligera

Luz regulable

DimmableLightDeviceType

home.matter.0000.types.0101

Es un dispositivo de iluminación que se puede encender o apagar, cuya intensidad de luz se puede ajustar y que se puede encender o apagar a través de un sensor de ocupación vinculado.

Atributos obligatorios
     matter IdentifyTrait
     matter OnOffTrait
     matter LevelControlTrait

Atributos opcionales
     google LightEffectsTrait
Ligera

Luz de color extendida

ExtendedColorLightDeviceType

home.matter.0000.types.010d

Es un dispositivo de iluminación que se puede encender o apagar, cuya intensidad de luz y temperatura de color se pueden ajustar, y que se puede encender o apagar a través de un sensor de ocupación vinculado.

Atributos obligatorios
     matter IdentifyTrait
     matter OnOffTrait
     matter LevelControlTrait
     matter ColorControlTrait

Atributos opcionales
     google LightEffectsTrait
     google ExtendedColorControlTrait
Ligera

Luz de encendido/apagado

OnOffLightDeviceType

home.matter.0000.types.0100

Un dispositivo de iluminación que se puede encender o apagar.

Atributos obligatorios
     matter IdentifyTrait
     matter OnOffTrait

Atributos opcionales
     matter LevelControlTrait
     google LightEffectsTrait
Ligera

Siempre verifica la compatibilidad de atributos y comandos de un dispositivo antes de usar cualquier función o intentar actualizar los atributos. Consulta Controla dispositivos en iOS para obtener más información.

Requisitos previos

Antes de trabajar con dispositivos y curvas de iluminación, asegúrate de que tu app inicialice el SDK de Home y de que incluya las importaciones requeridas:

import Foundation
import GoogleHomeSDK
import GoogleHomeTypes
import Network

Buscar dispositivos de iluminación

Para encontrar dispositivos de iluminación en una estructura, filtra la lista de dispositivos por tipo, como OnOffLightDeviceType y DimmableLightDeviceType.

let allDevices = try await home.devices().list()

// Get all On/Off Light devices in the structure
let onOffLights = allDevices.filter {
  $0.types.contains(OnOffLightDeviceType.self)
}

// Get all Dimmable Light devices in the structure
let dimmableLights = allDevices.filter {
  $0.types.contains(DimmableLightDeviceType.self)
}

// Retrieve a specific device type instance to access its traits
let onOffLightDeviceType =
  await onOffLights.first?.types.get(OnOffLightDeviceType.self)

let dimmableLightDeviceType =
  await dimmableLights.first?.types.get(DimmableLightDeviceType.self)

También puedes recuperar todos los dispositivos de iluminación de varios tipos de dispositivos de iluminación en un solo filtro:

// Get a list of devices with similar device types (lights)
let lightDevices =
  try await self.home.devices().list().compactMap {
    $0.types.contains(DimmableLightDeviceType.self)
      || $0.types.contains(OnOffLightDeviceType.self)
      || $0.types.contains(ColorTemperatureLightDeviceType.self)
      || $0.types.contains(ExtendedColorLightDeviceType.self)
  }

Obtén información básica sobre un dispositivo

   Implementado en la app de ejemplo para iOS   

El atributo BasicInformation incluye información como el nombre del proveedor, el ID del proveedor, el ID del producto, el nombre del producto (incluye información del modelo) y la versión de software de un dispositivo:

let vendorName = basicInfoTrait.attributes.vendorName!
let vendorID = basicInfoTrait.attributes.vendorID!
let productID = basicInfoTrait.attributes.productID!
let productName = basicInfoTrait.attributes.productName!
let softwareVersion = basicInfoTrait.attributes.softwareVersion!

Identifica un dispositivo de iluminación

Cuando una habitación contiene varias luces, puedes ayudar a los usuarios a ubicar una lámpara física específica activando un estado de identificación visual, como hacer parpadear la luz durante unos segundos. Los cuatro tipos de dispositivos de iluminación requieren el atributo Matter.IdentifyTrait.

Llama al comando identify con una duración de identifyTime en segundos para iniciar el estado de identificación. Si pasas 0, se detiene el estado de identificación de inmediato. También puedes llamar a triggerEffect para ejecutar un efecto visual específico, como Blink o Breathe.

func identifyLight(lightDeviceType: DimmableLightDeviceType) async throws {
  guard let identifyTrait = lightDeviceType.matterTraits.identifyTrait else {
    return
  }

  // Blink the light for 10 seconds so the user can locate it
  if identifyTrait.supportsIdentifyCommand {
    try await identifyTrait.identify(identifyTime: 10)
  }

  // Or trigger a specific visual identification effect
  if identifyTrait.supportsTriggerEffectCommand {
    try await identifyTrait.triggerEffect(
      effectIdentifier: .blink,
      effectVariant: .default
    )
  }
}

Verifica la conectividad de un dispositivo de iluminación

La conectividad de un dispositivo se verifica a nivel del tipo de dispositivo, ya que algunos dispositivos admiten varios tipos. El estado que se devuelve es una combinación de los estados de conectividad de todos los rasgos de ese dispositivo.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

Se puede observar un estado de partiallyOnline en el caso de tipos de dispositivos mixtos cuando no hay conectividad a Internet. Es posible que los atributos estándar de Matter sigan en línea debido al enrutamiento local, pero los atributos basados en la nube estarán sin conexión.

Obtén la dirección IP del dispositivo

Para encontrar la dirección IP del dispositivo, usa el atributo networkInterfaces de GeneralDiagnosticsTrait. Las direcciones se devuelven como objetos Data, a los que puedes dar formato de strings IPv4 o IPv6 estándar con el 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
}

Cómo controlar dispositivos de iluminación

Los tipos de dispositivos OnOffLight y DimmableLight usan rasgos estándar de Matter para identificar artefactos, activar o desactivar estados de energía y ajustar los niveles de brillo.

Encender o apagar una luz

Usa el atributo OnOffTrait para leer el estado de alimentación actual de un OnOffLight o DimmableLight, y para encender o apagar la luz.

Antes de leer el atributo onOff, verifica que el dispositivo lo admita. Algunos dispositivos funcionan como extremos de solo comando y no informan el estado.

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

Cuando onOff es true, la luz está encendida. Cuando onOff es false, la luz está apagada.

Para cambiar el estado de encendido de la luz, verifica que el rasgo admita el comando previsto y, luego, llama a on(), off() o 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")
}
// Calling a command on a trait.
do {
  try await onOffTraitTest.toggle()
} catch let _ as HomeError {
  // Code for handling the exception
}

También puedes llamar a on() y off() directamente para establecer un estado explícito:

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

Para apagar una luz con una transición visual gradual, llama a offWithEffect() y especifica un valor de EffectIdentifierEnum:

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

Ajustar los niveles de brillo

Un DimmableLight requiere el atributo LevelControlTrait, y un OnOffLight puede admitirlo de manera opcional. Usa este atributo para leer y controlar el nivel de brillo de una luz.

El atributo currentLevel informa el nivel de brillo actual en una escala de 0 a 254. También puedes inspeccionar minLevel y maxLevel para determinar el rango de brillo válido que admite el hardware.

Para establecer el brillo en un valor específico, llama a moveToLevel(). Ten en cuenta que moveToLevel() solo cambia el nivel actual cuando la luz ya está encendida, a menos que configures optionsOverride con executeIfOff. Para encender la luz automáticamente cuando se establece un nivel de brillo distinto de cero (o apagarla cuando se establece el nivel mínimo), usa moveToLevelWithOnOff().

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

En el siguiente ejemplo, se lee el nivel de brillo actual y se usa moveToLevelWithOnOff() para establecer una luz regulable en un 75% de brillo (190) durante una transición de 1 segundo (10 décimas de segundo):

func setLightBrightness(lightDeviceType: DimmableLightDeviceType) async throws {
  guard let levelControl = lightDeviceType.matterTraits.levelControlTrait else {
    return
  }

  // Read the current brightness level (0 to 254)
  let currentLevel: UInt8? = levelControl.attributes.currentLevel
  print("Current brightness level: \(String(describing: currentLevel))")

  // Move to ~75% brightness (190 out of 254) and turn on the light if it is off
  if levelControl.supportsMoveToLevelWithOnOffCommand {
    try await levelControl.moveToLevelWithOnOff(
      level: UInt8(190),
      transitionTime: 10,
      optionsMask: Matter.LevelControlTrait.OptionsBitmap(),
      optionsOverride: Matter.LevelControlTrait.OptionsBitmap()
    )
  }
}

También puedes aumentar o disminuir el brillo en relación con el nivel actual llamando a stepWithOnOff() con .up o .down y un stepSize.

Controla el color

El atributo ColorControlTrait está disponible en ColorTemperatureLightDeviceType y ExtendedColorLightDeviceType.

Este atributo te permite ajustar la temperatura de color en grados microrecíprocos o mireds.

guard let colorControlTrait =
  colorTempLightDeviceType.matterTraits.colorControlTrait
else {
  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)
let currentMireds = colorControlTrait.attributes.colorTemperatureMireds
let minMireds = colorControlTrait.attributes.colorTempPhysicalMinMireds ?? 153
let maxMireds = colorControlTrait.attributes.colorTempPhysicalMaxMireds ?? 500
// Clamp target (370 mireds ≈ 2700K) to the device's physical bounds
let targetMireds = min(max(UInt16(370), minMireds), maxMireds)
if colorControlTrait.supportsMoveToColorTemperatureCommand {
  try await colorControlTrait.moveToColorTemperature(
    colorTemperatureMireds: targetMireds,
    transitionTime: 20, // 2.0 seconds (in 0.1s units)
    optionsMask: Matter.ColorControlTrait.OptionsBitmap(),
    optionsOverride: Matter.ColorControlTrait.OptionsBitmap()
  )
}

También puedes establecer el color con las coordenadas de cromaticidad CIE 1931 y los valores de tono y saturación de 16 bits.

guard let colorControlTrait =
  extendedColorLightDeviceType.matterTraits.colorControlTrait
else {
  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.supportsMoveToColorCommand {
  try await colorControlTrait.moveToColor(
    colorX: 20493,
    colorY: 21561,
    transitionTime: 10, // 1.0 second (in 0.1s units)
    optionsMask: Matter.ColorControlTrait.OptionsBitmap(),
    optionsOverride: Matter.ColorControlTrait.OptionsBitmap()
  )
}
let currentX = colorControlTrait.attributes.currentX
let currentY = colorControlTrait.attributes.currentY
// 2. Move to 16-bit Enhanced Hue (0..65534) and 8-bit Saturation (0..254)
if colorControlTrait.supportsEnhancedMoveToHueAndSaturationCommand {
  try await colorControlTrait.enhancedMoveToHueAndSaturation(
    enhancedHue: 43690, // ~240° (Blue) on the 0..65534 scale
    saturation: 254,    // Full saturation
    transitionTime: 15, // 1.5 seconds (in 0.1s units)
    optionsMask: Matter.ColorControlTrait.OptionsBitmap(),
    optionsOverride: Matter.ColorControlTrait.OptionsBitmap()
  )
}
// 3. Start a hardware color loop across the device's hue range
if colorControlTrait.supportsColorLoopSetCommand {
  try await colorControlTrait.colorLoopSet(
    updateFlags: [
      .updateAction,
      .updateDirection,
      .updateTime,
      .updateStartHue
    ],
    action: .activateFromColorLoopStartEnhancedHue,
    direction: .increment,
    time: 30, // 30 seconds per full cycle
    startHue: 0,
    optionsMask: Matter.ColorControlTrait.OptionsBitmap(),
    optionsOverride: Matter.ColorControlTrait.OptionsBitmap()
  )
}

Google.ExtendedColorControlTrait es un atributo opcional de Google en ExtendedColorLightDevice que simplifica el control de color, ya que acepta nombres de colores, valores RGB o valores HSV unificados de punto flotante que combinan el color y el brillo en una sola unidad.

guard let extendedColorControlTrait =
  extendedColorLightDeviceType.googleTraits.extendedColorControlTrait
else {
  return
}
// 1. Set color by name
if extendedColorControlTrait.supportsMoveToColorNameCommand {
  try await extendedColorControlTrait.moveToColorName(colorName: "Lavender")
}
let currentColorName = extendedColorControlTrait.attributes.currentName
// 2. Set color using 8-bit RGB values (0..255 per channel)
// Automatically coordinates brightness (LevelControl) and color (ColorControl)
if extendedColorControlTrait.supportsMoveToColorRGBCommand {
  try await extendedColorControlTrait.moveToColorRGB(
    red: 255,
    green: 128,
    blue: 0
  )
}
let currentRed = extendedColorControlTrait.attributes.currentRed
let currentGreen = extendedColorControlTrait.attributes.currentGreen
let currentBlue = extendedColorControlTrait.attributes.currentBlue
// 3. Set color and brightness together using floating-point HSV
// hue: 0.0...360.0, saturation: 0.0...1.0, value (brightness): 0.0...1.0
if extendedColorControlTrait.supportsMoveToColorHSVCommand {
  try await extendedColorControlTrait.moveToColorHSV(
    hue: 210.0,
    saturation: 0.85,
    value: 0.75
  )
}
let currentHue = extendedColorControlTrait.attributes.currentHue
let currentSaturation = extendedColorControlTrait.attributes.currentSaturation
let currentValue = extendedColorControlTrait.attributes.currentValue

Administra las curvas de iluminación

Una curva de iluminación define un programa automatizado que realiza una transición fluida del brillo y la temperatura de color opcional de las luces de destino durante el día. Por ejemplo, una curva de iluminación puede aumentar gradualmente el brillo de las luces por la mañana y atenuarlas a un tono más cálido por la noche. Los tipos de dispositivos de iluminación que solo admiten el brillo, como la luz regulable, siguen la curva de brillo y, además, ignoran la temperatura de color.

La característica Google.LightingCurveTrait es una característica Google Home platform (GHP) a nivel de la estructura. Se accede a ella desde una instancia de Structure, en lugar de un dispositivo de iluminación individual.

Cada programa del atributo se representa con un LightingCurveSetting, que vincula un settingId único con un LightingCurveConfig. En la siguiente tabla, se describen los campos de configuración de LightingCurveConfig:

Campo Descripción
curvePointsArray Es una secuencia de, al menos, dos elementos CurvePoint con horas distintas. Cada punto especifica un time (CurveTimeOfDay con hours de 0 a 23 y minutes de 0 a 59), un brightnessPercent (de 0 a 100) y un colorTemperature opcional en Kelvin. Si se especifica colorTemperature para cualquier punto, debe ser un valor positivo para todos los puntos.
roomId Es el ID de la habitación de destino (por ejemplo, room@{uuid}). Aplica la curva de iluminación a las luces compatibles con atenuación y temperatura de color de esa habitación. Especifica roomId o devices.
devices Un objeto TargetDevices que contiene una lista de entradas TargetDevice, cada una con un id de dispositivo y un ID de type de dispositivo (como home.matter.0000.types.0101 para DimmableLight o home.matter.0000.types.010c para ColorTemperatureLight). Especifica devices o roomId.
daysOfWeekArray Son los días de la semana en los que se ejecuta la curva de iluminación (Locale.Weekday). Si la lista está vacía, la curva de iluminación se ejecuta a diario.
adaptive Es un valor booleano opcional que indica si la curva de iluminación es adaptable, lo que significa que una luz de destino reanuda el nivel de curva activo cuando se enciende durante el plazo programado. Cuando se establece en false, un cambio manual en una luz la desvincula de la curva de iluminación durante el resto del día. Cuando true, una luz que se apaga y se vuelve a encender durante el período de programación se vuelve a activar con la curva de iluminación, lo que hace que se ajuste al brillo y la temperatura de color actuales de la curva, y que siga la curva a partir de ese momento.
enabled Es un valor booleano opcional que indica si el parámetro de configuración de la curva de iluminación está activo. El valor predeterminado es true cuando se crea un parámetro de configuración nuevo. Cuando se omite enabled de un comando de actualización, el estado de enabled no cambia.

Cómo leer la configuración de la curva de iluminación

Para inspeccionar las curvas de iluminación configuradas para una estructura, recupera el atributo Google.LightingCurveTrait de Structure y lee su atributo lightingCurveSettingsArray.

func readLightingCurves(structure: Structure) async {
  guard let lightingCurve = await structure.traits.get(
    Google.LightingCurveTrait.self
  ) else {
    return
  }

  for setting in lightingCurve.attributes.lightingCurveSettingsArray {
    let settingId = setting.settingId
    let config = setting.config
    print(
      "Setting ID: \(String(describing: settingId)), " +
        "enabled: \(String(describing: config?.enabled))"
    )
    for point in config?.curvePointsArray ?? [] {
      print(
        "  Time: \(point.time?.hours ?? 0):\(point.time?.minutes ?? 0), " +
          "Brightness: \(point.brightnessPercent ?? 0)%, " +
          "ColorTemp: \(point.colorTemperature ?? 0)K"
      )
    }
  }
}

Crea un parámetro de configuración de curva de iluminación

Para crear un programa de curva de iluminación nuevo en una estructura, construye un LightingCurveConfig con al menos dos entradas CurvePoint, luces de destino (especificadas por roomId o devices) y los días activos de la semana. Luego, pasa la configuración a createLightingCurveSetting(). El comando devuelve el settingId único asignado al nuevo parámetro de configuración de la curva de iluminación.

En el siguiente ejemplo, se crea una curva de iluminación para los días de semana en una habitación que aumenta el brillo del 30% a las 7:00 a.m. al 80% a las 9:00 a.m. y se atenúa al 20% a las 9:00 p.m.:

func createRoomLightingCurve(
  structure: Structure,
  targetRoomId: String
) async throws -> String? {
  guard let lightingCurve = await structure.traits.get(
    Google.LightingCurveTrait.self
  ) else {
    return nil
  }

  let curvePoints = [
    Google.LightingCurveTrait.CurvePoint(
      time: Google.LightingCurveTrait.CurveTimeOfDay(hours: 7, minutes: 0),
      brightnessPercent: 30,
      colorTemperature: 2700
    ),
    Google.LightingCurveTrait.CurvePoint(
      time: Google.LightingCurveTrait.CurveTimeOfDay(hours: 9, minutes: 0),
      brightnessPercent: 80,
      colorTemperature: 4000
    ),
    Google.LightingCurveTrait.CurvePoint(
      time: Google.LightingCurveTrait.CurveTimeOfDay(hours: 21, minutes: 0),
      brightnessPercent: 20,
      colorTemperature: 2200
    ),
  ]

  let config = Google.LightingCurveTrait.LightingCurveConfig(
    curvePointsArray: curvePoints,
    roomId: targetRoomId,
    daysOfWeekArray: [
      .monday,
      .tuesday,
      .wednesday,
      .thursday,
      .friday,
    ],
    adaptive: true,
    enabled: true
  )

  let response = try await lightingCurve.createLightingCurveSetting(
    config: config
  )
  return response.settingId
}

Para segmentar dispositivos de iluminación específicos en lugar de una habitación completa, proporciona el parámetro devices con Google.LightingCurveTrait.TargetDevices:

let targetDevices = Google.LightingCurveTrait.TargetDevices(
  devicesArray: [
    Google.LightingCurveTrait.TargetDevice(
      id: dimmableLight.id,
      type: DimmableLightDeviceType.identifier
    )
  ]
)

let deviceCurveConfig = Google.LightingCurveTrait.LightingCurveConfig(
  curvePointsArray: curvePoints,
  devices: targetDevices,
  daysOfWeekArray: [.saturday, .sunday],
  adaptive: true,
  enabled: true
)

let response = try await lightingCurve.createLightingCurveSetting(
  config: deviceCurveConfig
)
let settingId = response.settingId

Actualiza un parámetro de configuración de la curva de iluminación

Para modificar una curva de iluminación existente, como cambiar sus puntos de curva, actualizar los días activos de la semana o habilitar e inhabilitar el programa, llama a updateLightingCurveSetting() con el settingId de destino y un LightingCurveConfig actualizado.

func updateLightingCurve(
  structure: Structure,
  settingId: String,
  updatedConfig: Google.LightingCurveTrait.LightingCurveConfig
) async throws {
  guard let lightingCurve = await structure.traits.get(
    Google.LightingCurveTrait.self
  ) else {
    return
  }

  _ = try await lightingCurve.updateLightingCurveSetting(
    settingId: settingId,
    config: updatedConfig
  )
}

Borra un parámetro de configuración de curva de iluminación

Para quitar un parámetro de configuración de la curva de iluminación de una estructura, llama a deleteLightingCurveSetting() con el settingId del parámetro de configuración que deseas borrar.

func deleteLightingCurve(
  structure: Structure,
  settingId: String
) async throws {
  guard let lightingCurve = await structure.traits.get(
    Google.LightingCurveTrait.self
  ) else {
    return
  }

  _ = try await lightingCurve.deleteLightingCurveSetting(settingId: settingId)
}