[avmfritz] Allow to set every userdefined color (#13317)

* Added INCREASE/DECREASE commands for brightness/color Channels
* Fixed NPE in HeatingModel
* Use set unmapped color command for color control of bulbs

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
Christoph Weitkamp 2022-09-03 14:42:31 +02:00 committed by GitHub
parent df432a7fbc
commit 32c76898c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 71 additions and 7 deletions

View File

@ -15,8 +15,10 @@ package org.openhab.binding.avmfritz.internal.dto;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.types.PercentType;
/**
@ -36,6 +38,10 @@ public class ColorControlModel {
public int currentMode;
public int hue;
public int saturation;
@XmlElement(name = "unmapped_hue")
public @Nullable Integer unmappedHue;
@XmlElement(name = "unmapped_saturation")
public @Nullable Integer unmappedSaturation;
public int temperature;
/**
@ -62,7 +68,8 @@ public class ColorControlModel {
@Override
public String toString() {
return new StringBuilder("[supportedModes=").append(supportedModes).append(",currentMode=").append(currentMode)
.append(",hue=").append(hue).append(",saturation=").append(saturation).append(",temperature=")
.append(",hue=").append(hue).append(",saturation=").append(saturation).append(",unmapped_hue=")
.append(unmappedHue).append(",unmapped_saturation=").append(unmappedSaturation).append(",temperature=")
.append(temperature).append("]").toString();
}

View File

@ -111,9 +111,9 @@ public class HeatingModel implements BatteryModel {
return MODE_OFF;
} else if (BigDecimal.ONE.equals(getWindowopenactiv())) {
return MODE_WINDOW_OPEN;
} else if (tsoll.compareTo(komfort) == 0) {
} else if (komfort != null && komfort.compareTo(tsoll) == 0) {
return MODE_COMFORT;
} else if (tsoll.compareTo(absenk) == 0) {
} else if (absenk != null && absenk.compareTo(tsoll) == 0) {
return MODE_ECO;
} else if (BigDecimal.ONE.equals(getBoostactive()) || TEMP_FRITZ_MAX.compareTo(tsoll) == 0) {
return MODE_BOOST;

View File

@ -411,12 +411,19 @@ public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implemen
if (command instanceof HSBType) {
HSBType hsbType = (HSBType) command;
brightness = hsbType.getBrightness().toBigDecimal();
fritzBox.setHueAndSaturation(ain, hsbType.getHue().intValue(),
fritzBox.setUnmappedHueAndSaturation(ain, hsbType.getHue().intValue(),
ColorControlModel.fromPercent(hsbType.getSaturation()), 0);
} else if (command instanceof PercentType) {
brightness = ((PercentType) command).toBigDecimal();
} else if (command instanceof OnOffType) {
fritzBox.setSwitch(ain, OnOffType.ON.equals(command));
} else if (command instanceof IncreaseDecreaseType) {
brightness = ((DeviceModel) currentDevice).getLevelControlModel().getLevelPercentage();
if (IncreaseDecreaseType.INCREASE.equals(command)) {
brightness.add(BigDecimal.TEN);
} else {
brightness.subtract(BigDecimal.TEN);
}
}
if (brightness != null) {
fritzBox.setLevelPercentage(ain, brightness);

View File

@ -330,11 +330,16 @@ public class FritzAhaWebInterface {
return asyncGet(callback);
}
public FritzAhaContentExchange setHueAndSaturation(String ain, int hue, int saturation, int duration) {
public FritzAhaContentExchange setMappedHueAndSaturation(String ain, int hue, int saturation, int duration) {
FritzAhaSetColorCallback callback = new FritzAhaSetColorCallback(this, ain, hue, saturation, duration);
return asyncGet(callback);
}
public FritzAhaContentExchange setUnmappedHueAndSaturation(String ain, int hue, int saturation, int duration) {
FritzAhaSetColorCallback callback = new FritzAhaSetColorCallback(this, ain, hue, saturation, duration, false);
return asyncGet(callback);
}
public FritzAhaContentExchange setBlind(String ain, BlindCommand command) {
FritzAhaSetBlindTargetCallback callback = new FritzAhaSetBlindTargetCallback(this, ain, command);
return asyncGet(callback);

View File

@ -27,6 +27,9 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault
public class FritzAhaSetColorCallback extends FritzAhaReauthCallback {
private static final String WEBSERVICE_SET_COLOR_COMMAND = "switchcmd=setcolor";
private static final String WEBSERVICE_SET_UNMAPPED_COLOR_COMMAND = "switchcmd=setunmappedcolor";
private final Logger logger = LoggerFactory.getLogger(FritzAhaSetColorCallback.class);
private final String ain;
@ -41,8 +44,25 @@ public class FritzAhaSetColorCallback extends FritzAhaReauthCallback {
* @param duration Duration of the change in 100ms. 0 immediately.
*/
public FritzAhaSetColorCallback(FritzAhaWebInterface webIface, String ain, int hue, int saturation, int duration) {
this(webIface, ain, hue, saturation, duration, true);
}
/**
* Constructor
*
* @param webIface Interface to FRITZ!Box
* @param ain AIN of the device that should be switched
* @param hue New hue
* @param saturation New saturation
* @param duration Duration of the change in 100ms. 0 immediately.
* @param mapped Use mapped or unmapped color command
*/
public FritzAhaSetColorCallback(FritzAhaWebInterface webIface, String ain, int hue, int saturation, int duration,
boolean mapped) {
super(WEBSERVICE_PATH,
"switchcmd=setcolor&ain=" + ain + "&hue=" + hue + "&saturation=" + saturation + "&duration=" + duration,
mapped ? WEBSERVICE_SET_COLOR_COMMAND
: WEBSERVICE_SET_UNMAPPED_COLOR_COMMAND + "&ain=" + ain + "&hue=" + hue + "&saturation="
+ saturation + "&duration=" + duration,
webIface, GET, 1);
this.ain = ain;
}

View File

@ -725,6 +725,8 @@ public class AVMFritzDeviceListModelTest {
assertNotNull(colorModel);
assertEquals(254, colorModel.hue);
assertEquals(100, colorModel.saturation);
assertEquals(0, colorModel.unmappedHue);
assertEquals(0, colorModel.unmappedSaturation);
assertEquals(2700, colorModel.temperature);
}

View File

@ -37,6 +37,16 @@ class ColorControlModelTest {
}
}
@Test
public void testColorControlModelPercentConversionRestrictsToLowerBounds() {
assertThat(ColorControlModel.toPercent(-1), is(PercentType.ZERO));
}
@Test
public void testColorControlModelPercentConversionRestrictsToUpperBounds() {
assertThat(ColorControlModel.toPercent(999), is(PercentType.HUNDRED));
}
@Test
public void hsbSaturationAlwaysGreaterThanZero() {
// a saturation greater than 1 should result in a percentage greater than 1

View File

@ -12,7 +12,8 @@
*/
package org.openhab.binding.avmfritz.internal.dto;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.openhab.binding.avmfritz.internal.AVMFritzBindingConstants.*;
import java.math.BigDecimal;
@ -60,4 +61,16 @@ public class HeatingModelTest {
assertEquals(BIGDECIMAL_FOURTEEN_POINT_FIVE, HeatingModel.normalizeCelsius(new BigDecimal("14.4")));
assertEquals(BIGDECIMAL_FOURTEEN_POINT_FIVE, HeatingModel.normalizeCelsius(new BigDecimal("14.6")));
}
@Test
public void validateGetRadiatorModeReturnsValidMode() {
HeatingModel heatingModel = new HeatingModel();
assertEquals(MODE_UNKNOWN, heatingModel.getRadiatorMode());
heatingModel.setTsoll(BigDecimal.ONE);
assertEquals(MODE_ON, heatingModel.getRadiatorMode());
heatingModel.setKomfort(BigDecimal.ONE);
assertEquals(MODE_COMFORT, heatingModel.getRadiatorMode());
}
}