[lifx] Add channels for controlling absolute color temperature in Kelvin (#11309)

* [lifx] Add channels for controlling absolute color temperature in Kelvin

Adds an 'abstemperature' channel to all Thing Types for controlling the absolute color temperature in Kelvin.
MultiZone lights also have 'abstemperaturezone' channels that allow for controlling the color temperature of a zone in Kelvin.
These channels make it easier to use the same color temperature with lights that have a different color temperature range.
Furthermore the channel type tags have been updated which simplifies using the generated items with the semantic model.

Signed-off-by: Wouter Born <github@maindrain.net>
This commit is contained in:
Wouter Born
2021-09-27 22:00:01 +02:00
committed by GitHub
parent b2db32da96
commit 89ef91bad3
15 changed files with 137 additions and 172 deletions

View File

@@ -43,14 +43,14 @@ The following table lists the thing types of the supported LIFX devices:
The thing type determines the capability of a device and with that the possible ways of interacting with it. The thing type determines the capability of a device and with that the possible ways of interacting with it.
The following matrix lists the capabilities (channels) for each type: The following matrix lists the capabilities (channels) for each type:
| Thing Type | On/Off | Brightness | Color | Color Zone | Color Temperature | Color Temperature Zone | HEV Cycle | Infrared | Tile Effects | | Thing Type | On/Off | Brightness | Color | Color Zone | (Abs) Color Temperature | (Abs) Color Temperature Zone | HEV Cycle | Infrared | Tile Effects |
|---------------|:------:|:----------:|:-----:|:----------:|:-----------------:|:----------------------:|:---------:|:--------:|:------------:| |---------------|:------:|:----------:|:-----:|:----------:|:-----------------------:|:----------------------------:|:---------:|:--------:|:------------:|
| colorlight | X | | X | | X | | | | | | colorlight | X | | X | | X | | | | |
| colorhevlight | X | | X | | X | | X | | | | colorhevlight | X | | X | | X | | X | | |
| colorirlight | X | | X | | X | | | X | | | colorirlight | X | | X | | X | | | X | |
| colormzlight | X | | X | X | X | X | | | | | colormzlight | X | | X | X | X | X | | | |
| tilelight | X | X | X | | X | | | | X | | tilelight | X | X | X | | X | | | | X |
| whitelight | X | X | | | X | | | | | | whitelight | X | X | | | X | | | | |
## Discovery ## Discovery
@@ -85,17 +85,19 @@ Thing lifx:colorirlight:porch [ host="10.120.130.4", fadetime=0 ]
All devices support some of the following channels: All devices support some of the following channels:
| Channel Type ID | Item Type | Description | Thing Types | | Channel Type ID | Item Type | Description | Thing Types |
|-----------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------| |--------------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|
| brightness | Dimmer | This channel supports adjusting the brightness value. | whitelight | | abstemperature | Number | This channel supports adjusting the color temperature in Kelvin. | colorlight, colorhevlight, colorirlight, colormzlight, tilelight, whitelight |
| color | Color | This channel supports full color control with hue, saturation and brightness values. | colorlight, colorhevlight, colorirlight, colormzlight, tilelight | | abstemperaturezone | Number | This channel supports adjusting the zone color temperature in Kelvin. | colormzlight |
| colorzone | Color | This channel supports full zone color control with hue, saturation and brightness values. | colormzlight | | brightness | Dimmer | This channel supports adjusting the brightness value. | whitelight |
| effect | String | This channel represents a type of light effect (e.g. for tile light: off, morph, flame) | tilelight | | color | Color | This channel supports full color control with hue, saturation and brightness values. | colorlight, colorhevlight, colorirlight, colormzlight, tilelight |
| hevcycle | Switch | This channel supports starting and stopping the HEV clean cycle. | colorhevlight | | colorzone | Color | This channel supports full zone color control with hue, saturation and brightness values. | colormzlight |
| infrared | Dimmer | This channel supports adjusting the infrared value. *Note:* IR capable lights only activate their infrared LEDs when the brightness drops below a certain level. | colorirlight | | effect | String | This channel represents a type of light effect (e.g. for tile light: off, morph, flame) | tilelight |
| signalstrength | Number | This channel represents signal strength with values 0, 1, 2, 3 or 4; 0 being worst strength and 4 being best strength. | colorlight, colorhevlight, colorirlight, colormzlight, tilelight, whitelight | | hevcycle | Switch | This channel supports starting and stopping the HEV clean cycle. | colorhevlight |
| temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | colorlight, colorhevlight, colorirlight, colormzlight, tilelight, whitelight | | infrared | Dimmer | This channel supports adjusting the infrared value. *Note:* IR capable lights only activate their infrared LEDs when the brightness drops below a certain level. | colorirlight |
| temperaturezone | Dimmer | This channel supports adjusting the zone color temperature from cold (0%) to warm (100%). | colormzlight | | signalstrength | Number | This channel represents signal strength with values 0, 1, 2, 3 or 4; 0 being worst strength and 4 being best strength. | colorlight, colorhevlight, colorirlight, colormzlight, tilelight, whitelight |
| temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | colorlight, colorhevlight, colorirlight, colormzlight, tilelight, whitelight |
| temperaturezone | Dimmer | This channel supports adjusting the zone color temperature from cold (0%) to warm (100%). | colormzlight |
The *color* and *brightness* channels have a "Power On Brightness" configuration option that is used to determine the brightness when a light is switched on. The *color* and *brightness* channels have a "Power On Brightness" configuration option that is used to determine the brightness when a light is switched on.
When it is left empty, the brightness of a light remains unchanged when a light is switched on or off. When it is left empty, the brightness of a light remains unchanged when a light is switched on or off.
@@ -107,9 +109,9 @@ If both "Power on brightness" and "Power On Color" configuration options are def
The *temperature* channels have a "Power On Temperature" configuration option that is used to determine the color temperature when a light is switched on. When it is left empty, the color temperature of a light remains unchanged when a light is switched on or off. The *temperature* channels have a "Power On Temperature" configuration option that is used to determine the color temperature when a light is switched on. When it is left empty, the color temperature of a light remains unchanged when a light is switched on or off.
MultiZone lights (*colormzlight*) have several channels (e.g. *colorzone0*, *temperaturezone0*, etc.) that allow for controlling specific zones of the light. MultiZone lights (*colormzlight*) have several channels (e.g. *colorzone0*, *temperaturezone0*, *abstemperaturezone0*, etc.) that allow for controlling specific zones of the light.
Changing the *color* and *temperature* channels will update the states of all zones. Changing the *color*, *temperature* and *abstemperature* channels will update the states of all zones.
The *color* and *temperature* channels of MultiZone lights always return the same state as *colorzone0*, *temperaturezone0*. The *color*, *temperature* and *abstemperature* channels of MultiZone lights always return the same state as *colorzone0*, *temperaturezone0*, *abstemperaturezone0*.
The *hevcycle* channels have an optional "HEV Cycle Duration" configuration option that can be used to override the cycle duration configured in the light. The *hevcycle* channels have an optional "HEV Cycle Duration" configuration option that can be used to override the cycle duration configured in the light.
@@ -174,36 +176,44 @@ Thing lifx:whitelight:kitchen [ deviceId="D073D5D4D4D4", fadetime=150 ]
// Living // Living
Color Living_Color { channel="lifx:colorlight:living:color" } Color Living_Color { channel="lifx:colorlight:living:color" }
Dimmer Living_Temperature { channel="lifx:colorlight:living:temperature" } Dimmer Living_Temperature { channel="lifx:colorlight:living:temperature" }
Number Living_Abs_Temperature { channel="lifx:colorlight:living:abstemperature" }
// Living2 (alternative approach) // Living2 (alternative approach)
Color Living2_Color { channel="lifx:colorlight:living2:color" } Color Living2_Color { channel="lifx:colorlight:living2:color" }
Switch Living2_Switch { channel="lifx:colorlight:living2:color" } Switch Living2_Switch { channel="lifx:colorlight:living2:color" }
Dimmer Living2_Dimmer { channel="lifx:colorlight:living2:color" } Dimmer Living2_Dimmer { channel="lifx:colorlight:living2:color" }
Dimmer Living2_Temperature { channel="lifx:colorlight:living2:temperature" } Dimmer Living2_Temperature { channel="lifx:colorlight:living2:temperature" }
Number Living2_Abs_Temperature { channel="lifx:colorlight:living2:abstemperature" }
// Desk // Desk
Color Desk_Color { channel="lifx:colorhevlight:desk:color" } Color Desk_Color { channel="lifx:colorhevlight:desk:color" }
Dimmer Desk_Temperature { channel="lifx:colorhevlight:desk:temperature" } Dimmer Desk_Temperature { channel="lifx:colorhevlight:desk:temperature" }
Number Desk_Abs_Temperature { channel="lifx:colorhevlight:desk:abstemperature" }
Switch Desk_HEV_Cycle { channel="lifx:colorhevlight:desk:hevcycle" } Switch Desk_HEV_Cycle { channel="lifx:colorhevlight:desk:hevcycle" }
// Porch // Porch
Color Porch_Color { channel="lifx:colorirlight:porch:color" } Color Porch_Color { channel="lifx:colorirlight:porch:color" }
Dimmer Porch_Infrared { channel="lifx:colorirlight:porch:infrared" } Dimmer Porch_Infrared { channel="lifx:colorirlight:porch:infrared" }
Dimmer Porch_Temperature { channel="lifx:colorirlight:porch:temperature" } Dimmer Porch_Temperature { channel="lifx:colorirlight:porch:temperature" }
Number Porch_Abs_Temperature { channel="lifx:colorirlight:porch:abstemperature" }
Number Porch_Signal_Strength { channel="lifx:colorirlight:porch:signalstrength" } Number Porch_Signal_Strength { channel="lifx:colorirlight:porch:signalstrength" }
// Ceiling // Ceiling
Color Ceiling_Color { channel="lifx:colormzlight:ceiling:color" } Color Ceiling_Color { channel="lifx:colormzlight:ceiling:color" }
Dimmer Ceiling_Temperature { channel="lifx:colormzlight:ceiling:temperature" } Dimmer Ceiling_Temperature { channel="lifx:colormzlight:ceiling:temperature" }
Number Ceiling_Abs_Temperature { channel="lifx:colormzlight:ceiling:abstemperature" }
Color Ceiling_Color_Zone_0 { channel="lifx:colormzlight:ceiling:colorzone0" } Color Ceiling_Color_Zone_0 { channel="lifx:colormzlight:ceiling:colorzone0" }
Dimmer Ceiling_Temperature_Zone_0 { channel="lifx:colormzlight:ceiling:temperaturezone0" } Dimmer Ceiling_Temperature_Zone_0 { channel="lifx:colormzlight:ceiling:temperaturezone0" }
Number Ceiling_Abs_Temperature_Zone_0 { channel="lifx:colormzlight:ceiling:abstemperaturezone0" }
Color Ceiling_Color_Zone_15 { channel="lifx:colormzlight:ceiling:colorzone15" } Color Ceiling_Color_Zone_15 { channel="lifx:colormzlight:ceiling:colorzone15" }
Dimmer Ceiling_Temperature_Zone_15 { channel="lifx:colormzlight:ceiling:temperaturezone15" } Dimmer Ceiling_Temperature_Zone_15 { channel="lifx:colormzlight:ceiling:temperaturezone15" }
Number Ceiling_Abs_Temperature_Zone_15 { channel="lifx:colormzlight:ceiling:abstemperaturezone15" }
// Kitchen // Kitchen
Switch Kitchen_Toggle { channel="lifx:whitelight:kichen:brightness" } Switch Kitchen_Toggle { channel="lifx:whitelight:kichen:brightness" }
Dimmer Kitchen_Brightness { channel="lifx:whitelight:kitchen:brightness" } Dimmer Kitchen_Brightness { channel="lifx:whitelight:kitchen:brightness" }
Dimmer Kitchen_Temperature { channel="lifx:whitelight:kitchen:temperature" } Dimmer Kitchen_Temperature { channel="lifx:whitelight:kitchen:temperature" }
Number Kitchen_Abs_Temperature { channel="lifx:whitelight:kitchen:abstemperature" }
``` ```
### demo.sitemap: ### demo.sitemap:
@@ -216,6 +226,7 @@ sitemap demo label="Main Menu"
Slider item=Living_Color Slider item=Living_Color
Colorpicker item=Living_Color Colorpicker item=Living_Color
Slider item=Living_Temperature Slider item=Living_Temperature
Slider item=Living_Abs_Temperature
} }
Frame label="Living2" { Frame label="Living2" {
@@ -223,6 +234,7 @@ sitemap demo label="Main Menu"
Slider item=Living2_Dimmer Slider item=Living2_Dimmer
Colorpicker item=Living2_Color Colorpicker item=Living2_Color
Slider item=Living2_Temperature Slider item=Living2_Temperature
Slider item=Living2_Abs_Temperature
} }
Frame label="Desk" { Frame label="Desk" {
@@ -230,6 +242,7 @@ sitemap demo label="Main Menu"
Slider item=Desk_Color Slider item=Desk_Color
Colorpicker item=Desk_Color Colorpicker item=Desk_Color
Slider item=Desk_Temperature Slider item=Desk_Temperature
Slider item=Desk_Abs_Temperature
Switch item=Desk_HEV_Cycle Switch item=Desk_HEV_Cycle
} }
@@ -238,6 +251,7 @@ sitemap demo label="Main Menu"
Slider item=Porch_Color Slider item=Porch_Color
Colorpicker item=Porch_Color Colorpicker item=Porch_Color
Slider item=Porch_Temperature Slider item=Porch_Temperature
Slider item=Porch_Abs_Temperature
Slider item=Porch_Infrared Slider item=Porch_Infrared
Text item=Porch_Signal_Strength Text item=Porch_Signal_Strength
} }
@@ -247,16 +261,20 @@ sitemap demo label="Main Menu"
Slider item=Ceiling_Color Slider item=Ceiling_Color
Colorpicker item=Ceiling_Color Colorpicker item=Ceiling_Color
Slider item=Ceiling_Temperature Slider item=Ceiling_Temperature
Slider item=Ceiling_Abs_Temperature
Colorpicker item=Ceiling_Color_Zone_0 Colorpicker item=Ceiling_Color_Zone_0
Slider item=Ceiling_Temperature_Zone_0 Slider item=Ceiling_Temperature_Zone_0
Slider item=Ceiling_Abs_Temperature_Zone_0
Colorpicker item=Ceiling_Color_Zone_15 Colorpicker item=Ceiling_Color_Zone_15
Slider item=Ceiling_Temperature_Zone_15 Slider item=Ceiling_Temperature_Zone_15
Slider item=Ceiling_Abs_Temperature_Zone_15
} }
Frame label="Kitchen" { Frame label="Kitchen" {
Switch item=Kitchen_Toggle Switch item=Kitchen_Toggle
Slider item=Kitchen_Brightness Slider item=Kitchen_Brightness
Slider item=Kitchen_Temperature Slider item=Kitchen_Temperature
Slider item=Kitchen_Abs_Temperature
} }
} }
``` ```

View File

@@ -49,6 +49,8 @@ public class LifxBindingConstants {
public static final PercentType DEFAULT_BRIGHTNESS = PercentType.HUNDRED; public static final PercentType DEFAULT_BRIGHTNESS = PercentType.HUNDRED;
// List of all Channel IDs // List of all Channel IDs
public static final String CHANNEL_ABS_TEMPERATURE = "abstemperature";
public static final String CHANNEL_ABS_TEMPERATURE_ZONE = "abstemperaturezone";
public static final String CHANNEL_BRIGHTNESS = "brightness"; public static final String CHANNEL_BRIGHTNESS = "brightness";
public static final String CHANNEL_COLOR = "color"; public static final String CHANNEL_COLOR = "color";
public static final String CHANNEL_COLOR_ZONE = "colorzone"; public static final String CHANNEL_COLOR_ZONE = "colorzone";
@@ -62,12 +64,10 @@ public class LifxBindingConstants {
// List of all Channel Type UIDs // List of all Channel Type UIDs
public static final ChannelTypeUID CHANNEL_TYPE_BRIGHTNESS = new ChannelTypeUID(BINDING_ID, CHANNEL_BRIGHTNESS); public static final ChannelTypeUID CHANNEL_TYPE_BRIGHTNESS = new ChannelTypeUID(BINDING_ID, CHANNEL_BRIGHTNESS);
public static final ChannelTypeUID CHANNEL_TYPE_COLOR = new ChannelTypeUID(BINDING_ID, CHANNEL_COLOR); public static final ChannelTypeUID CHANNEL_TYPE_COLOR = new ChannelTypeUID(BINDING_ID, CHANNEL_COLOR);
public static final ChannelTypeUID CHANNEL_TYPE_COLOR_ZONE = new ChannelTypeUID(BINDING_ID, CHANNEL_COLOR_ZONE);
public static final ChannelTypeUID CHANNEL_TYPE_EFFECT = new ChannelTypeUID(BINDING_ID, CHANNEL_EFFECT); public static final ChannelTypeUID CHANNEL_TYPE_EFFECT = new ChannelTypeUID(BINDING_ID, CHANNEL_EFFECT);
public static final ChannelTypeUID CHANNEL_TYPE_HEV_CYCLE = new ChannelTypeUID(BINDING_ID, CHANNEL_HEV_CYCLE);
public static final ChannelTypeUID CHANNEL_TYPE_INFRARED = new ChannelTypeUID(BINDING_ID, CHANNEL_INFRARED); public static final ChannelTypeUID CHANNEL_TYPE_INFRARED = new ChannelTypeUID(BINDING_ID, CHANNEL_INFRARED);
public static final ChannelTypeUID CHANNEL_TYPE_TEMPERATURE = new ChannelTypeUID(BINDING_ID, CHANNEL_TEMPERATURE); public static final ChannelTypeUID CHANNEL_TYPE_TEMPERATURE = new ChannelTypeUID(BINDING_ID, CHANNEL_TEMPERATURE);
public static final ChannelTypeUID CHANNEL_TYPE_TEMPERATURE_ZONE = new ChannelTypeUID(BINDING_ID,
CHANNEL_TEMPERATURE_ZONE);
// List of options for effect channel // List of options for effect channel
public static final String CHANNEL_TYPE_EFFECT_OPTION_OFF = "off"; public static final String CHANNEL_TYPE_EFFECT_OPTION_OFF = "off";

View File

@@ -24,6 +24,8 @@ import org.openhab.core.thing.ThingUID;
@NonNullByDefault @NonNullByDefault
public interface LifxChannelFactory { public interface LifxChannelFactory {
Channel createAbsTemperatureZoneChannel(ThingUID thingUID, int index);
Channel createColorZoneChannel(ThingUID thingUID, int index); Channel createColorZoneChannel(ThingUID thingUID, int index);
Channel createTemperatureZoneChannel(ThingUID thingUID, int index); Channel createTemperatureZoneChannel(ThingUID thingUID, int index);

View File

@@ -14,22 +14,14 @@ package org.openhab.binding.lifx.internal;
import static org.openhab.binding.lifx.internal.LifxBindingConstants.*; import static org.openhab.binding.lifx.internal.LifxBindingConstants.*;
import java.util.Locale;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
import org.openhab.core.thing.Channel; import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.DefaultSystemChannelTypeProvider;
import org.openhab.core.thing.ThingUID; import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.builder.ChannelBuilder; import org.openhab.core.thing.binding.builder.ChannelBuilder;
import org.osgi.framework.Bundle;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
/** /**
* The {@link LifxChannelFactoryImpl} creates dynamic LIFX channels. * The {@link LifxChannelFactoryImpl} creates dynamic LIFX channels.
@@ -40,71 +32,22 @@ import org.osgi.service.component.annotations.Reference;
@Component(service = LifxChannelFactory.class) @Component(service = LifxChannelFactory.class)
public class LifxChannelFactoryImpl implements LifxChannelFactory { public class LifxChannelFactoryImpl implements LifxChannelFactory {
private static final String COLOR_ZONE_LABEL_KEY = "channel-type.lifx.colorzone.label"; @Override
private static final String COLOR_ZONE_DESCRIPTION_KEY = "channel-type.lifx.colorzone.description"; public Channel createAbsTemperatureZoneChannel(ThingUID thingUID, int index) {
return ChannelBuilder
private static final String TEMPERATURE_ZONE_LABEL_KEY = "channel-type.lifx.temperaturezone.label"; .create(new ChannelUID(thingUID, CHANNEL_ABS_TEMPERATURE_ZONE + index), CoreItemFactory.NUMBER)
private static final String TEMPERATURE_ZONE_DESCRIPTION_KEY = "channel-type.lifx.temperaturezone.description"; .withType(DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_COLOR_TEMPERATURE_ABS).build();
}
private @NonNullByDefault({}) Bundle bundle;
private @NonNullByDefault({}) TranslationProvider i18nProvider;
private @NonNullByDefault({}) LocaleProvider localeProvider;
@Override @Override
public Channel createColorZoneChannel(ThingUID thingUID, int index) { public Channel createColorZoneChannel(ThingUID thingUID, int index) {
String label = getText(COLOR_ZONE_LABEL_KEY, index); return ChannelBuilder.create(new ChannelUID(thingUID, CHANNEL_COLOR_ZONE + index), CoreItemFactory.COLOR)
String description = getText(COLOR_ZONE_DESCRIPTION_KEY, index); .withType(DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_COLOR).build();
return ChannelBuilder.create(new ChannelUID(thingUID, CHANNEL_COLOR_ZONE + index), "Color")
.withType(CHANNEL_TYPE_COLOR_ZONE).withLabel(label).withDescription(description).build();
} }
@Override @Override
public Channel createTemperatureZoneChannel(ThingUID thingUID, int index) { public Channel createTemperatureZoneChannel(ThingUID thingUID, int index) {
String label = getText(TEMPERATURE_ZONE_LABEL_KEY, index); return ChannelBuilder.create(new ChannelUID(thingUID, CHANNEL_TEMPERATURE_ZONE + index), CoreItemFactory.DIMMER)
String description = getText(TEMPERATURE_ZONE_DESCRIPTION_KEY, index); .withType(DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_TYPE_UID_COLOR_TEMPERATURE).build();
return ChannelBuilder.create(new ChannelUID(thingUID, CHANNEL_TEMPERATURE_ZONE + index), "Dimmer")
.withType(CHANNEL_TYPE_TEMPERATURE_ZONE).withLabel(label).withDescription(description).build();
}
private @Nullable String getDefaultText(String key) {
return i18nProvider.getText(bundle, key, key, Locale.ENGLISH);
}
private String getText(String key, Object... arguments) {
Locale locale = localeProvider != null ? localeProvider.getLocale() : Locale.ENGLISH;
if (i18nProvider == null) {
return key;
}
String text = i18nProvider.getText(bundle, key, getDefaultText(key), locale, arguments);
return text != null ? text : key;
}
@Activate
protected void activate(ComponentContext componentContext) {
this.bundle = componentContext.getBundleContext().getBundle();
}
@Deactivate
protected void deactivate(ComponentContext componentContext) {
this.bundle = null;
}
@Reference
protected void setTranslationProvider(TranslationProvider i18nProvider) {
this.i18nProvider = i18nProvider;
}
protected void unsetTranslationProvider(TranslationProvider i18nProvider) {
this.i18nProvider = null;
}
@Reference
protected void setLocaleProvider(LocaleProvider localeProvider) {
this.localeProvider = localeProvider;
}
protected void unsetLocaleProvider(LocaleProvider localeProvider) {
this.localeProvider = null;
} }
} }

View File

@@ -182,6 +182,7 @@ public class LifxLightHandler extends BaseThingHandler {
updateStateIfChanged(CHANNEL_BRIGHTNESS, hsb.getBrightness()); updateStateIfChanged(CHANNEL_BRIGHTNESS, hsb.getBrightness());
updateStateIfChanged(CHANNEL_TEMPERATURE, updateStateIfChanged(CHANNEL_TEMPERATURE,
kelvinToPercentType(updateColor.getKelvin(), features.getTemperatureRange())); kelvinToPercentType(updateColor.getKelvin(), features.getTemperatureRange()));
updateStateIfChanged(CHANNEL_ABS_TEMPERATURE, new DecimalType(updateColor.getKelvin()));
updateZoneChannels(powerState, colors); updateZoneChannels(powerState, colors);
} }
@@ -240,6 +241,7 @@ public class LifxLightHandler extends BaseThingHandler {
updateStateIfChanged(CHANNEL_COLOR_ZONE + i, updateColor.getHSB()); updateStateIfChanged(CHANNEL_COLOR_ZONE + i, updateColor.getHSB());
updateStateIfChanged(CHANNEL_TEMPERATURE_ZONE + i, updateStateIfChanged(CHANNEL_TEMPERATURE_ZONE + i,
kelvinToPercentType(updateColor.getKelvin(), features.getTemperatureRange())); kelvinToPercentType(updateColor.getKelvin(), features.getTemperatureRange()));
updateStateIfChanged(CHANNEL_ABS_TEMPERATURE_ZONE + i, new DecimalType(updateColor.getKelvin()));
} }
} }
} }
@@ -473,7 +475,8 @@ public class LifxLightHandler extends BaseThingHandler {
// retain non-zone channels // retain non-zone channels
for (Channel channel : getThing().getChannels()) { for (Channel channel : getThing().getChannels()) {
String channelId = channel.getUID().getId(); String channelId = channel.getUID().getId();
if (!channelId.startsWith(CHANNEL_COLOR_ZONE) && !channelId.startsWith(CHANNEL_TEMPERATURE_ZONE)) { if (!channelId.startsWith(CHANNEL_ABS_TEMPERATURE_ZONE) && !channelId.startsWith(CHANNEL_COLOR_ZONE)
&& !channelId.startsWith(CHANNEL_TEMPERATURE_ZONE)) {
newChannels.add(channel); newChannels.add(channel);
} }
} }
@@ -482,6 +485,7 @@ public class LifxLightHandler extends BaseThingHandler {
for (int i = 0; i < zones; i++) { for (int i = 0; i < zones; i++) {
newChannels.add(channelFactory.createColorZoneChannel(getThing().getUID(), i)); newChannels.add(channelFactory.createColorZoneChannel(getThing().getUID(), i));
newChannels.add(channelFactory.createTemperatureZoneChannel(getThing().getUID(), i)); newChannels.add(channelFactory.createTemperatureZoneChannel(getThing().getUID(), i));
newChannels.add(channelFactory.createAbsTemperatureZoneChannel(getThing().getUID(), i));
} }
updateThing(editThing().withChannels(newChannels).build()); updateThing(editThing().withChannels(newChannels).build());
@@ -552,6 +556,13 @@ public class LifxLightHandler extends BaseThingHandler {
private @Nullable Runnable getChannelCommandRunnable(ChannelUID channelUID, Command command) { private @Nullable Runnable getChannelCommandRunnable(ChannelUID channelUID, Command command) {
switch (channelUID.getId()) { switch (channelUID.getId()) {
case CHANNEL_ABS_TEMPERATURE:
case CHANNEL_TEMPERATURE:
if (command instanceof DecimalType) {
return () -> handleTemperatureCommand((DecimalType) command);
} else if (command instanceof IncreaseDecreaseType) {
return () -> handleIncreaseDecreaseTemperatureCommand((IncreaseDecreaseType) command);
}
case CHANNEL_BRIGHTNESS: case CHANNEL_BRIGHTNESS:
if (command instanceof PercentType) { if (command instanceof PercentType) {
return () -> handlePercentCommand((PercentType) command); return () -> handlePercentCommand((PercentType) command);
@@ -559,8 +570,6 @@ public class LifxLightHandler extends BaseThingHandler {
return () -> handleOnOffCommand((OnOffType) command); return () -> handleOnOffCommand((OnOffType) command);
} else if (command instanceof IncreaseDecreaseType) { } else if (command instanceof IncreaseDecreaseType) {
return () -> handleIncreaseDecreaseCommand((IncreaseDecreaseType) command); return () -> handleIncreaseDecreaseCommand((IncreaseDecreaseType) command);
} else {
return null;
} }
case CHANNEL_COLOR: case CHANNEL_COLOR:
if (command instanceof HSBType) { if (command instanceof HSBType) {
@@ -571,40 +580,29 @@ public class LifxLightHandler extends BaseThingHandler {
return () -> handleOnOffCommand((OnOffType) command); return () -> handleOnOffCommand((OnOffType) command);
} else if (command instanceof IncreaseDecreaseType) { } else if (command instanceof IncreaseDecreaseType) {
return () -> handleIncreaseDecreaseCommand((IncreaseDecreaseType) command); return () -> handleIncreaseDecreaseCommand((IncreaseDecreaseType) command);
} else {
return null;
} }
case CHANNEL_EFFECT: case CHANNEL_EFFECT:
if (command instanceof StringType && features.hasFeature(TILE_EFFECT)) { if (command instanceof StringType && features.hasFeature(TILE_EFFECT)) {
return () -> handleTileEffectCommand((StringType) command); return () -> handleTileEffectCommand((StringType) command);
} else {
return null;
} }
case CHANNEL_HEV_CYCLE: case CHANNEL_HEV_CYCLE:
if (command instanceof OnOffType) { if (command instanceof OnOffType) {
return () -> handleHevCycleCommand((OnOffType) command); return () -> handleHevCycleCommand((OnOffType) command);
} else {
return null;
} }
case CHANNEL_INFRARED: case CHANNEL_INFRARED:
if (command instanceof PercentType) { if (command instanceof PercentType) {
return () -> handleInfraredCommand((PercentType) command); return () -> handleInfraredCommand((PercentType) command);
} else if (command instanceof IncreaseDecreaseType) { } else if (command instanceof IncreaseDecreaseType) {
return () -> handleIncreaseDecreaseInfraredCommand((IncreaseDecreaseType) command); return () -> handleIncreaseDecreaseInfraredCommand((IncreaseDecreaseType) command);
} else {
return null;
}
case CHANNEL_TEMPERATURE:
if (command instanceof PercentType) {
return () -> handleTemperatureCommand((PercentType) command);
} else if (command instanceof IncreaseDecreaseType) {
return () -> handleIncreaseDecreaseTemperatureCommand((IncreaseDecreaseType) command);
} else {
return null;
} }
default: default:
try { try {
if (channelUID.getId().startsWith(CHANNEL_COLOR_ZONE)) { if (channelUID.getId().startsWith(CHANNEL_ABS_TEMPERATURE_ZONE)) {
int zoneIndex = Integer.parseInt(channelUID.getId().replace(CHANNEL_ABS_TEMPERATURE_ZONE, ""));
if (command instanceof DecimalType) {
return () -> handleTemperatureCommand((DecimalType) command, zoneIndex);
}
} else if (channelUID.getId().startsWith(CHANNEL_COLOR_ZONE)) {
int zoneIndex = Integer.parseInt(channelUID.getId().replace(CHANNEL_COLOR_ZONE, "")); int zoneIndex = Integer.parseInt(channelUID.getId().replace(CHANNEL_COLOR_ZONE, ""));
if (command instanceof HSBType) { if (command instanceof HSBType) {
return () -> handleHSBCommand((HSBType) command, zoneIndex); return () -> handleHSBCommand((HSBType) command, zoneIndex);
@@ -612,8 +610,6 @@ public class LifxLightHandler extends BaseThingHandler {
return () -> handlePercentCommand((PercentType) command, zoneIndex); return () -> handlePercentCommand((PercentType) command, zoneIndex);
} else if (command instanceof IncreaseDecreaseType) { } else if (command instanceof IncreaseDecreaseType) {
return () -> handleIncreaseDecreaseCommand((IncreaseDecreaseType) command, zoneIndex); return () -> handleIncreaseDecreaseCommand((IncreaseDecreaseType) command, zoneIndex);
} else {
return null;
} }
} else if (channelUID.getId().startsWith(CHANNEL_TEMPERATURE_ZONE)) { } else if (channelUID.getId().startsWith(CHANNEL_TEMPERATURE_ZONE)) {
int zoneIndex = Integer.parseInt(channelUID.getId().replace(CHANNEL_TEMPERATURE_ZONE, "")); int zoneIndex = Integer.parseInt(channelUID.getId().replace(CHANNEL_TEMPERATURE_ZONE, ""));
@@ -622,18 +618,14 @@ public class LifxLightHandler extends BaseThingHandler {
} else if (command instanceof IncreaseDecreaseType) { } else if (command instanceof IncreaseDecreaseType) {
return () -> handleIncreaseDecreaseTemperatureCommand((IncreaseDecreaseType) command, return () -> handleIncreaseDecreaseTemperatureCommand((IncreaseDecreaseType) command,
zoneIndex); zoneIndex);
} else {
return null;
} }
} else {
return null;
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
logger.error("Failed to parse zone index for a command of a light ({}) : {}", logId, logger.error("Failed to parse zone index for a command of a light ({}) : {}", logId,
e.getMessage()); e.getMessage());
return null;
} }
} }
return null;
} }
private LifxLightState getLightStateForCommand() { private LifxLightState getLightStateForCommand() {
@@ -650,6 +642,10 @@ public class LifxLightHandler extends BaseThingHandler {
private void handleRefreshCommand(ChannelUID channelUID) { private void handleRefreshCommand(ChannelUID channelUID) {
channelStates.remove(channelUID.getId()); channelStates.remove(channelUID.getId());
switch (channelUID.getId()) { switch (channelUID.getId()) {
case CHANNEL_ABS_TEMPERATURE:
case CHANNEL_TEMPERATURE:
sendPacket(new GetRequest());
break;
case CHANNEL_COLOR: case CHANNEL_COLOR:
case CHANNEL_BRIGHTNESS: case CHANNEL_BRIGHTNESS:
sendPacket(new GetLightPowerRequest()); sendPacket(new GetLightPowerRequest());
@@ -669,25 +665,22 @@ public class LifxLightHandler extends BaseThingHandler {
case CHANNEL_SIGNAL_STRENGTH: case CHANNEL_SIGNAL_STRENGTH:
sendPacket(new GetWifiInfoRequest()); sendPacket(new GetWifiInfoRequest());
break; break;
case CHANNEL_TEMPERATURE:
sendPacket(new GetRequest());
break;
default: default:
break; break;
} }
} }
private void handleTemperatureCommand(PercentType temperature) { private void handleTemperatureCommand(DecimalType temperature) {
HSBK newColor = getLightStateForCommand().getColor(); HSBK newColor = getLightStateForCommand().getColor();
newColor.setSaturation(PercentType.ZERO); newColor.setSaturation(PercentType.ZERO);
newColor.setKelvin(percentTypeToKelvin(temperature, features.getTemperatureRange())); newColor.setKelvin(commandToKelvin(temperature, features.getTemperatureRange()));
getLightStateForCommand().setColor(newColor); getLightStateForCommand().setColor(newColor);
} }
private void handleTemperatureCommand(PercentType temperature, int zoneIndex) { private void handleTemperatureCommand(DecimalType temperature, int zoneIndex) {
HSBK newColor = getLightStateForCommand().getColor(zoneIndex); HSBK newColor = getLightStateForCommand().getColor(zoneIndex);
newColor.setSaturation(PercentType.ZERO); newColor.setSaturation(PercentType.ZERO);
newColor.setKelvin(percentTypeToKelvin(temperature, features.getTemperatureRange())); newColor.setKelvin(commandToKelvin(temperature, features.getTemperatureRange()));
getLightStateForCommand().setColor(newColor, zoneIndex); getLightStateForCommand().setColor(newColor, zoneIndex);
} }

View File

@@ -102,6 +102,16 @@ public final class LifxMessageUtil {
return new PercentType(value); return new PercentType(value);
} }
public static int commandToKelvin(DecimalType temperature, TemperatureRange temperatureRange) {
return temperature instanceof PercentType ? percentTypeToKelvin((PercentType) temperature, temperatureRange)
: decimalTypeToKelvin(temperature, temperatureRange);
}
public static int decimalTypeToKelvin(DecimalType temperature, TemperatureRange temperatureRange) {
return Math.round(Math.min(Math.max(temperature.intValue(), temperatureRange.getMinimum()),
temperatureRange.getMaximum()));
}
public static int percentTypeToKelvin(PercentType temperature, TemperatureRange temperatureRange) { public static int percentTypeToKelvin(PercentType temperature, TemperatureRange temperatureRange) {
return Math.round( return Math.round(
temperatureRange.getMaximum() - (temperature.floatValue() * (temperatureRange.getRange() / 100))); temperatureRange.getMaximum() - (temperature.floatValue() * (temperatureRange.getRange() / 100)));

View File

@@ -20,24 +20,20 @@ thing-type.config.lifx.light.fadetime.description = The time to fade to the new
# channel types # channel types
channel-type.lifx.brightness.label = Brightness channel-type.lifx.brightness.label = Brightness
channel-type.lifx.brightness.description = Sets the brightness of the light channel-type.lifx.brightness.description = Controls the brightness and switches the light on and off
channel-type.lifx.color.label = Color channel-type.lifx.color.label = Color
channel-type.lifx.color.description = Selects the color of the light channel-type.lifx.color.description = Controls the color of the light
channel-type.lifx.colorzone.label = Color Zone {0}
channel-type.lifx.colorzone.description = Selects the zone {0} color of the light
channel-type.lifx.effect.label = Effect channel-type.lifx.effect.label = Effect
channel-type.lifx.effect.description = Sets the effect of the light channel-type.lifx.effect.description = Controls the effect of the light
channel-type.lifx.effect.state.option.off = Off channel-type.lifx.effect.state.option.off = Off
channel-type.lifx.effect.state.option.morph = Morph channel-type.lifx.effect.state.option.morph = Morph
channel-type.lifx.effect.state.option.flame = Flame channel-type.lifx.effect.state.option.flame = Flame
channel-type.lifx.hevcycle.label = HEV Cycle channel-type.lifx.hevcycle.label = HEV Cycle
channel-type.lifx.hevcycle.description = Controls the HEV clean cycle of the light channel-type.lifx.hevcycle.description = Controls the HEV clean cycle of the light
channel-type.lifx.infrared.label = Infrared channel-type.lifx.infrared.label = Infrared
channel-type.lifx.infrared.description = Sets the infrared of the light channel-type.lifx.infrared.description = Controls the infrared level of the light
channel-type.lifx.temperature.label = Temperature channel-type.lifx.temperature.label = Color Temperature
channel-type.lifx.temperature.description = Sets the temperature of the light channel-type.lifx.temperature.description = Controls the color temperature of the light from 0 (cold) to 100 (warm)
channel-type.lifx.temperaturezone.label = Temperature Zone {0}
channel-type.lifx.temperaturezone.description = Sets the zone {0} temperature of the light
# channel type configuration # channel type configuration
channel-type.config.lifx.brightness.powerOnBrightness.label = Power On Brightness channel-type.config.lifx.brightness.powerOnBrightness.label = Power On Brightness

View File

@@ -20,24 +20,20 @@ thing-type.config.lifx.light.fadetime.description = De tijdsduur van het vervage
# channel types # channel types
channel-type.lifx.brightness.label = Helderheid channel-type.lifx.brightness.label = Helderheid
channel-type.lifx.brightness.description = Bepaalt de helderheid van de lamp channel-type.lifx.brightness.description = Bepaalt de helderheid en schakelt het licht aan en uit
channel-type.lifx.color.label = Kleur channel-type.lifx.color.label = Kleur
channel-type.lifx.color.description = Bepaalt de kleur van de lamp channel-type.lifx.color.description = Bepaalt de kleur van het licht
channel-type.lifx.colorzone.label = Kleur Zone {0}
channel-type.lifx.colorzone.description = Bepaalt de kleur van lampzone {0}
channel-type.lifx.effect.label = Effect channel-type.lifx.effect.label = Effect
channel-type.lifx.effect.description = Bepaalt het lichteffect channel-type.lifx.effect.description = Bepaalt het lichteffect
channel-type.lifx.effect.state.option.off = Uit channel-type.lifx.effect.state.option.off = Uit
channel-type.lifx.effect.state.option.morph = Morph channel-type.lifx.effect.state.option.morph = Morph
channel-type.lifx.effect.state.option.flame = Vlam channel-type.lifx.effect.state.option.flame = Vlam
channel-type.lifx.hevcycle.label = HEV Cyclus channel-type.lifx.hevcycle.label = HEV Cyclus
channel-type.lifx.hevcycle.description = Bedient de HEV schoonmaakcylcus van de lamp channel-type.lifx.hevcycle.description = Bedient de HEV schoonmaakcyclus van de lamp
channel-type.lifx.infrared.label = Infrarood channel-type.lifx.infrared.label = Infrarood
channel-type.lifx.infrared.description = Bepaalt het infraroodniveau van de lamp channel-type.lifx.infrared.description = Bepaalt het infraroodniveau van de lamp
channel-type.lifx.temperature.label = Temperatuur channel-type.lifx.temperature.label = Kleurtemperatuur
channel-type.lifx.temperature.description = Bepaalt de kleurtemperatuur van de lamp channel-type.lifx.temperature.description = Bepaalt de kleurtemperatuur van het licht van 0 (koud) tot 100 (warm)
channel-type.lifx.temperaturezone.label = Temperatuur Zone {0}
channel-type.lifx.temperaturezone.description = Bepaalt de kleurtemperatuur van lampzone {0}
# channel type configuration # channel type configuration
channel-type.config.lifx.brightness.powerOnBrightness.label = Inschakelhelderheid channel-type.config.lifx.brightness.powerOnBrightness.label = Inschakelhelderheid

View File

@@ -7,10 +7,11 @@
<channel-type id="brightness"> <channel-type id="brightness">
<item-type>Dimmer</item-type> <item-type>Dimmer</item-type>
<label>Brightness</label> <label>Brightness</label>
<description>Sets the brightness of the light</description> <description>Controls the brightness and switches the light on and off</description>
<category>DimmableLight</category> <category>DimmableLight</category>
<tags> <tags>
<tag>Lighting</tag> <tag>Control</tag>
<tag>Light</tag>
</tags> </tags>
<config-description-ref uri="channel-type:lifx:brightness"/> <config-description-ref uri="channel-type:lifx:brightness"/>
</channel-type> </channel-type>
@@ -18,56 +19,56 @@
<channel-type id="color"> <channel-type id="color">
<item-type>Color</item-type> <item-type>Color</item-type>
<label>Color</label> <label>Color</label>
<description>Selects the color of the light</description> <description>Controls the color of the light</description>
<category>ColorLight</category> <category>ColorLight</category>
<tags> <tags>
<tag>Lighting</tag> <tag>Control</tag>
<tag>Light</tag>
</tags> </tags>
<config-description-ref uri="channel-type:lifx:color"/> <config-description-ref uri="channel-type:lifx:color"/>
</channel-type> </channel-type>
<channel-type id="colorzone" advanced="true">
<item-type>Color</item-type>
<label>Color Zone</label>
<description>Selects the zone color of the light</description>
<category>ColorLight</category>
<tags>
<tag>Lighting</tag>
</tags>
</channel-type>
<channel-type id="hevcycle"> <channel-type id="hevcycle">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>HEV Cycle</label> <label>HEV Cycle</label>
<description>Controls the HEV clean cycle of the light</description> <description>Controls the HEV clean cycle of the light</description>
<tags>
<tag>Control</tag>
<tag>Light</tag>
</tags>
<config-description-ref uri="channel-type:lifx:hevcycle"/> <config-description-ref uri="channel-type:lifx:hevcycle"/>
</channel-type> </channel-type>
<channel-type id="infrared"> <channel-type id="infrared">
<item-type>Dimmer</item-type> <item-type>Dimmer</item-type>
<label>Infrared</label> <label>Infrared</label>
<description>Sets the infrared of the light</description> <description>Controls the infrared level of the light</description>
<tags>
<tag>Control</tag>
<tag>Light</tag>
</tags>
</channel-type> </channel-type>
<channel-type id="temperature"> <channel-type id="temperature">
<item-type>Dimmer</item-type> <item-type>Dimmer</item-type>
<label>Temperature</label> <label>Color Temperature</label>
<description>Sets the temperature of the light</description> <description>Controls the color temperature of the light from 0 (cold) to 100 (warm)</description>
<category>ColorLight</category> <category>ColorLight</category>
<tags>
<tag>Control</tag>
<tag>ColorTemperature</tag>
</tags>
<config-description-ref uri="channel-type:lifx:temperature"/> <config-description-ref uri="channel-type:lifx:temperature"/>
</channel-type> </channel-type>
<channel-type id="temperaturezone" advanced="true">
<item-type>Dimmer</item-type>
<label>Temperature Zone</label>
<description>Sets the zone temperature of the light</description>
<category>ColorLight</category>
</channel-type>
<channel-type id="effect"> <channel-type id="effect">
<item-type>String</item-type> <item-type>String</item-type>
<label>Effect</label> <label>Effect</label>
<description>Sets the effect of the light</description> <description>Controls the effect of the light</description>
<tags>
<tag>Control</tag>
<tag>Light</tag>
</tags>
<state> <state>
<options> <options>
<option value="off">Off</option> <option value="off">Off</option>

View File

@@ -9,6 +9,7 @@
<channels> <channels>
<channel id="color" typeId="color"/> <channel id="color" typeId="color"/>
<channel id="temperature" typeId="temperature"/> <channel id="temperature" typeId="temperature"/>
<channel id="abstemperature" typeId="system.color-temperature-abs"/>
<channel id="hevcycle" typeId="hevcycle"/> <channel id="hevcycle" typeId="hevcycle"/>
<channel id="signalstrength" typeId="system.signal-strength"/> <channel id="signalstrength" typeId="system.signal-strength"/>
</channels> </channels>

View File

@@ -9,6 +9,7 @@
<channels> <channels>
<channel id="color" typeId="color"/> <channel id="color" typeId="color"/>
<channel id="temperature" typeId="temperature"/> <channel id="temperature" typeId="temperature"/>
<channel id="abstemperature" typeId="system.color-temperature-abs"/>
<channel id="infrared" typeId="infrared"/> <channel id="infrared" typeId="infrared"/>
<channel id="signalstrength" typeId="system.signal-strength"/> <channel id="signalstrength" typeId="system.signal-strength"/>
</channels> </channels>

View File

@@ -9,6 +9,7 @@
<channels> <channels>
<channel id="color" typeId="color"/> <channel id="color" typeId="color"/>
<channel id="temperature" typeId="temperature"/> <channel id="temperature" typeId="temperature"/>
<channel id="abstemperature" typeId="system.color-temperature-abs"/>
<channel id="signalstrength" typeId="system.signal-strength"/> <channel id="signalstrength" typeId="system.signal-strength"/>
</channels> </channels>
<representation-property>macAddress</representation-property> <representation-property>macAddress</representation-property>

View File

@@ -9,6 +9,7 @@
<channels> <channels>
<channel id="color" typeId="color"/> <channel id="color" typeId="color"/>
<channel id="temperature" typeId="temperature"/> <channel id="temperature" typeId="temperature"/>
<channel id="abstemperature" typeId="system.color-temperature-abs"/>
<channel id="signalstrength" typeId="system.signal-strength"/> <channel id="signalstrength" typeId="system.signal-strength"/>
</channels> </channels>
<representation-property>macAddress</representation-property> <representation-property>macAddress</representation-property>

View File

@@ -9,6 +9,7 @@
<channels> <channels>
<channel id="color" typeId="color"/> <channel id="color" typeId="color"/>
<channel id="temperature" typeId="temperature"/> <channel id="temperature" typeId="temperature"/>
<channel id="abstemperature" typeId="system.color-temperature-abs"/>
<channel id="signalstrength" typeId="system.signal-strength"/> <channel id="signalstrength" typeId="system.signal-strength"/>
<channel id="effect" typeId="effect"/> <channel id="effect" typeId="effect"/>
</channels> </channels>

View File

@@ -9,6 +9,7 @@
<channels> <channels>
<channel id="brightness" typeId="brightness"/> <channel id="brightness" typeId="brightness"/>
<channel id="temperature" typeId="temperature"/> <channel id="temperature" typeId="temperature"/>
<channel id="abstemperature" typeId="system.color-temperature-abs"/>
<channel id="signalstrength" typeId="system.signal-strength"/> <channel id="signalstrength" typeId="system.signal-strength"/>
</channels> </channels>
<representation-property>macAddress</representation-property> <representation-property>macAddress</representation-property>