Skip to content

Commit

Permalink
[nuvo] Auto update source channel for grouped zones (#14012)
Browse files Browse the repository at this point in the history
* Auto update source channel for grouped zones

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
  • Loading branch information
mlobstein authored Dec 27, 2022
1 parent e39e691 commit 4a98295
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 10 deletions.
9 changes: 2 additions & 7 deletions bundles/org.openhab.binding.nuvo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public enum NuvoCommand {
PAGE_OFF("PAGE0"),
CFGTIME("CFGTIME"),
STATUS("STATUS"),
STATUS_QUERY("STATUS?"),
EQ_QUERY("EQ?"),
DISPINFO("DISPINFO"),
DISPLINE("DISPLINE"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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[]>();
Expand Down Expand Up @@ -231,6 +234,11 @@ public void initialize() {
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);

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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));
Expand All @@ -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:
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 4a98295

Please sign in to comment.