照明デバイスのガイド

照明デバイスは、標準の 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

オン / オフ、明るさ
浅い睡眠

拡張カラーライト

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

1 つのフィルタで、複数の照明デバイスタイプにわたるすべての照明デバイスを取得することもできます。

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

照明デバイスを識別する

部屋に複数の照明がある場合、数秒間照明を点滅させるなど、視覚的な識別状態をトリガーすることで、ユーザーが特定の物理的な照明器具を見つけられるようにすることができます。4 つの照明デバイスタイプはすべて、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() を呼び出します。moveToLevel() は、optionsOverride を executeIfOff で構成しない限り、ライトがすでに点灯している場合にのみ現在のレベルを変更します。ゼロ以外の明るさレベルを設定するときにライトを自動的にオンにする(またはレベルを最小に設定するときにライトをオフにする)には、moveToLevelWithOnOff() を使用します。

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

次の例では、現在の明るさレベルを読み取り、moveToLevelWithOnOff() を使用して、1 秒(10u 10 分の 1 秒)の遷移で調光可能なライトを 75% の明るさ(190u)に設定します。

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

StepModeEnum.Up または StepModeEnum.Down と stepSize を指定して stepWithOnOff() を呼び出すことで、現在のレベルを基準に明るさを増減することもできます。

コントロールの色

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 値、または色と明るさを 1 つの単位にまとめた統合浮動小数点 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

照明曲線を管理する

照明曲線は、1 日を通してターゲット ライトの明るさとオプションの色温度をスムーズに移行する自動スケジュールを定義します。たとえば、照明曲線を使用すると、朝は照明を徐々に明るくし、夕方は暖色系のトーンに暗くすることができます。明るさのみをサポートする照明デバイスタイプ(調光可能ライトなど)は、明るさの曲線に従い、色温度を無視します。

LightingCurve トレイトは、構造レベルの Google Home platform トレイトです。個々の照明デバイスからではなく、Structure インスタンスからアクセスします。

トレイトの各スケジュールは LightingCurveSetting で表され、一意の settingId と LightingCurveConfig がペアになっています。次の表に、LightingCurveConfig の構成フィールドを示します。

フィールド 説明
curvePointsList 異なる時刻を持つ 2 つ以上の CurvePoint アイテムのシーケンス。各ポイントは、time(CurveTimeOfDay、hours は 0~23、minutes は 0~59)、brightnessPercent(0~100)、オプションの colorTemperature(ケルビン単位)を指定します。colorTemperature を指定する場合は、すべての地点で正の値にする必要があります。
roomId 対象の部屋の ID(例: room@{uuid})。その部屋にある、対応する調光可能なライトと色温度ライトに照明曲線が適用されます。roomId または devices を指定します。
devices TargetDevice エントリのリストを含む TargetDevices オブジェクト。各エントリにはデバイス 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"
      )
    }
  }
}

照明曲線設定を作成する

ストラクチャに新しい照明カーブ スケジュールを作成するには、少なくとも 2 つの CurvePoint エントリ、ターゲット ライト(roomId または devices で指定)、有効な曜日を含む LightingCurveConfig を作成します。次に、構成を createLightingCurveSetting() に渡します。このコマンドは、新しい照明曲線設定に割り当てられた一意の settingId を返します。

次の例では、部屋の平日の照明カーブを作成しています。午前 7 時に暖色 2,700K で明るさ 30% から始まり、午前 9 時に寒色 4,000K で 80% になり、午後 9 時までに非常に暖色 2,200K で 20% に暗くなります。

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

照明カーブの設定を削除する

ストラクチャから照明曲線設定を削除するには、削除する設定の settingId を指定して deleteLightingCurveSetting() を呼び出します。

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

  lightingCurve.deleteLightingCurveSetting(settingId = settingId)
}