[nuvo] Auto update source channel for grouped zones (#14012)

* Auto update source channel for grouped zones

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
This commit is contained in:
mlobstein 2022-12-27 05:54:26 -06:00 committed by GitHub
parent e39e69144b
commit 4a982957c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 10 deletions

View File

@ -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:

View File

@ -29,6 +29,7 @@ public enum NuvoCommand {
PAGE_OFF("PAGE0"),
CFGTIME("CFGTIME"),
STATUS("STATUS"),
STATUS_QUERY("STATUS?"),
EQ_QUERY("EQ?"),
DISPINFO("DISPINFO"),
DISPLINE("DISPLINE"),

View File

@ -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<String, Set<String>> nuvoGroupMap = new HashMap<String, Set<String>>();
private HashMap<String, Integer> nuvoNetSrcMap = new HashMap<String, Integer>();
private HashMap<String, String> favPrefixMap = new HashMap<String, String>();
private HashMap<String, String[]> favoriteMap = new HashMap<String, String[]>();
@ -231,6 +234,11 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
nuvoNetSrcMap.put("5", config.nuvoNetSrc5);
nuvoNetSrcMap.put("6", config.nuvoNetSrc6);
nuvoGroupMap.put("1", new HashSet<String>());
nuvoGroupMap.put("2", new HashSet<String>());
nuvoGroupMap.put("3", new HashSet<String>());
nuvoGroupMap.put("4", new HashSet<String>());
if (this.isMps4) {
logger.debug("Port set to {} configuring binding for MPS4 compatability", MPS4_PORT);
@ -734,6 +742,18 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
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 class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
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 class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
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 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
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) {