diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCommand.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCommand.java index c3103ebe91dbe..b6365097c8d18 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCommand.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCommand.java @@ -35,6 +35,7 @@ public enum MiIoCommand { SET_MODE_BASIC("set_mode"), SET_POWER("set_power"), SET_BRIGHT("set_bright"), + SET_RGB("set_rgb"), SET_WIFI_LET("set_wifi_led"), SET_FAVORITE("set_level_favorite"), ACTION("action"), diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/ActionConditions.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/ActionConditions.java index fdc92223f03b2..fb86a4aadf300 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/ActionConditions.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/ActionConditions.java @@ -16,6 +16,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.HSBType; +import org.eclipse.smarthome.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,35 +42,33 @@ public class ActionConditions { * @return value in case firmware is matching, return null if not */ private static @Nullable JsonElement firmwareCheck(MiIoDeviceActionCondition condition, - Map deviceVariables, @Nullable JsonElement value) { + @Nullable Map deviceVariables, @Nullable JsonElement value) { // TODO: placeholder for firmware version check to allow for firmware dependent actions return value; } /** - * Check if the value is a valid brightness between 1-99. - * If <1 returns Off, if >99 returns On to activate the power On/Off switch + * Check if the value is a valid brightness for operating power On/Off switch. + * If brightness <1 returns Off, if >=1 returns On * * @param value * @return */ private static @Nullable JsonElement brightness(@Nullable JsonElement value) { if (value != null && value.isJsonPrimitive() && value.getAsJsonPrimitive().isNumber()) { - int intVal = value.getAsInt(); - if (intVal > 99) { - return new JsonPrimitive("on"); - } - if (intVal < 1) { + if (value.getAsInt() < 1) { return new JsonPrimitive("off"); + } else { + return new JsonPrimitive("on"); } } else { LOGGER.debug("Could not parse brightness. Value '{}' is not an int", value); } - return null; + return value; } /** - * Check if the value is a valid brightness between 1-99 which can be send to brightness channel. + * Check if the value is a valid brightness between 1-100 which can be send to brightness channel. * If not returns a null * * @param value @@ -77,17 +77,36 @@ public class ActionConditions { private static @Nullable JsonElement brightnessExists(@Nullable JsonElement value) { if (value != null && value.isJsonPrimitive() && value.getAsJsonPrimitive().isNumber()) { int intVal = value.getAsInt(); - if (intVal > 0 && intVal < 99) { + if (intVal > 0 && intVal <= 100) { return value; + } else if (intVal > 100) { + return new JsonPrimitive(100); } + return null; } else { LOGGER.debug("Could not parse brightness. Value '{}' is not an int", value); } + return value; + } + + /** + * Check if the value is a color which can be send to Color channel. + * If not returns a null + * + * @param command + * + * @param value + * @return + */ + private static @Nullable JsonElement hsbOnly(@Nullable Command command, @Nullable JsonElement value) { + if (command != null && command instanceof HSBType) { + return value; + } return null; } public static @Nullable JsonElement executeAction(MiIoDeviceActionCondition condition, - Map deviceVariables, @Nullable JsonElement value) { + @Nullable Map deviceVariables, @Nullable JsonElement value, @Nullable Command command) { switch (condition.getName().toUpperCase()) { case "FIRMWARE": return firmwareCheck(condition, deviceVariables, value); @@ -95,6 +114,8 @@ public class ActionConditions { return brightnessExists(value); case "BRIGHTNESSONOFF": return brightness(value); + case "HSBONLY": + return hsbOnly(command, value); default: LOGGER.debug("Condition {} not found. Returning '{}'", condition, value != null ? value.toString() : ""); diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java index 43c55131f1414..4d2827494a5fd 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java @@ -130,7 +130,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { if (channelUID.getId().equals(CHANNEL_COMMAND)) { cmds.put(sendCommand(command.toString()), command.toString()); } - logger.debug("Locating action for channel {}: {}", channelUID.getId(), command); + logger.debug("Locating action for channel '{}': '{}'", channelUID.getId(), command); if (!actions.isEmpty()) { if (actions.containsKey(channelUID)) { int valuePos = 0; @@ -156,8 +156,9 @@ public void handleCommand(ChannelUID channelUID, Command command) { (color.getRed() << 16) + (color.getGreen() << 8) + color.getBlue()); } else if (command instanceof DecimalType) { // actually brightness is being set instead of a color - cmd = "set_bright"; value = new JsonPrimitive(((DecimalType) command).toBigDecimal()); + } else if (command instanceof OnOffType) { + value = new JsonPrimitive(command == OnOffType.ON ? 100 : 0); } else { logger.debug("Unsupported command for COLOR: {}", command); } @@ -184,14 +185,15 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else { value = new JsonPrimitive(command.toString().toLowerCase()); } + final MiIoDeviceActionCondition miIoDeviceActionCondition = action.getCondition(); + if (miIoDeviceActionCondition != null) { + value = ActionConditions.executeAction(miIoDeviceActionCondition, deviceVariables, value, + command); + } // Check for miot channel if (miIoBasicChannel.isMiOt()) { value = miotTransform(miIoBasicChannel, value); } - final MiIoDeviceActionCondition miIoDeviceActionCondition = action.getCondition(); - if (miIoDeviceActionCondition != null) { - value = ActionConditions.executeAction(miIoDeviceActionCondition, deviceVariables, value); - } if (paramType != CommandParameterType.NONE && value != null) { if (parameters.size() > 0) { parameters.set(valuePos, value); @@ -357,7 +359,13 @@ private boolean buildChannelStructure(String deviceName) { if (channelUID != null) { actions.put(channelUID, miChannel); channelsAdded++; + } else { + logger.debug("Channel for {} ({}) not loaded", miChannel.getChannel(), + miChannel.getFriendlyName()); } + } else { + logger.debug("Channel {} ({}), not loaded, missing type", miChannel.getChannel(), + miChannel.getFriendlyName()); } } } diff --git a/bundles/org.openhab.binding.miio/src/main/resources/database/yeelink.light.color1.json b/bundles/org.openhab.binding.miio/src/main/resources/database/yeelink.light.color1.json index 37c6bfe0d7402..cb8e63dc9941e 100644 --- a/bundles/org.openhab.binding.miio/src/main/resources/database/yeelink.light.color1.json +++ b/bundles/org.openhab.binding.miio/src/main/resources/database/yeelink.light.color1.json @@ -10,6 +10,7 @@ "yeelink.light.bslamp1", "yeelink.light.bslamp2" ], + "maxProperties": 7, "channels": [ { "property": "power", @@ -53,7 +54,7 @@ "property": "delayoff", "friendlyName": "Shutdown Timer", "channel": "delayoff", - "type": "String", + "type": "Number", "refresh": true, "ChannelGroup": "actions", "actions": [ @@ -120,13 +121,28 @@ { "command": "set_rgb", "parameterType": "COLOR", - "parameter1": "\"smooth\"", - "parameter2": "500", + "condition": { + "name": "HSBOnly" + }, "parameters": [ "$value$", "smooth", 500 ] + }, + { + "command": "set_bright", + "parameterType": "NUMBER", + "condition": { + "name": "BrightnessExisting" + } + }, + { + "command": "set_power", + "parameterType": "ONOFF", + "condition": { + "name": "BrightnessOnOff" + } } ] }, diff --git a/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/ActionConditionTest.java b/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/ActionConditionTest.java new file mode 100644 index 0000000000000..8f11fd0f86179 --- /dev/null +++ b/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/ActionConditionTest.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.miio.internal; + +import static org.junit.Assert.*; + +import java.util.Collections; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.Test; +import org.openhab.binding.miio.internal.basic.ActionConditions; +import org.openhab.binding.miio.internal.basic.MiIoDeviceActionCondition; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +/** + * Test case for {@link ActionConditions} + * + * @author Marcel Verpaalen - Initial contribution + * + */ +@NonNullByDefault +public class ActionConditionTest { + + @Test + public void assertBrightnessExisting() { + MiIoDeviceActionCondition condition = new MiIoDeviceActionCondition(); + condition.setName("BrightnessExisting"); + Map deviceVariables = Collections.emptyMap(); + JsonElement value = new JsonPrimitive(1); + JsonElement resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + // dimmed to 1 + assertNotNull(resp); + assertEquals(new JsonPrimitive(1), resp); + + // fully on + value = new JsonPrimitive(100); + resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + assertNotNull(resp); + assertEquals(new JsonPrimitive(100), resp); + + // >100 + value = new JsonPrimitive(200); + resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + assertNotNull(resp); + assertEquals(new JsonPrimitive(100), resp); + + // switched off = invalid brightness + value = new JsonPrimitive(0); + resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + assertNull(resp); + assertNotEquals(new JsonPrimitive(0), resp); + + value = new JsonPrimitive(-1); + resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + assertNull(resp); + assertNotEquals(new JsonPrimitive(-1), resp); + } +}