Для идентификации светильников, переключения состояний питания и регулировки уровней яркости в осветительных приборах используются стандартные характеристики Matter.
Самый простой тип осветительного устройства – OnOffLight. Он реализуется с помощью функций OnOff и Identify. Также можно добавить функции LevelControl и LightEffects.
Другие типы освещения предлагают дополнительные возможности и реализуются с помощью различных признаков:
| Тип устройства Home API | Черты характера | Пример приложения на Kotlin | История успеха |
|---|---|---|---|
|
Цветовая температура (свет)
Осветительное устройство, которое можно включать и выключать, а также регулировать его яркость и цветовую температуру. |
Обязательные характеристики matter Identify matter OnOff matter LevelControl matter ColorControl |
включение и выключение, яркость |
Light (Светлая). |
|
Светильник с регулируемой яркостью
Осветительное устройство, которое можно включать и выключать, регулировать интенсивность его света и управлять с помощью связанного датчика присутствия. |
Обязательные свойства matter Identify matter OnOff matter LevelControl |
включение и выключение, яркость |
Light (Светлая). |
|
Светильник с расширенной цветовой гаммой
Осветительное устройство, которое можно включать и выключать, регулировать интенсивность его света и цветовую температуру. Оно может переключаться с помощью связанного датчика присутствия. |
Обязательные характеристики matter Identify matter OnOff matter LevelControl matter ColorControl |
включение и выключение, яркость |
Light (Светлая). |
|
Включение/выключение света
Осветительное устройство, которое можно включать и выключать. |
Обязательные характеристики matter Идентификация matter OnOff |
включение и выключение, яркость |
Light (Светлая). |
Прежде чем использовать функции или обновлять атрибуты, всегда проверяйте, поддерживаются ли они на устройстве. Подробнее о том, как управлять устройствами на платформе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 содержит информацию об устройстве, например название и идентификатор поставщика, идентификатор и название товара (включая сведения о модели), а также версию ПО.
// 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-адрес устройства, используйте атрибут 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, чтобы идентифицировать светильники, переключать режимы питания и настраивать уровни яркости.
Включить или выключить свет
Используйте типаж 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(), чтобы установить яркость регулируемого источника света на 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 – необязательный признак Google для типа ExtendedColorLightDevice, который упрощает управление цветом, принимая названия цветов, значения 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 |
Идентификатор целевой комнаты (например, room@{uuid}). Применяет кривую освещения к совместимым светильникам с регулируемой яркостью и цветовой температурой в этой комнате. Укажите roomId или devices. |
devices |
Объект TargetDevices, содержащий список записей TargetDevice, каждая из которых включает id устройства и type идентификатор устройства (например, home.matter.0000.types.0101 для DimmableLight или home.matter.0000.types.010c для ColorTemperatureLight). Укажите devices или roomId. |
daysOfWeekList |
Дни недели, в которые работает кривая освещения (DayOfWeek). Если список пуст, кривая освещения работает ежедневно. |
adaptive |
Необязательное логическое значение, указывающее, является ли кривая освещения адаптивной. Это означает, что целевой источник света возобновляет активный уровень кривой при включении в течение запланированного окна. Если включен режим false, то при ручной настройке светильник отключается от кривой освещения до конца дня. Если true, то светильник, выключенный и снова включенный в период действия расписания, снова подключается к кривой освещения, в результате чего его яркость и цветовая температура соответствуют текущим значениям кривой и следуют за ней. |
enabled |
Необязательное логическое значение, указывающее, активна ли настройка кривой освещения. При создании новой настройки по умолчанию используется значение true. Если в команде обновления не указан параметр enabled, то его состояние enabled не меняется. |
Просмотр настроек кривой освещения
Чтобы проверить кривые освещения, настроенные для структуры, получите типаж LightingCurve из Structure и прочитайте его атрибут 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 %, а температура – 2700 К. К 9:00 яркость увеличивается до 80 %, а температура – до 4000 К. К 21:00 яркость снижается до 20 %, а температура – до 2200 К.
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)
}
Чтобы настроить определенные осветительные приборы, а не всю комнату, укажите параметр devices с помощью LightingCurveTrait.TargetDevices:
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
)
Как изменить настройки кривой освещения
Чтобы изменить существующую кривую освещения, например изменить ее точки, обновить активные дни недели или включить и отключить расписание, вызовите updateLightingCurveSetting() с целевым settingId и обновленным LightingCurveConfig.
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)
}