Light device guide

Light devices use standard Matter traits to identify fixtures, toggle power states, and adjust brightness levels.

The most basic light device type is the OnOffLightDeviceType which is implemented with the OnOffTrait and IdentifyTrait traits and optionally supports the LevelControlTrait trait and LightEffectsTrait trait.

Other light types offer additional capabilities and are implemented with different traits:

Home APIs Device Type Traits Swift Sample App Use Case

Color Temperature Light

ColorTemperatureLightDeviceType

home.matter.0000.types.010c

A lighting device that is capable of being switched on or off, the intensity of its light adjusted, and its color temperature adjusted.

Required Traits
     matter IdentifyTrait
     matter OnOffTrait
     matter LevelControlTrait
     matter ColorControlTrait

Optional Traits
     google LightEffectsTrait
     google ExtendedColorControlTrait
Light

Dimmable Light

DimmableLightDeviceType

home.matter.0000.types.0101

A lighting device that is capable of being switched on or off, the intensity of its light adjusted, and being switched by means of a bound occupancy sensor.

Required Traits
     matter IdentifyTrait
     matter OnOffTrait
     matter LevelControlTrait

Optional Traits
     google LightEffectsTrait
Light

Extended Color Light

ExtendedColorLightDeviceType

home.matter.0000.types.010d

A lighting device that is capable of being switched on or off, the intensity of its light adjusted, its color temperature adjusted, and being switched by means of a bound occupancy sensor.

Required Traits
     matter IdentifyTrait
     matter OnOffTrait
     matter LevelControlTrait
     matter ColorControlTrait

Optional Traits
     google LightEffectsTrait
     google ExtendedColorControlTrait
Light

On/Off Light

OnOffLightDeviceType

home.matter.0000.types.0100

A lighting device that is capable of being switched on or off.

Required Traits
     matter IdentifyTrait
     matter OnOffTrait

Optional Traits
     matter LevelControlTrait
     google LightEffectsTrait
Light

Always check for attribute and command support for a device prior to using any features or attempting to update attributes. See Control devices on iOS for more information.

Prerequisites

Before working with lighting devices and lighting curves, make sure your app initializes the Home SDK and includes the required imports:

import Foundation
import GoogleHomeSDK
import GoogleHomeTypes
import Network

Find light devices

To find lighting devices in a structure, filter the device list by device type, such as OnOffLightDeviceType and 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)

You can also retrieve all lighting devices across multiple light device types in a single filter:

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

Get basic information about a device

   Implemented in Sample App for iOS   

The BasicInformation trait includes information like vendor name, vendor ID, product ID, product name (includes model information), and software version for a device:

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!

Identify a lighting device

When a room contains multiple lights, you can help users locate a specific physical fixture by triggering a visual identification state, such as blinking the light for a few seconds. All four light device types require the Matter.IdentifyTrait trait.

Call the identify command with an identifyTime duration in seconds to start the identification state. Passing 0 stops the identification state immediately. You can also call triggerEffect to run a specific visual effect, such as Blink or 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
    )
  }
}

Check the connectivity of a lighting device

Connectivity for a device is actually checked at the device type level because some devices support multiple device types. The state returned is a combination of the connectivity states for all traits on that device.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

A state of partiallyOnline may be observed in the case of mixed device types when there is no internet connectivity. Matter standard traits may still be online due to local routing, but cloud-based traits will be offline.

Get the IP address of the device

To find the IP address of the device, use the networkInterfaces attribute of the GeneralDiagnosticsTrait. The addresses are returned as Data objects, which you can format to standard IPv4 or IPv6 strings using the Network framework:

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
}

Control lighting devices

The OnOffLight and DimmableLight device types use standard Matter traits to identify fixtures, toggle power states, and adjust brightness levels.

Turn a light on or off

Use the OnOffTrait trait to read the current power state of an OnOffLight or DimmableLight and to switch the light on or off.

Before reading the onOff attribute, verify that the device supports it. Some devices operate as command-only endpoints and don't report state.

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

When onOff is true, the light is on. When onOff is false, the light is off.

To change the power state of the light, verify that the trait supports the intended command and then call on(), off(), or 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
}

You can also call on() and off() directly to set an explicit state:

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

To turn off a light with a gradual visual transition, call offWithEffect() and specify an EffectIdentifierEnum value:

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

Adjust brightness levels

A DimmableLight requires the LevelControlTrait trait, and an OnOffLight can optionally support it. Use this trait to read and control the brightness level of a light.

The currentLevel attribute reports the current brightness level on a scale from 0 to 254. You can also inspect minLevel and maxLevel to determine the valid brightness range supported by the hardware.

To set the brightness to a specific value, call moveToLevel(). Note that moveToLevel() only changes the current level when the light is already on, unless you configure optionsOverride with executeIfOff. To automatically turn the light on when setting a non-zero brightness level (or turn it off when setting the level to minimum), use 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
}

The following example reads the current brightness level and uses moveToLevelWithOnOff() to set a dimmable light to 75% brightness (190) over a 1-second (10 tenths of a second) transition:

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()
    )
  }
}

You can also increment or decrement brightness relative to the current level by calling stepWithOnOff() with .up or .down and a stepSize.

Control color

The ColorControlTrait trait is available on both the ColorTemperatureLightDeviceType and ExtendedColorLightDeviceType.

This trait lets you adjust color temperature in micro-reciprocal degrees or 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()
  )
}

You can also set color using CIE 1931 chromaticity coordinates and 16-bit hue and saturation values.

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 is an optional Google trait on ExtendedColorLightDevice that simplifies color control by accepting color names, RGB values, or unified floating-point HSV values that combine color and brightness in a single unit.

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

Manage lighting curves

A lighting curve defines an automated schedule that smoothly transitions the brightness and optional color temperature of target lights throughout the day. For example, a lighting curve can gradually brighten lights in the morning and dim them to a warmer tone in the evening. Light device types that only support brightness, such as Dimmable Light, follow the brightness curve and ignore color temperature.

The Google.LightingCurveTrait trait is a structure-level Google Home platform (GHP) trait. You access it from a Structure instance rather than from an individual lighting device.

Each schedule on the trait is represented by a LightingCurveSetting, which pairs a unique settingId with a LightingCurveConfig. The following table describes the configuration fields of LightingCurveConfig:

Field Description
curvePointsArray A sequence of at least two CurvePoint items with distinct times. Each point specifies a time (CurveTimeOfDay with hours from 0 to 23 and minutes from 0 to 59), a brightnessPercent (0 to 100), and an optional colorTemperature in Kelvin. If colorTemperature is specified for any point, it must be a positive value for all points.
roomId The ID of the target room (for example, room@{uuid}). Applies the lighting curve to compatible dimmable and color temperature lights in that room. Specify either roomId or devices.
devices A TargetDevices object containing a list of TargetDevice entries, each with a device id and device type ID (such as home.matter.0000.types.0101 for DimmableLight or home.matter.0000.types.010c for ColorTemperatureLight). Specify either devices or roomId.
daysOfWeekArray The days of the week on which the lighting curve runs (Locale.Weekday). If the list is empty, the lighting curve runs daily.
adaptive Optional boolean indicating whether the lighting curve is adaptive, meaning that a target light resumes the active curve level when turned on during the scheduled window. When false, a manual change to a light disengages the light from the lighting curve for the rest of the day. When true, a light that is turned off and then turned back on during the schedule window re-engages the light with the lighting curve, causing it to conform to the curve's current brightness and color temperature, and to follow the curve from there.
enabled Optional boolean indicating whether the lighting curve setting is active. Defaults to true when creating a new setting. When enabled is omitted from an update command, the state of enabled doesn't change.

Read lighting curve settings

To inspect the lighting curves configured for a structure, retrieve the Google.LightingCurveTrait trait from the Structure and read its lightingCurveSettingsArray attribute.

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

Create a lighting curve setting

To create a new lighting curve schedule on a structure, construct a LightingCurveConfig with at least two CurvePoint entries, target lights (specified by roomId or devices), and the active days of the week. Then pass the configuration to createLightingCurveSetting(). The command returns the unique settingId assigned to the new lighting curve setting.

The following example creates a weekday lighting curve for a room that ramps brightness from 30% at 7:00 AM to 80% at 9:00 AM and dims to 20% at 9:00 PM:

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
}

To target specific lighting devices instead of an entire room, provide the devices parameter using 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

Update a lighting curve setting

To modify an existing lighting curve—such as changing its curve points, updating the active days of the week, or enabling and disabling the schedule—call updateLightingCurveSetting() with the target settingId and an updated LightingCurveConfig.

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

Delete a lighting curve setting

To remove a lighting curve setting from a structure, call deleteLightingCurveSetting() with the settingId of the setting you want to delete.

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