]> git.basschouten.com Git - openhab-addons.git/commitdiff
[nuvo] Add zone actions for rules (#13658)
authormlobstein <michael.lobstein@gmail.com>
Sat, 12 Nov 2022 15:57:22 +0000 (09:57 -0600)
committerGitHub <noreply@github.com>
Sat, 12 Nov 2022 15:57:22 +0000 (16:57 +0100)
* Add zone actions for rules
* Don't scan for NuvoNet source messages if openHAB NuvoNet sources are not being used

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
bundles/org.openhab.binding.nuvo/README.md
bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/NuvoBindingConstants.java
bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/communication/NuvoConnector.java
bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/communication/NuvoMessageEvent.java
bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/handler/NuvoHandler.java
bundles/org.openhab.binding.nuvo/src/main/resources/OH-INF/i18n/nuvo.properties
bundles/org.openhab.binding.nuvo/src/main/resources/OH-INF/thing/channels.xml

index 618b7b7ead955ac8e369ae782f207dfe31316157..e4a407cd821fa989dbcd1445dcd42594849311bd 100644 (file)
@@ -85,35 +85,36 @@ connection: &conNuvo
 
 The following channels are available:
 
-| Channel ID                           | Item Type   | Description                                                                                                                 |
-|--------------------------------------|-------------|-----------------------------------------------------------------------------------------------------------------------------|
-| system#alloff                        | Switch      | Turn all zones off simultaneously                                                                                           |
-| system#allmute                       | Switch      | Mute or unmute all zones simultaneously                                                                                     |
-| system#page                          | Switch      | Turn on or off the Page All Zones feature (while on the amplifier switches to source 6)                                     |
-| system#sendcmd                       | String      | Send a command to the amplifier                                                                                             |
-| zoneN#power (where N= 1-20)          | Switch      | Turn the power for a zone on or off                                                                                         |
-| zoneN#source (where N= 1-20)         | Number      | Select the source input for a zone (1-6)                                                                                    |
-| zoneN#volume (where N= 1-20)         | Dimmer      | Control the volume for a zone (0-100%) [translates to 0-79]                                                                 |
-| zoneN#mute (where N= 1-20)           | Switch      | Mute or unmute a zone                                                                                                       |
-| zoneN#favorite (where N= 1-20)       | Number      | Select a preset Favorite for a zone (1-12)                                                                                  |
-| zoneN#control (where N= 1-20)        | Player      | Simulate pressing the transport control buttons on the keypad e.g. play/pause/next/previous                                 |
-| zoneN#treble (where N= 1-20)         | Number      | Adjust the treble control for a zone (-18 to 18 [in increments of 2]) -18=none, 0=flat, 18=full                             |
-| zoneN#bass (where N= 1-20)           | Number      | Adjust the bass control for a zone (-18 to 18 [in increments of 2]) -18=none, 0=flat, 18=full                               |
-| zoneN#balance (where N= 1-20)        | Number      | Adjust the balance control for a zone (-18 to 18 [in increments of 2]) -18=left, 0=center, 18=right                         |
-| zoneN#loudness (where N= 1-20)       | Switch      | Turn on or off the loudness compensation setting for the zone                                                               |
-| zoneN#dnd (where N= 1-20)            | Switch      | Turn on or off the Do Not Disturb for the zone (for when the amplifier's Page All Zones feature is activated)               |
-| zoneN#lock (where N= 1-20)           | Contact     | Indicates if this zone is currently locked                                                                                  |
-| zoneN#party (where N= 1-20)          | Switch      | Turn on or off the party mode feature with this zone as the host                                                            |
-| sourceN#display_line1 (where N= 1-6) | String      | 1st line of text being displayed on the keypad. Can be updated for a non NuvoNet source                                     |
-| sourceN#display_line2 (where N= 1-6) | String      | 2nd line of text being displayed on the keypad. Can be updated for a non NuvoNet source                                     |
-| sourceN#display_line3 (where N= 1-6) | String      | 3rd line of text being displayed on the keypad. Can be updated for a non NuvoNet source                                     |
-| sourceN#display_line4 (where N= 1-6) | String      | 4th line of text being displayed on the keypad. Can be updated for a non NuvoNet source                                     |
-| sourceN#play_mode (where N= 1-6)     | String      | The current playback mode of the source, ie: Playing, Paused, etc. (ReadOnly) See rules example for updating                |
-| sourceN#track_length (where N= 1-6)  | Number:Time | The total running time of the current playing track (ReadOnly) See rules example for updating                               |
-| sourceN#track_position (where N= 1-6)| Number:Time | The running time elapsed of the current playing track (ReadOnly) See rules example for updating                             |
-| sourceN#button_press (where N= 1-6)  | String      | Indicates the last button pressed on the keypad for a non NuvoNet source or openHAB NuvoNet source (ReadOnly)               |
-| sourceN#art_url (where N= 1-6)       | String      | MPS4 Only! The URL of the Album Art JPG for this source that is displayed on a CTP-36. See *very advanced* rules (SendOnly) |
-| sourceN#album_art (where N= 1-6)     | Image       | The Album Art loaded from the art_url channel for display in a UI widget (ReadOnly)                                         |
+| Channel ID                           | Item Type   | Description                                                                                                                    |
+|--------------------------------------|-------------|--------------------------------------------------------------------------------------------------------------------------------|
+| system#alloff                        | Switch      | Turn all zones off simultaneously                                                                                              |
+| system#allmute                       | Switch      | Mute or unmute all zones simultaneously                                                                                        |
+| system#page                          | Switch      | Turn on or off the Page All Zones feature (while on the amplifier switches to source 6)                                        |
+| system#sendcmd                       | String      | Send a command to the amplifier                                                                                                |
+| system#buttonpress                   | String      | Indicates the zone number followed by a comma and the last button pressed or NuvoNet menu item selected on a keypad (ReadOnly) |
+| zoneN#power (where N= 1-20)          | Switch      | Turn the power for a zone on or off                                                                                            |
+| zoneN#source (where N= 1-20)         | Number      | Select the source input for a zone (1-6)                                                                                       |
+| zoneN#volume (where N= 1-20)         | Dimmer      | Control the volume for a zone (0-100%) [translates to 0-79]                                                                    |
+| zoneN#mute (where N= 1-20)           | Switch      | Mute or unmute a zone                                                                                                          |
+| zoneN#favorite (where N= 1-20)       | Number      | Select a preset Favorite for a zone (1-12)                                                                                     |
+| zoneN#control (where N= 1-20)        | Player      | Simulate pressing the transport control buttons on the keypad e.g. play/pause/next/previous                                    |
+| zoneN#treble (where N= 1-20)         | Number      | Adjust the treble control for a zone (-18 to 18 [in increments of 2]) -18=none, 0=flat, 18=full                                |
+| zoneN#bass (where N= 1-20)           | Number      | Adjust the bass control for a zone (-18 to 18 [in increments of 2]) -18=none, 0=flat, 18=full                                  |
+| zoneN#balance (where N= 1-20)        | Number      | Adjust the balance control for a zone (-18 to 18 [in increments of 2]) -18=left, 0=center, 18=right                            |
+| zoneN#loudness (where N= 1-20)       | Switch      | Turn on or off the loudness compensation setting for the zone                                                                  |
+| zoneN#dnd (where N= 1-20)            | Switch      | Turn on or off the Do Not Disturb for the zone (for when the amplifier's Page All Zones feature is activated)                  |
+| zoneN#lock (where N= 1-20)           | Contact     | Indicates if this zone is currently locked                                                                                     |
+| zoneN#party (where N= 1-20)          | Switch      | Turn on or off the party mode feature with this zone as the host                                                               |
+| sourceN#display_line1 (where N= 1-6) | String      | 1st line of text being displayed on the keypad. Can be updated for a non NuvoNet source                                        |
+| sourceN#display_line2 (where N= 1-6) | String      | 2nd line of text being displayed on the keypad. Can be updated for a non NuvoNet source                                        |
+| sourceN#display_line3 (where N= 1-6) | String      | 3rd line of text being displayed on the keypad. Can be updated for a non NuvoNet source                                        |
+| sourceN#display_line4 (where N= 1-6) | String      | 4th line of text being displayed on the keypad. Can be updated for a non NuvoNet source                                        |
+| sourceN#play_mode (where N= 1-6)     | String      | The current playback mode of the source, ie: Playing, Paused, etc. (ReadOnly) See rules example for updating                   |
+| sourceN#track_length (where N= 1-6)  | Number:Time | The total running time of the current playing track (ReadOnly) See rules example for updating                                  |
+| sourceN#track_position (where N= 1-6)| Number:Time | The running time elapsed of the current playing track (ReadOnly) See rules example for updating                                |
+| sourceN#button_press (where N= 1-6)  | String      | Indicates the last button pressed on the keypad for a non NuvoNet source or openHAB NuvoNet source (ReadOnly)                  |
+| sourceN#art_url (where N= 1-6)       | String      | MPS4 Only! The URL of the Album Art JPG for this source that is displayed on a CTP-36. See *very advanced* rules (SendOnly)    |
+| sourceN#album_art (where N= 1-6)     | Image       | The Album Art loaded from the art_url channel for display in a UI widget (ReadOnly)                                            |
 
 ## Full Example
 
@@ -139,6 +140,7 @@ Switch nuvo_system_alloff "All Zones Off" { channel="nuvo:amplifier:myamp:system
 Switch nuvo_system_allmute "All Zones Mute" { channel="nuvo:amplifier:myamp:system#allmute" }
 Switch nuvo_system_page "Page All Zones" { channel="nuvo:amplifier:myamp:system#page" }
 String nuvo_system_sendcmd "Send Command" { channel="nuvo:amplifier:myamp:system#sendcmd" }
+String nuvo_system_buttonpress "Zone Button: [%s]" { channel="nuvo:amplifier:myamp:system#buttonpress" }
 
 // zones
 Switch nuvo_z1_power "Power" { channel="nuvo:amplifier:myamp:zone1#power" }
@@ -473,12 +475,57 @@ A complete XML string for the desired menu is then stored in the `menuXmlSrcN` c
     <item>menu3 x</item>
     <item>menu3 y</item>
 </topmenu>
+<topmenu text="Turn off other zones"/>
 ```
 
 When a menu item is selected, the text of the topmenu item and sub menu item (if applicable) will be sent to the button channel in a pipe delimited format.
 For example, when item `menu1 b` is selected, the text `Top menu 1|menu1 b` will be sent to the button channel.
 When the item `Top menu 2` is selected the text sent to the button channel will simply be `Top menu 2` since this menu item does not have any sub menu items.
 
+### Rule to trigger an action based on which keypad zone where a button was pressed or menu item selected
+
+By using the `system#buttonpress` channel it is possible to trigger an action based on which keypad zone was used to send the action.
+This channel appends the zone number and a comma before the button action or menu item selection.  
+
+For example if the Play/Pause button is pressed on Zone 7, the channel will display: `7,PLAYPAUSE`  
+Also if a menu item from a custom menu was selected, ie: `Top menu 1` on Zone 5, the channel will display: `5,Top menu 1`  
+
+The functionality can be used to create very powerful rules as demontrated below. The following rule triggered from a menu item turns off all zones except for the zone that triggered the rule.
+
+nuvo-turn-off-all-but-caller.rules:
+
+```
+rule "Turn off all zones except caller zone"
+when
+    Item nuvo_system_buttonpress received update
+then
+    var callerZone = newState.toString().split(",").get(0)
+    var button = newState.toString().split(",").get(1)
+
+    if (button == "Turn off other zones") {
+        if (callerZone != "1") {
+            nuvo_z1_power.sendCommand(OFF)
+        }
+        if (callerZone != "2") {
+            nuvo_z2_power.sendCommand(OFF)
+        }
+        if (callerZone != "3") {
+            nuvo_z3_power.sendCommand(OFF)
+        }
+        if (callerZone != "4") {
+            nuvo_z4_power.sendCommand(OFF)
+        }
+        if (callerZone != "5") {
+            nuvo_z5_power.sendCommand(OFF)
+        }
+        if (callerZone != "6") {
+            nuvo_z6_power.sendCommand(OFF)
+        }
+    }
+end
+
+```
+
 ### MPS4 openHAB NuvoNet source custom integration rules *(very advanced)*
 
 The following are a set of example rules necessary to integrate metadata and control of another openHAB connected source (ie: Chromecast) into an openHAB NuvoNet source.
index c3cf2497c825fb31c8a751803d550b6d1a3d26f0..d65fceda035eb366c1154e648f934cfbc5c78d1d 100644 (file)
@@ -35,6 +35,7 @@ public class NuvoBindingConstants {
     public static final String CHANNEL_TYPE_ALLMUTE = "allmute";
     public static final String CHANNEL_TYPE_PAGE = "page";
     public static final String CHANNEL_TYPE_SENDCMD = "sendcmd";
+    public static final String CHANNEL_TYPE_BUTTONPRESS = "buttonpress";
 
     // zone
     public static final String CHANNEL_TYPE_POWER = "power";
@@ -71,14 +72,14 @@ public class NuvoBindingConstants {
     public static final String TYPE_PAGE = "page";
     public static final String TYPE_SOURCE_UPDATE = "source_update";
     public static final String TYPE_ZONE_UPDATE = "zone_update";
-    public static final String TYPE_ZONE_BUTTON = "zone_button";
-    public static final String TYPE_ZONE_BUTTON2 = "zone_button2";
-    public static final String TYPE_ZONE_MENUREQ = "zone_menureq";
-    public static final String TYPE_MENU_ITEM_SELECTED = "top_menu_button";
     public static final String TYPE_ZONE_CONFIG = "zone_config";
-    public static final String TYPE_ALBUM_ART_REQ = "album_art_req";
-    public static final String TYPE_ALBUM_ART_FRAG_REQ = "album_art_frag_req";
-    public static final String TYPE_FAVORITE_REQ = "favorite_req";
+    public static final String TYPE_ZONE_SOURCE_BUTTON = "zone_source_button";
+    public static final String TYPE_NN_BUTTON = "nn_button";
+    public static final String TYPE_NN_MENUREQ = "nn_menureq";
+    public static final String TYPE_NN_MENU_ITEM_SELECTED = "nn_menu_item_selected";
+    public static final String TYPE_NN_ALBUM_ART_REQ = "nn_album_art_req";
+    public static final String TYPE_NN_ALBUM_ART_FRAG_REQ = "nn_album_art_frag_req";
+    public static final String TYPE_NN_FAVORITE_REQ = "nn_favorite_req";
 
     // misc
     public static final String ON = "ON";
index bb084ffd78240b2b4cff9a9992a20ee8f1940349..c3321eb3c650b9912383b7ca6d2fb7be1c66faa7 100644 (file)
@@ -54,21 +54,21 @@ public abstract class NuvoConnector {
 
     private static final Pattern SRC_PATTERN = Pattern.compile("^#S(\\d{1})(.*)$");
     private static final Pattern ZONE_PATTERN = Pattern.compile("^#Z(\\d{1,2}),(.*)$");
-    private static final Pattern ZONE_BUTTON_PATTERN = Pattern.compile("^#Z(\\d{1,2})S(\\d{1})(.*)$");
-    private static final Pattern ZONE_MENUREQ_PATTERN = Pattern.compile("^#Z(\\d{1,2})S(\\d{1})MENUREQ(.*)$");
-    private static final Pattern ZONE_BUTTON2_PATTERN = Pattern.compile("^#Z(\\d{1,2})S(\\d{1})BUTTON(.*)$");
-    private static final Pattern ZONE_BUTTONTWO_PATTERN = Pattern.compile("^#Z(\\d{1,2})S(\\d{1})BUTTONTWO(.*)$");
+    private static final Pattern ZONE_SOURCE_PATTERN = Pattern.compile("^#Z(\\d{1,2})S(\\d{1})(.*)$");
+    private static final Pattern NN_MENUREQ_PATTERN = Pattern.compile("^#Z(\\d{1,2})S(\\d{1})MENUREQ(.*)$");
+    private static final Pattern NN_BUTTON_PATTERN = Pattern.compile("^#Z(\\d{1,2})S(\\d{1})BUTTON(.*)$");
+    private static final Pattern NN_BUTTONTWO_PATTERN = Pattern.compile("^#Z(\\d{1,2})S(\\d{1})BUTTONTWO(.*)$");
 
     private static final Pattern ZONE_CFG_PATTERN = Pattern.compile("^#ZCFG(\\d{1,2}),(.*)$");
 
     // S2ALBUMARTREQ0x620FD879,80,80,2,0x00C0C0C0,0,0,0,0,1
-    private static final Pattern ALBUM_ART_REQ = Pattern.compile("^#S(\\d{1})ALBUMARTREQ(.*)$");
+    private static final Pattern NN_ALBUM_ART_REQ = Pattern.compile("^#S(\\d{1})ALBUMARTREQ(.*)$");
 
     // S2ALBUMARTFRAGREQ0x620FD879,0,750
-    private static final Pattern ALBUM_ART_FRAG_REQ = Pattern.compile("^#S(\\d{1})ALBUMARTFRAGREQ(.*)$");
+    private static final Pattern NN_ALBUM_ART_FRAG_REQ = Pattern.compile("^#S(\\d{1})ALBUMARTFRAGREQ(.*)$");
 
     // S6FAVORITE0x000003E8
-    private static final Pattern FAVORITE_PATTERN = Pattern.compile("^#S(\\d{1})FAVORITE0x(.*)$");
+    private static final Pattern NN_FAVORITE_PATTERN = Pattern.compile("^#S(\\d{1})FAVORITE0x(.*)$");
 
     private final Logger logger = LoggerFactory.getLogger(NuvoConnector.class);
 
@@ -88,6 +88,7 @@ public abstract class NuvoConnector {
     private List<NuvoMessageEventListener> listeners = new ArrayList<>();
 
     private boolean isEssentia = true;
+    private boolean isAnyOhNuvoNet = false;
 
     /**
      * Get whether the connection is established or not
@@ -116,6 +117,15 @@ public abstract class NuvoConnector {
         this.isEssentia = isEssentia;
     }
 
+    /**
+     * Tell the connector to listen for NuvoNet source messages
+     *
+     * @param true if any sources are configured as openHAB NuvoNet sources
+     */
+    public void setAnyOhNuvoNet(boolean isAnyOhNuvoNet) {
+        this.isAnyOhNuvoNet = isAnyOhNuvoNet;
+    }
+
     /**
      * Set the thread that handles the feedback messages
      *
@@ -307,7 +317,7 @@ public abstract class NuvoConnector {
     }
 
     /**
-     * Analyze an incoming message and dispatch corresponding (type, key, value) to the event listeners
+     * Analyze an incoming message and dispatch corresponding (type, zone, src, value) to the event listeners
      *
      * @param incomingMessage the received message
      */
@@ -327,119 +337,117 @@ public abstract class NuvoConnector {
             } catch (NuvoException e) {
                 logger.debug("Error sending response to PING command");
             }
-            dispatchKeyValue(TYPE_PING, BLANK, BLANK);
+            dispatchKeyValue(TYPE_PING, BLANK);
             return;
         }
 
         if (RESTART.equals(message)) {
-            dispatchKeyValue(TYPE_RESTART, BLANK, BLANK);
+            dispatchKeyValue(TYPE_RESTART, BLANK);
             return;
         }
 
         if (message.contains(VER_STR_E6) || message.contains(VER_STR_GC)) {
             // example: #VER"NV-E6G FWv2.66 HWv0"
             // split on " and return the version number
-            dispatchKeyValue(TYPE_VERSION, "", message.split("\"")[1]);
+            dispatchKeyValue(TYPE_VERSION, message.split("\"")[1]);
             return;
         }
 
         if (message.equals(ALL_OFF)) {
-            dispatchKeyValue(TYPE_ALLOFF, BLANK, BLANK);
+            dispatchKeyValue(TYPE_ALLOFF, BLANK);
             return;
         }
 
         if (message.contains(MUTE)) {
-            dispatchKeyValue(TYPE_ALLMUTE, BLANK, message.substring(message.length() - 1));
+            dispatchKeyValue(TYPE_ALLMUTE, message.substring(message.length() - 1));
             return;
         }
 
         if (message.contains(PAGE)) {
-            dispatchKeyValue(TYPE_PAGE, BLANK, message.substring(message.length() - 1));
+            dispatchKeyValue(TYPE_PAGE, message.substring(message.length() - 1));
             return;
         }
 
-        // Amp controller sent an album art request
-        Matcher matcher = ALBUM_ART_REQ.matcher(message);
-        if (matcher.find()) {
-            // pull out the source id and the remainder of the message
-            dispatchKeyValue(TYPE_ALBUM_ART_REQ, matcher.group(1), matcher.group(2));
-            return;
-        }
+        Matcher matcher;
 
-        // Amp controller sent an album art fragment request
-        matcher = ALBUM_ART_FRAG_REQ.matcher(message);
-        if (matcher.find()) {
-            // pull out the source id and the remainder of the message
-            dispatchKeyValue(TYPE_ALBUM_ART_FRAG_REQ, matcher.group(1), matcher.group(2));
-            return;
-        }
+        if (isAnyOhNuvoNet) {
+            // Amp controller sent a NuvoNet album art request
+            matcher = NN_ALBUM_ART_REQ.matcher(message);
+            if (matcher.find()) {
+                dispatchKeyValue(TYPE_NN_ALBUM_ART_REQ, BLANK, matcher.group(1), matcher.group(2));
+                return;
+            }
 
-        // Amp controller sent a request to play a favorite
-        matcher = FAVORITE_PATTERN.matcher(message);
-        if (matcher.find()) {
-            // pull out the source id and the remainder of the message
-            dispatchKeyValue(TYPE_FAVORITE_REQ, matcher.group(1), matcher.group(2));
-            return;
+            // Amp controller sent a NuvoNet album art fragment request
+            matcher = NN_ALBUM_ART_FRAG_REQ.matcher(message);
+            if (matcher.find()) {
+                dispatchKeyValue(TYPE_NN_ALBUM_ART_FRAG_REQ, BLANK, matcher.group(1), matcher.group(2));
+                return;
+            }
+
+            // Amp controller sent a request for a NuvoNet source to play a favorite
+            matcher = NN_FAVORITE_PATTERN.matcher(message);
+            if (matcher.find()) {
+                dispatchKeyValue(TYPE_NN_FAVORITE_REQ, BLANK, matcher.group(1), matcher.group(2));
+                return;
+            }
         }
 
         // Amp controller sent a source update ie: #S2DISPINFO,DUR3380,POS3090,STATUS2
         // or #S2DISPLINE1,"1 of 17"
         matcher = SRC_PATTERN.matcher(message);
         if (matcher.find()) {
-            // pull out the source id and the remainder of the message
-            dispatchKeyValue(TYPE_SOURCE_UPDATE, matcher.group(1), matcher.group(2));
+            dispatchKeyValue(TYPE_SOURCE_UPDATE, BLANK, matcher.group(1), matcher.group(2));
             return;
         }
 
         // Amp controller sent a zone update ie: #Z11,ON,SRC3,VOL63,DND0,LOCK0
         matcher = ZONE_PATTERN.matcher(message);
         if (matcher.find()) {
-            // pull out the zone id and the remainder of the message
-            dispatchKeyValue(TYPE_ZONE_UPDATE, matcher.group(1), matcher.group(2));
+            dispatchKeyValue(TYPE_ZONE_UPDATE, matcher.group(1), BLANK, matcher.group(2));
             return;
         }
 
-        // Amp controller sent a zone BUTTONTWO press event ie: #Z11S3BUTTONTWO4,2,0,0,0
-        matcher = ZONE_BUTTONTWO_PATTERN.matcher(message);
-        if (matcher.find()) {
-            // redundant - ignore
-            return;
-        }
+        if (isAnyOhNuvoNet) {
+            // Amp controller sent a NuvoNet zone/source BUTTONTWO press event ie: #Z11S3BUTTONTWO4,2,0,0,0
+            matcher = NN_BUTTONTWO_PATTERN.matcher(message);
+            if (matcher.find()) {
+                // redundant - ignore
+                return;
+            }
 
-        // Amp controller sent a zone BUTTON press event ie: #Z4S6BUTTON1,1,0xFFFFFFFF,1,3
-        matcher = ZONE_BUTTON2_PATTERN.matcher(message);
-        if (matcher.find()) {
-            // pull out the remainder of the message: button #, action, menuid, itemid, itemidx
-            String[] buttonSplit = matcher.group(3).split(COMMA);
-
-            // second field is button action, only send DOWNUP (0) or DOWN (1), ignore UP (2)
-            if (ZERO.equals(buttonSplit[1]) || ONE.equals(buttonSplit[1])) {
-                // a button in a menu was pressed, send SxZy,menuid,itemidx
-                if (!ZERO.equals(buttonSplit[2])) {
-                    dispatchKeyValue(TYPE_MENU_ITEM_SELECTED, matcher.group(2), SRC_KEY + matcher.group(2) + ZONE_KEY
-                            + matcher.group(1) + COMMA + buttonSplit[2] + COMMA + buttonSplit[3]);
-                } else {
-                    // send the button # in the event, don't send extra fields menuid, itemid, etc..
-                    dispatchKeyValue(TYPE_ZONE_BUTTON2, matcher.group(2), buttonSplit[0]);
+            // Amp controller sent a NuvoNet zone/source BUTTON press event ie: #Z4S6BUTTON1,1,0xFFFFFFFF,1,3
+            matcher = NN_BUTTON_PATTERN.matcher(message);
+            if (matcher.find()) {
+                // pull out the remainder of the message: button #, action, menuid, itemid, itemidx
+                String[] buttonSplit = matcher.group(3).split(COMMA);
+
+                // second field is button action, only send DOWNUP (0) or DOWN (1), ignore UP (2)
+                if (ZERO.equals(buttonSplit[1]) || ONE.equals(buttonSplit[1])) {
+                    // a button in a menu was pressed, send 'menuid,itemidx'
+                    if (!ZERO.equals(buttonSplit[2])) {
+                        dispatchKeyValue(TYPE_NN_MENU_ITEM_SELECTED, matcher.group(1), matcher.group(2),
+                                buttonSplit[2] + COMMA + buttonSplit[3]);
+                    } else {
+                        // send the button # in the event, don't send extra fields menuid, itemid, etc..
+                        dispatchKeyValue(TYPE_NN_BUTTON, matcher.group(1), matcher.group(2), buttonSplit[0]);
+                    }
                 }
+                return;
             }
-            return;
-        }
 
-        // Amp controller sent a menu request event ie: #Z2S6MENUREQ0x0000000B,1,0,0
-        matcher = ZONE_MENUREQ_PATTERN.matcher(message);
-        if (matcher.find()) {
-            // pull out the source id and send SxZy plus the remainder of the message
-            dispatchKeyValue(TYPE_ZONE_MENUREQ, matcher.group(2),
-                    SRC_KEY + matcher.group(2) + ZONE_KEY + matcher.group(1) + COMMA + matcher.group(3));
-            return;
+            // Amp controller sent a NuvoNet zone/source menu request event ie: #Z2S6MENUREQ0x0000000B,1,0,0
+            matcher = NN_MENUREQ_PATTERN.matcher(message);
+            if (matcher.find()) {
+                dispatchKeyValue(TYPE_NN_MENUREQ, matcher.group(1), matcher.group(2), matcher.group(3));
+                return;
+            }
         }
 
-        // Amp controller sent a zone button press event ie: #Z11S3PLAYPAUSE
-        matcher = ZONE_BUTTON_PATTERN.matcher(message);
+        // Amp controller sent a zone/source button press event ie: #Z11S3PLAYPAUSE
+        matcher = ZONE_SOURCE_PATTERN.matcher(message);
         if (matcher.find()) {
-            // pull out the source id and the remainder of the message, ignore the zone id
-            dispatchKeyValue(TYPE_ZONE_BUTTON, matcher.group(2), matcher.group(3));
+            dispatchKeyValue(TYPE_ZONE_SOURCE_BUTTON, matcher.group(1), matcher.group(2), matcher.group(3));
             return;
         }
 
@@ -447,7 +455,7 @@ public abstract class NuvoConnector {
         matcher = ZONE_CFG_PATTERN.matcher(message);
         if (matcher.find()) {
             // pull out the zone id and the remainder of the message
-            dispatchKeyValue(TYPE_ZONE_CONFIG, matcher.group(1), matcher.group(2));
+            dispatchKeyValue(TYPE_ZONE_CONFIG, matcher.group(1), BLANK, matcher.group(2));
             return;
         }
 
@@ -455,14 +463,25 @@ public abstract class NuvoConnector {
     }
 
     /**
-     * Dispatch an event (type, key, value) to the event listeners
+     * Dispatch a system level event without zone or src to the event listeners
+     *
+     * @param type the type
+     * @param value the value
+     */
+    private void dispatchKeyValue(String type, String value) {
+        dispatchKeyValue(type, BLANK, BLANK, value);
+    }
+
+    /**
+     * Dispatch an event (type, zone, src, value) to the event listeners
      *
      * @param type the type
-     * @param key the key
+     * @param zone the zone id
+     * @param src the source id
      * @param value the value
      */
-    private void dispatchKeyValue(String type, String key, String value) {
-        NuvoMessageEvent event = new NuvoMessageEvent(this, type, key, value);
+    private void dispatchKeyValue(String type, String zone, String src, String value) {
+        NuvoMessageEvent event = new NuvoMessageEvent(this, type, zone, src, value);
         listeners.forEach(l -> l.onNewMessageEvent(event));
     }
 }
index 7539c941bf3986c67f34e6c13097e670ab6f07d5..2e6cd59ae030361e94b4a961620fe25bbbdca228 100644 (file)
@@ -25,13 +25,15 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
 public class NuvoMessageEvent extends EventObject {
     private static final long serialVersionUID = 1L;
     private final String type;
-    private final String key;
+    private final String zone;
+    private final String src;
     private final String value;
 
-    public NuvoMessageEvent(Object source, String type, String key, String value) {
+    public NuvoMessageEvent(Object source, String type, String zone, String src, String value) {
         super(source);
         this.type = type;
-        this.key = key;
+        this.zone = zone;
+        this.src = src;
         this.value = value;
     }
 
@@ -39,8 +41,12 @@ public class NuvoMessageEvent extends EventObject {
         return type;
     }
 
-    public String getKey() {
-        return key;
+    public String getZone() {
+        return zone;
+    }
+
+    public String getSrc() {
+        return src;
     }
 
     public String getValue() {
index 56320cb5ced2f7358955b5577f3a3b414b2cdd82..bfa27e0837737b0603a260913fc5e41d3437469f 100644 (file)
@@ -215,7 +215,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
 
         if (serialPort != null && !serialPort.isEmpty()) {
             connector = new NuvoSerialConnector(serialPortManager, serialPort, uid);
-        } else if (port != null) {
+        } else if (host != null && port != null) {
             connector = new NuvoIpConnector(host, port, uid);
             this.isMps4 = (port.intValue() == MPS4_PORT);
         } else {
@@ -239,6 +239,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
 
             if (this.isAnyOhNuvoNet) {
                 logger.debug("At least one source is configured as an openHAB NuvoNet source");
+                connector.setAnyOhNuvoNet(true);
                 loadMenuConfiguration(config);
 
                 favoriteMap.put("1",
@@ -640,11 +641,12 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
      */
     @Override
     public void onNewMessageEvent(NuvoMessageEvent evt) {
-        logger.debug("onNewMessageEvent: key {} = {}", evt.getKey(), evt.getValue());
+        logger.debug("onNewMessageEvent: zone {}, source {}, value {}", evt.getZone(), evt.getSrc(), evt.getValue());
         lastEventReceived = System.currentTimeMillis();
 
         String type = evt.getType();
-        String key = evt.getKey();
+        String zoneId = evt.getZone();
+        String srcId = evt.getSrc();
         String updateData = evt.getValue().trim();
         if (this.getThing().getStatus() != ThingStatus.ONLINE) {
             updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, this.versionString);
@@ -687,8 +689,8 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
                 updateChannelState(NuvoEnum.SYSTEM, CHANNEL_TYPE_PAGE, ONE.equals(updateData) ? ON : OFF);
                 break;
             case TYPE_SOURCE_UPDATE:
-                logger.debug("Source update: Source: {} - Value: {}", key, updateData);
-                NuvoEnum targetSource = NuvoEnum.valueOf(SOURCE + key);
+                logger.debug("Source update: Source: {} - Value: {}", srcId, updateData);
+                NuvoEnum targetSource = NuvoEnum.valueOf(SOURCE + srcId);
 
                 if (updateData.contains(DISPLINE)) {
                     // example: DISPLINE2,"Play My Song (Featuring Dee Ajayi)"
@@ -712,16 +714,16 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
                 } else if (updateData.contains(NAME_QUOTE)) {
                     // example: NAME"Ipod"
                     String name = updateData.split("\"")[1];
-                    sourceLabels.put(key, name);
+                    sourceLabels.put(srcId, name);
                 }
                 break;
             case TYPE_ZONE_UPDATE:
-                logger.debug("Zone update: Zone: {} - Value: {}", key, updateData);
+                logger.debug("Zone update: Zone: {} - Value: {}", zoneId, updateData);
                 // example : OFF
                 // or: ON,SRC3,VOL63,DND0,LOCK0
                 // or: ON,SRC3,MUTE,DND0,LOCK0
 
-                NuvoEnum targetZone = NuvoEnum.valueOf(ZONE + key);
+                NuvoEnum targetZone = NuvoEnum.valueOf(ZONE + zoneId);
 
                 if (OFF.equals(updateData)) {
                     updateChannelState(targetZone, CHANNEL_TYPE_POWER, OFF);
@@ -746,35 +748,43 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
                     }
                 }
                 break;
-            case TYPE_ZONE_BUTTON:
-                logger.debug("Zone Button pressed: Source: {} - Button: {}", key, updateData);
-                updateChannelState(NuvoEnum.valueOf(SOURCE + key), CHANNEL_BUTTON_PRESS, updateData);
+            case TYPE_ZONE_SOURCE_BUTTON:
+                logger.debug("Source Button pressed: Source: {} - Button: {}", srcId, updateData);
+                updateChannelState(NuvoEnum.valueOf(SOURCE + srcId), CHANNEL_BUTTON_PRESS, updateData);
+                updateChannelState(NuvoEnum.SYSTEM, CHANNEL_TYPE_BUTTONPRESS, zoneId + COMMA + updateData);
                 break;
-            case TYPE_ZONE_BUTTON2:
+            case TYPE_NN_BUTTON:
                 String buttonAction = NuvoStatusCodes.BUTTON_CODE.get(updateData);
 
                 if (buttonAction != null) {
-                    logger.debug("Zone NuvoNet Button pressed: Source: {} - Button: {}", key, buttonAction);
-                    updateChannelState(NuvoEnum.valueOf(SOURCE + key), CHANNEL_BUTTON_PRESS, buttonAction);
+                    logger.debug("NuvoNet Source Button pressed: Source: {} - Button: {}", srcId, buttonAction);
+                    updateChannelState(NuvoEnum.valueOf(SOURCE + srcId), CHANNEL_BUTTON_PRESS, buttonAction);
+                    updateChannelState(NuvoEnum.SYSTEM, CHANNEL_TYPE_BUTTONPRESS, zoneId + COMMA + buttonAction);
                 } else {
-                    logger.debug("Zone NuvoNet Button pressed: Source: {} - Unknown button code: {}", key, updateData);
-                    updateChannelState(NuvoEnum.valueOf(SOURCE + key), CHANNEL_BUTTON_PRESS, updateData);
+                    logger.debug("NuvoNet Source Button pressed: Source: {} - Unknown button code: {}", srcId,
+                            updateData);
+                    updateChannelState(NuvoEnum.valueOf(SOURCE + srcId), CHANNEL_BUTTON_PRESS, updateData);
+                    updateChannelState(NuvoEnum.SYSTEM, CHANNEL_TYPE_BUTTONPRESS, zoneId + COMMA + updateData);
                 }
                 break;
-            case TYPE_MENU_ITEM_SELECTED:
+            case TYPE_NN_MENU_ITEM_SELECTED:
                 // ignore this update unless openHAB is handling this source
-                if (nuvoNetSrcMap.get(key).equals(2)) {
+                if (nuvoNetSrcMap.get(srcId).equals(2)) {
+                    String sourceZone = SRC_KEY + srcId + ZONE_KEY + zoneId;
                     String[] updateDataSplit = updateData.split(COMMA);
-                    String zoneSource = updateDataSplit[0];
-                    String menuId = updateDataSplit[1];
-                    int menuItemIdx = Integer.parseInt(updateDataSplit[2]) - 1;
+                    String menuId = updateDataSplit[0];
+                    int menuItemIdx = Integer.parseInt(updateDataSplit[1]) - 1;
 
                     boolean exitMenu = false;
                     if ("0xFFFFFFFF".equals(menuId)) {
-                        TopMenu topMenuItem = nuvoMenus.getSource().get(Integer.parseInt(key) - 1).getTopMenu()
+                        TopMenu topMenuItem = nuvoMenus.getSource().get(Integer.parseInt(srcId) - 1).getTopMenu()
                                 .get(menuItemIdx);
-                        logger.debug("Top Menu item selected: Source: {} - Menu Item: {}", key, topMenuItem.getText());
-                        updateChannelState(NuvoEnum.valueOf(SOURCE + key), CHANNEL_BUTTON_PRESS, topMenuItem.getText());
+                        logger.debug("Top Menu item selected: Source: {} - Menu Item: {}", srcId,
+                                topMenuItem.getText());
+                        updateChannelState(NuvoEnum.valueOf(SOURCE + srcId), CHANNEL_BUTTON_PRESS,
+                                topMenuItem.getText());
+                        updateChannelState(NuvoEnum.SYSTEM, CHANNEL_TYPE_BUTTONPRESS,
+                                zoneId + COMMA + topMenuItem.getText());
 
                         List<String> subMenuItems = topMenuItem.getItems();
 
@@ -784,135 +794,139 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
                             // send submenu (maximum of 20 items)
                             int subMenuSize = subMenuItems.size() < 20 ? subMenuItems.size() : 20;
                             try {
-                                connector.sendCommand(zoneSource + "MENU" + (menuItemIdx + 11) + ",0,0," + subMenuSize
+                                connector.sendCommand(sourceZone + "MENU" + (menuItemIdx + 11) + ",0,0," + subMenuSize
                                         + ",0,0," + subMenuSize + ",\"" + topMenuItem.getText() + "\"");
                                 Thread.sleep(SLEEP_BETWEEN_CMD_MS);
 
                                 for (int i = 0; i < subMenuSize; i++) {
                                     connector.sendCommand(
-                                            zoneSource + "MENUITEM" + (i + 1) + ",0,0,\"" + subMenuItems.get(i) + "\"");
+                                            sourceZone + "MENUITEM" + (i + 1) + ",0,0,\"" + subMenuItems.get(i) + "\"");
                                 }
                             } catch (NuvoException | InterruptedException e) {
-                                logger.debug("Error sending sub menu for {}", zoneSource);
+                                logger.debug("Error sending sub menu to {}", sourceZone);
                             }
                         }
                     } else {
                         // a sub menu item was selected
-                        TopMenu topMenuItem = nuvoMenus.getSource().get(Integer.parseInt(key) - 1).getTopMenu()
+                        TopMenu topMenuItem = nuvoMenus.getSource().get(Integer.parseInt(srcId) - 1).getTopMenu()
                                 .get(Integer.decode(menuId) - 11);
                         String subMenuItem = topMenuItem.getItems().get(menuItemIdx);
 
-                        logger.debug("Sub Menu item selected: Source: {} - Menu Item: {}", key,
+                        logger.debug("Sub Menu item selected: Source: {} - Menu Item: {}", srcId,
                                 topMenuItem.getText() + "|" + subMenuItem);
-                        updateChannelState(NuvoEnum.valueOf(SOURCE + key), CHANNEL_BUTTON_PRESS,
+                        updateChannelState(NuvoEnum.valueOf(SOURCE + srcId), CHANNEL_BUTTON_PRESS,
                                 topMenuItem.getText() + "|" + subMenuItem);
+                        updateChannelState(NuvoEnum.SYSTEM, CHANNEL_TYPE_BUTTONPRESS,
+                                zoneId + COMMA + topMenuItem.getText() + "|" + subMenuItem);
                         exitMenu = true;
                     }
 
                     if (exitMenu) {
                         try {
                             // tell the zone to exit the menu
-                            connector.sendCommand(zoneSource + "MENU0,0,0,0,0,0,0,\"\"");
+                            connector.sendCommand(sourceZone + "MENU0,0,0,0,0,0,0,\"\"");
                         } catch (NuvoException e) {
-                            logger.debug("Error sending exit menu command for {}", zoneSource);
+                            logger.debug("Error sending exit menu command to {}", sourceZone);
                         }
                     }
                 }
                 break;
-            case TYPE_ZONE_MENUREQ:
+            case TYPE_NN_MENUREQ:
                 // ignore this update unless openHAB is handling this source
-                if (nuvoNetSrcMap.get(key).equals(2)) {
-                    logger.debug("Menu Request: Source: {} - Value: {}", key, updateData);
-                    // For now we only support one level deep menus. If third field is '1', indicates go back to main
+                if (nuvoNetSrcMap.get(srcId).equals(2)) {
+                    logger.debug("Menu Request: Source: {} - Value: {}", srcId, updateData);
+                    String sourceZone = SRC_KEY + srcId + ZONE_KEY + zoneId;
+                    // For now we only support one level deep menus. If second field is '1', indicates go back to main
                     // menu.
-                    String[] menuDataSplit = updateData.split(",");
-                    if (menuDataSplit.length > 3 && ONE.equals(menuDataSplit[2])) {
+                    String[] menuDataSplit = updateData.split(COMMA);
+                    if (menuDataSplit.length > 2 && ONE.equals(menuDataSplit[1])) {
                         try {
-                            connector.sendCommand(menuDataSplit[0] + "MENU0xFFFFFFFF,0,0,0,0,0,0,\"\"");
+                            connector.sendCommand(sourceZone + "MENU0xFFFFFFFF,0,0,0,0,0,0,\"\"");
                         } catch (NuvoException e) {
-                            logger.debug("Error sending main menu command for {}", menuDataSplit[0]);
+                            logger.debug("Error sending main menu command to {}", sourceZone);
                         }
                     }
                 }
                 break;
             case TYPE_ZONE_CONFIG:
-                logger.debug("Zone Configuration: Zone: {} - Value: {}", key, updateData);
+                logger.debug("Zone Configuration: Zone: {} - Value: {}", zoneId, updateData);
                 // example: BASS1,TREB-2,BALR2,LOUDCMP1
                 Matcher matcher = ZONE_CFG_PATTERN.matcher(updateData);
                 if (matcher.find()) {
-                    updateChannelState(NuvoEnum.valueOf(ZONE + key), CHANNEL_TYPE_BASS, matcher.group(1));
-                    updateChannelState(NuvoEnum.valueOf(ZONE + key), CHANNEL_TYPE_TREBLE, matcher.group(2));
-                    updateChannelState(NuvoEnum.valueOf(ZONE + key), CHANNEL_TYPE_BALANCE,
+                    updateChannelState(NuvoEnum.valueOf(ZONE + zoneId), CHANNEL_TYPE_BASS, matcher.group(1));
+                    updateChannelState(NuvoEnum.valueOf(ZONE + zoneId), CHANNEL_TYPE_TREBLE, matcher.group(2));
+                    updateChannelState(NuvoEnum.valueOf(ZONE + zoneId), CHANNEL_TYPE_BALANCE,
                             NuvoStatusCodes.getBalanceFromStr(matcher.group(3)));
-                    updateChannelState(NuvoEnum.valueOf(ZONE + key), CHANNEL_TYPE_LOUDNESS,
+                    updateChannelState(NuvoEnum.valueOf(ZONE + zoneId), CHANNEL_TYPE_LOUDNESS,
                             ONE.equals(matcher.group(4)) ? ON : OFF);
                 } else {
                     logger.debug("no match on message: {}", updateData);
                 }
                 break;
-            case TYPE_ALBUM_ART_REQ:
+            case TYPE_NN_ALBUM_ART_REQ:
                 // ignore this update unless openHAB is handling this source
-                if (nuvoNetSrcMap.get(key).equals(2)) {
-                    logger.debug("Album Art Request for Source: {} - Data: {}", key, updateData);
+                if (nuvoNetSrcMap.get(srcId).equals(2)) {
+                    logger.debug("Album Art Request for Source: {} - Data: {}", srcId, updateData);
                     // 0x620FD879,80,80,2,0x00C0C0C0,0,0,0,0,1
                     String[] albumArtReq = updateData.split(COMMA);
-                    albumArtIds.put(SRC_KEY + key, Integer.decode(albumArtReq[0]));
+                    albumArtIds.put(SRC_KEY + srcId, Integer.decode(albumArtReq[0]));
 
                     try {
-                        if (albumArtMap.get(SRC_KEY + key).length > 1) {
-                            connector.sendCommand(SRC_KEY + key + ALBUM_ART_AVAILABLE + albumArtIds.get(SRC_KEY + key)
-                                    + COMMA + albumArtMap.get(SRC_KEY + key).length);
+                        if (albumArtMap.get(SRC_KEY + srcId).length > 1) {
+                            connector.sendCommand(
+                                    SRC_KEY + srcId + ALBUM_ART_AVAILABLE + albumArtIds.get(SRC_KEY + srcId) + COMMA
+                                            + albumArtMap.get(SRC_KEY + srcId).length);
                         } else {
-                            connector.sendCommand(SRC_KEY + key + ALBUM_ART_AVAILABLE + ZERO_COMMA);
+                            connector.sendCommand(SRC_KEY + srcId + ALBUM_ART_AVAILABLE + ZERO_COMMA);
                         }
                     } catch (NuvoException e) {
-                        logger.debug("Error sending ALBUMARTAVAILABLE command for source: {}", key);
+                        logger.debug("Error sending ALBUMARTAVAILABLE command for source: {}", srcId);
                     }
                 }
                 break;
-            case TYPE_ALBUM_ART_FRAG_REQ:
+            case TYPE_NN_ALBUM_ART_FRAG_REQ:
                 // ignore this update unless openHAB is handling this source
-                if (nuvoNetSrcMap.get(key).equals(2)) {
-                    logger.debug("Album Art Fragment Request for Source: {} - Data: {}", key, updateData);
+                if (nuvoNetSrcMap.get(srcId).equals(2)) {
+                    logger.debug("Album Art Fragment Request for Source: {} - Data: {}", srcId, updateData);
                     // 0x620FD879,0,750 (id, requested offset from start of image, byte length requested)
                     String[] albumArtFragReq = updateData.split(COMMA);
                     int requestedId = Integer.decode(albumArtFragReq[0]);
                     int offset = Integer.parseInt(albumArtFragReq[1]);
                     int length = Integer.parseInt(albumArtFragReq[2]);
 
-                    if (requestedId == albumArtIds.get(SRC_KEY + key)) {
+                    if (requestedId == albumArtIds.get(SRC_KEY + srcId)) {
                         byte[] chunk = new byte[length];
-                        byte[] albumArtBytes = albumArtMap.get(SRC_KEY + key);
+                        byte[] albumArtBytes = albumArtMap.get(SRC_KEY + srcId);
 
                         if (albumArtBytes != null) {
                             System.arraycopy(albumArtBytes, offset, chunk, 0, length);
                             final String frag = Base64.getEncoder().encodeToString(chunk);
                             try {
-                                connector.sendCommand(SRC_KEY + key + ALBUM_ART_FRAG + requestedId + COMMA + offset
+                                connector.sendCommand(SRC_KEY + srcId + ALBUM_ART_FRAG + requestedId + COMMA + offset
                                         + COMMA + frag.length() + COMMA + frag);
                             } catch (NuvoException e) {
-                                logger.debug("Error sending ALBUMARTFRAG command for source: {}, artId: {}", key,
+                                logger.debug("Error sending ALBUMARTFRAG command for source: {}, artId: {}", srcId,
                                         requestedId);
                             }
                         }
                     }
                 }
                 break;
-            case TYPE_FAVORITE_REQ:
+            case TYPE_NN_FAVORITE_REQ:
                 // ignore this update unless openHAB is handling this source
-                if (nuvoNetSrcMap.get(key).equals(2)) {
-                    logger.debug("Favorite request for source: {} - favoriteId: {}", key, updateData);
+                if (nuvoNetSrcMap.get(srcId).equals(2)) {
+                    logger.debug("Favorite request for source: {} - favoriteId: {}", srcId, updateData);
                     try {
                         int playlistIdx = Integer.parseInt(updateData, 16) - 1000;
-                        updateChannelState(NuvoEnum.valueOf(SOURCE + key), CHANNEL_BUTTON_PRESS,
-                                "PLAY_MUSIC_PRESET:" + favoriteMap.get(key)[playlistIdx]);
+                        updateChannelState(NuvoEnum.valueOf(SOURCE + srcId), CHANNEL_BUTTON_PRESS,
+                                "PLAY_MUSIC_PRESET:" + favoriteMap.get(srcId)[playlistIdx]);
                     } catch (NumberFormatException nfe) {
                         logger.debug("Unable to parse favoriteId: {}", updateData);
                     }
                 }
                 break;
             default:
-                logger.debug("onNewMessageEvent: unhandled key {}", key);
+                logger.debug("onNewMessageEvent: unhandled event type {}", type);
                 // Return here because receiving an unknown message does not indicate that one can poll
                 return;
         }
index b882e74e53738a0ae00cf5ae78468bb813e7e449..4d69eef37badcd2003c2a28cd138dd6c5cb3b0b6 100644 (file)
@@ -165,7 +165,7 @@ channel-type.nuvo.balance.description = Adjust the Balance Setting for the Zone
 channel-type.nuvo.bass.label = Bass Adjustment
 channel-type.nuvo.bass.description = Adjust the Bass Setting for the Zone
 channel-type.nuvo.button_press.label = Button Pressed
-channel-type.nuvo.button_press.description = Indicates the Last Button Pressed On the Keypad for a Non NuvoNet Source
+channel-type.nuvo.button_press.description = Indicates the Last Button Pressed On the Keypad
 channel-type.nuvo.control.label = Control
 channel-type.nuvo.control.description = Transport Controls e.g. Play/Pause/Next/Previous for the Current Source
 channel-type.nuvo.display_line1.label = Display Line 1
index 023af7f53dd5d7e5618694dc0f8d0a2e387aa383..3b35889c4d38442680913d75c8abe96babf43d32 100644 (file)
                        <channel id="allmute" typeId="system.mute"/>
                        <channel id="page" typeId="page"/>
                        <channel id="sendcmd" typeId="sendcmd"/>
+                       <channel id="buttonpress" typeId="button_press"/>
                </channels>
        </channel-group-type>
 
        <channel-type id="button_press">
                <item-type>String</item-type>
                <label>Button Pressed</label>
-               <description>Indicates the Last Button Pressed On the Keypad for a Non NuvoNet Source</description>
+               <description>Indicates the Last Button Pressed On the Keypad</description>
                <state readOnly="true"/>
        </channel-type>