From 2b80c0ea971acd06b0fc794b1fd6a828b845abb7 Mon Sep 17 00:00:00 2001 From: Ben Jones Date: Thu, 17 Feb 2022 21:30:30 +1300 Subject: [PATCH] [amplipi] Add support for incremental volume control (#12297) Signed-off-by: Ben Jones --- .../internal/AmpliPiBindingConstants.java | 1 + .../amplipi/internal/AmpliPiGroupHandler.java | 39 +++++++++++++++---- .../amplipi/internal/AmpliPiUtils.java | 5 +++ .../amplipi/internal/AmpliPiZoneHandler.java | 39 +++++++++++++++---- .../resources/OH-INF/thing/thing-types.xml | 12 ++++++ 5 files changed, 80 insertions(+), 16 deletions(-) diff --git a/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiBindingConstants.java b/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiBindingConstants.java index 91d15ff68..5b0b48ead 100644 --- a/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiBindingConstants.java +++ b/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiBindingConstants.java @@ -41,4 +41,5 @@ public class AmpliPiBindingConstants { // list of configuration parameters public static final String CFG_PARAM_HOSTNAME = "hostname"; public static final String CFG_PARAM_ID = "id"; + public static final String CFG_PARAM_VOLUME_DELTA = "volumeDelta"; } diff --git a/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiGroupHandler.java b/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiGroupHandler.java index 800958e2b..9fa545d29 100644 --- a/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiGroupHandler.java +++ b/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiGroupHandler.java @@ -27,6 +27,7 @@ import org.openhab.binding.amplipi.internal.model.Group; import org.openhab.binding.amplipi.internal.model.GroupUpdate; import org.openhab.binding.amplipi.internal.model.Status; import org.openhab.core.library.types.DecimalType; +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.thing.Bridge; @@ -58,6 +59,8 @@ public class AmpliPiGroupHandler extends BaseThingHandler implements AmpliPiStat private @Nullable AmpliPiHandler bridgeHandler; + private @Nullable Group groupState; + public AmpliPiGroupHandler(Thing thing, HttpClient httpClient) { super(thing); this.httpClient = httpClient; @@ -68,6 +71,10 @@ public class AmpliPiGroupHandler extends BaseThingHandler implements AmpliPiStat return Integer.valueOf(thing.getConfiguration().get(AmpliPiBindingConstants.CFG_PARAM_ID).toString()); } + private int getVolumeDelta(Thing thing) { + return Integer.valueOf(thing.getConfiguration().get(AmpliPiBindingConstants.CFG_PARAM_VOLUME_DELTA).toString()); + } + @Override public void initialize() { Bridge bridge = getBridge(); @@ -104,6 +111,17 @@ public class AmpliPiGroupHandler extends BaseThingHandler implements AmpliPiStat case AmpliPiBindingConstants.CHANNEL_VOLUME: if (command instanceof PercentType) { update.setVolDelta(AmpliPiUtils.percentTypeToVolume((PercentType) command)); + } else if (command instanceof IncreaseDecreaseType) { + if (groupState != null) { + if (IncreaseDecreaseType.INCREASE.equals(command)) { + groupState.setVolDelta(Math.min(groupState.getVolDelta() + getVolumeDelta(thing), + AmpliPiUtils.MAX_VOLUME_DB)); + } else { + groupState.setVolDelta(Math.max(groupState.getVolDelta() - getVolumeDelta(thing), + AmpliPiUtils.MIN_VOLUME_DB)); + } + update.setVolDelta(groupState.getVolDelta()); + } } break; case AmpliPiBindingConstants.CHANNEL_SOURCE: @@ -136,13 +154,18 @@ public class AmpliPiGroupHandler extends BaseThingHandler implements AmpliPiStat public void receive(Status status) { int id = getId(thing); Optional group = status.getGroups().stream().filter(z -> z.getId().equals(id)).findFirst(); - if (group.isPresent()) { - Boolean mute = group.get().getMute(); - Integer volume = group.get().getVolDelta(); - Integer source = group.get().getSourceId(); - updateState(AmpliPiBindingConstants.CHANNEL_MUTE, mute ? OnOffType.ON : OnOffType.OFF); - updateState(AmpliPiBindingConstants.CHANNEL_VOLUME, AmpliPiUtils.volumeToPercentType(volume)); - updateState(AmpliPiBindingConstants.CHANNEL_SOURCE, new DecimalType(source)); - } + group.ifPresent(this::updateGroupState); + } + + private void updateGroupState(Group state) { + this.groupState = state; + + Boolean mute = groupState.getMute(); + Integer volDelta = groupState.getVolDelta(); + Integer sourceId = groupState.getSourceId(); + + updateState(AmpliPiBindingConstants.CHANNEL_MUTE, mute ? OnOffType.ON : OnOffType.OFF); + updateState(AmpliPiBindingConstants.CHANNEL_VOLUME, AmpliPiUtils.volumeToPercentType(volDelta)); + updateState(AmpliPiBindingConstants.CHANNEL_SOURCE, new DecimalType(sourceId)); } } diff --git a/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiUtils.java b/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiUtils.java index 007f635a4..8bfbdd3c0 100644 --- a/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiUtils.java +++ b/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiUtils.java @@ -23,6 +23,11 @@ import org.openhab.core.library.types.PercentType; */ @NonNullByDefault public class AmpliPiUtils { + /** + * The supported volume range in decibels for the AmpliPi + */ + public static final int MIN_VOLUME_DB = -79; + public static final int MAX_VOLUME_DB = 0; /** * Converts a volume from AmpliPi to an openHAB PercentType diff --git a/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiZoneHandler.java b/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiZoneHandler.java index c5e48c3fc..852be84d6 100644 --- a/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiZoneHandler.java +++ b/bundles/org.openhab.binding.amplipi/src/main/java/org/openhab/binding/amplipi/internal/AmpliPiZoneHandler.java @@ -27,6 +27,7 @@ import org.openhab.binding.amplipi.internal.model.Status; import org.openhab.binding.amplipi.internal.model.Zone; import org.openhab.binding.amplipi.internal.model.ZoneUpdate; import org.openhab.core.library.types.DecimalType; +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.thing.Bridge; @@ -58,6 +59,8 @@ public class AmpliPiZoneHandler extends BaseThingHandler implements AmpliPiStatu private @Nullable AmpliPiHandler bridgeHandler; + private @Nullable Zone zoneState; + public AmpliPiZoneHandler(Thing thing, HttpClient httpClient) { super(thing); this.httpClient = httpClient; @@ -88,6 +91,10 @@ public class AmpliPiZoneHandler extends BaseThingHandler implements AmpliPiStatu return Integer.valueOf(thing.getConfiguration().get(AmpliPiBindingConstants.CFG_PARAM_ID).toString()); } + private int getVolumeDelta(Thing thing) { + return Integer.valueOf(thing.getConfiguration().get(AmpliPiBindingConstants.CFG_PARAM_VOLUME_DELTA).toString()); + } + @Override public void handleCommand(ChannelUID channelUID, Command command) { if (command == RefreshType.REFRESH) { @@ -104,6 +111,17 @@ public class AmpliPiZoneHandler extends BaseThingHandler implements AmpliPiStatu case AmpliPiBindingConstants.CHANNEL_VOLUME: if (command instanceof PercentType) { update.setVol(AmpliPiUtils.percentTypeToVolume((PercentType) command)); + } else if (command instanceof IncreaseDecreaseType) { + if (zoneState != null) { + if (IncreaseDecreaseType.INCREASE.equals(command)) { + zoneState.setVol( + Math.min(zoneState.getVol() + getVolumeDelta(thing), AmpliPiUtils.MAX_VOLUME_DB)); + } else { + zoneState.setVol( + Math.max(zoneState.getVol() - getVolumeDelta(thing), AmpliPiUtils.MIN_VOLUME_DB)); + } + update.setVol(zoneState.getVol()); + } } break; case AmpliPiBindingConstants.CHANNEL_SOURCE: @@ -135,13 +153,18 @@ public class AmpliPiZoneHandler extends BaseThingHandler implements AmpliPiStatu public void receive(Status status) { int id = getId(thing); Optional zone = status.getZones().stream().filter(z -> z.getId().equals(id)).findFirst(); - if (zone.isPresent()) { - Boolean mute = zone.get().getMute(); - Integer volume = zone.get().getVol(); - Integer source = zone.get().getSourceId(); - updateState(AmpliPiBindingConstants.CHANNEL_MUTE, mute ? OnOffType.ON : OnOffType.OFF); - updateState(AmpliPiBindingConstants.CHANNEL_VOLUME, AmpliPiUtils.volumeToPercentType(volume)); - updateState(AmpliPiBindingConstants.CHANNEL_SOURCE, new DecimalType(source)); - } + zone.ifPresent(this::updateZoneState); + } + + private void updateZoneState(Zone state) { + this.zoneState = state; + + Boolean mute = zoneState.getMute(); + Integer vol = zoneState.getVol(); + Integer sourceId = zoneState.getSourceId(); + + updateState(AmpliPiBindingConstants.CHANNEL_MUTE, mute ? OnOffType.ON : OnOffType.OFF); + updateState(AmpliPiBindingConstants.CHANNEL_VOLUME, AmpliPiUtils.volumeToPercentType(vol)); + updateState(AmpliPiBindingConstants.CHANNEL_SOURCE, new DecimalType(sourceId)); } } diff --git a/bundles/org.openhab.binding.amplipi/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amplipi/src/main/resources/OH-INF/thing/thing-types.xml index d73b03109..df5f8400c 100644 --- a/bundles/org.openhab.binding.amplipi/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amplipi/src/main/resources/OH-INF/thing/thing-types.xml @@ -61,6 +61,12 @@ The ID of the zone + + + How much to change the zone volume for each INCREASE/DECREASE command (in dB) + 1 + true + @@ -83,6 +89,12 @@ The ID of the group + + + How much to change the group volume for each INCREASE/DECREASE command (in dB) + 1 + true +