mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[denonmarantz] Add HTTP protocol support for newer receivers (#16748)
* Add HTTP protocol support for newer receivers Resolves #16747 Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
6992ccbd40
commit
5718df4e4d
@ -7,18 +7,18 @@ This binding integrates Denon & Marantz AV receivers by using either Telnet or a
|
||||
This binding supports Denon and Marantz receivers having a Telnet interface or a web based controller at `http://<AVR IP address>/`.
|
||||
The thing type for all of them is `avr`.
|
||||
|
||||
Tested models: Marantz SR5008, Denon AVR-X2000 / X3000 / X1200W / X2100W / X2200W / X3100W / X3300W / X4400H
|
||||
|
||||
Denon models with HEOS support (`AVR-X..00H`) do not support the HTTP API. They do support Telnet.
|
||||
During Discovery this is auto-detected and configured.
|
||||
Tested models: Marantz SR5008, Denon AVR-3808 / AVR-4520 / AVR-X2000 / X3000 / X1200W / X2100W / X2200W / X3100W / X3300W / X4400H / X4800H
|
||||
|
||||
## Discovery
|
||||
|
||||
This binding can discover Denon and Marantz receivers using mDNS.
|
||||
The serial number (which is the MAC address of the network interface) is used as unique identifier.
|
||||
|
||||
The protocol will be auto-detected.
|
||||
The HTTP port as well as slight variations in the API will be auto-detected as well.
|
||||
|
||||
It tries to detect the number of zones (when the AVR responds to HTTP).
|
||||
It defaults to 2 zones.
|
||||
It defaults to two zones.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
|
@ -14,14 +14,16 @@ package org.openhab.binding.denonmarantz.internal.connector.http;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
@ -35,11 +37,17 @@ import javax.xml.stream.util.StreamReaderDelegate;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.api.Response;
|
||||
import org.eclipse.jetty.client.api.Result;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.openhab.binding.denonmarantz.internal.DenonMarantzState;
|
||||
import org.openhab.binding.denonmarantz.internal.config.DenonMarantzConfiguration;
|
||||
import org.openhab.binding.denonmarantz.internal.connector.DenonMarantzConnector;
|
||||
import org.openhab.binding.denonmarantz.internal.exception.HttpCommunicationException;
|
||||
import org.openhab.binding.denonmarantz.internal.xml.dto.Deviceinfo;
|
||||
import org.openhab.binding.denonmarantz.internal.xml.dto.Main;
|
||||
import org.openhab.binding.denonmarantz.internal.xml.dto.ZoneStatus;
|
||||
@ -48,7 +56,7 @@ import org.openhab.binding.denonmarantz.internal.xml.dto.commands.AppCommandRequ
|
||||
import org.openhab.binding.denonmarantz.internal.xml.dto.commands.AppCommandResponse;
|
||||
import org.openhab.binding.denonmarantz.internal.xml.dto.commands.CommandRx;
|
||||
import org.openhab.binding.denonmarantz.internal.xml.dto.commands.CommandTx;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
import org.openhab.binding.denonmarantz.internal.xml.dto.types.StringType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -92,6 +100,8 @@ public class DenonMarantzHttpConnector extends DenonMarantzConnector {
|
||||
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
|
||||
private boolean legacyApiSupported = true;
|
||||
|
||||
public DenonMarantzHttpConnector(DenonMarantzConfiguration config, DenonMarantzState state,
|
||||
ScheduledExecutorService scheduler, HttpClient httpClient) {
|
||||
super(config, scheduler, state);
|
||||
@ -114,16 +124,19 @@ public class DenonMarantzHttpConnector extends DenonMarantzConnector {
|
||||
logger.debug("HTTP polling started.");
|
||||
try {
|
||||
setConfigProperties();
|
||||
} catch (IOException e) {
|
||||
} catch (TimeoutException | ExecutionException | HttpCommunicationException e) {
|
||||
logger.debug("IO error while retrieving document:", e);
|
||||
state.connectionError("IO error while connecting to AVR: " + e.getMessage());
|
||||
return;
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("Interrupted while retrieving document: {}", e.getMessage());
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
refreshHttpProperties();
|
||||
} catch (IOException e) {
|
||||
} catch (TimeoutException | ExecutionException e) {
|
||||
logger.debug("IO error while retrieving document", e);
|
||||
state.connectionError("IO error while connecting to AVR: " + e.getMessage());
|
||||
stopPolling();
|
||||
@ -137,6 +150,9 @@ public class DenonMarantzHttpConnector extends DenonMarantzConnector {
|
||||
sb.append(s.toString()).append("\n");
|
||||
}
|
||||
logger.error("Error while polling Http: \"{}\". Stacktrace: \n{}", e.getMessage(), sb.toString());
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("Interrupted while polling: {}", e.getMessage());
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}, 0, config.httpPollingInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
@ -186,96 +202,163 @@ public class DenonMarantzHttpConnector extends DenonMarantzConnector {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateMain() throws IOException {
|
||||
private void updateMain() throws TimeoutException, ExecutionException, InterruptedException {
|
||||
String url = statusUrl + URL_MAIN;
|
||||
logger.trace("Refreshing URL: {}", url);
|
||||
|
||||
Main statusMain = getDocument(url, Main.class);
|
||||
if (statusMain != null) {
|
||||
state.setPower(statusMain.getPower().getValue());
|
||||
try {
|
||||
Main statusMain = getDocument(url, Main.class);
|
||||
if (statusMain != null) {
|
||||
state.setPower(statusMain.getPower().getValue());
|
||||
}
|
||||
} catch (HttpCommunicationException e) {
|
||||
if (e.getHttpStatus() == HttpStatus.FORBIDDEN_403) {
|
||||
legacyApiSupported = false;
|
||||
logger.debug("Legacy API not supported, will attempt app command method");
|
||||
} else {
|
||||
logger.debug("Failed to update main by legacy API: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMainZone() throws IOException {
|
||||
private void updateMainZone() throws TimeoutException, ExecutionException, InterruptedException {
|
||||
String url = statusUrl + URL_ZONE_MAIN;
|
||||
logger.trace("Refreshing URL: {}", url);
|
||||
|
||||
ZoneStatus mainZone = getDocument(url, ZoneStatus.class);
|
||||
if (mainZone != null) {
|
||||
state.setInput(mainZone.getInputFuncSelect().getValue());
|
||||
state.setMainVolume(mainZone.getMasterVolume().getValue());
|
||||
state.setMainZonePower(mainZone.getPower().getValue());
|
||||
state.setMute(mainZone.getMute().getValue());
|
||||
try {
|
||||
ZoneStatus mainZone = getDocument(url, ZoneStatus.class);
|
||||
if (mainZone != null) {
|
||||
state.setInput(mainZone.getInputFuncSelect().getValue());
|
||||
state.setMainVolume(mainZone.getMasterVolume().getValue());
|
||||
state.setMainZonePower(mainZone.getPower().getValue());
|
||||
state.setMute(mainZone.getMute().getValue());
|
||||
|
||||
if (config.inputOptions == null) {
|
||||
config.inputOptions = mainZone.getInputFuncList();
|
||||
if (config.inputOptions == null) {
|
||||
config.inputOptions = mainZone.getInputFuncList();
|
||||
}
|
||||
|
||||
StringType surroundMode = mainZone.getSurrMode();
|
||||
if (surroundMode == null) {
|
||||
logger.debug("Unable to get the SURROUND_MODE. MainZone update may not be correct.");
|
||||
} else {
|
||||
state.setSurroundProgram(surroundMode.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (mainZone.getSurrMode() == null) {
|
||||
logger.debug("Unable to get the SURROUND_MODE. MainZone update may not be correct.");
|
||||
} catch (HttpCommunicationException e) {
|
||||
if (e.getHttpStatus() == HttpStatus.FORBIDDEN_403) {
|
||||
legacyApiSupported = false;
|
||||
logger.debug("Legacy API not supported, will attempt app command method");
|
||||
} else {
|
||||
state.setSurroundProgram(mainZone.getSurrMode().getValue());
|
||||
logger.debug("Failed to update main zone by legacy API: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSecondaryZones() throws IOException {
|
||||
private void updateMainZoneByAppCommand() throws TimeoutException, ExecutionException, InterruptedException {
|
||||
String url = statusUrl + URL_APP_COMMAND;
|
||||
logger.trace("Refreshing URL: {}", url);
|
||||
|
||||
AppCommandRequest request = AppCommandRequest.of(CommandTx.CMD_ALL_POWER).add(CommandTx.CMD_VOLUME_LEVEL)
|
||||
.add(CommandTx.CMD_MUTE_STATUS).add(CommandTx.CMD_SOURCE_STATUS).add(CommandTx.CMD_SURROUND_STATUS);
|
||||
|
||||
try {
|
||||
AppCommandResponse response = postDocument(url, AppCommandResponse.class, request);
|
||||
|
||||
if (response != null) {
|
||||
for (CommandRx rx : response.getCommands()) {
|
||||
String inputSource = rx.getSource();
|
||||
if (inputSource != null) {
|
||||
state.setInput(inputSource);
|
||||
}
|
||||
Boolean power = rx.getZone1();
|
||||
if (power != null) {
|
||||
state.setMainZonePower(power.booleanValue());
|
||||
}
|
||||
BigDecimal volume = rx.getVolume();
|
||||
if (volume != null) {
|
||||
state.setMainVolume(volume);
|
||||
}
|
||||
Boolean mute = rx.getMute();
|
||||
if (mute != null) {
|
||||
state.setMute(mute.booleanValue());
|
||||
}
|
||||
String surroundMode = rx.getSurround();
|
||||
if (surroundMode != null) {
|
||||
state.setSurroundProgram(surroundMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (HttpCommunicationException e) {
|
||||
logger.debug("Failed to update main zone by app command: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSecondaryZones() throws TimeoutException, ExecutionException, InterruptedException {
|
||||
for (int i = 2; i <= config.getZoneCount(); i++) {
|
||||
String url = String.format("%s" + URL_ZONE_SECONDARY_LITE, statusUrl, i, i);
|
||||
logger.trace("Refreshing URL: {}", url);
|
||||
ZoneStatusLite zoneSecondary = getDocument(url, ZoneStatusLite.class);
|
||||
if (zoneSecondary != null) {
|
||||
switch (i) {
|
||||
// maximum 2 secondary zones are supported
|
||||
case 2:
|
||||
state.setZone2Power(zoneSecondary.getPower().getValue());
|
||||
state.setZone2Volume(zoneSecondary.getMasterVolume().getValue());
|
||||
state.setZone2Mute(zoneSecondary.getMute().getValue());
|
||||
state.setZone2Input(zoneSecondary.getInputFuncSelect().getValue());
|
||||
break;
|
||||
case 3:
|
||||
state.setZone3Power(zoneSecondary.getPower().getValue());
|
||||
state.setZone3Volume(zoneSecondary.getMasterVolume().getValue());
|
||||
state.setZone3Mute(zoneSecondary.getMute().getValue());
|
||||
state.setZone3Input(zoneSecondary.getInputFuncSelect().getValue());
|
||||
break;
|
||||
case 4:
|
||||
state.setZone4Power(zoneSecondary.getPower().getValue());
|
||||
state.setZone4Volume(zoneSecondary.getMasterVolume().getValue());
|
||||
state.setZone4Mute(zoneSecondary.getMute().getValue());
|
||||
state.setZone4Input(zoneSecondary.getInputFuncSelect().getValue());
|
||||
break;
|
||||
try {
|
||||
ZoneStatusLite zoneSecondary = getDocument(url, ZoneStatusLite.class);
|
||||
if (zoneSecondary != null) {
|
||||
switch (i) {
|
||||
// maximum 2 secondary zones are supported
|
||||
case 2:
|
||||
state.setZone2Power(zoneSecondary.getPower().getValue());
|
||||
state.setZone2Volume(zoneSecondary.getMasterVolume().getValue());
|
||||
state.setZone2Mute(zoneSecondary.getMute().getValue());
|
||||
state.setZone2Input(zoneSecondary.getInputFuncSelect().getValue());
|
||||
break;
|
||||
case 3:
|
||||
state.setZone3Power(zoneSecondary.getPower().getValue());
|
||||
state.setZone3Volume(zoneSecondary.getMasterVolume().getValue());
|
||||
state.setZone3Mute(zoneSecondary.getMute().getValue());
|
||||
state.setZone3Input(zoneSecondary.getInputFuncSelect().getValue());
|
||||
break;
|
||||
case 4:
|
||||
state.setZone4Power(zoneSecondary.getPower().getValue());
|
||||
state.setZone4Volume(zoneSecondary.getMasterVolume().getValue());
|
||||
state.setZone4Mute(zoneSecondary.getMute().getValue());
|
||||
state.setZone4Input(zoneSecondary.getInputFuncSelect().getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (HttpCommunicationException e) {
|
||||
logger.debug("Failed to update zone {}: {}", i, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDisplayInfo() throws IOException {
|
||||
private void updateDisplayInfo() throws TimeoutException, ExecutionException, InterruptedException {
|
||||
String url = statusUrl + URL_APP_COMMAND;
|
||||
logger.trace("Refreshing URL: {}", url);
|
||||
|
||||
AppCommandRequest request = AppCommandRequest.of(CommandTx.CMD_NET_STATUS);
|
||||
AppCommandResponse response = postDocument(url, AppCommandResponse.class, request);
|
||||
try {
|
||||
AppCommandResponse response = postDocument(url, AppCommandResponse.class, request);
|
||||
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
CommandRx titleInfo = response.getCommands().get(0);
|
||||
String artist = titleInfo.getText("artist");
|
||||
if (artist != null) {
|
||||
state.setNowPlayingArtist(artist);
|
||||
}
|
||||
String album = titleInfo.getText("album");
|
||||
if (album != null) {
|
||||
state.setNowPlayingAlbum(album);
|
||||
}
|
||||
String track = titleInfo.getText("track");
|
||||
if (track != null) {
|
||||
state.setNowPlayingTrack(track);
|
||||
if (response == null) {
|
||||
return;
|
||||
}
|
||||
CommandRx titleInfo = response.getCommands().get(0);
|
||||
String artist = titleInfo.getText("artist");
|
||||
if (artist != null) {
|
||||
state.setNowPlayingArtist(artist);
|
||||
}
|
||||
String album = titleInfo.getText("album");
|
||||
if (album != null) {
|
||||
state.setNowPlayingAlbum(album);
|
||||
}
|
||||
String track = titleInfo.getText("track");
|
||||
if (track != null) {
|
||||
state.setNowPlayingTrack(track);
|
||||
}
|
||||
} catch (HttpCommunicationException e) {
|
||||
logger.debug("Failed to update display info: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean setConfigProperties() throws IOException {
|
||||
private boolean setConfigProperties()
|
||||
throws TimeoutException, ExecutionException, InterruptedException, HttpCommunicationException {
|
||||
String url = statusUrl + URL_DEVICE_INFO;
|
||||
logger.debug("Refreshing URL: {}", url);
|
||||
|
||||
@ -295,20 +378,39 @@ public class DenonMarantzHttpConnector extends DenonMarantzConnector {
|
||||
return (deviceinfo != null);
|
||||
}
|
||||
|
||||
private void refreshHttpProperties() throws IOException {
|
||||
private void refreshHttpProperties() throws TimeoutException, ExecutionException, InterruptedException {
|
||||
logger.trace("Refreshing Denon status");
|
||||
|
||||
updateMain();
|
||||
updateMainZone();
|
||||
if (legacyApiSupported) {
|
||||
updateMain();
|
||||
updateMainZone();
|
||||
}
|
||||
|
||||
if (!legacyApiSupported) {
|
||||
updateMainZoneByAppCommand();
|
||||
}
|
||||
|
||||
updateSecondaryZones();
|
||||
updateDisplayInfo();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T> T getDocument(String uri, Class<T> response) throws IOException {
|
||||
private <T> T getDocument(String uri, Class<T> response)
|
||||
throws TimeoutException, ExecutionException, InterruptedException, HttpCommunicationException {
|
||||
try {
|
||||
String result = HttpUtil.executeUrl("GET", uri, REQUEST_TIMEOUT_MS);
|
||||
logger.trace("result of getDocument for uri '{}':\r\n{}", uri, result);
|
||||
Request request = httpClient.newRequest(uri).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
||||
.method(HttpMethod.GET);
|
||||
|
||||
ContentResponse contentResponse = request.send();
|
||||
|
||||
String result = contentResponse.getContentAsString();
|
||||
int status = contentResponse.getStatus();
|
||||
|
||||
logger.trace("result of getDocument for uri '{}' (status code {}):\r\n{}", uri, status, result);
|
||||
|
||||
if (!HttpStatus.isSuccess(status)) {
|
||||
throw new HttpCommunicationException("Error retrieving document for uri '" + uri + "'", status);
|
||||
}
|
||||
|
||||
if (result != null && !result.isBlank()) {
|
||||
JAXBContext jc = JAXBContext.newInstance(response);
|
||||
@ -336,15 +438,28 @@ public class DenonMarantzHttpConnector extends DenonMarantzConnector {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T, S> T postDocument(String uri, Class<T> response, S request) throws IOException {
|
||||
private <T, S> T postDocument(String uri, Class<T> response, S request)
|
||||
throws TimeoutException, ExecutionException, InterruptedException, HttpCommunicationException {
|
||||
try {
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(request.getClass());
|
||||
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
|
||||
StringWriter sw = new StringWriter();
|
||||
jaxbMarshaller.marshal(request, sw);
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(sw.toString().getBytes(StandardCharsets.UTF_8));
|
||||
String result = HttpUtil.executeUrl("POST", uri, inputStream, CONTENT_TYPE_XML, REQUEST_TIMEOUT_MS);
|
||||
Request httpRequest = httpClient.newRequest(uri).timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
||||
.content(new StringContentProvider(sw.toString(), StandardCharsets.UTF_8), CONTENT_TYPE_XML)
|
||||
.method(HttpMethod.POST);
|
||||
|
||||
ContentResponse contentResponse = httpRequest.send();
|
||||
|
||||
String result = contentResponse.getContentAsString();
|
||||
int status = contentResponse.getStatus();
|
||||
|
||||
logger.trace("result of postDocument for uri '{}' (status code {}):\r\n{}", uri, status, result);
|
||||
|
||||
if (!HttpStatus.isSuccess(status)) {
|
||||
throw new HttpCommunicationException("Error retrieving document for uri '" + uri + "'", status);
|
||||
}
|
||||
|
||||
if (result != null && !result.isBlank()) {
|
||||
JAXBContext jcResponse = JAXBContext.newInstance(response);
|
||||
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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.denonmarantz.internal.exception;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* {@link HttpCommunicationException} is a generic exception thrown in case
|
||||
* of communication failure or unexpected response.
|
||||
*
|
||||
* @author Jacob Laursen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HttpCommunicationException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private int httpStatus = 0;
|
||||
|
||||
public HttpCommunicationException(String message, int httpStatus) {
|
||||
super(message);
|
||||
this.httpStatus = httpStatus;
|
||||
}
|
||||
|
||||
public int getHttpStatus() {
|
||||
return httpStatus;
|
||||
}
|
||||
}
|
@ -229,7 +229,7 @@ public class DenonMarantzHandler extends BaseThingHandler implements DenonMarant
|
||||
httpApiUsable = true;
|
||||
}
|
||||
} catch (TimeoutException | ExecutionException e) {
|
||||
logger.debug("Error when trying to access AVR using HTTP on port 80, reverting to Telnet mode.", e);
|
||||
logger.debug("Error when trying to access AVR using HTTP on port 80.", e);
|
||||
}
|
||||
|
||||
if (telnetEnable) {
|
||||
@ -239,13 +239,15 @@ public class DenonMarantzHandler extends BaseThingHandler implements DenonMarant
|
||||
response = httpClient.newRequest("http://" + host + ":8080/goform/Deviceinfo.xml")
|
||||
.timeout(3, TimeUnit.SECONDS).send();
|
||||
if (response.getStatus() == HttpURLConnection.HTTP_OK) {
|
||||
logger.debug(
|
||||
"This model responds to HTTP port 8080, we use this port to retrieve the number of zones.");
|
||||
logger.debug("This model responds to HTTP port 8080, disabling the Telnet mode by default.");
|
||||
telnetEnable = false;
|
||||
httpPort = 8080;
|
||||
httpApiUsable = true;
|
||||
}
|
||||
} catch (TimeoutException | ExecutionException e) {
|
||||
logger.debug("Additionally tried to connect to port 8080, this also failed", e);
|
||||
logger.debug(
|
||||
"Additionally tried to connect to port 8080, this also failed. Reverting to Telnet mode.",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.denonmarantz.internal.xml.dto.commands;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -20,9 +21,12 @@ import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.denonmarantz.internal.xml.adapters.OnOffAdapter;
|
||||
import org.openhab.binding.denonmarantz.internal.xml.adapters.VolumeAdapter;
|
||||
|
||||
/**
|
||||
* Response to a {@link CommandTx}
|
||||
@ -33,21 +37,27 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class CommandRx {
|
||||
|
||||
private String zone1;
|
||||
@XmlJavaTypeAdapter(OnOffAdapter.class)
|
||||
private Boolean zone1;
|
||||
|
||||
private String zone2;
|
||||
@XmlJavaTypeAdapter(OnOffAdapter.class)
|
||||
private Boolean zone2;
|
||||
|
||||
private String zone3;
|
||||
@XmlJavaTypeAdapter(OnOffAdapter.class)
|
||||
private Boolean zone3;
|
||||
|
||||
private String zone4;
|
||||
@XmlJavaTypeAdapter(OnOffAdapter.class)
|
||||
private Boolean zone4;
|
||||
|
||||
private String volume;
|
||||
@XmlJavaTypeAdapter(value = VolumeAdapter.class)
|
||||
private BigDecimal volume;
|
||||
|
||||
private String disptype;
|
||||
|
||||
private String dispvalue;
|
||||
|
||||
private String mute;
|
||||
@XmlJavaTypeAdapter(OnOffAdapter.class)
|
||||
private Boolean mute;
|
||||
|
||||
private String type;
|
||||
|
||||
@ -72,46 +82,48 @@ public class CommandRx {
|
||||
|
||||
private String source;
|
||||
|
||||
private String surround;
|
||||
|
||||
public CommandRx() {
|
||||
}
|
||||
|
||||
public String getZone1() {
|
||||
public Boolean getZone1() {
|
||||
return zone1;
|
||||
}
|
||||
|
||||
public void setZone1(String zone1) {
|
||||
public void setZone1(Boolean zone1) {
|
||||
this.zone1 = zone1;
|
||||
}
|
||||
|
||||
public String getZone2() {
|
||||
public Boolean getZone2() {
|
||||
return zone2;
|
||||
}
|
||||
|
||||
public void setZone2(String zone2) {
|
||||
public void setZone2(Boolean zone2) {
|
||||
this.zone2 = zone2;
|
||||
}
|
||||
|
||||
public String getZone3() {
|
||||
public Boolean getZone3() {
|
||||
return zone3;
|
||||
}
|
||||
|
||||
public void setZone3(String zone3) {
|
||||
public void setZone3(Boolean zone3) {
|
||||
this.zone3 = zone3;
|
||||
}
|
||||
|
||||
public String getZone4() {
|
||||
public Boolean getZone4() {
|
||||
return zone4;
|
||||
}
|
||||
|
||||
public void setZone4(String zone4) {
|
||||
public void setZone4(Boolean zone4) {
|
||||
this.zone4 = zone4;
|
||||
}
|
||||
|
||||
public String getVolume() {
|
||||
public BigDecimal getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public void setVolume(String volume) {
|
||||
public void setVolume(BigDecimal volume) {
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
@ -131,11 +143,11 @@ public class CommandRx {
|
||||
this.dispvalue = dispvalue;
|
||||
}
|
||||
|
||||
public String getMute() {
|
||||
public Boolean getMute() {
|
||||
return mute;
|
||||
}
|
||||
|
||||
public void setMute(String mute) {
|
||||
public void setMute(Boolean mute) {
|
||||
this.mute = mute;
|
||||
}
|
||||
|
||||
@ -187,6 +199,14 @@ public class CommandRx {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public String getSurround() {
|
||||
return surround;
|
||||
}
|
||||
|
||||
public void setSurround(String surround) {
|
||||
this.surround = surround;
|
||||
}
|
||||
|
||||
public @Nullable String getText(@NonNull String key) {
|
||||
for (Text text : texts) {
|
||||
if (key.equals(text.getId())) {
|
||||
|
Loading…
Reference in New Issue
Block a user