diff --git a/bundles/org.openhab.binding.nuvo/README.md b/bundles/org.openhab.binding.nuvo/README.md index e77b4540c59ff..e705a9c37f69b 100644 --- a/bundles/org.openhab.binding.nuvo/README.md +++ b/bundles/org.openhab.binding.nuvo/README.md @@ -5,8 +5,8 @@ Up to 20 keypad zones can be controlled when zone expansion modules are used (if The binding supports three different kinds of connections: -- serial connection, -- serial over IP connection, +- serial port connection +- serial over IP connection - direct IP connection via a Nuvo MPS4 music server For users without a serial connector on the server side, you can use a USB to serial adapter. @@ -27,11 +27,6 @@ It has the `amplifier` id. Discovery is not supported. You have to add all things manually. -## Binding Configuration - -There are no overall binding configuration settings that need to be set. -All settings are through thing configuration parameters. - ## Thing Configuration The thing has the following configuration parameters: diff --git a/bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/communication/NuvoCommand.java b/bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/communication/NuvoCommand.java index e6b0a1999a19f..537ae9338c7f6 100644 --- a/bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/communication/NuvoCommand.java +++ b/bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/communication/NuvoCommand.java @@ -29,6 +29,7 @@ public enum NuvoCommand { PAGE_OFF("PAGE0"), CFGTIME("CFGTIME"), STATUS("STATUS"), + STATUS_QUERY("STATUS?"), EQ_QUERY("EQ?"), DISPINFO("DISPINFO"), DISPLINE("DISPLINE"), diff --git a/bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/handler/NuvoHandler.java b/bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/handler/NuvoHandler.java index 34fe2f98ad4b8..e339233989b17 100644 --- a/bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/handler/NuvoHandler.java +++ b/bundles/org.openhab.binding.nuvo/src/main/java/org/openhab/binding/nuvo/internal/handler/NuvoHandler.java @@ -134,7 +134,9 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis private static final Pattern DISP_PATTERN = Pattern.compile("^DISPLINE(\\d{1}),\"(.*)\"$"); private static final Pattern DISP_INFO_PATTERN = Pattern .compile("^DISPINFO,DUR(\\d{1,6}),POS(\\d{1,6}),STATUS(\\d{1,2})$"); - private static final Pattern ZONE_CFG_PATTERN = Pattern.compile("^BASS(.*),TREB(.*),BAL(.*),LOUDCMP([0-1])$"); + private static final Pattern ZONE_CFG_EQ_PATTERN = Pattern.compile("^BASS(.*),TREB(.*),BAL(.*),LOUDCMP([0-1])$"); + private static final Pattern ZONE_CFG_PATTERN = Pattern.compile( + "^ENABLE1,NAME\"(.*)\",SLAVETO(.*),GROUP([0-4]),SOURCES(.*),XSRC(.*),IR(.*),DND(.*),LOCKED(.*),SLAVEEQ(.*)$"); private final Logger logger = LoggerFactory.getLogger(NuvoHandler.class); private final NuvoStateDescriptionOptionProvider stateDescriptionProvider; @@ -155,6 +157,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis private boolean isAnyOhNuvoNet = false; private NuvoMenu nuvoMenus = new NuvoMenu(); + private HashMap> nuvoGroupMap = new HashMap>(); private HashMap nuvoNetSrcMap = new HashMap(); private HashMap favPrefixMap = new HashMap(); private HashMap favoriteMap = new HashMap(); @@ -231,6 +234,11 @@ public void initialize() { nuvoNetSrcMap.put("5", config.nuvoNetSrc5); nuvoNetSrcMap.put("6", config.nuvoNetSrc6); + nuvoGroupMap.put("1", new HashSet()); + nuvoGroupMap.put("2", new HashSet()); + nuvoGroupMap.put("3", new HashSet()); + nuvoGroupMap.put("4", new HashSet()); + if (this.isMps4) { logger.debug("Port set to {} configuring binding for MPS4 compatability", MPS4_PORT); @@ -734,6 +742,18 @@ public void onNewMessageEvent(NuvoMessageEvent evt) { updateChannelState(targetZone, CHANNEL_TYPE_POWER, ON); updateChannelState(targetZone, CHANNEL_TYPE_SOURCE, matcher.group(1)); + // check if this zone is in a group, if so update the other group member's selected source + nuvoGroupMap.forEach((groupId, groupZones) -> { + if (groupZones.contains(zoneId)) { + groupZones.forEach(z -> { + if (!zoneId.equals(z)) { + updateChannelState(NuvoEnum.valueOf(ZONE + z), CHANNEL_TYPE_SOURCE, + matcher.group(1)); + } + }); + } + }); + if (MUTE.equals(matcher.group(2))) { updateChannelState(targetZone, CHANNEL_TYPE_MUTE, ON); } else { @@ -851,7 +871,7 @@ public void onNewMessageEvent(NuvoMessageEvent evt) { case TYPE_ZONE_CONFIG: logger.debug("Zone Configuration: Zone: {} - Value: {}", zoneId, updateData); // example: BASS1,TREB-2,BALR2,LOUDCMP1 - Matcher matcher = ZONE_CFG_PATTERN.matcher(updateData); + Matcher matcher = ZONE_CFG_EQ_PATTERN.matcher(updateData); if (matcher.find()) { updateChannelState(NuvoEnum.valueOf(ZONE + zoneId), CHANNEL_TYPE_BASS, matcher.group(1)); updateChannelState(NuvoEnum.valueOf(ZONE + zoneId), CHANNEL_TYPE_TREBLE, matcher.group(2)); @@ -860,7 +880,18 @@ public void onNewMessageEvent(NuvoMessageEvent evt) { updateChannelState(NuvoEnum.valueOf(ZONE + zoneId), CHANNEL_TYPE_LOUDNESS, ONE.equals(matcher.group(4)) ? ON : OFF); } else { - logger.debug("no match on message: {}", updateData); + matcher = ZONE_CFG_PATTERN.matcher(updateData); + // example: ENABLE1,NAME"Great Room",SLAVETO0,GROUP1,SOURCES63,XSRC0,IR1,DND0,LOCKED0,SLAVEEQ0 + if (matcher.find()) { + // TODO: utilize other info such as zone name, available sources bitmask, etc. + + // if this zone is a member of a group (1-4), add the zone's id to the appropriate group map + if (!ZERO.equals(matcher.group(3))) { + nuvoGroupMap.get(matcher.group(3)).add(zoneId); + } + } else { + logger.debug("no match on message: {}", updateData); + } } break; case TYPE_NN_ALBUM_ART_REQ: @@ -1145,6 +1176,8 @@ private void pollStatus() { try { connector.sendQuery(NuvoEnum.valueOf(ZONE + zoneNum), NuvoCommand.STATUS); Thread.sleep(SLEEP_BETWEEN_CMD_MS); + connector.sendCfgCommand(NuvoEnum.valueOf(ZONE + zoneNum), NuvoCommand.STATUS_QUERY, BLANK); + Thread.sleep(SLEEP_BETWEEN_CMD_MS); connector.sendCfgCommand(NuvoEnum.valueOf(ZONE + zoneNum), NuvoCommand.EQ_QUERY, BLANK); Thread.sleep(SLEEP_BETWEEN_CMD_MS); } catch (NuvoException | InterruptedException e) {