]> git.basschouten.com Git - openhab-addons.git/commitdiff
[monopriceaudio] Fix compiler warnings and code improvements (#16991)
authormlobstein <michael.lobstein@gmail.com>
Tue, 16 Jul 2024 04:42:28 +0000 (23:42 -0500)
committerGitHub <noreply@github.com>
Tue, 16 Jul 2024 04:42:28 +0000 (06:42 +0200)
* Fix compiler warnings and code improvements

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
bundles/org.openhab.binding.monopriceaudio/src/main/java/org/openhab/binding/monopriceaudio/internal/communication/AmplifierModel.java
bundles/org.openhab.binding.monopriceaudio/src/main/java/org/openhab/binding/monopriceaudio/internal/communication/MonopriceAudioConnector.java
bundles/org.openhab.binding.monopriceaudio/src/main/java/org/openhab/binding/monopriceaudio/internal/communication/MonopriceAudioDefaultConnector.java [deleted file]
bundles/org.openhab.binding.monopriceaudio/src/main/java/org/openhab/binding/monopriceaudio/internal/communication/MonopriceAudioIpConnector.java
bundles/org.openhab.binding.monopriceaudio/src/main/java/org/openhab/binding/monopriceaudio/internal/communication/MonopriceAudioSerialConnector.java
bundles/org.openhab.binding.monopriceaudio/src/main/java/org/openhab/binding/monopriceaudio/internal/handler/MonopriceAudioHandler.java

index 70ccfb5d6866045e201078426a15ce24a6d9d4ad..1c030f19518bf7c36ad8d8242a7fef4a7d5ed3a1 100644 (file)
  */
 package org.openhab.binding.monopriceaudio.internal.communication;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.IntStream;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.openhab.binding.monopriceaudio.internal.configuration.MonopriceAudioThingConfiguration;
@@ -82,7 +84,7 @@ public enum AmplifierModel {
             2, false, List.of("1", "2", "3", "4", "5", "6")) {
         @Override
         public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
-            MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
+            final MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
 
             Matcher matcher = MONOPRICE70_PATTERN.matcher(newZoneData);
             if (matcher.find()) {
@@ -127,8 +129,8 @@ public enum AmplifierModel {
             false, List.of("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16")) {
         @Override
         public MonopriceAudioZoneDTO getZoneData(String newZoneData) {
-            MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
-            Matcher matcher = XANTECH_PATTERN.matcher(newZoneData);
+            final MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
+            final Matcher matcher = XANTECH_PATTERN.matcher(newZoneData);
 
             if (matcher.find()) {
                 zoneData.setZone(matcher.group(1));
@@ -156,8 +158,8 @@ public enum AmplifierModel {
 
     // Used by 10761/DAX66 and DAX88
     private static MonopriceAudioZoneDTO getMonopriceZoneData(String newZoneData) {
-        MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
-        Matcher matcher = MONOPRICE_PATTERN.matcher(newZoneData);
+        final MonopriceAudioZoneDTO zoneData = new MonopriceAudioZoneDTO();
+        final Matcher matcher = MONOPRICE_PATTERN.matcher(newZoneData);
 
         if (matcher.find()) {
             zoneData.setZone(matcher.group(1));
@@ -191,31 +193,31 @@ public enum AmplifierModel {
     private static final Pattern XANTECH_PATTERN = Pattern.compile(
             "^#(\\d{1,2})ZS PR(\\d{1}) SS(\\d{1}) VO(\\d{1,2}) MU(\\d{1}) TR(\\d{1,2}) BS(\\d{1,2}) BA(\\d{1,2}) LS(\\d{1}) PS(\\d{1})+");
 
-    private String cmdPrefix;
-    private String cmdSuffix;
-    private String queryPrefix;
-    private String querySuffix;
-    private String respPrefix;
-    private String powerCmd;
-    private String sourceCmd;
-    private String volumeCmd;
-    private String muteCmd;
-    private String trebleCmd;
-    private String bassCmd;
-    private String balanceCmd;
-    private String dndCmd;
-    private int maxVol;
-    private int minTone;
-    private int maxTone;
-    private int toneOffset;
-    private int minBal;
-    private int maxBal;
-    private int balOffset;
-    private int maxZones;
-    private int numSources;
-    private boolean padNumbers;
-    private List<String> zoneIds;
-    private Map<String, String> zoneIdMap = new HashMap<>();
+    private final String cmdPrefix;
+    private final String cmdSuffix;
+    private final String queryPrefix;
+    private final String querySuffix;
+    private final String respPrefix;
+    private final String powerCmd;
+    private final String sourceCmd;
+    private final String volumeCmd;
+    private final String muteCmd;
+    private final String trebleCmd;
+    private final String bassCmd;
+    private final String balanceCmd;
+    private final String dndCmd;
+    private final int maxVol;
+    private final int minTone;
+    private final int maxTone;
+    private final int toneOffset;
+    private final int minBal;
+    private final int maxBal;
+    private final int balOffset;
+    private final int maxZones;
+    private final int numSources;
+    private final boolean padNumbers;
+    private final List<String> zoneIds;
+    private final Map<String, String> zoneIdMap;
 
     private static final String ON_STR = "1";
     private static final String OFF_STR = "0";
@@ -256,11 +258,10 @@ public enum AmplifierModel {
         this.padNumbers = padNumbers;
         this.zoneIds = zoneIds;
 
-        int i = 1;
-        for (String zoneId : zoneIds) {
-            zoneIdMap.put(zoneId, "zone" + i);
-            i++;
-        }
+        // Build a map between the amp's physical zone IDs and the thing's logical zone names
+        final Map<String, String> zoneIdMap = new HashMap<>();
+        IntStream.range(0, zoneIds.size()).forEach(i -> zoneIdMap.put(zoneIds.get(i), "zone" + (i + 1)));
+        this.zoneIdMap = Collections.unmodifiableMap(zoneIdMap);
     }
 
     public abstract MonopriceAudioZoneDTO getZoneData(String newZoneData);
@@ -378,26 +379,14 @@ public enum AmplifierModel {
     }
 
     public String getFormattedValue(Integer value) {
-        if (padNumbers) {
-            return String.format("%02d", value);
-        } else {
-            return value.toString();
-        }
+        return padNumbers ? String.format("%02d", value) : value.toString();
     }
 
     public String getOnStr() {
-        if (padNumbers) {
-            return ON_STR_PAD;
-        } else {
-            return ON_STR;
-        }
+        return padNumbers ? ON_STR_PAD : ON_STR;
     }
 
     public String getOffStr() {
-        if (padNumbers) {
-            return OFF_STR_PAD;
-        } else {
-            return OFF_STR;
-        }
+        return padNumbers ? OFF_STR_PAD : OFF_STR;
     }
 }
index 8b7c2c161d197b2a6716195120fe8cc9d98bf45a..c6e8d03381b0e9cdf34d66c7fb3f182b36729f65 100644 (file)
@@ -52,7 +52,7 @@ public abstract class MonopriceAudioConnector {
     private boolean connected;
     private boolean pingResponseOnly;
 
-    private @Nullable AmplifierModel amp;
+    protected AmplifierModel amp = AmplifierModel.MONOPRICE;
 
     private @Nullable Thread readerThread;
 
@@ -77,15 +77,6 @@ public abstract class MonopriceAudioConnector {
         this.pingResponseOnly = false;
     }
 
-    /**
-     * Set the AmplifierModel
-     *
-     * @param amp the AmplifierModel being used
-     */
-    protected void setAmplifierModel(AmplifierModel amp) {
-        this.amp = amp;
-    }
-
     /**
      * Set the thread that handles the feedback messages
      *
@@ -177,7 +168,7 @@ public abstract class MonopriceAudioConnector {
     public void sendPing() throws MonopriceAudioException {
         pingResponseOnly = true;
         // poll zone 1 status only to see if the amp responds
-        queryZone(amp.getZoneIds().get(0));
+        queryZone(amp.getZoneIds().iterator().next());
     }
 
     /**
diff --git a/bundles/org.openhab.binding.monopriceaudio/src/main/java/org/openhab/binding/monopriceaudio/internal/communication/MonopriceAudioDefaultConnector.java b/bundles/org.openhab.binding.monopriceaudio/src/main/java/org/openhab/binding/monopriceaudio/internal/communication/MonopriceAudioDefaultConnector.java
deleted file mode 100644 (file)
index 4b2202b..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright (c) 2010-2024 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.monopriceaudio.internal.communication;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.monopriceaudio.internal.MonopriceAudioException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Class to create a default MonopriceAudioConnector before initialization is complete.
- *
- * @author Laurent Garnier - Initial contribution
- * @author Michael Lobstein - Adapted for the MonopriceAudio binding
- */
-@NonNullByDefault
-public class MonopriceAudioDefaultConnector extends MonopriceAudioConnector {
-
-    private final Logger logger = LoggerFactory.getLogger(MonopriceAudioDefaultConnector.class);
-
-    @Override
-    public void open() throws MonopriceAudioException {
-        logger.warn(
-                "MonopriceAudio binding incorrectly configured. Please configure for Serial or IP over serial connection");
-        setConnected(false);
-    }
-
-    @Override
-    public void close() {
-        setConnected(false);
-    }
-
-    @Override
-    public void sendCommand(@Nullable String zone, String cmd, @Nullable Integer value) {
-        logger.warn(
-                "MonopriceAudio binding incorrectly configured. Please configure for Serial or IP over serial connection");
-        setConnected(false);
-    }
-}
index 5eea9d8d722d23e2e3f9f95b9404d2b9f94caac8..c72d6ac14908e31afd4f6f0443645129ad5055cb 100644 (file)
@@ -54,7 +54,16 @@ public class MonopriceAudioIpConnector extends MonopriceAudioConnector {
         this.address = address;
         this.port = port;
         this.uid = uid;
-        setAmplifierModel(amp);
+        super.amp = amp;
+    }
+
+    /**
+     * Default constructor for temporary connector object that gets replaced during initialize()
+     */
+    public MonopriceAudioIpConnector() {
+        this.address = "";
+        this.port = -1;
+        this.uid = "";
     }
 
     @Override
index f731548efaf660a044a10f37c3f912c0a3dd6222..e4914c46ae4876a45e61e20d7d22f91a0e718772 100644 (file)
@@ -58,7 +58,7 @@ public class MonopriceAudioSerialConnector extends MonopriceAudioConnector {
         this.serialPortManager = serialPortManager;
         this.serialPortName = serialPortName;
         this.uid = uid;
-        setAmplifierModel(amp);
+        super.amp = amp;
     }
 
     @Override
index b5506f1db04fb809df5088be4c57da0ae80978e1..b03f8bcdc22ae6c9229b5c806f0a1bc26e05dcaf 100644 (file)
@@ -32,7 +32,6 @@ import org.openhab.binding.monopriceaudio.internal.MonopriceAudioException;
 import org.openhab.binding.monopriceaudio.internal.MonopriceAudioStateDescriptionOptionProvider;
 import org.openhab.binding.monopriceaudio.internal.communication.AmplifierModel;
 import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioConnector;
-import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioDefaultConnector;
 import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioIpConnector;
 import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioMessageEvent;
 import org.openhab.binding.monopriceaudio.internal.communication.MonopriceAudioMessageEventListener;
@@ -87,7 +86,7 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
     private @Nullable ScheduledFuture<?> reconnectJob;
     private @Nullable ScheduledFuture<?> pollingJob;
 
-    private MonopriceAudioConnector connector = new MonopriceAudioDefaultConnector();
+    private MonopriceAudioConnector connector = new MonopriceAudioIpConnector();
 
     private Map<String, MonopriceAudioZoneDTO> zoneDataMap = Map.of(ZONE, new MonopriceAudioZoneDTO());
     private Set<String> ignoreZones = new HashSet<>();
@@ -214,11 +213,11 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
 
     @Override
     public void handleCommand(ChannelUID channelUID, Command command) {
-        String channel = channelUID.getId();
-        String[] channelSplit = channel.split(CHANNEL_DELIMIT);
-        String channelType = channelSplit[1];
-        String zoneName = channelSplit[0];
-        String zoneId = amp.getZoneIdFromZoneName(zoneName);
+        final String channel = channelUID.getId();
+        final String[] channelSplit = channel.split(CHANNEL_DELIMIT);
+        final String channelType = channelSplit[1];
+        final String zoneName = channelSplit[0];
+        final String zoneId = amp.getZoneIdFromZoneName(zoneName);
 
         if (getThing().getStatus() != ThingStatus.ONLINE) {
             logger.debug("Thing is not ONLINE; command {} from channel {} is ignored", command, channel);
@@ -237,166 +236,192 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
                 return;
             }
 
-            Stream<String> zoneStream = amp.getZoneIds().stream().limit(numZones);
             try {
-                switch (channelType) {
-                    case CHANNEL_TYPE_POWER:
-                        if (command instanceof OnOffType) {
-                            connector.sendCommand(zoneId, amp.getPowerCmd(), command == OnOffType.ON ? ONE : ZERO);
-                            zoneDataMap.get(zoneId)
-                                    .setPower(command == OnOffType.ON ? amp.getOnStr() : amp.getOffStr());
-                        }
-                        break;
-                    case CHANNEL_TYPE_SOURCE:
-                        if (command instanceof DecimalType decimalCommand) {
-                            final int value = decimalCommand.intValue();
-                            if (value >= ONE && value <= amp.getNumSources()) {
-                                logger.debug("Got source command {} zone {}", value, zoneId);
-                                connector.sendCommand(zoneId, amp.getSourceCmd(), value);
-                                zoneDataMap.get(zoneId).setSource(amp.getFormattedValue(value));
+                if (!"all".equals(zoneName)) {
+                    MonopriceAudioZoneDTO dto = zoneDataMap.get(zoneId);
+                    if (dto == null) {
+                        logger.debug("no zoneData for zoneId: {}", zoneId);
+                        return;
+                    }
+
+                    switch (channelType) {
+                        case CHANNEL_TYPE_POWER:
+                            if (command instanceof OnOffType) {
+                                connector.sendCommand(zoneId, amp.getPowerCmd(), command == OnOffType.ON ? ONE : ZERO);
+                                dto.setPower(command == OnOffType.ON ? amp.getOnStr() : amp.getOffStr());
                             }
-                        }
-                        break;
-                    case CHANNEL_TYPE_VOLUME:
-                        if (command instanceof PercentType percentCommand) {
-                            final int value = (int) Math
-                                    .round(percentCommand.doubleValue() / 100.0 * (amp.getMaxVol() - MIN_VOLUME))
-                                    + MIN_VOLUME;
-                            logger.debug("Got volume command {} zone {}", value, zoneId);
-                            connector.sendCommand(zoneId, amp.getVolumeCmd(), value);
-                            zoneDataMap.get(zoneId).setVolume(value);
-                        }
-                        break;
-                    case CHANNEL_TYPE_MUTE:
-                        if (command instanceof OnOffType) {
-                            connector.sendCommand(zoneId, amp.getMuteCmd(), command == OnOffType.ON ? ONE : ZERO);
-                            zoneDataMap.get(zoneId).setMute(command == OnOffType.ON ? amp.getOnStr() : amp.getOffStr());
-                        }
-                        break;
-                    case CHANNEL_TYPE_TREBLE:
-                        if (command instanceof DecimalType decimalCommand) {
-                            final int value = decimalCommand.intValue();
-                            if (value >= amp.getMinTone() && value <= amp.getMaxTone()) {
-                                logger.debug("Got treble command {} zone {}", value, zoneId);
-                                connector.sendCommand(zoneId, amp.getTrebleCmd(), value + amp.getToneOffset());
-                                zoneDataMap.get(zoneId).setTreble(value + amp.getToneOffset());
+                            break;
+                        case CHANNEL_TYPE_SOURCE:
+                            if (command instanceof DecimalType decimalCommand) {
+                                final int value = decimalCommand.intValue();
+                                if (value >= ONE && value <= amp.getNumSources()) {
+                                    logger.debug("Got source command {} zone {}", value, zoneId);
+                                    connector.sendCommand(zoneId, amp.getSourceCmd(), value);
+                                    dto.setSource(amp.getFormattedValue(value));
+                                }
                             }
-                        }
-                        break;
-                    case CHANNEL_TYPE_BASS:
-                        if (command instanceof DecimalType decimalCommand) {
-                            final int value = decimalCommand.intValue();
-                            if (value >= amp.getMinTone() && value <= amp.getMaxTone()) {
-                                logger.debug("Got bass command {} zone {}", value, zoneId);
-                                connector.sendCommand(zoneId, amp.getBassCmd(), value + amp.getToneOffset());
-                                zoneDataMap.get(zoneId).setBass(value + amp.getToneOffset());
+                            break;
+                        case CHANNEL_TYPE_VOLUME:
+                            if (command instanceof PercentType percentCommand) {
+                                final int value = (int) Math
+                                        .round(percentCommand.doubleValue() / 100.0 * (amp.getMaxVol() - MIN_VOLUME))
+                                        + MIN_VOLUME;
+                                logger.debug("Got volume command {} zone {}", value, zoneId);
+                                connector.sendCommand(zoneId, amp.getVolumeCmd(), value);
+                                dto.setVolume(value);
                             }
-                        }
-                        break;
-                    case CHANNEL_TYPE_BALANCE:
-                        if (command instanceof DecimalType decimalCommand) {
-                            final int value = decimalCommand.intValue();
-                            if (value >= amp.getMinBal() && value <= amp.getMaxBal()) {
-                                logger.debug("Got balance command {} zone {}", value, zoneId);
-                                connector.sendCommand(zoneId, amp.getBalanceCmd(), value + amp.getBalOffset());
-                                zoneDataMap.get(zoneId).setBalance(value + amp.getBalOffset());
+                            break;
+                        case CHANNEL_TYPE_MUTE:
+                            if (command instanceof OnOffType) {
+                                connector.sendCommand(zoneId, amp.getMuteCmd(), command == OnOffType.ON ? ONE : ZERO);
+                                dto.setMute(command == OnOffType.ON ? amp.getOnStr() : amp.getOffStr());
                             }
-                        }
-                        break;
-                    case CHANNEL_TYPE_DND:
-                        if (command instanceof OnOffType) {
-                            connector.sendCommand(zoneId, amp.getDndCmd(), command == OnOffType.ON ? ONE : ZERO);
-                            zoneDataMap.get(zoneId).setDnd(command == OnOffType.ON ? amp.getOnStr() : amp.getOffStr());
-                        }
-                        break;
-                    case CHANNEL_TYPE_ALLPOWER:
-                        if (command instanceof OnOffType) {
-                            final int cmd = command == OnOffType.ON ? ONE : ZERO;
-                            zoneStream.forEach((streamZoneId) -> {
-                                if (command == OnOffType.OFF || !ignoreZones.contains(amp.getZoneName(streamZoneId))) {
-                                    try {
-                                        connector.sendCommand(streamZoneId, amp.getPowerCmd(), cmd);
-                                        zoneDataMap.get(streamZoneId).setPower(amp.getFormattedValue(cmd));
-                                        updateChannelState(streamZoneId, CHANNEL_TYPE_POWER);
-
-                                        if (command == OnOffType.ON) {
-                                            // reset the volume of each zone to allVolume
-                                            connector.sendCommand(streamZoneId, amp.getVolumeCmd(), allVolume);
-                                            zoneDataMap.get(streamZoneId).setVolume(allVolume);
-                                            updateChannelState(streamZoneId, CHANNEL_TYPE_VOLUME);
-                                        }
-                                    } catch (MonopriceAudioException e) {
-                                        logger.debug("Error Turning All Zones On: {}", e.getMessage());
-                                    }
+                            break;
+                        case CHANNEL_TYPE_TREBLE:
+                            if (command instanceof DecimalType decimalCommand) {
+                                final int value = decimalCommand.intValue();
+                                if (value >= amp.getMinTone() && value <= amp.getMaxTone()) {
+                                    logger.debug("Got treble command {} zone {}", value, zoneId);
+                                    connector.sendCommand(zoneId, amp.getTrebleCmd(), value + amp.getToneOffset());
+                                    dto.setTreble(value + amp.getToneOffset());
+                                }
+                            }
+                            break;
+                        case CHANNEL_TYPE_BASS:
+                            if (command instanceof DecimalType decimalCommand) {
+                                final int value = decimalCommand.intValue();
+                                if (value >= amp.getMinTone() && value <= amp.getMaxTone()) {
+                                    logger.debug("Got bass command {} zone {}", value, zoneId);
+                                    connector.sendCommand(zoneId, amp.getBassCmd(), value + amp.getToneOffset());
+                                    dto.setBass(value + amp.getToneOffset());
                                 }
+                            }
+                            break;
+                        case CHANNEL_TYPE_BALANCE:
+                            if (command instanceof DecimalType decimalCommand) {
+                                final int value = decimalCommand.intValue();
+                                if (value >= amp.getMinBal() && value <= amp.getMaxBal()) {
+                                    logger.debug("Got balance command {} zone {}", value, zoneId);
+                                    connector.sendCommand(zoneId, amp.getBalanceCmd(), value + amp.getBalOffset());
+                                    dto.setBalance(value + amp.getBalOffset());
+                                }
+                            }
+                            break;
+                        case CHANNEL_TYPE_DND:
+                            if (command instanceof OnOffType) {
+                                connector.sendCommand(zoneId, amp.getDndCmd(), command == OnOffType.ON ? ONE : ZERO);
+                                dto.setDnd(command == OnOffType.ON ? amp.getOnStr() : amp.getOffStr());
+                            }
+                            break;
+                        default:
+                            success = false;
+                            logger.debug("Command {} from channel {} failed: unexpected command", command, channel);
+                            break;
+                    }
+                } else {
+                    Stream<String> zoneStream = amp.getZoneIds().stream().limit(numZones);
 
-                            });
-                        }
-                        break;
-                    case CHANNEL_TYPE_ALLSOURCE:
-                        if (command instanceof DecimalType decimalCommand) {
-                            final int value = decimalCommand.intValue();
-                            if (value >= ONE && value <= amp.getNumSources()) {
+                    switch (channelType) {
+                        case CHANNEL_TYPE_ALLPOWER:
+                            if (command instanceof OnOffType) {
+                                final int cmd = command == OnOffType.ON ? ONE : ZERO;
                                 zoneStream.forEach((streamZoneId) -> {
-                                    if (!ignoreZones.contains(amp.getZoneName(streamZoneId))) {
+                                    if (command == OnOffType.OFF
+                                            || !ignoreZones.contains(amp.getZoneName(streamZoneId))) {
                                         try {
-                                            connector.sendCommand(streamZoneId, amp.getSourceCmd(), value);
-                                            if (zoneDataMap.get(streamZoneId).isPowerOn()
-                                                    && !zoneDataMap.get(streamZoneId).isMuted()) {
-                                                zoneDataMap.get(streamZoneId).setSource(amp.getFormattedValue(value));
-                                                updateChannelState(streamZoneId, CHANNEL_TYPE_SOURCE);
+                                            MonopriceAudioZoneDTO streamDto = zoneDataMap.get(streamZoneId);
+                                            if (streamDto != null) {
+                                                connector.sendCommand(streamZoneId, amp.getPowerCmd(), cmd);
+                                                streamDto.setPower(amp.getFormattedValue(cmd));
+                                                updateChannelState(streamZoneId, CHANNEL_TYPE_POWER);
+
+                                                if (command == OnOffType.ON) {
+                                                    // reset the volume of each zone to allVolume
+                                                    connector.sendCommand(streamZoneId, amp.getVolumeCmd(), allVolume);
+                                                    streamDto.setVolume(allVolume);
+                                                    updateChannelState(streamZoneId, CHANNEL_TYPE_VOLUME);
+                                                }
                                             }
                                         } catch (MonopriceAudioException e) {
-                                            logger.debug("Error Setting Source for All Zones: {}", e.getMessage());
+                                            logger.debug("Error Turning All Zones On: {}", e.getMessage());
                                         }
                                     }
+
                                 });
                             }
-                        }
-                        break;
-                    case CHANNEL_TYPE_ALLVOLUME:
-                        if (command instanceof PercentType percentCommand) {
-                            allVolume = (int) Math
-                                    .round(percentCommand.doubleValue() / 100.0 * (amp.getMaxVol() - MIN_VOLUME))
-                                    + MIN_VOLUME;
-                            zoneStream.forEach((streamZoneId) -> {
-                                if (!ignoreZones.contains(amp.getZoneName(streamZoneId))) {
-                                    try {
-                                        connector.sendCommand(streamZoneId, amp.getVolumeCmd(), allVolume);
-                                        if (zoneDataMap.get(streamZoneId).isPowerOn()
-                                                && !zoneDataMap.get(streamZoneId).isMuted()) {
-                                            zoneDataMap.get(streamZoneId).setVolume(allVolume);
-                                            updateChannelState(streamZoneId, CHANNEL_TYPE_VOLUME);
+                            break;
+                        case CHANNEL_TYPE_ALLSOURCE:
+                            if (command instanceof DecimalType decimalCommand) {
+                                final int value = decimalCommand.intValue();
+                                if (value >= ONE && value <= amp.getNumSources()) {
+                                    zoneStream.forEach((streamZoneId) -> {
+                                        if (!ignoreZones.contains(amp.getZoneName(streamZoneId))) {
+                                            try {
+                                                MonopriceAudioZoneDTO streamDto = zoneDataMap.get(streamZoneId);
+                                                if (streamDto != null) {
+                                                    connector.sendCommand(streamZoneId, amp.getSourceCmd(), value);
+                                                    if (streamDto.isPowerOn() && !streamDto.isMuted()) {
+                                                        streamDto.setSource(amp.getFormattedValue(value));
+                                                        updateChannelState(streamZoneId, CHANNEL_TYPE_SOURCE);
+                                                    }
+                                                }
+                                            } catch (MonopriceAudioException e) {
+                                                logger.debug("Error Setting Source for All Zones: {}", e.getMessage());
+                                            }
                                         }
-                                    } catch (MonopriceAudioException e) {
-                                        logger.debug("Error Setting Volume for All Zones: {}", e.getMessage());
-                                    }
+                                    });
                                 }
-                            });
-                        }
-                        break;
-                    case CHANNEL_TYPE_ALLMUTE:
-                        if (command instanceof OnOffType) {
-                            final int cmd = command == OnOffType.ON ? ONE : ZERO;
-                            zoneStream.forEach((streamZoneId) -> {
-                                if (!ignoreZones.contains(amp.getZoneName(streamZoneId))) {
-                                    try {
-                                        connector.sendCommand(streamZoneId, amp.getMuteCmd(), cmd);
-                                        if (zoneDataMap.get(streamZoneId).isPowerOn()) {
-                                            zoneDataMap.get(streamZoneId).setMute(amp.getFormattedValue(cmd));
-                                            updateChannelState(streamZoneId, CHANNEL_TYPE_MUTE);
+                            }
+                            break;
+                        case CHANNEL_TYPE_ALLVOLUME:
+                            if (command instanceof PercentType percentCommand) {
+                                allVolume = (int) Math
+                                        .round(percentCommand.doubleValue() / 100.0 * (amp.getMaxVol() - MIN_VOLUME))
+                                        + MIN_VOLUME;
+                                zoneStream.forEach((streamZoneId) -> {
+                                    if (!ignoreZones.contains(amp.getZoneName(streamZoneId))) {
+                                        try {
+                                            MonopriceAudioZoneDTO streamDto = zoneDataMap.get(streamZoneId);
+                                            if (streamDto != null) {
+                                                connector.sendCommand(streamZoneId, amp.getVolumeCmd(), allVolume);
+                                                if (streamDto.isPowerOn() && !streamDto.isMuted()) {
+                                                    streamDto.setVolume(allVolume);
+                                                    updateChannelState(streamZoneId, CHANNEL_TYPE_VOLUME);
+                                                }
+                                            }
+                                        } catch (MonopriceAudioException e) {
+                                            logger.debug("Error Setting Volume for All Zones: {}", e.getMessage());
                                         }
-                                    } catch (MonopriceAudioException e) {
-                                        logger.debug("Error Setting Mute for All Zones: {}", e.getMessage());
                                     }
-                                }
-                            });
-                        }
-                        break;
-                    default:
-                        success = false;
-                        logger.debug("Command {} from channel {} failed: unexpected command", command, channel);
-                        break;
+                                });
+                            }
+                            break;
+                        case CHANNEL_TYPE_ALLMUTE:
+                            if (command instanceof OnOffType) {
+                                final int cmd = command == OnOffType.ON ? ONE : ZERO;
+                                zoneStream.forEach((streamZoneId) -> {
+                                    if (!ignoreZones.contains(amp.getZoneName(streamZoneId))) {
+                                        try {
+                                            MonopriceAudioZoneDTO streamDto = zoneDataMap.get(streamZoneId);
+                                            if (streamDto != null) {
+                                                connector.sendCommand(streamZoneId, amp.getMuteCmd(), cmd);
+                                                if (streamDto.isPowerOn()) {
+                                                    streamDto.setMute(amp.getFormattedValue(cmd));
+                                                    updateChannelState(streamZoneId, CHANNEL_TYPE_MUTE);
+                                                }
+                                            }
+                                        } catch (MonopriceAudioException e) {
+                                            logger.debug("Error Setting Mute for All Zones: {}", e.getMessage());
+                                        }
+                                    }
+                                });
+                            }
+                            break;
+                        default:
+                            success = false;
+                            logger.debug("Command {} from all channel {} failed: unexpected command", command, channel);
+                            break;
+                    }
                 }
 
                 if (success) {
@@ -442,9 +467,8 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
     @Override
     public void onNewMessageEvent(MonopriceAudioMessageEvent evt) {
         updateStatus(ThingStatus.ONLINE);
-        String key = evt.getKey();
 
-        switch (key) {
+        switch (evt.getKey()) {
             case MonopriceAudioConnector.KEY_ZONE_UPDATE:
                 MonopriceAudioZoneDTO newZoneData = amp.getZoneData(evt.getValue());
                 MonopriceAudioZoneDTO zoneData = zoneDataMap.get(newZoneData.getZone());
@@ -455,7 +479,7 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
                         processZoneUpdate(zoneData, newZoneData);
                     }
                 } else {
-                    logger.debug("invalid event: {} for key: {} or zone data null", evt.getValue(), key);
+                    logger.debug("invalid event: {} for key: {} or zone data null", evt.getValue(), evt.getKey());
                 }
                 break;
 
@@ -464,7 +488,7 @@ public class MonopriceAudioHandler extends BaseThingHandler implements Monoprice
                 break;
 
             default:
-                logger.debug("onNewMessageEvent: unhandled key {}", key);
+                logger.debug("onNewMessageEvent: unhandled key {}", evt.getKey());
                 break;
         }
     }