燈具裝置指南

燈具裝置會使用標準 Matter 特性來識別燈具、切換電源狀態,以及調整亮度等級。

最基本的燈具裝置類型是 OnOffLight,使用 OnOff 和 Identify 特性實作,並可選擇支援 LevelControl 特性和 LightEffects 特性。

其他燈具類型提供額外功能,並透過不同特性實作:

Home API 裝置類型 特徵 Kotlin 範例應用程式 用途

色溫燈

ColorTemperatureLightDevice

home.matter.0000.types.010c

可開啟或關閉、調整光線強度和色溫的照明裝置。

必要特性
     matter Identify
     matter OnOff
     matter LevelControl
     matter ColorControl

選用特徵
     google LightEffects
     google ExtendedColorControl

開關、亮度
輕度

可調光燈具

DimmableLightDevice

home.matter.0000.types.0101

可開啟或關閉、調整亮度,以及透過繫結的活動情形感應器切換的照明裝置。

必要特性
     matter Identify
     matter OnOff
     matter LevelControl

選用特徵
     google LightEffects

開關、亮度
輕度

Extended Color Light

ExtendedColorLightDevice

home.matter.0000.types.010d

可開啟或關閉、調整亮度、調整色溫,以及透過繫結的活動情形感應器切換的照明裝置。

必要特性
     matter Identify
     matter OnOff
     matter LevelControl
     matter ColorControl

選用特質
     google LightEffects
     google ExtendedColorControl

開關、亮度
輕度

開關燈

OnOffLightDevice

home.matter.0000.types.0100

可開啟或關閉的照明裝置。

必要特性
     matter Identify
     matter OnOff

選用特徵
     Matter LevelControl
     Google LightEffects

開關、亮度
輕度

使用任何功能或嘗試更新屬性前,請務必確認裝置是否支援該屬性和指令。詳情請參閱「在Android上控制裝置」。

必要條件

使用照明裝置和照明曲線前,請確認應用程式已初始化 Home SDK,並包含必要的匯入項目:

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

尋找燈具裝置

如要尋找住家中的照明裝置,請依裝置類型篩選裝置清單,例如 OnOffLightDevice 和 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()

您也可以在單一篩選器中,擷取多種照明裝置類型的所有照明裝置:

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

取得裝置的基本資訊

   在 Android 範例應用程式中導入   

BasicInformation 特性包含裝置的供應商名稱、供應商 ID、產品 ID、產品名稱 (包含型號資訊) 和軟體版本等資訊:

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

辨識照明裝置

如果房間內有多盞燈,你可以觸發視覺辨識狀態 (例如讓燈閃爍幾秒),協助使用者找到特定實體燈具。這四種燈具裝置類型都必須具備 Identify 特性。

呼叫 identify 指令,並以秒為單位指定 identifyTime 持續時間,即可啟動辨識狀態。傳遞 0 會立即停止辨識狀態。您也可以呼叫 triggerEffect 來執行特定視覺效果,例如 Blink 或 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
    )
  }
}

檢查照明裝置的連線

系統實際上會檢查裝置類型層級的裝置連線能力,因為部分裝置支援多種裝置類型。傳回的狀態是該裝置所有特性的連線狀態組合。

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

如果裝置類型不一,且沒有網際網路連線,可能會看到 partiallyOnline 狀態。由於本機路由,Matter 標準特徵可能仍會上線,但雲端式特徵會離線。

取得裝置的 IP 位址

如要找出裝置的 IP 位址,請使用 GeneralDiagnosticsTrait 的 networkInterfaces 屬性。位址會以 Data 物件的形式傳回,您可以使用 Network 架構將其格式化為標準 IPv4 或 IPv6 字串:

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
}

控制照明裝置

OnOffLight 和 DimmableLight 裝置類型會使用標準 Matter 特性,識別燈具、切換電源狀態,以及調整亮度等級。

開啟或關閉燈具

使用 OnOff 特性讀取 OnOffLight 或 DimmableLight 的目前電源狀態,以及開啟或關閉燈光。

讀取 onOff 屬性前,請先確認裝置是否支援。部分裝置僅能做為指令端點,不會回報狀態。

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

onOff為true時,指示燈會亮起。當 onOff 為 false 時,燈會關閉。

如要變更燈具的電源狀態,請確認特性能支援預期指令,然後呼叫 on()、off() 或 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
}

您也可以直接呼叫 on() 和 off(),設定明確狀態:

onOffTrait.off()
onOffTrait.on()

如要關閉燈具,並逐漸轉換視覺效果,請呼叫 offWithEffect() 並指定 EffectIdentifierEnum 值:

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

調整亮度

DimmableLight 必須具備 LevelControl 特性,OnOffLight 則可選擇是否支援。這項特徵可用於讀取及控制燈具的亮度。

currentLevel 屬性會回報目前的亮度等級,範圍為 0 至 254。您也可以檢查 minLevel 和 maxLevel,判斷硬體支援的有效亮度範圍。

如要將亮度設為特定值,請呼叫 moveToLevel()。請注意,除非您使用 executeIfOff 設定 optionsOverride,否則 moveToLevel() 只會在燈光開啟時變更目前亮度。如要在設定非零亮度等級時自動開啟燈光 (或在設定最低等級時關閉燈光),請使用 moveToLevelWithOnOff()。

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

以下範例會讀取目前的亮度等級,並使用 moveToLevelWithOnOff() 將可調光燈具的亮度設為 75% (190u),轉換時間為 1 秒 (10u 秒):

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

您也可以呼叫 stepWithOnOff(),並使用 StepModeEnum.Up 或 StepModeEnum.Down 和 stepSize,相對於目前等級增加或減少亮度。

控制項顏色

ColorControl 特性適用於 ColorTemperatureLightDevice 和 ExtendedColorLightDevice。

這項特性能以微倒數度或邁爾德為單位調整色溫。

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

您也可以使用 CIE 1931 色度座標和 16 位元色相和飽和度值設定顏色。

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 是 ExtendedColorLightDevice 的選用 Google 特性,可接受顏色名稱、RGB 值或統一浮點 HSV 值 (將顏色和亮度合併為單一單位),簡化顏色控制。

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

管理光照曲線

照明曲線可定義自動化時間表,在一天中平順地轉換目標燈具的亮度和選用色溫。舉例來說,照明曲線可以在早上逐漸調亮燈光,並在晚上調暗燈光,呈現較溫暖的色調。僅支援亮度的燈具裝置類型 (例如可調光燈具) 會遵循亮度曲線,並忽略色溫。

LightingCurve 特性是結構層級的 Google Home platform 特性。您是透過 Structure 執行個體存取,而非個別照明裝置。

特性的每個時間表都以 LightingCurveSetting 表示,其中不重複的 settingId 會與 LightingCurveConfig 配對。下表說明 LightingCurveConfig 的設定欄位:

欄位 說明
curvePointsList 至少兩個時間不同的 CurvePoint 項目序列。每個點都會指定 time (CurveTimeOfDay,hours 介於 0 到 23 之間,minutes 介於 0 到 59 之間)、brightnessPercent (0 到 100),以及選用的 colorTemperature (以克耳文為單位)。如果為任何點指定 colorTemperature,則所有點的值都必須為正值。
roomId 目標房間的 ID (例如 room@{uuid}),系統會將照明曲線套用至該房間內相容的可調光和色溫燈具。指定 roomId 或 devices。
devices TargetDevices 物件,包含 TargetDevice 項目清單,每個項目都有裝置 id 和裝置 type ID (例如 DimmableLight 的 home.matter.0000.types.0101 或 ColorTemperatureLight 的 home.matter.0000.types.010c)。請指定 devices 或 roomId。
daysOfWeekList 執行照明曲線的星期幾 (DayOfWeek)。如果清單空白,則每天都會執行照明曲線。
adaptive 選用布林值,指出照明曲線是否為自動調整,也就是說,目標燈具在可預約時間範圍內開啟時,會恢復為有效曲線等級。false時,如果手動調整燈具,該燈具在當天剩餘時間內就會脫離照明曲線。當 true 時,在時間表期間關閉再開啟的燈具會重新與照明曲線連結,使燈具符合曲線目前的亮度和色溫,並從該處開始遵循曲線。
enabled 選用布林值,指出是否啟用光線曲線設定。建立新設定時,預設值為 true。如果更新指令省略 enabled,enabled 的狀態就不會變更。

讀取亮度曲線設定

如要檢查為住家設定的照明曲線,請從 Structure 擷取 LightingCurve 特性,並讀取其 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"
      )
    }
  }
}

建立光線曲線設定

如要在住家建立新的照明曲線時間表,請建構 LightingCurveConfig,其中至少包含兩個 CurvePoint 項目、目標燈具 (由 roomId 或 devices 指定),以及一週中的有效日期。然後將設定傳遞至 createLightingCurveSetting()。指令會傳回指派給新亮度曲線設定的不重複 settingId。

以下範例會為房間建立平日照明曲線。早上 7:00 時,亮度為 30%,色溫為 2700K 暖色;早上 9:00 時,亮度為 80%,色溫為 4000K 冷色;晚上 9:00 時,亮度為 20%,色溫為 2200K 極暖色:

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

如要指定特定照明裝置,而非整個房間,請使用 LightingCurveTrait.TargetDevices 提供 devices 參數:

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
)

更新亮度曲線設定

如要修改現有的光照曲線 (例如變更曲線點、更新一週中的有效天數,或啟用/停用時間表),請使用目標 settingId 和更新後的 LightingCurveConfig 呼叫 updateLightingCurveSetting()。

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

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

刪除亮度曲線設定

如要從住家結構體中移除照明曲線設定,請呼叫 deleteLightingCurveSetting(),並提供要刪除的設定 settingId。

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

  lightingCurve.deleteLightingCurveSetting(settingId = settingId)
}