Руководство к устройству Light

Для идентификации светильников, переключения состояний питания и регулировки уровней яркости в осветительных приборах используются стандартные характеристики Matter.

Самый простой тип осветительного устройства – OnOffLightDeviceType. Он реализуется с помощью функций OnOffTrait и IdentifyTrait. Также можно добавить функции LevelControlTrait и LightEffectsTrait.

Другие типы освещения предлагают дополнительные возможности и реализуются с помощью различных признаков:

Тип устройства Home API Черты характера Пример приложения на Swift История успеха

Цветовая температура (свет)

ColorTemperatureLightDeviceType

home.matter.0000.types.010c

Осветительное устройство, которое можно включать и выключать, а также регулировать его яркость и цветовую температуру.

Обязательные характеристики
     matter IdentifyTrait
     matter OnOffTrait
     matter LevelControlTrait
     matter ColorControlTrait

Optional Traits
     google LightEffectsTrait
     google ExtendedColorControlTrait
Light (Светлая).

Светильник с регулируемой яркостью

DimmableLightDeviceType

home.matter.0000.types.0101

Осветительное устройство, которое можно включать и выключать, регулировать интенсивность его света и управлять с помощью связанного датчика присутствия.

Обязательные характеристики
     matter IdentifyTrait
     matter OnOffTrait
     matter LevelControlTrait

Необязательные свойства
     google LightEffectsTrait
Light (Светлая).

Светильник с расширенной цветовой гаммой

ExtendedColorLightDeviceType

home.matter.0000.types.010d

Осветительное устройство, которое можно включать и выключать, регулировать интенсивность его света и цветовую температуру. Оно может переключаться с помощью связанного датчика присутствия.

Обязательные характеристики
     matter IdentifyTrait
     matter OnOffTrait
     matter LevelControlTrait
     matter ColorControlTrait

Optional Traits
     google LightEffectsTrait
     google ExtendedColorControlTrait
Light (Светлая).

Включение/выключение света

OnOffLightDeviceType

home.matter.0000.types.0100

Осветительное устройство, которое можно включать и выключать.

Обязательные типажи
     matter IdentifyTrait
     matter OnOffTrait

Необязательные характеристики
     matter LevelControlTrait
     google LightEffectsTrait
Light (Светлая).

Прежде чем использовать функции или обновлять атрибуты, всегда проверяйте, поддерживаются ли они на устройстве. Подробнее о том, как управлять устройствами на платформеiOS…

Требования

Прежде чем работать с осветительными устройствами и кривыми освещения, убедитесь, что ваше приложение инициализирует Home SDK и включает необходимые импорты:

import Foundation
import GoogleHomeSDK
import GoogleHomeTypes
import Network

Найти осветительные приборы

Чтобы найти осветительные устройства в доме, отфильтруйте список устройств по типу, например OnOffLightDeviceType и 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)

Вы также можете получить все осветительные устройства нескольких типов в одном фильтре:

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

Как получить основные сведения об устройстве

   Реализовано в примере приложения для iOS   

Функция BasicInformation содержит информацию об устройстве, например название и идентификатор поставщика, идентификатор и название товара (включая сведения о модели), а также версию ПО.

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!

Как идентифицировать осветительное устройство

Если в комнате несколько светильников, вы можете помочь пользователям найти конкретный физический прибор, запустив визуальную идентификацию, например мигание света в течение нескольких секунд. Для всех четырех типов осветительных устройств требуется типаж Matter.IdentifyTrait.

Чтобы запустить режим идентификации, вызовите команду identify с длительностью identifyTime в секундах. Если передать 0, идентификация будет немедленно остановлена. Вы также можете вызвать triggerEffect, чтобы запустить определенный визуальный эффект, например Blink или 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
    )
  }
}

Проверьте подключение осветительного устройства

Подключение устройства проверяется на уровне типа устройства, поскольку некоторые устройства поддерживают несколько типов. Возвращаемое состояние представляет собой комбинацию состояний подключения для всех характеристик на этом устройстве.

let lightConnectivity =
  dimmableLightDeviceType.metadata.sourceConnectivity
  .connectivityState

Если у вас устройства разных типов и нет подключения к интернету, может отображаться статус partiallyOnline. Стандартные функции Matter могут быть доступны онлайн благодаря локальной маршрутизации, но облачные функции будут недоступны.

Как узнать IP-адрес устройства

Чтобы найти IP-адрес устройства, используйте атрибут networkInterfaces объекта GeneralDiagnosticsTrait. Адреса возвращаются в виде объектов Data, которые можно преобразовать в стандартные строки IPv4 или IPv6 с помощью фреймворка 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
}

Управление осветительными приборами

Типы устройств OnOffLight и DimmableLight используют стандартные типажи Matter, чтобы идентифицировать светильники, переключать режимы питания и настраивать уровни яркости.

Включить или выключить свет

Используйте типаж OnOffTrait, чтобы узнать текущее состояние питания устройства OnOffLight или DimmableLight и включить или выключить свет.

Прежде чем считывать атрибут onOff, убедитесь, что устройство его поддерживает. Некоторые устройства работают только как конечные точки для команд и не сообщают о своем состоянии.

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

Если onOff – true, индикатор горит. Если onOff – false, индикатор не горит.

Чтобы изменить состояние питания светильника, убедитесь, что типаж поддерживает нужную команду, а затем вызовите on(), off() или 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
}

Вы также можете напрямую вызвать on() и off(), чтобы задать явное состояние:

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

Чтобы выключить свет с постепенным визуальным переходом, вызовите offWithEffect() и укажите значение 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
}

Настроить яркость

Для DimmableLight требуется типаж LevelControlTrait, а для OnOffLight он необязателен. Используйте этот типаж, чтобы считывать и контролировать уровень яркости света.

Атрибут currentLevel сообщает текущий уровень яркости по шкале от 0 до 254. Вы также можете проверить minLevel и maxLevel, чтобы определить допустимый диапазон яркости, поддерживаемый аппаратным обеспечением.

Чтобы установить определенный уровень яркости, вызовите moveToLevel(). Обратите внимание, что moveToLevel() меняет текущий уровень, только когда свет уже включен, если вы не настроите optionsOverride с помощью executeIfOff. Чтобы свет автоматически включался при установке ненулевого уровня яркости (или выключался при установке минимального уровня), используйте 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
}

В следующем примере считывается текущий уровень яркости и используется moveToLevelWithOnOff(), чтобы установить яркость регулируемого источника света на 75 % (190) за 1 секунду (10 десятых долей секунды):

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

Вы также можете увеличивать или уменьшать яркость относительно текущего уровня, вызывая stepWithOnOff() с .up или .down и stepSize.

Цвет элементов управления

Типаж ColorControlTrait доступен как для ColorTemperatureLightDeviceType, так и для ExtendedColorLightDeviceType.

Это свойство позволяет настраивать цветовую температуру в микрообратных градусах, или майредах.

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

Вы также можете задать цвет, используя координаты цветности CIE 1931 и 16-битные значения оттенка и насыщенности.

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 – необязательный признак Google для типа ExtendedColorLightDevice, который упрощает управление цветом, принимая названия цветов, значения RGB или унифицированные значения HSV с записью с плавающей запятой, объединяющие цвет и яркость в одну единицу.

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

Управление кривыми освещения

Кривая освещения определяет автоматическое расписание, которое плавно меняет яркость и, если нужно, цветовую температуру целевых светильников в течение дня. Например, кривая освещения может постепенно увеличивать яркость света утром и уменьшать ее до более теплого тона вечером. Типы осветительных устройств, которые поддерживают только яркость, например регулируемый светильник, следуют кривой яркости и игнорируют цветовую температуру.

Google.LightingCurveTrait – это свойство Google Home platform (GHP) на уровне структуры. Доступ к нему осуществляется через экземпляр Structure, а не через отдельное осветительное устройство.

Каждое расписание в свойстве представлено объектом LightingCurveSetting, который связывает уникальный идентификатор settingId с объектом LightingCurveConfig. В таблице ниже описаны поля конфигурации LightingCurveConfig.

Поле Описание
curvePointsArray Последовательность как минимум из двух элементов CurvePoint с разным временем. Каждая точка задает time (CurveTimeOfDay с hours от 0 до 23 и minutes от 0 до 59), brightnessPercent (от 0 до 100) и необязательную colorTemperature в кельвинах. Если для какой-либо точки указано значение colorTemperature, оно должно быть положительным для всех точек.
roomId Идентификатор целевой комнаты (например, room@{uuid}). Применяет кривую освещения к совместимым светильникам с регулируемой яркостью и цветовой температурой в этой комнате. Укажите roomId или devices.
devices Объект TargetDevices, содержащий список записей TargetDevice, каждая из которых включает id устройства и type идентификатор устройства (например, home.matter.0000.types.0101 для DimmableLight или home.matter.0000.types.010c для ColorTemperatureLight). Укажите devices или roomId.
daysOfWeekArray Дни недели, в которые работает кривая освещения (Locale.Weekday). Если список пуст, кривая освещения работает ежедневно.
adaptive Необязательное логическое значение, указывающее, является ли кривая освещения адаптивной. Это означает, что целевой источник света возобновляет активный уровень кривой при включении в течение запланированного окна. Если включен режим false, то при ручной настройке светильник отключается от кривой освещения до конца дня. Если true, то светильник, выключенный и снова включенный в период действия расписания, снова подключается к кривой освещения, в результате чего его яркость и цветовая температура соответствуют текущим значениям кривой и следуют за ней.
enabled Необязательное логическое значение, указывающее, активна ли настройка кривой освещения. При создании новой настройки по умолчанию используется значение true. Если в команде обновления не указан параметр enabled, то его состояние enabled не меняется.

Просмотр настроек кривой освещения

Чтобы проверить кривые освещения, настроенные для структуры, получите типаж Google.LightingCurveTrait из Structure и прочитайте его атрибут 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"
      )
    }
  }
}

Как создать настройку кривой освещения

Чтобы создать новое расписание кривой освещения для здания, создайте LightingCurveConfig по крайней мере с двумя записями CurvePoint, целевыми светильниками (указанными в roomId или devices) и активными днями недели. Затем передайте конфигурацию в createLightingCurveSetting(). Команда возвращает уникальный идентификатор settingId, назначенный новой настройке кривой освещения.

В следующем примере создается кривая освещения для комнаты в будние дни, которая увеличивает яркость с 30% в 7:00 до 80% в 9:00 и уменьшает до 20% в 21:00:

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
}

Чтобы настроить определенные осветительные приборы, а не всю комнату, укажите параметр devices с помощью 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

Как изменить настройки кривой освещения

Чтобы изменить существующую кривую освещения, например изменить ее точки, обновить активные дни недели или включить и отключить расписание, вызовите updateLightingCurveSetting() с целевым settingId и обновленным 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
  )
}

Как удалить настройку кривой освещения

Чтобы удалить настройку кривой освещения из структуры, вызовите deleteLightingCurveSetting() с settingId настройки, которую нужно удалить.

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