Add image size configurations (#17222)

Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
mlobstein 2024-08-13 14:24:03 -05:00 committed by Ciprian Pascu
parent 59207c9e0e
commit f4aae57417
7 changed files with 120 additions and 36 deletions

View File

@ -28,6 +28,15 @@ It has the `amplifier` id.
Discovery is not supported.
You have to add all things manually.
## Binding Configuration
The binding has the following configuration parameters:
| Parameter Label | Parameter ID | Description | Accepted Values |
|--------------------------|--------------- |---------------------------------------------------------------|-----------------------|
| Image Height | imageHeight | Height (in pixels) for album art images loaded from the MPS4. | 1 - 1024; default 150 |
| Image Width | imageWidth | Width (in pixels) for album art images loaded from the MPS4. | 1 - 1024; default 150 |
## Thing Configuration
The thing has the following configuration parameters:

View File

@ -120,5 +120,5 @@ public class NuvoBindingConstants {
public static final String GET_MCS_INSTANCE = "http://%s/api/Script/MRAD.SetZone%%20Zone_%s/MRAD.GetStatus/?clientId=%s";
public static final String GET_MCS_STATUS = "http://%s/api/Script/SetInstance%%20%s/GetStatus?clientId=%s";
public static final String GET_MCS_JSON = "http://%s/api/?clientId=%s";
public static final String GET_MCS_ART = "http://%s/getArt?guid=%s&instance=%s&h=143&w=143&changed=true&c=1&fmt=jpg";
public static final String GET_MCS_ART = "http://%s/getArt?guid=%s&instance=%s&h=%s&w=%s&changed=true&c=1&fmt=jpg";
}

View File

@ -14,11 +14,13 @@ package org.openhab.binding.nuvo.internal;
import static org.openhab.binding.nuvo.internal.NuvoBindingConstants.*;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.nuvo.internal.configuration.NuvoBindingConfiguration;
import org.openhab.binding.nuvo.internal.handler.NuvoHandler;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.io.transport.serial.SerialPortManager;
@ -27,6 +29,7 @@ import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@ -49,6 +52,8 @@ public class NuvoHandlerFactory extends BaseThingHandlerFactory {
private final HttpClient httpClient;
private final NuvoBindingConfiguration bindingConf;
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
@ -56,11 +61,13 @@ public class NuvoHandlerFactory extends BaseThingHandlerFactory {
@Activate
public NuvoHandlerFactory(final @Reference NuvoStateDescriptionOptionProvider provider,
final @Reference SerialPortManager serialPortManager,
final @Reference HttpClientFactory httpClientFactory) {
final @Reference SerialPortManager serialPortManager, final @Reference HttpClientFactory httpClientFactory,
ComponentContext componentContext, Map<String, Object> config) {
super.activate(componentContext);
this.stateDescriptionProvider = provider;
this.serialPortManager = serialPortManager;
this.httpClient = httpClientFactory.getCommonHttpClient();
this.bindingConf = new NuvoBindingConfiguration(config);
}
@Override
@ -68,7 +75,7 @@ public class NuvoHandlerFactory extends BaseThingHandlerFactory {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
return new NuvoHandler(thing, stateDescriptionProvider, serialPortManager, httpClient);
return new NuvoHandler(thing, stateDescriptionProvider, serialPortManager, httpClient, bindingConf);
}
return null;

View File

@ -0,0 +1,33 @@
/**
* 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.nuvo.internal.configuration;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link NuvoBindingConfiguration} is responsible for holding configuration of the binding itself.
*
* @author Michael Lobstein - Initial contribution
*/
@NonNullByDefault
public class NuvoBindingConfiguration {
public final String imageHeight;
public final String imageWidth;
public NuvoBindingConfiguration(Map<String, Object> config) {
this.imageHeight = (String) config.getOrDefault("imageHeight", "150");
this.imageWidth = (String) config.getOrDefault("imageWidth", "150");
}
}

View File

@ -62,6 +62,7 @@ import org.openhab.binding.nuvo.internal.communication.NuvoMessageEvent;
import org.openhab.binding.nuvo.internal.communication.NuvoMessageEventListener;
import org.openhab.binding.nuvo.internal.communication.NuvoSerialConnector;
import org.openhab.binding.nuvo.internal.communication.NuvoStatusCodes;
import org.openhab.binding.nuvo.internal.configuration.NuvoBindingConfiguration;
import org.openhab.binding.nuvo.internal.configuration.NuvoThingConfiguration;
import org.openhab.binding.nuvo.internal.dto.JAXBUtils;
import org.openhab.binding.nuvo.internal.dto.NuvoMenu;
@ -140,6 +141,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
private static final Pattern ART_GUID_PATTERN = Pattern.compile("NowPlayingGuid\",\"value\":\"\\{(.*?)\\}\"\\}");
private final Logger logger = LoggerFactory.getLogger(NuvoHandler.class);
private final NuvoBindingConfiguration bindingConf;
private final NuvoStateDescriptionOptionProvider stateDescriptionProvider;
private final SerialPortManager serialPortManager;
private final HttpClient httpClient;
@ -184,11 +186,12 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
* Constructor
*/
public NuvoHandler(Thing thing, NuvoStateDescriptionOptionProvider stateDescriptionProvider,
SerialPortManager serialPortManager, HttpClient httpClient) {
SerialPortManager serialPortManager, HttpClient httpClient, NuvoBindingConfiguration bindingConf) {
super(thing);
this.stateDescriptionProvider = stateDescriptionProvider;
this.serialPortManager = serialPortManager;
this.httpClient = httpClient;
this.bindingConf = bindingConf;
}
@Override
@ -377,12 +380,13 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
});
// need '1' flag for sources configured as an MPS4 NuvoNet source, but disable openHAB NuvoNet sources
connector.sendCommand("SNUMBERS" + (nuvoNetSrcMap.get(NuvoEnum.SOURCE1).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.get(NuvoEnum.SOURCE2).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.get(NuvoEnum.SOURCE3).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.get(NuvoEnum.SOURCE4).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.get(NuvoEnum.SOURCE5).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.get(NuvoEnum.SOURCE6).equals(1) ? ONE : ZERO));
connector.sendCommand(
"SNUMBERS" + (nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE1, 0).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE2, 0).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE3, 0).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE4, 0).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE5, 0).equals(1) ? ONE : ZERO) + COMMA
+ (nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE6, 0).equals(1) ? ONE : ZERO));
} catch (NuvoException e) {
logger.debug("Error sending SNUMBERS command to disable NuvoNet sources");
}
@ -467,7 +471,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
String sourceNum = String.valueOf(value / 100);
NuvoEnum source = NuvoEnum.valueOf(SOURCE + sourceNum);
updateChannelState(source, CHANNEL_BUTTON_PRESS,
PLAY_MUSIC_PRESET + favoriteMap.get(source)[value % 100]);
PLAY_MUSIC_PRESET + getFavorite(source, value % 100));
connector.sendCommand(target, NuvoCommand.SOURCE, sourceNum);
// if this zone is in a group, update the other group member's selected source
@ -595,7 +599,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
// if 'albumartid' is present, substitute it with the albumArtId hex string
connector.sendCommand(commandStr.replace(ALBUM_ART_ID,
(OFFSET_ZERO + Integer.toHexString(albumArtIds.get(source)))));
(OFFSET_ZERO + Integer.toHexString(albumArtIds.getOrDefault(source, 0)))));
} else {
connector.sendCommand(commandStr);
}
@ -631,8 +635,9 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
// re-send the cached DISPINFOTWO message, substituting in the new albumArtId
if (dispInfoCache.get(target) != null) {
connector.sendCommand(dispInfoCache.get(target).replace(ALBUM_ART_ID,
(OFFSET_ZERO + Integer.toHexString(albumArtIds.get(target)))));
connector.sendCommand(dispInfoCache.getOrDefault(target, BLANK).replace(
ALBUM_ART_ID,
(OFFSET_ZERO + Integer.toHexString(albumArtIds.getOrDefault(target, 0)))));
}
} else {
albumArtMap.put(target, NO_ART);
@ -842,7 +847,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
break;
case TYPE_NN_MENU_ITEM_SELECTED:
// ignore this update unless openHAB is handling this source
if (nuvoNetSrcMap.get(source).equals(2)) {
if (nuvoNetSrcMap.getOrDefault(source, 0).equals(2)) {
String[] updateDataSplit = updateData.split(COMMA);
String menuId = updateDataSplit[0];
int menuItemIdx = Integer.parseInt(updateDataSplit[1]) - 1;
@ -903,7 +908,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
break;
case TYPE_NN_MENUREQ:
// ignore this update unless openHAB is handling this source
if (nuvoNetSrcMap.get(source).equals(2)) {
if (nuvoNetSrcMap.getOrDefault(source, 0).equals(2)) {
logger.debug("Menu Request: Source: {} - Value: {}", source.getNum(), updateData);
// For now we only support one level deep menus. If second field is '1', indicates go back to main
// menu.
@ -934,7 +939,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
// if this zone is a member of a group (1-4), add the zone's enum to the appropriate group map
if (!ZERO.equals(matcher.group(3))) {
nuvoGroupMap.get(matcher.group(3)).add(zone);
nuvoGroupMap.getOrDefault(matcher.group(3), new HashSet<>()).add(zone);
}
} else {
logger.debug("no match on message: {}", updateData);
@ -943,16 +948,17 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
break;
case TYPE_NN_ALBUM_ART_REQ:
// ignore this update unless openHAB is handling this source
if (nuvoNetSrcMap.get(source).equals(2)) {
if (nuvoNetSrcMap.getOrDefault(source, 0).equals(2)) {
logger.debug("Album Art Request for Source: {} - Data: {}", source.getNum(), updateData);
// 0x620FD879,80,80,2,0x00C0C0C0,0,0,0,0,1
String[] albumArtReq = updateData.split(COMMA);
albumArtIds.put(source, Integer.decode(albumArtReq[0]));
try {
if (albumArtMap.get(source).length > 1) {
connector.sendCommand(source.getId() + ALBUM_ART_AVAILABLE + albumArtIds.get(source) + COMMA
+ albumArtMap.get(source).length);
if (albumArtMap.getOrDefault(source, NO_ART).length > 1) {
connector.sendCommand(
source.getId() + ALBUM_ART_AVAILABLE + albumArtIds.getOrDefault(source, 0) + COMMA
+ albumArtMap.getOrDefault(source, NO_ART).length);
} else {
connector.sendCommand(source.getId() + ALBUM_ART_AVAILABLE + ZERO_COMMA);
}
@ -963,7 +969,7 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
break;
case TYPE_NN_ALBUM_ART_FRAG_REQ:
// ignore this update unless openHAB is handling this source
if (nuvoNetSrcMap.get(source).equals(2)) {
if (nuvoNetSrcMap.getOrDefault(source, 0).equals(2)) {
logger.debug("Album Art Fragment Request for Source: {} - Data: {}", source.getNum(), updateData);
// 0x620FD879,0,750 (id, requested offset from start of image, byte length requested)
String[] albumArtFragReq = updateData.split(COMMA);
@ -991,12 +997,12 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
break;
case TYPE_NN_FAVORITE_REQ:
// ignore this update unless openHAB is handling this source
if (nuvoNetSrcMap.get(source).equals(2)) {
if (nuvoNetSrcMap.getOrDefault(source, 0).equals(2)) {
logger.debug("Favorite request for source: {} - favoriteId: {}", source.getNum(), updateData);
try {
int playlistIdx = Integer.parseInt(updateData, 16) - 1000;
updateChannelState(source, CHANNEL_BUTTON_PRESS,
PLAY_MUSIC_PRESET + favoriteMap.get(source)[playlistIdx]);
PLAY_MUSIC_PRESET + getFavorite(source, playlistIdx));
} catch (NumberFormatException nfe) {
logger.debug("Unable to parse favoriteId: {}", updateData);
}
@ -1087,12 +1093,12 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
try {
// set '1' flag for each source configured as an MPS4 NuvoNet source or openHAB NuvoNet source
connector.sendCommand("SNUMBERS" + nuvoNetSrcMap.get(NuvoEnum.SOURCE1).compareTo(0) + COMMA
+ nuvoNetSrcMap.get(NuvoEnum.SOURCE2).compareTo(0) + COMMA
+ nuvoNetSrcMap.get(NuvoEnum.SOURCE3).compareTo(0) + COMMA
+ nuvoNetSrcMap.get(NuvoEnum.SOURCE4).compareTo(0) + COMMA
+ nuvoNetSrcMap.get(NuvoEnum.SOURCE5).compareTo(0) + COMMA
+ nuvoNetSrcMap.get(NuvoEnum.SOURCE6).compareTo(0));
connector.sendCommand("SNUMBERS" + nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE1, 0).compareTo(0) + COMMA
+ nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE2, 0).compareTo(0) + COMMA
+ nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE3, 0).compareTo(0) + COMMA
+ nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE4, 0).compareTo(0) + COMMA
+ nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE5, 0).compareTo(0) + COMMA
+ nuvoNetSrcMap.getOrDefault(NuvoEnum.SOURCE6, 0).compareTo(0));
Thread.sleep(SLEEP_BETWEEN_CMD_MS);
} catch (NuvoException | InterruptedException e) {
logger.debug("Error sending SNUMBERS command");
@ -1533,13 +1539,15 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
if (matcher.find()) {
final String nowPlayingGuid = matcher.group(1);
// If streaming (NowPlayingType=Radio), always retrieve because the same NowPlayingGuid can
// If streaming (not local mp3 or flac) always retrieve because the same NowPlayingGuid can
// get a different image written to it by Gracenote when the track changes
if (!mps4ArtGuids.get(source).equals(nowPlayingGuid)
|| json.contains("NowPlayingType\",\"value\":\"Radio\"}")) {
if (!mps4ArtGuids.getOrDefault(source, BLANK).equals(nowPlayingGuid)
|| !(json.contains("NowPlayingSrce\",\"value\":\"WMP\"")
|| json.contains("NowPlayingSrce\",\"value\":\"Flac\""))) {
ContentResponse artResponse = httpClient
.newRequest(String.format(GET_MCS_ART, mps4Host, nowPlayingGuid, instance)).method(GET)
.timeout(10, TimeUnit.SECONDS).send();
.newRequest(String.format(GET_MCS_ART, mps4Host, nowPlayingGuid, instance,
bindingConf.imageHeight, bindingConf.imageWidth))
.method(GET).timeout(10, TimeUnit.SECONDS).send();
if (artResponse.getStatus() == OK_200) {
logger.debug("Retrieved album art for guid: {}", nowPlayingGuid);
@ -1597,4 +1605,9 @@ public class NuvoHandler extends BaseThingHandler implements NuvoMessageEventLis
logger.debug("Got error response {} when sending json command url: {}", commandResp.getStatus(), commandUrl);
return BLANK;
}
private String getFavorite(NuvoEnum source, int playlistIdx) {
final String[] favoritesArr = favoriteMap.get(source);
return favoritesArr != null ? favoritesArr[playlistIdx] : BLANK;
}
}

View File

@ -8,6 +8,21 @@
<description>Controls the Nuvo Grand Concerto or Essentia G Whole House Amplifier.</description>
<connection>local</connection>
<config-description>
<parameter name="imageHeight" type="integer" min="1" max="1024" required="false">
<label>Image Height</label>
<description>Height for MPS4 album art images</description>
<default>150</default>
<advanced>true</advanced>
</parameter>
<parameter name="imageWidth" type="integer" min="1" max="1024" required="false">
<label>Image Width</label>
<description>Width for MPS4 album art images</description>
<default>150</default>
<advanced>true</advanced>
</parameter>
</config-description>
<discovery-methods>
<discovery-method>
<service-type>mdns</service-type>

View File

@ -3,6 +3,13 @@
addon.nuvo.name = Nuvo Whole House Audio Binding
addon.nuvo.description = Controls the Nuvo Grand Concerto or Essentia G Whole House Amplifier.
# add-on config
addon.config.nuvo.imageHeight.label = Image Height
addon.config.nuvo.imageHeight.description = Height for MPS4 album art images
addon.config.nuvo.imageWidth.label = Image Width
addon.config.nuvo.imageWidth.description = Width for MPS4 album art images
# thing types
thing-type.nuvo.amplifier.label = Nuvo Whole House Amplifier