diff --git a/bundles/org.openhab.binding.hdpowerview/README.md b/bundles/org.openhab.binding.hdpowerview/README.md index cda450a74d1d4..339069015ed18 100644 --- a/bundles/org.openhab.binding.hdpowerview/README.md +++ b/bundles/org.openhab.binding.hdpowerview/README.md @@ -129,12 +129,13 @@ On Generation 3 gateways the signal strength is displayed in dBm (deciBel-milliW ### Channels for Repeaters (Thing type `repeater`)[1/2] -| Channel | Item Type | Description | -|-----------------|-----------|---------------------------------------------------------------------------------------------| -| color | Color | Controls the color of the LED ring. A switch item can be linked: ON = white, OFF = turn off | -| brightness | Dimmer | Controls the brightness of the LED ring. | -| identify | String | Flash repeater to identify. Valid values are: `IDENTIFY` | -| blinkingEnabled | Switch | Blink during commands. | +| Channel | Item Type | Description | +|-----------------|-----------|----------------------------------------------------------| +| color | Color | Controls the color of the LED ring. | +| color | Dimmer | Controls the brightness of the LED ring. | +| color | Switch | Switches the LED ring on or off. | +| identify | String | Flash repeater to identify. Valid values are: `IDENTIFY` | +| blinkingEnabled | Switch | Blink during commands. | ### Roller Shutter Up/Down Position vs. Open/Close State @@ -292,7 +293,7 @@ Repeater items[1/2]: ```java Color Bedroom_Repeater_Color "Bedroom Repeater Color" {channel="hdpowerview:repeater:home:r16384:color"} -Dimmer Bedroom_Repeater_Brightness "Bedroom Repeater Brightness" {channel="hdpowerview:repeater:home:r16384:brightness"} +Dimmer Bedroom_Repeater_Brightness "Bedroom Repeater Brightness" {channel="hdpowerview:repeater:home:r16384:color"} String Bedroom_Repeater_Identify "Bedroom Repeater Identify" {channel="hdpowerview:repeater:home:r16384:identify"} Switch Bedroom_Repeater_BlinkingEnabled "Bedroom Repeater Blinking Enabled [%s]" {channel="hdpowerview:repeater:home:r16384:blinkingEnabled"} ``` diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java index 6649024bae82c..34d070858e999 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java @@ -51,7 +51,6 @@ public class HDPowerViewBindingConstants { public static final String CHANNEL_SHADE_REPEATER_RSSI = "repeaterRssi"; public static final String CHANNEL_REPEATER_COLOR = "color"; - public static final String CHANNEL_REPEATER_BRIGHTNESS = "brightness"; public static final String CHANNEL_REPEATER_IDENTIFY = "identify"; public static final String CHANNEL_REPEATER_BLINKING_ENABLED = "blinkingEnabled"; diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java index 631cfb6ba7540..3d6c33ca92965 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java @@ -34,6 +34,10 @@ public Color(int brightness, java.awt.Color color) { this(brightness, color.getRed(), color.getGreen(), color.getBlue()); } + public Color(int brightness, Color color) { + this(brightness, color.red, color.green, color.blue); + } + public Color(int brightness, int red, int green, int blue) { this.brightness = brightness; this.red = red; @@ -41,6 +45,10 @@ public Color(int brightness, int red, int green, int blue) { this.blue = blue; } + public boolean isBlack() { + return red == 0 && green == 0 && blue == 0; + } + @Override public String toString() { return String.format("%d.%d.%d/%d%%", red, green, blue, brightness); diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewRepeaterHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewRepeaterHandler.java index 1d806fb9bf982..e5d456b4aaeba 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewRepeaterHandler.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewRepeaterHandler.java @@ -28,6 +28,7 @@ import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException; import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException; import org.openhab.core.library.types.HSBType; +import org.openhab.core.library.types.IncreaseDecreaseType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.StringType; @@ -37,6 +38,7 @@ import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.types.Command; +import org.openhab.core.types.RefreshType; import org.openhab.core.types.UnDefType; import org.openhab.core.util.ColorUtil; import org.slf4j.Logger; @@ -54,6 +56,7 @@ public class HDPowerViewRepeaterHandler extends AbstractHubbedThingHandler { private static final int REFRESH_INTERVAL_MINUTES = 5; private static final int IDENTITY_PERIOD_SECONDS = 3; + private static final int BRIGHTNESS_STEP_PERCENT = 5; private static final String COMMAND_IDENTIFY = "IDENTIFY"; private @Nullable ScheduledFuture refreshStatusFuture = null; @@ -94,40 +97,17 @@ public void handleCommand(ChannelUID channelUID, Command command) { logger.warn("Missing bridge handler"); return; } + if (command == RefreshType.REFRESH) { + scheduleRefreshJob(); + return; + } HDPowerViewWebTargets webTargets = bridge.getWebTargets(); try { RepeaterData repeaterData; switch (channelUID.getId()) { case CHANNEL_REPEATER_COLOR: - if (command instanceof HSBType hsbCommand) { - Color currentColor = webTargets.getRepeater(repeaterId).color; - if (currentColor != null) { - var color = new Color(currentColor.brightness, ColorUtil.hsbTosRgb(hsbCommand)); - repeaterData = webTargets.setRepeaterColor(repeaterId, color); - scheduler.submit(() -> updatePropertyAndStates(repeaterData)); - } - } else if (command instanceof OnOffType) { - Color currentColor = webTargets.getRepeater(repeaterId).color; - if (currentColor != null) { - var color = command == OnOffType.ON - ? new Color(currentColor.brightness, java.awt.Color.WHITE) - : new Color(currentColor.brightness, java.awt.Color.BLACK); - repeaterData = webTargets.setRepeaterColor(repeaterId, color); - scheduler.submit(() -> updatePropertyAndStates(repeaterData)); - } - } - break; - case CHANNEL_REPEATER_BRIGHTNESS: - if (command instanceof PercentType brightnessCommand) { - Color currentColor = webTargets.getRepeater(repeaterId).color; - if (currentColor != null) { - var color = new Color(brightnessCommand.intValue(), currentColor.red, currentColor.green, - currentColor.blue); - repeaterData = webTargets.setRepeaterColor(repeaterId, color); - scheduler.submit(() -> updatePropertyAndStates(repeaterData)); - } - } + handleColorCommand(command, webTargets); break; case CHANNEL_REPEATER_IDENTIFY: if (command instanceof StringType stringCommand) { @@ -163,6 +143,54 @@ public void handleCommand(ChannelUID channelUID, Command command) { } } + private void handleColorCommand(Command command, HDPowerViewWebTargets webTargets) throws HubException { + if (command instanceof HSBType hsbCommand) { + var color = new Color(hsbCommand.getBrightness().intValue(), ColorUtil.hsbTosRgb(hsbCommand)); + RepeaterData repeaterData = webTargets.setRepeaterColor(repeaterId, color); + scheduler.submit(() -> updatePropertyAndStates(repeaterData)); + return; + } + Color currentColor = webTargets.getRepeater(repeaterId).color; + if (currentColor == null) { + return; + } + Color newColor; + if (command instanceof PercentType brightnessCommand) { + newColor = applyBrightnessToColor(currentColor, brightnessCommand.intValue()); + } else if (command instanceof IncreaseDecreaseType increaseDecreaseCommand) { + int brightness = switch (increaseDecreaseCommand) { + case INCREASE -> currentColor.brightness + BRIGHTNESS_STEP_PERCENT; + case DECREASE -> currentColor.brightness - BRIGHTNESS_STEP_PERCENT; + }; + brightness = brightness < 0 ? 0 : brightness > 100 ? 100 : brightness; + newColor = applyBrightnessToColor(currentColor, brightness); + } else if (command instanceof OnOffType) { + // Light is turned off either by RGB black or zero brightness. + int brightness; + if (command == OnOffType.ON) { + // Turn on with maximum brightness level per default, + // if no existing brightness level is available. + brightness = currentColor.brightness > 0 ? currentColor.brightness : 100; + } else { + // Turn off by zero brightness to preserve color. + brightness = 0; + } + newColor = applyBrightnessToColor(currentColor, brightness); + } else { + logger.warn("Unsupported command: {}", command); + return; + } + RepeaterData repeaterData = webTargets.setRepeaterColor(repeaterId, newColor); + scheduler.submit(() -> updatePropertyAndStates(repeaterData)); + } + + private Color applyBrightnessToColor(Color currentColor, int brightness) { + // If light is off by RGB black, then reset to white since otherwise brightness + // would have no effect; otherwise preserve color. + return currentColor.isBlack() ? new Color(brightness, java.awt.Color.WHITE) + : new Color(brightness, currentColor); + } + private void cancelResetIdentifyStateJob() { ScheduledFuture scheduledJob = resetIdentifyStateFuture; if (scheduledJob != null) { @@ -182,7 +210,7 @@ private void scheduleRefreshJob() { private void cancelRefreshJob() { ScheduledFuture future = this.refreshStatusFuture; if (future != null) { - future.cancel(false); + future.cancel(true); } this.refreshStatusFuture = null; } @@ -228,10 +256,17 @@ private void updatePropertyAndStates(RepeaterData repeaterData) { Color color = repeaterData.color; if (color != null) { logger.debug("Repeater color data received: {}", color.toString()); - updateState(CHANNEL_REPEATER_COLOR, HSBType.fromRGB(color.red, color.green, color.red)); - updateState(CHANNEL_REPEATER_BRIGHTNESS, new PercentType(color.brightness)); + HSBType hsb; + if (color.isBlack()) { + // Light is off when RGB black, so discard brightness as otherwise it would appear on. + hsb = HSBType.BLACK; + } else { + hsb = HSBType.fromRGB(color.red, color.green, color.red); + hsb = new HSBType(hsb.getHue(), hsb.getSaturation(), new PercentType(color.brightness)); + } + updateState(CHANNEL_REPEATER_COLOR, hsb); } - updateState(CHANNEL_REPEATER_BLINKING_ENABLED, repeaterData.blinkEnabled ? OnOffType.ON : OnOffType.OFF); + updateState(CHANNEL_REPEATER_BLINKING_ENABLED, OnOffType.from(repeaterData.blinkEnabled)); } } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties index fc10667c8eb4a..8785d2082b3fe 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties @@ -11,8 +11,7 @@ thing-type.hdpowerview.hub.label = PowerView Hub thing-type.hdpowerview.hub.description = Hunter Douglas (Luxaflex) PowerView Hub thing-type.hdpowerview.repeater.label = PowerView Repeater thing-type.hdpowerview.repeater.description = Hunter Douglas (Luxaflex) PowerView Repeater -thing-type.hdpowerview.repeater.channel.brightness.description = Controls the brightness of the LED ring -thing-type.hdpowerview.repeater.channel.color.description = Controls the color of the LED ring +thing-type.hdpowerview.repeater.channel.color.description = Controls the color and brightness of the LED ring thing-type.hdpowerview.shade.label = PowerView Shade thing-type.hdpowerview.shade.description = Hunter Douglas (Luxaflex) PowerView Gen 1/2 Shade thing-type.hdpowerview.shade.channel.hubRssi.label = Hub RSSI diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/repeater.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/repeater.xml index c415c5140f19b..60babc67de520 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/repeater.xml +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/repeater.xml @@ -13,16 +13,14 @@ - Controls the color of the LED ring - - - Controls the brightness of the LED ring + Controls the color and brightness of the LED ring + 1 Hunter Douglas (Luxaflex) PowerView Repeater diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml index 70a692f2f238d..bf5468878a3ea 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml @@ -3,19 +3,9 @@ xmlns:update="https://openhab.org/schemas/update-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd"> - + - - powerview:shade-position - - - powerview:shade-position - - The secondary vertical position (on top-down/bottom-up shades) - - - powerview:shade-vane - +