added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.enigma2-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-enigma2" description="Enigma2 Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.enigma2/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.actions;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.enigma2.handler.Enigma2Handler;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2BindingConstants;
|
||||
import org.openhab.core.automation.annotation.ActionInput;
|
||||
import org.openhab.core.automation.annotation.RuleAction;
|
||||
import org.openhab.core.thing.binding.ThingActions;
|
||||
import org.openhab.core.thing.binding.ThingActionsScope;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
|
||||
/**
|
||||
* This is the automation engine actions handler service for the
|
||||
* enigma2 actions.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@ThingActionsScope(name = "enigma2")
|
||||
@NonNullByDefault
|
||||
public class Enigma2Actions implements ThingActions, IEnigma2Actions {
|
||||
private @Nullable Enigma2Handler handler;
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
this.handler = (Enigma2Handler) handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Enigma2Handler getThingHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/actions.enigma2.send-rc-button.label", description = "@text/actions.enigma2.send-rc-button.description")
|
||||
@SuppressWarnings("null")
|
||||
public void sendRcCommand(
|
||||
@ActionInput(name = "rcButton", label = "@text/actions-input.enigma2.rc-button.label", description = "@text/actions-input.enigma2.rc-button.description") String rcButton) {
|
||||
handler.sendRcCommand(rcButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/actions.enigma2.send-info.label", description = "@text/actions.enigma2.send-info.description")
|
||||
@SuppressWarnings("null")
|
||||
public void sendInfo(
|
||||
@ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text) {
|
||||
handler.sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/actions.enigma2.send-info.label", description = "@text/actions.enigma2.send-info.description")
|
||||
@SuppressWarnings("null")
|
||||
public void sendInfo(
|
||||
@ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text,
|
||||
@ActionInput(name = "timeout", label = "@text/actions-input.enigma2.timeout.label", description = "@text/actions-input.enigma2.timeout.description") int timeout) {
|
||||
handler.sendInfo(timeout, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/actions.enigma2.send-warning.label", description = "@text/actions.enigma2.send-warning.description")
|
||||
@SuppressWarnings("null")
|
||||
public void sendWarning(
|
||||
@ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text) {
|
||||
handler.sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/actions.enigma2.send-warning.label", description = "@text/actions.enigma2.send-warning.description")
|
||||
@SuppressWarnings("null")
|
||||
public void sendWarning(
|
||||
@ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text,
|
||||
@ActionInput(name = "timeout", label = "@text/actions-input.enigma2.timeout.label", description = "@text/actions-input.enigma2.timeout.description") int timeout) {
|
||||
handler.sendWarning(timeout, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/actions.enigma2.send-error.label", description = "@text/actions.enigma2.send-error.description")
|
||||
@SuppressWarnings("null")
|
||||
public void sendError(
|
||||
@ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text) {
|
||||
handler.sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/actions.enigma2.send-error.label", description = "@text/actions.enigma2.send-error.description")
|
||||
@SuppressWarnings("null")
|
||||
public void sendError(
|
||||
@ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text,
|
||||
@ActionInput(name = "timeout", label = "@text/actions-input.enigma2.timeout.label", description = "@text/actions-input.enigma2.timeout.description") int timeout) {
|
||||
handler.sendError(timeout, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/actions.enigma2.send-error.label", description = "@text/actions.enigma2.send-question.description")
|
||||
@SuppressWarnings("null")
|
||||
public void sendQuestion(
|
||||
@ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text) {
|
||||
handler.sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RuleAction(label = "@text/actions.enigma2.send-error.label", description = "@text/actions.enigma2.send-question.description")
|
||||
@SuppressWarnings("null")
|
||||
public void sendQuestion(
|
||||
@ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text,
|
||||
@ActionInput(name = "timeout", label = "@text/actions-input.enigma2.timeout.label", description = "@text/actions-input.enigma2.timeout.description") int timeout) {
|
||||
handler.sendQuestion(timeout, text);
|
||||
}
|
||||
|
||||
// delegation methods for "legacy" rule support
|
||||
public static void sendRcCommand(@Nullable ThingActions actions, String rcButton) {
|
||||
invokeMethodOf(actions).sendRcCommand(rcButton);
|
||||
}
|
||||
|
||||
public static void sendInfo(@Nullable ThingActions actions, String info) {
|
||||
invokeMethodOf(actions).sendInfo(info);
|
||||
}
|
||||
|
||||
public static void sendInfo(@Nullable ThingActions actions, String info, int timeout) {
|
||||
invokeMethodOf(actions).sendInfo(info, timeout);
|
||||
}
|
||||
|
||||
public static void sendWarning(@Nullable ThingActions actions, String warning) {
|
||||
invokeMethodOf(actions).sendWarning(warning);
|
||||
}
|
||||
|
||||
public static void sendWarning(@Nullable ThingActions actions, String warning, int timeout) {
|
||||
invokeMethodOf(actions).sendWarning(warning, timeout);
|
||||
}
|
||||
|
||||
public static void sendError(@Nullable ThingActions actions, String error) {
|
||||
invokeMethodOf(actions).sendError(error);
|
||||
}
|
||||
|
||||
public static void sendError(@Nullable ThingActions actions, String error, int timeout) {
|
||||
invokeMethodOf(actions).sendError(error, timeout);
|
||||
}
|
||||
|
||||
public static void sendQuestion(@Nullable ThingActions actions, String text) {
|
||||
invokeMethodOf(actions).sendQuestion(text);
|
||||
}
|
||||
|
||||
public static void sendQuestion(@Nullable ThingActions actions, String text, int timeout) {
|
||||
invokeMethodOf(actions).sendQuestion(text, timeout);
|
||||
}
|
||||
|
||||
private static IEnigma2Actions invokeMethodOf(@Nullable ThingActions actions) {
|
||||
if (actions == null) {
|
||||
throw new IllegalArgumentException("actions cannot be null");
|
||||
}
|
||||
if (actions.getClass().getName().equals(Enigma2Actions.class.getName())) {
|
||||
if (actions instanceof IEnigma2Actions) {
|
||||
return (IEnigma2Actions) actions;
|
||||
} else {
|
||||
return (IEnigma2Actions) Proxy.newProxyInstance(IEnigma2Actions.class.getClassLoader(),
|
||||
new Class[] { IEnigma2Actions.class }, (Object proxy, Method method, Object[] args) -> {
|
||||
Method m = actions.getClass().getDeclaredMethod(method.getName(),
|
||||
method.getParameterTypes());
|
||||
return m.invoke(actions, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Actions is not an instance of Enigma2Actions");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.actions;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link IEnigma2Actions} defines the interface for all thing actions supported by the binding.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface IEnigma2Actions {
|
||||
void sendRcCommand(String rcButton);
|
||||
|
||||
void sendInfo(String text);
|
||||
|
||||
void sendInfo(String text, int timeout);
|
||||
|
||||
void sendWarning(String text);
|
||||
|
||||
void sendWarning(String text, int timeout);
|
||||
|
||||
void sendError(String text);
|
||||
|
||||
void sendError(String text, int timeout);
|
||||
|
||||
void sendQuestion(String text);
|
||||
|
||||
void sendQuestion(String text, int timeout);
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.handler;
|
||||
|
||||
import static org.openhab.binding.enigma2.internal.Enigma2BindingConstants.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.enigma2.actions.Enigma2Actions;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2Client;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2Configuration;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2RemoteKey;
|
||||
import org.openhab.core.library.types.*;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2Handler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Enigma2Handler extends BaseThingHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(Enigma2Handler.class);
|
||||
private Enigma2Configuration configuration = new Enigma2Configuration();
|
||||
private Optional<Enigma2Client> enigma2Client = Optional.empty();
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
private LocalDateTime lastAnswerTime = LocalDateTime.now();
|
||||
|
||||
public Enigma2Handler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
configuration = getConfigAs(Enigma2Configuration.class);
|
||||
if (configuration.host.isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "host must not be empty");
|
||||
} else if (configuration.timeout <= 0 || configuration.timeout > 300) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"timeout must be between 0 and 300 seconds");
|
||||
} else if (configuration.refreshInterval <= 0 || configuration.refreshInterval > 3600) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"refreshInterval must be between 0 and 3600 seconds");
|
||||
}
|
||||
enigma2Client = Optional.of(new Enigma2Client(configuration.host, configuration.user, configuration.password,
|
||||
configuration.timeout));
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(this::refresh, 2, configuration.refreshInterval,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
getEnigma2Client().ifPresent(client -> {
|
||||
boolean online = client.refresh();
|
||||
if (online) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
updateState(CHANNEL_POWER, client.isPower() ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(CHANNEL_MUTE, client.isMute() ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(CHANNEL_VOLUME, new PercentType(client.getVolume()));
|
||||
updateState(CHANNEL_CHANNEL, new StringType(client.getChannel()));
|
||||
updateState(CHANNEL_TITLE, new StringType(client.getTitle()));
|
||||
updateState(CHANNEL_DESCRIPTION, new StringType(client.getDescription()));
|
||||
if (lastAnswerTime.isBefore(client.getLastAnswerTime())) {
|
||||
lastAnswerTime = client.getLastAnswerTime();
|
||||
updateState(CHANNEL_ANSWER, new StringType(client.getAnswer()));
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ScheduledFuture<?> job = this.refreshJob;
|
||||
if (job != null) {
|
||||
job.cancel(true);
|
||||
}
|
||||
this.refreshJob = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("handleCommand({},{})", channelUID, command);
|
||||
getEnigma2Client().ifPresent(client -> {
|
||||
switch (channelUID.getId()) {
|
||||
case CHANNEL_POWER:
|
||||
handlePower(channelUID, command, client);
|
||||
break;
|
||||
case CHANNEL_CHANNEL:
|
||||
handleChannel(channelUID, command, client);
|
||||
break;
|
||||
case CHANNEL_MEDIA_PLAYER:
|
||||
handleMediaPlayer(channelUID, command);
|
||||
break;
|
||||
case CHANNEL_MEDIA_STOP:
|
||||
handleMediaStop(channelUID, command);
|
||||
break;
|
||||
case CHANNEL_MUTE:
|
||||
handleMute(channelUID, command, client);
|
||||
break;
|
||||
case CHANNEL_VOLUME:
|
||||
handleVolume(channelUID, command, client);
|
||||
break;
|
||||
case CHANNEL_TITLE:
|
||||
handleTitle(channelUID, command, client);
|
||||
break;
|
||||
case CHANNEL_DESCRIPTION:
|
||||
handleDescription(channelUID, command, client);
|
||||
break;
|
||||
case CHANNEL_ANSWER:
|
||||
handleAnswer(channelUID, command, client);
|
||||
break;
|
||||
default:
|
||||
logger.debug("Channel {} is not supported", channelUID);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleVolume(ChannelUID channelUID, Command command, Enigma2Client client) {
|
||||
if (command instanceof RefreshType) {
|
||||
client.refreshVolume();
|
||||
updateState(channelUID, new PercentType(client.getVolume()));
|
||||
} else if (command instanceof PercentType) {
|
||||
client.setVolume(((PercentType) command).intValue());
|
||||
} else if (command instanceof DecimalType) {
|
||||
client.setVolume(((DecimalType) command).intValue());
|
||||
} else {
|
||||
logger.info("Channel {} only accepts PercentType, DecimalType, RefreshType. Type was {}.", channelUID,
|
||||
command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMute(ChannelUID channelUID, Command command, Enigma2Client client) {
|
||||
if (command instanceof RefreshType) {
|
||||
client.refreshVolume();
|
||||
updateState(channelUID, client.isMute() ? OnOffType.ON : OnOffType.OFF);
|
||||
} else if (OnOffType.ON.equals(command)) {
|
||||
client.setMute(true);
|
||||
} else if (OnOffType.OFF.equals(command)) {
|
||||
client.setMute(false);
|
||||
} else {
|
||||
logger.info("Channel {} only accepts OnOffType, RefreshType. Type was {}.", channelUID, command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleAnswer(ChannelUID channelUID, Command command, Enigma2Client client) {
|
||||
if (command instanceof RefreshType) {
|
||||
client.refreshAnswer();
|
||||
if (lastAnswerTime.isBefore(client.getLastAnswerTime())) {
|
||||
lastAnswerTime = client.getLastAnswerTime();
|
||||
updateState(channelUID, new StringType(client.getAnswer()));
|
||||
}
|
||||
} else {
|
||||
logger.info("Channel {} only accepts RefreshType. Type was {}.", channelUID, command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMediaStop(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
return;
|
||||
} else if (command instanceof OnOffType) {
|
||||
sendRcCommand(Enigma2RemoteKey.STOP);
|
||||
} else {
|
||||
logger.info("Channel {} only accepts OnOffType, RefreshType. Type was {}.", channelUID, command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMediaPlayer(ChannelUID channelUID, Command command) {
|
||||
if (RefreshType.REFRESH == command) {
|
||||
return;
|
||||
} else if (PlayPauseType.PLAY == command) {
|
||||
sendRcCommand(Enigma2RemoteKey.PLAY);
|
||||
} else if (PlayPauseType.PAUSE == command) {
|
||||
sendRcCommand(Enigma2RemoteKey.PAUSE);
|
||||
} else if (NextPreviousType.NEXT == command) {
|
||||
sendRcCommand(Enigma2RemoteKey.FAST_FORWARD);
|
||||
} else if (NextPreviousType.PREVIOUS == command) {
|
||||
sendRcCommand(Enigma2RemoteKey.FAST_BACKWARD);
|
||||
} else {
|
||||
logger.info("Channel {} only accepts PlayPauseType, NextPreviousType, RefreshType. Type was {}.",
|
||||
channelUID, command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChannel(ChannelUID channelUID, Command command, Enigma2Client client) {
|
||||
if (command instanceof RefreshType) {
|
||||
client.refreshChannel();
|
||||
updateState(channelUID, new StringType(client.getChannel()));
|
||||
} else if (command instanceof StringType) {
|
||||
client.setChannel(command.toString());
|
||||
} else {
|
||||
logger.info("Channel {} only accepts StringType, RefreshType. Type was {}.", channelUID,
|
||||
command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTitle(ChannelUID channelUID, Command command, Enigma2Client client) {
|
||||
if (command instanceof RefreshType) {
|
||||
client.refreshEpg();
|
||||
updateState(channelUID, new StringType(client.getTitle()));
|
||||
} else {
|
||||
logger.info("Channel {} only accepts RefreshType. Type was {}.", channelUID, command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDescription(ChannelUID channelUID, Command command, Enigma2Client client) {
|
||||
if (command instanceof RefreshType) {
|
||||
client.refreshEpg();
|
||||
updateState(channelUID, new StringType(client.getDescription()));
|
||||
} else {
|
||||
logger.info("Channel {} only accepts RefreshType. Type was {}.", channelUID, command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePower(ChannelUID channelUID, Command command, Enigma2Client client) {
|
||||
if (RefreshType.REFRESH == command) {
|
||||
client.refreshPower();
|
||||
updateState(channelUID, client.isPower() ? OnOffType.ON : OnOffType.OFF);
|
||||
} else if (OnOffType.ON == command) {
|
||||
client.setPower(true);
|
||||
} else if (OnOffType.OFF == command) {
|
||||
client.setPower(false);
|
||||
} else {
|
||||
logger.info("Channel {} only accepts OnOffType, RefreshType. Type was {}.", channelUID, command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
public void sendRcCommand(String rcButton) {
|
||||
logger.debug("sendRcCommand({})", rcButton);
|
||||
try {
|
||||
Enigma2RemoteKey remoteKey = Enigma2RemoteKey.valueOf(rcButton);
|
||||
sendRcCommand(remoteKey);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
logger.warn("{} is not a valid value for button - available are: {}", rcButton,
|
||||
Stream.of(Enigma2RemoteKey.values()).map(b -> b.name()).collect(Collectors.joining(", ")));
|
||||
}
|
||||
}
|
||||
|
||||
private void sendRcCommand(Enigma2RemoteKey remoteKey) {
|
||||
getEnigma2Client().ifPresent(client -> client.sendRcCommand(remoteKey.getValue()));
|
||||
}
|
||||
|
||||
public void sendInfo(int timeout, String text) {
|
||||
getEnigma2Client().ifPresent(client -> client.sendInfo(timeout, text));
|
||||
}
|
||||
|
||||
public void sendWarning(int timeout, String text) {
|
||||
getEnigma2Client().ifPresent(client -> client.sendWarning(timeout, text));
|
||||
}
|
||||
|
||||
public void sendError(int timeout, String text) {
|
||||
getEnigma2Client().ifPresent(client -> client.sendError(timeout, text));
|
||||
}
|
||||
|
||||
public void sendQuestion(int timeout, String text) {
|
||||
getEnigma2Client().ifPresent(client -> client.sendQuestion(timeout, text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singleton(Enigma2Actions.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for Test-Injection
|
||||
*
|
||||
* @return Enigma2Client.
|
||||
*/
|
||||
Optional<Enigma2Client> getEnigma2Client() {
|
||||
return enigma2Client;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2BindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Enigma2BindingConstants {
|
||||
|
||||
private static final String BINDING_ID = "enigma2";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device");
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_DEVICE);
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_VOLUME = "volume";
|
||||
public static final String CHANNEL_POWER = "power";
|
||||
public static final String CHANNEL_MUTE = "mute";
|
||||
public static final String CHANNEL_CHANNEL = "channel";
|
||||
public static final String CHANNEL_TITLE = "title";
|
||||
public static final String CHANNEL_DESCRIPTION = "description";
|
||||
public static final String CHANNEL_MEDIA_PLAYER = "mediaPlayer";
|
||||
public static final String CHANNEL_MEDIA_STOP = "mediaStop";
|
||||
public static final String CHANNEL_ANSWER = "answer";
|
||||
|
||||
// List of all configuration parameters
|
||||
public static final String CONFIG_HOST = "host";
|
||||
public static final String CONFIG_USER = "user";
|
||||
public static final String CONFIG_PASSWORD = "password";
|
||||
public static final String CONFIG_REFRESH = "refreshInterval";
|
||||
public static final String CONFIG_TIMEOUT = "timeout";
|
||||
|
||||
public static final int MESSAGE_TIMEOUT = 30;
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.util.UrlEncoded;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2Client} class is responsible for communicating with the Enigma2 device.
|
||||
*
|
||||
* @see <a href=
|
||||
* "https://github.com/E2OpenPlugins/e2openplugin-OpenWebif/wiki/OpenWebif-API-documentation">OpenWebif-API-documentation</a>
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Enigma2Client {
|
||||
private final Logger logger = LoggerFactory.getLogger(Enigma2Client.class);
|
||||
|
||||
static final String PATH_REMOTE_CONTROL = "/web/remotecontrol?command=";
|
||||
static final String PATH_POWER = "/web/powerstate";
|
||||
static final String PATH_VOLUME = "/web/vol";
|
||||
static final String PATH_SET_VOLUME = "/web/vol?set=set";
|
||||
static final String PATH_TOGGLE_MUTE = "/web/vol?set=mute";
|
||||
static final String PATH_TOGGLE_POWER = "/web/powerstate?newstate=0";
|
||||
static final String PATH_MESSAGE = "/web/message?type=";
|
||||
static final String PATH_ALL_SERVICES = "/web/getallservices";
|
||||
static final String PATH_ZAP = "/web/zap?sRef=";
|
||||
static final String PATH_CHANNEL = "/web/subservices";
|
||||
static final String PATH_EPG = "/web/epgservicenow?sRef=";
|
||||
static final String PATH_ANSWER = "/web/messageanswer?getanswer=now";
|
||||
static final int TYPE_QUESTION = 0;
|
||||
static final int TYPE_INFO = 1;
|
||||
static final int TYPE_WARNING = 2;
|
||||
static final int TYPE_ERROR = 3;
|
||||
private final Map<String, @Nullable String> channels = new ConcurrentHashMap<>();
|
||||
private final String host;
|
||||
private boolean power;
|
||||
private String channel = "";
|
||||
private String title = "";
|
||||
private String description = "";
|
||||
private String answer = "";
|
||||
private int volume = 0;
|
||||
private boolean mute;
|
||||
private boolean online;
|
||||
private boolean initialized;
|
||||
private boolean asking;
|
||||
private LocalDateTime lastAnswerTime = LocalDateTime.of(2020, 1, 1, 0, 0); // Date in the past
|
||||
private final Enigma2HttpClient enigma2HttpClient;
|
||||
private final DocumentBuilderFactory factory;
|
||||
|
||||
public Enigma2Client(String host, @Nullable String user, @Nullable String password, int requestTimeout) {
|
||||
this.enigma2HttpClient = new Enigma2HttpClient(requestTimeout);
|
||||
this.factory = DocumentBuilderFactory.newInstance();
|
||||
if (StringUtils.isNotEmpty(user) && StringUtils.isNotEmpty(password)) {
|
||||
this.host = "http://" + user + ":" + password + "@" + host;
|
||||
} else {
|
||||
this.host = "http://" + host;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean refresh() {
|
||||
boolean wasOnline = online;
|
||||
refreshPower();
|
||||
if (!wasOnline && online) {
|
||||
// Only refresh all services if the box changed from offline to online and power is on
|
||||
// because it is a performance intensive action.
|
||||
refreshAllServices();
|
||||
}
|
||||
refreshChannel();
|
||||
refreshEpg();
|
||||
refreshVolume();
|
||||
refreshAnswer();
|
||||
return online;
|
||||
}
|
||||
|
||||
public void refreshPower() {
|
||||
Optional<Document> document = transmitWithResult(PATH_POWER);
|
||||
if (document.isPresent()) {
|
||||
online = true;
|
||||
processPowerResult(document.get());
|
||||
} else {
|
||||
online = false;
|
||||
power = false;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public void refreshAllServices() {
|
||||
if (power || channels.isEmpty()) {
|
||||
transmitWithResult(PATH_ALL_SERVICES).ifPresent(this::processAllServicesResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshChannel() {
|
||||
if (power) {
|
||||
transmitWithResult(PATH_CHANNEL).ifPresent(this::processChannelResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshAnswer() {
|
||||
if (asking) {
|
||||
transmitWithResult(PATH_ANSWER).ifPresent(this::processAnswerResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshVolume() {
|
||||
if (power) {
|
||||
transmitWithResult(PATH_VOLUME).ifPresent(this::processVolumeResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshEpg() {
|
||||
if (power) {
|
||||
Optional.ofNullable(channels.get(channel))
|
||||
.flatMap(name -> transmitWithResult(PATH_EPG + UrlEncoded.encodeString(name)))
|
||||
.ifPresent(this::processEpgResult);
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Document> transmitWithResult(String path) {
|
||||
try {
|
||||
Optional<String> xml = transmit(path);
|
||||
if (xml.isPresent()) {
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
return Optional.ofNullable(builder.parse(new InputSource(new StringReader(xml.get()))));
|
||||
}
|
||||
return Optional.empty();
|
||||
} catch (IOException | SAXException | ParserConfigurationException | IllegalArgumentException e) {
|
||||
if (online || !initialized) {
|
||||
logger.debug("Error on transmit {}{}.", host, path, e);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<String> transmit(String path) {
|
||||
String url = host + path;
|
||||
try {
|
||||
logger.debug("Transmitting {}", url);
|
||||
String result = getEnigma2HttpClient().get(url);
|
||||
logger.debug("Transmitting result is {}", result);
|
||||
return Optional.ofNullable(result);
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
if (online || !initialized) {
|
||||
logger.debug("Error on transmit {}.", url, e);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMute(boolean mute) {
|
||||
refreshVolume();
|
||||
if (this.mute != mute) {
|
||||
transmitWithResult(PATH_TOGGLE_MUTE).ifPresent(this::processVolumeResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPower(boolean power) {
|
||||
refreshPower();
|
||||
if (this.power != power) {
|
||||
transmitWithResult(PATH_TOGGLE_POWER).ifPresent(this::processPowerResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void setVolume(int volume) {
|
||||
transmitWithResult(PATH_SET_VOLUME + volume).ifPresent(this::processVolumeResult);
|
||||
}
|
||||
|
||||
public void setChannel(String name) {
|
||||
if (channels.containsKey(name)) {
|
||||
String id = channels.get(name);
|
||||
transmitWithResult(PATH_ZAP + UrlEncoded.encodeString(id)).ifPresent(document -> channel = name);
|
||||
} else {
|
||||
logger.warn("Channel {} not found.", name);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendRcCommand(int key) {
|
||||
transmit(PATH_REMOTE_CONTROL + key);
|
||||
}
|
||||
|
||||
public void sendError(int timeout, String text) {
|
||||
sendMessage(TYPE_ERROR, timeout, text);
|
||||
}
|
||||
|
||||
public void sendWarning(int timeout, String text) {
|
||||
sendMessage(TYPE_WARNING, timeout, text);
|
||||
}
|
||||
|
||||
public void sendInfo(int timeout, String text) {
|
||||
sendMessage(TYPE_INFO, timeout, text);
|
||||
}
|
||||
|
||||
public void sendQuestion(int timeout, String text) {
|
||||
asking = true;
|
||||
sendMessage(TYPE_QUESTION, timeout, text);
|
||||
}
|
||||
|
||||
private void sendMessage(int type, int timeout, String text) {
|
||||
transmit(PATH_MESSAGE + type + "&timeout=" + timeout + "&text=" + UrlEncoded.encodeString(text));
|
||||
}
|
||||
|
||||
private void processPowerResult(Document document) {
|
||||
power = !getBoolean(document, "e2instandby");
|
||||
if (!power) {
|
||||
title = "";
|
||||
description = "";
|
||||
channel = "";
|
||||
}
|
||||
}
|
||||
|
||||
private void processChannelResult(Document document) {
|
||||
channel = getString(document, "e2servicename");
|
||||
// Add channel-Reference-ID if not known
|
||||
if (!channels.containsKey(channel)) {
|
||||
channels.put(channel, getString(document, "e2servicereference"));
|
||||
}
|
||||
}
|
||||
|
||||
private void processAnswerResult(Document document) {
|
||||
if (asking) {
|
||||
boolean state = getBoolean(document, "e2state");
|
||||
if (state) {
|
||||
String[] text = getString(document, "e2statetext").split(" ");
|
||||
answer = text[text.length - 1].replace("!", "");
|
||||
asking = false;
|
||||
lastAnswerTime = LocalDateTime.now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processVolumeResult(Document document) {
|
||||
volume = getInt(document, "e2current");
|
||||
mute = getBoolean(document, "e2ismuted");
|
||||
}
|
||||
|
||||
private void processEpgResult(Document document) {
|
||||
title = getString(document, "e2eventtitle");
|
||||
description = getString(document, "e2eventdescription");
|
||||
}
|
||||
|
||||
private void processAllServicesResult(Document document) {
|
||||
NodeList bouquetList = document.getElementsByTagName("e2bouquet");
|
||||
channels.clear();
|
||||
for (int i = 0; i < bouquetList.getLength(); i++) {
|
||||
Element bouquet = (Element) bouquetList.item(i);
|
||||
NodeList serviceList = bouquet.getElementsByTagName("e2service");
|
||||
for (int j = 0; j < serviceList.getLength(); j++) {
|
||||
Element service = (Element) serviceList.item(j);
|
||||
String id = service.getElementsByTagName("e2servicereference").item(0).getTextContent();
|
||||
String name = service.getElementsByTagName("e2servicename").item(0).getTextContent();
|
||||
channels.put(name, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getString(Document document, String elementId) {
|
||||
return Optional.ofNullable(document.getElementsByTagName(elementId)).map(nodeList -> nodeList.item(0))
|
||||
.map(Node::getTextContent).map(String::trim).orElse("");
|
||||
}
|
||||
|
||||
private boolean getBoolean(Document document, String elementId) {
|
||||
return Boolean.parseBoolean(getString(document, elementId));
|
||||
}
|
||||
|
||||
private int getInt(Document document, String elementId) {
|
||||
try {
|
||||
return Integer.parseInt(getString(document, elementId));
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public boolean isMute() {
|
||||
return mute;
|
||||
}
|
||||
|
||||
public boolean isPower() {
|
||||
return power;
|
||||
}
|
||||
|
||||
public LocalDateTime getLastAnswerTime() {
|
||||
return lastAnswerTime;
|
||||
}
|
||||
|
||||
public String getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getAnswer() {
|
||||
return answer;
|
||||
}
|
||||
|
||||
public Collection<String> getChannels() {
|
||||
return channels.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for Test-Injection
|
||||
*
|
||||
* @return HttpGet.
|
||||
*/
|
||||
Enigma2HttpClient getEnigma2HttpClient() {
|
||||
return enigma2HttpClient;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2Configuration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Enigma2Configuration {
|
||||
|
||||
/**
|
||||
* Hostname or IP address of the Enigma2 device.
|
||||
*/
|
||||
public String host = "";
|
||||
/**
|
||||
* The refresh interval in seconds.
|
||||
*/
|
||||
public int refreshInterval = 5;
|
||||
/**
|
||||
* The refresh interval in seconds.
|
||||
*/
|
||||
public int timeout = 5;
|
||||
/**
|
||||
* The Username of the Enigma2 Web API.
|
||||
*/
|
||||
public String user = "";
|
||||
/**
|
||||
* The Password of the Enigma2 Web API.
|
||||
*/
|
||||
public String password = "";
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal;
|
||||
|
||||
import static org.openhab.binding.enigma2.internal.Enigma2BindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.enigma2.handler.Enigma2Handler;
|
||||
import org.openhab.core.thing.Thing;
|
||||
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.annotations.Component;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2HandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.enigma2", service = ThingHandlerFactory.class)
|
||||
public class Enigma2HandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_DEVICE.equals(thingTypeUID)) {
|
||||
return new Enigma2Handler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2HttpClient} class is responsible for sending HTTP-Get requests to the Enigma2 device.
|
||||
* It is devided from {@link Enigma2Client} for better testing purpose.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Enigma2HttpClient {
|
||||
public static final Pattern PATTERN = Pattern
|
||||
.compile("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFF]+");
|
||||
private final int timeout;
|
||||
|
||||
public Enigma2HttpClient(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public String get(String url) throws IOException, IllegalArgumentException {
|
||||
String xml = HttpUtil.executeUrl("GET", url, timeout * 1000);
|
||||
// remove some unsupported xml-characters
|
||||
return PATTERN.matcher(xml).replaceAll("");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2RemoteKey} class defines the remote keys of an enigma2 device
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum Enigma2RemoteKey {
|
||||
POWER(116),
|
||||
|
||||
KEY_0(11),
|
||||
KEY_1(2),
|
||||
KEY_2(3),
|
||||
KEY_3(4),
|
||||
KEY_4(5),
|
||||
KEY_5(6),
|
||||
KEY_6(7),
|
||||
KEY_7(8),
|
||||
KEY_8(9),
|
||||
KEY_9(10),
|
||||
|
||||
ARROW_LEFT(412),
|
||||
ARROW_RIGHT(407),
|
||||
|
||||
VOLUME_DOWN(114),
|
||||
VOLUME_UP(115),
|
||||
MUTE(113),
|
||||
|
||||
CHANNEL_UP(402),
|
||||
CHANNEL_DOWN(403),
|
||||
|
||||
LEFT(105),
|
||||
RIGHT(106),
|
||||
UP(103),
|
||||
DOWN(108),
|
||||
OK(352),
|
||||
EXIT(174),
|
||||
|
||||
RED(398),
|
||||
GREEN(399),
|
||||
YELLOW(400),
|
||||
BLUE(401),
|
||||
|
||||
PLAY(207),
|
||||
PAUSE(119),
|
||||
STOP(128),
|
||||
RECORD(167),
|
||||
FAST_FORWARD(208),
|
||||
FAST_BACKWARD(168),
|
||||
|
||||
TV(377),
|
||||
RADIO(385),
|
||||
AUDIO(392),
|
||||
VIDEO(393),
|
||||
TEXT(388),
|
||||
INFO(358),
|
||||
MENU(139),
|
||||
HELP(138),
|
||||
SUBTITLE(370),
|
||||
EPG(358);
|
||||
|
||||
private final int value;
|
||||
|
||||
Enigma2RemoteKey(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal.discovery;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.jmdns.ServiceInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2BindingConstants;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2HttpClient;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2DiscoveryParticipant} is responsible processing the
|
||||
* results of searches for mDNS services of type _http._tcp.local. and finding a webinterface
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = MDNSDiscoveryParticipant.class, immediate = true)
|
||||
public class Enigma2DiscoveryParticipant implements MDNSDiscoveryParticipant {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(Enigma2DiscoveryParticipant.class);
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
|
||||
return Enigma2BindingConstants.SUPPORTED_THING_TYPES_UIDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable DiscoveryResult createResult(ServiceInfo info) {
|
||||
logger.debug("ServiceInfo {}", info);
|
||||
String ipAddress = getIPAddress(info);
|
||||
if (ipAddress != null && isEnigma2Device(ipAddress)) {
|
||||
logger.debug("Enigma2 device discovered: IP-Adress={}, name={}", ipAddress, info.getName());
|
||||
ThingUID uid = getThingUID(info);
|
||||
if (uid != null) {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(Enigma2BindingConstants.CONFIG_HOST, ipAddress);
|
||||
properties.put(Enigma2BindingConstants.CONFIG_REFRESH, 5);
|
||||
properties.put(Enigma2BindingConstants.CONFIG_TIMEOUT, 5);
|
||||
return DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(info.getName()).build();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingUID getThingUID(ServiceInfo info) {
|
||||
logger.debug("ServiceInfo {}", info);
|
||||
String ipAddress = getIPAddress(info);
|
||||
if (ipAddress != null) {
|
||||
return new ThingUID(Enigma2BindingConstants.THING_TYPE_DEVICE, ipAddress.replace(".", "_"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return "_http._tcp.local.";
|
||||
}
|
||||
|
||||
private boolean isEnigma2Device(String ipAddress) {
|
||||
try {
|
||||
return getEnigma2HttpClient().get("http://" + ipAddress + "/web/about").contains("e2enigmaversion");
|
||||
} catch (IOException ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable String getIPAddress(ServiceInfo info) {
|
||||
InetAddress[] addresses = info.getInet4Addresses();
|
||||
if (addresses.length > 1) {
|
||||
logger.debug("Enigma2 device {} reports multiple addresses - using the first one! {}", info.getName(),
|
||||
addresses);
|
||||
}
|
||||
return Stream.of(addresses).findFirst().map(InetAddress::getHostAddress).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for Test-Injection
|
||||
*
|
||||
* @return HttpGet.
|
||||
*/
|
||||
Enigma2HttpClient getEnigma2HttpClient() {
|
||||
return new Enigma2HttpClient(5);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="enigma2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>Enigma2 Binding</name>
|
||||
<description>This is the binding for Enigma2.</description>
|
||||
<author>Guido Dolfen</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,36 @@
|
||||
# FIXME: please substitute the xx_XX with a proper locale, ie. de_DE
|
||||
# FIXME: please do not add the file to the repo if you add or change no content
|
||||
# binding
|
||||
binding.enigma2.name = Enigma2 Binding
|
||||
binding.enigma2.description = This is the binding for Enigma2
|
||||
|
||||
# thing types
|
||||
thing-type.enigma2.device.label = Enigma2
|
||||
thing-type.enigma2.device.description = The Thing represents an Enigma2 device
|
||||
|
||||
# thing type config description
|
||||
thing-type.config.enigma2.host.label = Host Address
|
||||
thing-type.config.enigma2.host.description = Hostname or IP address of the Enigma2 device
|
||||
|
||||
# channel types
|
||||
channel-type.enigma2.power.label = Power
|
||||
channel-type.enigma2.power.description = Setting the power to on/off.
|
||||
|
||||
# actions
|
||||
action.enigma2.send-rc-button.label=sendRcCommand
|
||||
action.enigma2.send-rc-button.description=Send an Remote Control Command
|
||||
action-input.enigma2.rc-button.label=rcButton
|
||||
action-input.enigma2.rc-button.description=The Remote Control Button
|
||||
|
||||
action.enigma2.send-info.label=sendInfo
|
||||
action.enigma2.send-info.description=Send an info message to the TV screen
|
||||
action.enigma2.send-warning.label=sendWarning
|
||||
action.enigma2.send-warning.description=Send an warning message to the TV screen
|
||||
action.enigma2.send-error.label=sendError
|
||||
action.enigma2.send-error.description=Send an error message to the TV screen
|
||||
action.enigma2.send-question.label=sendQuestion
|
||||
action.enigma2.send-question.description=Send a question message to the TV screen
|
||||
action-input.enigma2.text.label=text
|
||||
action-input.enigma2.text.description=The message text
|
||||
action-input.enigma2.timeout.label=timeout
|
||||
action-input.enigma2.timeout.description=The timeout in seconds
|
||||
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="enigma2"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<thing-type id="device">
|
||||
<label>Enigma2</label>
|
||||
<description>The Thing represents an Enigma2 device</description>
|
||||
<channels>
|
||||
<channel id="power" typeId="powerType"/>
|
||||
<channel id="mute" typeId="muteType"/>
|
||||
<channel id="volume" typeId="volumeType"/>
|
||||
<channel id="channel" typeId="channelType"/>
|
||||
<channel id="title" typeId="titleType"/>
|
||||
<channel id="description" typeId="descriptionType"/>
|
||||
<channel id="mediaPlayer" typeId="mediaPlayerType"/>
|
||||
<channel id="mediaStop" typeId="mediaStopType"/>
|
||||
<channel id="answer" typeId="answerType"/>
|
||||
</channels>
|
||||
<config-description>
|
||||
<parameter name="host" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>Host Address</label>
|
||||
<description>Hostname or IP address of the Enigma2 device.</description>
|
||||
</parameter>
|
||||
<parameter name="refreshInterval" type="integer" required="false" min="1" max="3600" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>The refresh interval in seconds.</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="timeout" type="integer" required="false" min="1" max="300" unit="s">
|
||||
<label>Timeout</label>
|
||||
<description>The timeout for reading from the device in seconds.</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
<parameter name="user" type="text" required="false">
|
||||
<label>Username</label>
|
||||
<description>The Username of the Enigma2 Web API.</description>
|
||||
</parameter>
|
||||
<parameter name="password" type="text" required="false">
|
||||
<context>password</context>
|
||||
<label>Password</label>
|
||||
<description>The Password of the Enigma2 Web API.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
<channel-type id="powerType">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Power</label>
|
||||
<description>Setting the power to on/off.</description>
|
||||
</channel-type>
|
||||
<channel-type id="muteType">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Mute</label>
|
||||
<description>Current Mute Setting</description>
|
||||
<category>SoundVolume</category>
|
||||
</channel-type>
|
||||
<channel-type id="volumeType">
|
||||
<item-type>Dimmer</item-type>
|
||||
<label>Volume</label>
|
||||
<description>Current Volume Setting</description>
|
||||
<category>SoundVolume</category>
|
||||
<state min="0" max="100" step="5"></state>
|
||||
</channel-type>
|
||||
<channel-type id="channelType">
|
||||
<item-type>String</item-type>
|
||||
<label>Channel</label>
|
||||
<description>Current Channel</description>
|
||||
</channel-type>
|
||||
<channel-type id="titleType">
|
||||
<item-type>String</item-type>
|
||||
<label>Title</label>
|
||||
<description>Current Title of the current Channel</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="descriptionType">
|
||||
<item-type>String</item-type>
|
||||
<label>Description</label>
|
||||
<description>Current Description of the current Channel</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="mediaPlayerType">
|
||||
<item-type>Player</item-type>
|
||||
<label>Media Control</label>
|
||||
<description>Control media (e.g. audio or video) playback</description>
|
||||
<category>MediaControl</category>
|
||||
</channel-type>
|
||||
<channel-type id="mediaStopType">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Stop</label>
|
||||
<description>Stop Playback</description>
|
||||
</channel-type>
|
||||
<channel-type id="answerType">
|
||||
<item-type>String</item-type>
|
||||
<label>Answer</label>
|
||||
<description>Receives an answer to a send question of the device</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.actions;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.enigma2.handler.Enigma2Handler;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2BindingConstants;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2ActionsTest} class is responsible for testing {@link Enigma2Actions}.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@SuppressWarnings("null")
|
||||
@NonNullByDefault
|
||||
public class Enigma2ActionsTest {
|
||||
@Nullable
|
||||
private Enigma2Actions enigma2Actions;
|
||||
@Nullable
|
||||
private Enigma2Handler enigma2Handler;
|
||||
public static final String SOME_TEXT = "some Text";
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
enigma2Handler = mock(Enigma2Handler.class);
|
||||
enigma2Actions = new Enigma2Actions();
|
||||
enigma2Actions.setThingHandler(enigma2Handler);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetThingHandler() {
|
||||
assertThat(enigma2Actions.getThingHandler(), is(enigma2Handler));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendRcCommand() {
|
||||
enigma2Actions.sendRcCommand("KEY_1");
|
||||
verify(enigma2Handler).sendRcCommand("KEY_1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendInfo() {
|
||||
enigma2Actions.sendInfo(SOME_TEXT);
|
||||
verify(enigma2Handler).sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendInfoTimeout() {
|
||||
enigma2Actions.sendInfo(SOME_TEXT, 10);
|
||||
verify(enigma2Handler).sendInfo(10, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendError() {
|
||||
enigma2Actions.sendError(SOME_TEXT);
|
||||
verify(enigma2Handler).sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendErrorTimeout() {
|
||||
enigma2Actions.sendError(SOME_TEXT, 10);
|
||||
verify(enigma2Handler).sendError(10, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendWarning() {
|
||||
enigma2Actions.sendWarning(SOME_TEXT);
|
||||
verify(enigma2Handler).sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendWarningTimeout() {
|
||||
enigma2Actions.sendWarning(SOME_TEXT, 10);
|
||||
verify(enigma2Handler).sendWarning(10, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendQuestion() {
|
||||
enigma2Actions.sendQuestion(SOME_TEXT);
|
||||
verify(enigma2Handler).sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendQuestionTimeout() {
|
||||
enigma2Actions.sendQuestion(SOME_TEXT, 10);
|
||||
verify(enigma2Handler).sendQuestion(10, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendRcCommandStatic() {
|
||||
Enigma2Actions.sendRcCommand(enigma2Actions, "KEY_1");
|
||||
verify(enigma2Handler).sendRcCommand("KEY_1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testSendRcCommandStaticWithException() {
|
||||
Enigma2Actions.sendRcCommand(null, "KEY_1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendInfoStatic() {
|
||||
Enigma2Actions.sendInfo(enigma2Actions, SOME_TEXT);
|
||||
verify(enigma2Handler).sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendInfoTimeoutStatic() {
|
||||
Enigma2Actions.sendInfo(enigma2Actions, SOME_TEXT, 10);
|
||||
verify(enigma2Handler).sendInfo(10, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testSendInfoStaticWithException() {
|
||||
Enigma2Actions.sendInfo(null, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendErrorStatic() {
|
||||
Enigma2Actions.sendError(enigma2Actions, SOME_TEXT);
|
||||
verify(enigma2Handler).sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendErrorTimeoutStatic() {
|
||||
Enigma2Actions.sendError(enigma2Actions, SOME_TEXT, 10);
|
||||
verify(enigma2Handler).sendError(10, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testSendErrorStaticWithException() {
|
||||
Enigma2Actions.sendError(null, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendWarningStatic() {
|
||||
Enigma2Actions.sendWarning(enigma2Actions, SOME_TEXT);
|
||||
verify(enigma2Handler).sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendWarningTimeoutStatic() {
|
||||
Enigma2Actions.sendWarning(enigma2Actions, SOME_TEXT, 10);
|
||||
verify(enigma2Handler).sendWarning(10, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testSendWarningStaticWithException() {
|
||||
Enigma2Actions.sendWarning(null, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendQuestionStatic() {
|
||||
Enigma2Actions.sendQuestion(enigma2Actions, SOME_TEXT);
|
||||
verify(enigma2Handler).sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendQuestionTimeoutStatic() {
|
||||
Enigma2Actions.sendQuestion(enigma2Actions, SOME_TEXT, 10);
|
||||
verify(enigma2Handler).sendQuestion(10, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testSendQuestionStaticWithException() {
|
||||
Enigma2Actions.sendQuestion(null, SOME_TEXT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.handler;
|
||||
|
||||
import static org.eclipse.jdt.annotation.Checks.requireNonNull;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.enigma2.actions.Enigma2Actions;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2BindingConstants;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2Client;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2Configuration;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2RemoteKey;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.*;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.binding.ThingHandlerCallback;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2HandlerTest} class is responsible for testing {@link Enigma2Handler}.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@SuppressWarnings({ "null", "unchecked" })
|
||||
@NonNullByDefault
|
||||
public class Enigma2HandlerTest {
|
||||
public static final String CHANNEL_UID_PREFIX = "enigma2:device:192_168_0_3:";
|
||||
public static final String SOME_TEXT = "some Text";
|
||||
@Nullable
|
||||
private Enigma2Handler enigma2Handler;
|
||||
@Nullable
|
||||
private Enigma2Client enigma2Client;
|
||||
@Nullable
|
||||
private Thing thing;
|
||||
@Nullable
|
||||
private Configuration configuration;
|
||||
@Nullable
|
||||
private ThingHandlerCallback callback;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
enigma2Client = mock(Enigma2Client.class);
|
||||
thing = mock(Thing.class);
|
||||
callback = mock(ThingHandlerCallback.class);
|
||||
configuration = mock(Configuration.class);
|
||||
when(thing.getConfiguration()).thenReturn(requireNonNull(configuration));
|
||||
when(configuration.as(Enigma2Configuration.class)).thenReturn(new Enigma2Configuration());
|
||||
enigma2Handler = spy(new Enigma2Handler(requireNonNull(thing)));
|
||||
enigma2Handler.setCallback(callback);
|
||||
when(enigma2Handler.getEnigma2Client()).thenReturn(Optional.of(requireNonNull(enigma2Client)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendRcCommand() {
|
||||
enigma2Handler.sendRcCommand("KEY_1");
|
||||
verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.KEY_1.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendInfo() {
|
||||
enigma2Handler.sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
verify(enigma2Client).sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendWarning() {
|
||||
enigma2Handler.sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
verify(enigma2Client).sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendError() {
|
||||
enigma2Handler.sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
verify(enigma2Client).sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendQuestion() {
|
||||
enigma2Handler.sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
verify(enigma2Client).sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEnigma2Client() {
|
||||
enigma2Handler = new Enigma2Handler(requireNonNull(thing));
|
||||
assertThat(enigma2Handler.getEnigma2Client(), is(Optional.empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetServices() {
|
||||
enigma2Handler = new Enigma2Handler(requireNonNull(thing));
|
||||
assertThat(enigma2Handler.getServices(), contains(Enigma2Actions.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendRcCommandUnsupported() {
|
||||
enigma2Handler.sendRcCommand("KEY_X");
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandPowerRefreshFalse() {
|
||||
when(enigma2Client.isPower()).thenReturn(false);
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshPower();
|
||||
verify(callback).stateUpdated(channelUID, OnOffType.OFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandPowerRefreshTrue() {
|
||||
when(enigma2Client.isPower()).thenReturn(true);
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshPower();
|
||||
verify(callback).stateUpdated(channelUID, OnOffType.ON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandPowerOn() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER);
|
||||
enigma2Handler.handleCommand(channelUID, OnOffType.ON);
|
||||
verify(enigma2Client).setPower(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandPowerOff() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER);
|
||||
enigma2Handler.handleCommand(channelUID, OnOffType.OFF);
|
||||
verify(enigma2Client).setPower(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandPowerUnsupported() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandChannelRefresh() {
|
||||
when(enigma2Client.getChannel()).thenReturn(SOME_TEXT);
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_CHANNEL);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshChannel();
|
||||
verify(callback).stateUpdated(channelUID, new StringType(SOME_TEXT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMuteRefreshFalse() {
|
||||
when(enigma2Client.isMute()).thenReturn(false);
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshVolume();
|
||||
verify(callback).stateUpdated(channelUID, OnOffType.OFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMuteRefreshTrue() {
|
||||
when(enigma2Client.isMute()).thenReturn(true);
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshVolume();
|
||||
verify(callback).stateUpdated(channelUID, OnOffType.ON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMuteOn() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE);
|
||||
enigma2Handler.handleCommand(channelUID, OnOffType.ON);
|
||||
verify(enigma2Client).setMute(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMuteOff() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE);
|
||||
enigma2Handler.handleCommand(channelUID, OnOffType.OFF);
|
||||
verify(enigma2Client).setMute(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMuteUnsupported() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandChannelString() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_CHANNEL);
|
||||
enigma2Handler.handleCommand(channelUID, new StringType(SOME_TEXT));
|
||||
verify(enigma2Client).setChannel(SOME_TEXT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandChannelUnsupported() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_CHANNEL);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaPlayerRefresh() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaPlay() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PLAY);
|
||||
verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.PLAY.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaPause() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE);
|
||||
verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.PAUSE.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaNext() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER);
|
||||
enigma2Handler.handleCommand(channelUID, NextPreviousType.NEXT);
|
||||
verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.FAST_FORWARD.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaPrevious() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER);
|
||||
enigma2Handler.handleCommand(channelUID, NextPreviousType.PREVIOUS);
|
||||
verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.FAST_BACKWARD.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaPlayerUnsupported() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER);
|
||||
enigma2Handler.handleCommand(channelUID, OnOffType.ON);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaStopRefresh() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_STOP);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaStopOn() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_STOP);
|
||||
enigma2Handler.handleCommand(channelUID, OnOffType.ON);
|
||||
verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.STOP.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaStopOff() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_STOP);
|
||||
enigma2Handler.handleCommand(channelUID, OnOffType.OFF);
|
||||
verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.STOP.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandMediaStopUnsupported() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_STOP);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandTitleUnsupported() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_TITLE);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandTitleRefresh() {
|
||||
when(enigma2Client.getTitle()).thenReturn(SOME_TEXT);
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_TITLE);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshEpg();
|
||||
verify(callback).stateUpdated(channelUID, new StringType(SOME_TEXT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandAnswerUnsupported() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_ANSWER);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandAnswerRefresh() {
|
||||
when(enigma2Client.getAnswer()).thenReturn(SOME_TEXT);
|
||||
when(enigma2Client.getLastAnswerTime()).thenReturn(LocalDateTime.now().plus(1, ChronoUnit.SECONDS));
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_ANSWER);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshAnswer();
|
||||
verify(callback).stateUpdated(channelUID, new StringType(SOME_TEXT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandAnswerRefreshFalse() {
|
||||
when(enigma2Client.getAnswer()).thenReturn(SOME_TEXT);
|
||||
when(enigma2Client.getLastAnswerTime()).thenReturn(LocalDateTime.of(2020, 1, 1, 0, 0));
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_ANSWER);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshAnswer();
|
||||
verifyNoInteractions(callback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandDescriptionUnsupported() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_DESCRIPTION);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandDescriptionRefresh() {
|
||||
when(enigma2Client.getDescription()).thenReturn(SOME_TEXT);
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_DESCRIPTION);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshEpg();
|
||||
verify(callback).stateUpdated(channelUID, new StringType(SOME_TEXT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandVolumeRefresh() {
|
||||
when(enigma2Client.getVolume()).thenReturn(35);
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_VOLUME);
|
||||
enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH);
|
||||
verify(enigma2Client).refreshVolume();
|
||||
verify(callback).stateUpdated(channelUID, new PercentType(35));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandVolumePercent() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_VOLUME);
|
||||
enigma2Handler.handleCommand(channelUID, new PercentType(30));
|
||||
verify(enigma2Client).setVolume(30);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandVolumeDecimal() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_VOLUME);
|
||||
enigma2Handler.handleCommand(channelUID, new DecimalType(40));
|
||||
verify(enigma2Client).setVolume(40);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandVolumeUnsupported() {
|
||||
ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_VOLUME);
|
||||
enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE);
|
||||
verifyNoInteractions(enigma2Client);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal;
|
||||
|
||||
import static org.eclipse.jdt.annotation.Checks.requireNonNull;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2ClientTest} class is responsible for testing {@link Enigma2Client}.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@SuppressWarnings({ "null" })
|
||||
@NonNullByDefault
|
||||
public class Enigma2ClientTest {
|
||||
public static final String HOST = "http://user:password@localhost:8080";
|
||||
public static final String SOME_TEXT = "some Text";
|
||||
public static final String SOME_TEXT_ENCODED = "some+Text";
|
||||
@Nullable
|
||||
private Enigma2Client enigma2Client;
|
||||
@Nullable
|
||||
private Enigma2HttpClient enigma2HttpClient;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
enigma2HttpClient = mock(Enigma2HttpClient.class);
|
||||
enigma2Client = spy(new Enigma2Client("localhost:8080", "user", "password", 5));
|
||||
when(enigma2Client.getEnigma2HttpClient()).thenReturn(requireNonNull(enigma2HttpClient));
|
||||
when(enigma2HttpClient.get(anyString())).thenReturn("<emptyResult/>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetPowerFalse() throws IOException {
|
||||
whenStandby("true");
|
||||
enigma2Client.setPower(false);
|
||||
verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_POWER);
|
||||
verifyNoMoreInteractions(enigma2HttpClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetPower() throws IOException {
|
||||
whenStandby("true");
|
||||
enigma2Client.setPower(true);
|
||||
verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_TOGGLE_POWER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetVolume() throws IOException {
|
||||
enigma2Client.setVolume(20);
|
||||
verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_SET_VOLUME + 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetChannel() throws IOException {
|
||||
whenStandby("false");
|
||||
whenAllServices();
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.refreshAllServices();
|
||||
enigma2Client.setChannel("Channel 3");
|
||||
verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_ZAP + 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetChannelUnknown() throws IOException {
|
||||
enigma2Client.setChannel("Channel 3");
|
||||
verifyNoInteractions(enigma2HttpClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMuteFalse() throws IOException {
|
||||
whenStandby("false");
|
||||
whenVolume("10", false);
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.setMute(false);
|
||||
verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_POWER);
|
||||
verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_VOLUME);
|
||||
verifyNoMoreInteractions(enigma2HttpClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMute() throws IOException {
|
||||
whenStandby("false");
|
||||
whenVolume("10", false);
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.setMute(true);
|
||||
verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_TOGGLE_MUTE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendRcCommand() throws IOException {
|
||||
enigma2Client.sendRcCommand(2);
|
||||
verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_REMOTE_CONTROL + 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendError() throws IOException {
|
||||
enigma2Client.sendError(20, SOME_TEXT);
|
||||
verify(enigma2HttpClient).get(HOST + "/web/message?type=3&timeout=20&text=" + SOME_TEXT_ENCODED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendWarning() throws IOException {
|
||||
enigma2Client.sendWarning(35, SOME_TEXT);
|
||||
verify(enigma2HttpClient).get(HOST + "/web/message?type=2&timeout=35&text=" + SOME_TEXT_ENCODED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendInfo() throws IOException {
|
||||
enigma2Client.sendInfo(40, SOME_TEXT);
|
||||
verify(enigma2HttpClient).get(HOST + "/web/message?type=1&timeout=40&text=" + SOME_TEXT_ENCODED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendQuestion() throws IOException {
|
||||
enigma2Client.sendQuestion(50, SOME_TEXT);
|
||||
verify(enigma2HttpClient).get(HOST + "/web/message?type=0&timeout=50&text=" + SOME_TEXT_ENCODED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshPowerTrue() throws IOException {
|
||||
whenStandby(" FALSE ");
|
||||
enigma2Client.refreshPower();
|
||||
assertThat(enigma2Client.isPower(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshVolumeMuteTrue() throws IOException {
|
||||
whenStandby("false");
|
||||
whenVolume("30", true);
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.refreshVolume();
|
||||
assertThat(enigma2Client.isMute(), is(true));
|
||||
assertThat(enigma2Client.getVolume(), is(30));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshVolumeMuteFalse() throws IOException {
|
||||
whenStandby("false");
|
||||
whenVolume("30", false);
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.refreshVolume();
|
||||
assertThat(enigma2Client.isMute(), is(false));
|
||||
assertThat(enigma2Client.getVolume(), is(30));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshVolumePowerOff() throws IOException {
|
||||
enigma2Client.refreshVolume();
|
||||
assertThat(enigma2Client.isMute(), is(false));
|
||||
assertThat(enigma2Client.getVolume(), is(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshPowerFalse() throws IOException {
|
||||
whenStandby(" TRUE ");
|
||||
enigma2Client.refreshPower();
|
||||
assertThat(enigma2Client.isPower(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshPowerOffline() throws IOException {
|
||||
IOException ioException = new IOException();
|
||||
when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_POWER)).thenThrow(ioException);
|
||||
enigma2Client.refreshPower();
|
||||
assertThat(enigma2Client.isPower(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshAllServices() throws IOException {
|
||||
whenStandby("false");
|
||||
whenAllServices();
|
||||
enigma2Client.refreshAllServices();
|
||||
assertThat(enigma2Client.getChannels(), containsInAnyOrder("Channel 1", "Channel 2", "Channel 3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshChannel() throws IOException {
|
||||
whenStandby("false");
|
||||
whenChannel("2", "Channel 2");
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.refreshChannel();
|
||||
assertThat(enigma2Client.getChannel(), is("Channel 2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshEpg() throws IOException {
|
||||
whenStandby("false");
|
||||
whenAllServices();
|
||||
whenChannel("2", "Channel 2");
|
||||
whenEpg("2", "Title", "Description");
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.refreshAllServices();
|
||||
enigma2Client.refreshChannel();
|
||||
enigma2Client.refreshEpg();
|
||||
assertThat(enigma2Client.getTitle(), is("Title"));
|
||||
assertThat(enigma2Client.getDescription(), is("Description"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshAnswerTimeout() throws IOException {
|
||||
whenStandby("false");
|
||||
whenAnswer("False", "Timeout");
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.refreshAnswer();
|
||||
assertThat(enigma2Client.getLastAnswerTime().isAfter(LocalDateTime.of(2020, 1, 1, 0, 0)), is(false));
|
||||
assertThat(enigma2Client.getAnswer(), is(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshAnswerNoQuestion() throws IOException {
|
||||
whenStandby("false");
|
||||
whenAnswer("True", "Antwort lautet NEIN!");
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.refreshAnswer();
|
||||
assertThat(enigma2Client.getLastAnswerTime().isAfter(LocalDateTime.of(2020, 1, 1, 0, 0)), is(false));
|
||||
assertThat(enigma2Client.getAnswer(), is(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshAnswer() throws IOException {
|
||||
whenStandby("false");
|
||||
whenAnswer("True", "Antwort lautet NEIN!");
|
||||
enigma2Client.refreshPower();
|
||||
enigma2Client.sendQuestion(50, SOME_TEXT);
|
||||
enigma2Client.refreshAnswer();
|
||||
assertThat(enigma2Client.getLastAnswerTime().isAfter(LocalDateTime.of(2020, 1, 1, 0, 0)), is(true));
|
||||
assertThat(enigma2Client.getAnswer(), is("NEIN"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefresh() throws IOException {
|
||||
whenStandby("false");
|
||||
whenAllServices();
|
||||
whenVolume("A", false);
|
||||
whenChannel("1", "Channel 1");
|
||||
whenEpg("1", "Title", "Description");
|
||||
assertThat(enigma2Client.refresh(), is(true));
|
||||
assertThat(enigma2Client.isPower(), is(true));
|
||||
assertThat(enigma2Client.isMute(), is(false));
|
||||
assertThat(enigma2Client.getVolume(), is(0));
|
||||
assertThat(enigma2Client.getChannel(), is("Channel 1"));
|
||||
assertThat(enigma2Client.getTitle(), is("Title"));
|
||||
assertThat(enigma2Client.getDescription(), is("Description"));
|
||||
assertThat(enigma2Client.getChannels(), containsInAnyOrder("Channel 1", "Channel 2", "Channel 3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshOffline() throws IOException {
|
||||
IOException ioException = new IOException();
|
||||
when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_POWER)).thenThrow(ioException);
|
||||
assertThat(enigma2Client.refresh(), is(false));
|
||||
assertThat(enigma2Client.isPower(), is(false));
|
||||
assertThat(enigma2Client.isMute(), is(false));
|
||||
assertThat(enigma2Client.getVolume(), is(0));
|
||||
assertThat(enigma2Client.getChannel(), is(""));
|
||||
assertThat(enigma2Client.getTitle(), is(""));
|
||||
assertThat(enigma2Client.getDescription(), is(""));
|
||||
assertThat(enigma2Client.getChannels().isEmpty(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEnigma2HttpClient() {
|
||||
enigma2Client = new Enigma2Client("http://localhost:8080", null, null, 5);
|
||||
assertThat(enigma2Client.getEnigma2HttpClient(), is(notNullValue()));
|
||||
}
|
||||
|
||||
private void whenVolume(String volume, boolean mute) throws IOException {
|
||||
when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_VOLUME)).thenReturn(
|
||||
"<e2volume><e2current>" + volume + "</e2current><e2ismuted>" + mute + "</e2ismuted></e2volume>");
|
||||
}
|
||||
|
||||
private void whenEpg(String id, String title, String description) throws IOException {
|
||||
when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_EPG + id)).thenReturn("<e2event><e2eventtitle>" + title
|
||||
+ "</e2eventtitle><e2eventdescription>" + description + "</e2eventdescription></e2event>");
|
||||
}
|
||||
|
||||
private void whenAnswer(String state, String answer) throws IOException {
|
||||
when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_ANSWER)).thenReturn("<e2simplexmlresult><e2state>" + state
|
||||
+ "</e2state><e2statetext>" + answer + "</e2statetext></e2simplexmlresult>");
|
||||
}
|
||||
|
||||
private void whenStandby(String standby) throws IOException {
|
||||
when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_POWER))
|
||||
.thenReturn("<e2powerstate><e2instandby>" + standby + "</e2instandby></e2powerstate>");
|
||||
}
|
||||
|
||||
private void whenChannel(String id, String name) throws IOException {
|
||||
when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_CHANNEL)).thenReturn(
|
||||
"<e2servicelist><e2service><e2servicereference>" + id + "</e2servicereference><e2servicename>" + name
|
||||
+ "</e2servicename></e2service></e2servicelist>");
|
||||
}
|
||||
|
||||
private void whenAllServices() throws IOException {
|
||||
when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_ALL_SERVICES))
|
||||
.thenReturn("<e2servicelistrecursive>" + "<e2bouquet>" + "<e2servicelist>" + "<e2service>"
|
||||
+ "<e2servicereference>1</e2servicereference>" + "<e2servicename>Channel 1</e2servicename>"
|
||||
+ "</e2service>" + "<e2service>" + "<e2servicereference>2</e2servicereference>"
|
||||
+ "<e2servicename>Channel 2</e2servicename>" + "</e2service>" + "</e2servicelist>"
|
||||
+ "</e2bouquet>" + "<e2bouquet>" + "<e2servicelist>" + "<e2service>"
|
||||
+ "<e2servicereference>3</e2servicereference>" + "<e2servicename>Channel 3</e2servicename>"
|
||||
+ "</e2service>" + "</e2servicelist>" + "</e2bouquet>" + "</e2servicelistrecursive>");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal;
|
||||
|
||||
import static org.eclipse.jdt.annotation.Checks.requireNonNull;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.openhab.binding.enigma2.internal.Enigma2BindingConstants.THING_TYPE_DEVICE;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.Test;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2HandlerFactoryTest} class is responsible for testing {@link Enigma2HandlerFactory}.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@SuppressWarnings("null")
|
||||
@NonNullByDefault
|
||||
public class Enigma2HandlerFactoryTest {
|
||||
@Nullable
|
||||
private Thing thing;
|
||||
@Nullable
|
||||
private Configuration configuration;
|
||||
|
||||
@Test
|
||||
public void testSupportsThingType() {
|
||||
assertThat(new Enigma2HandlerFactory().supportsThingType(Enigma2BindingConstants.THING_TYPE_DEVICE), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupportsThingTypeFalse() {
|
||||
assertThat(new Enigma2HandlerFactory().supportsThingType(new ThingTypeUID("any", "device")), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateHandlerNull() {
|
||||
thing = mock(Thing.class);
|
||||
assertThat(new Enigma2HandlerFactory().createHandler(requireNonNull(thing)), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateHandler() {
|
||||
thing = mock(Thing.class);
|
||||
configuration = mock(Configuration.class);
|
||||
when(thing.getConfiguration()).thenReturn(requireNonNull(configuration));
|
||||
when(configuration.as(Enigma2Configuration.class)).thenReturn(new Enigma2Configuration());
|
||||
when(thing.getThingTypeUID()).thenReturn(THING_TYPE_DEVICE);
|
||||
assertThat(new Enigma2HandlerFactory().createHandler(requireNonNull(thing)), is(notNullValue()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2RemoteKeyTest} class is responsible for testing {@link Enigma2RemoteKey}.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Enigma2RemoteKeyTest {
|
||||
@Test
|
||||
public void testGetValue() {
|
||||
assertThat(Enigma2RemoteKey.ARROW_LEFT.getValue(), is(412));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.enigma2.internal.discovery;
|
||||
|
||||
import static org.eclipse.jdt.annotation.Checks.requireNonNull;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import javax.jmdns.ServiceInfo;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2BindingConstants;
|
||||
import org.openhab.binding.enigma2.internal.Enigma2HttpClient;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
|
||||
/**
|
||||
* The {@link Enigma2DiscoveryParticipantTest} class is responsible for testing {@link Enigma2DiscoveryParticipant}.
|
||||
*
|
||||
* @author Guido Dolfen - Initial contribution
|
||||
*/
|
||||
@SuppressWarnings({ "null" })
|
||||
@NonNullByDefault
|
||||
public class Enigma2DiscoveryParticipantTest {
|
||||
@Nullable
|
||||
private ServiceInfo serviceInfo;
|
||||
@Nullable
|
||||
private Enigma2HttpClient enigma2HttpClient;
|
||||
@Nullable
|
||||
private Enigma2DiscoveryParticipant enigma2DiscoveryParticipant;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
enigma2HttpClient = mock(Enigma2HttpClient.class);
|
||||
serviceInfo = mock(ServiceInfo.class);
|
||||
enigma2DiscoveryParticipant = spy(new Enigma2DiscoveryParticipant());
|
||||
when(enigma2DiscoveryParticipant.getEnigma2HttpClient()).thenReturn(requireNonNull(enigma2HttpClient));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSupportedThingTypeUIDs() {
|
||||
assertThat(enigma2DiscoveryParticipant.getSupportedThingTypeUIDs(),
|
||||
contains(Enigma2BindingConstants.THING_TYPE_DEVICE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetServiceType() {
|
||||
assertThat(enigma2DiscoveryParticipant.getServiceType(), is("_http._tcp.local."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateResult() throws Exception {
|
||||
when(serviceInfo.getName()).thenReturn("enigma2");
|
||||
when(enigma2HttpClient.get("http://192.168.10.3/web/about"))
|
||||
.thenReturn("<e2abouts><e2about><e2enigmaversion>2020-01-11</e2enigmaversion></e2about></e2abouts>");
|
||||
when(serviceInfo.getInet4Addresses())
|
||||
.thenReturn(new Inet4Address[] { (Inet4Address) InetAddress.getAllByName("192.168.10.3")[0] });
|
||||
DiscoveryResult discoveryResult = enigma2DiscoveryParticipant.createResult(requireNonNull(serviceInfo));
|
||||
assertThat(discoveryResult, is(notNullValue()));
|
||||
assertThat(discoveryResult.getLabel(), is("enigma2"));
|
||||
assertThat(discoveryResult.getThingUID(),
|
||||
is(new ThingUID(Enigma2BindingConstants.THING_TYPE_DEVICE, "192_168_10_3")));
|
||||
assertThat(discoveryResult.getProperties(), is(notNullValue()));
|
||||
assertThat(discoveryResult.getProperties(), hasEntry(Enigma2BindingConstants.CONFIG_HOST, "192.168.10.3"));
|
||||
assertThat(discoveryResult.getProperties(), hasEntry(Enigma2BindingConstants.CONFIG_REFRESH, 5));
|
||||
assertThat(discoveryResult.getProperties(), hasEntry(Enigma2BindingConstants.CONFIG_TIMEOUT, 5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateResultNotFound() throws Exception {
|
||||
when(enigma2HttpClient.get("http://192.168.10.3/web/about")).thenReturn("any");
|
||||
when(serviceInfo.getInet4Addresses())
|
||||
.thenReturn(new Inet4Address[] { (Inet4Address) InetAddress.getAllByName("192.168.10.3")[0] });
|
||||
assertThat(enigma2DiscoveryParticipant.createResult(requireNonNull(serviceInfo)), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetThingUID() throws Exception {
|
||||
when(serviceInfo.getInet4Addresses())
|
||||
.thenReturn(new Inet4Address[] { (Inet4Address) InetAddress.getAllByName("192.168.10.3")[0] });
|
||||
assertThat(enigma2DiscoveryParticipant.getThingUID(requireNonNull(serviceInfo)),
|
||||
is(new ThingUID(Enigma2BindingConstants.THING_TYPE_DEVICE, "192_168_10_3")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetThingUIDTwoAddresses() throws Exception {
|
||||
when(serviceInfo.getName()).thenReturn("enigma2");
|
||||
Inet4Address[] addresses = { (Inet4Address) InetAddress.getAllByName("192.168.10.3")[0],
|
||||
(Inet4Address) InetAddress.getAllByName("192.168.10.4")[0] };
|
||||
when(serviceInfo.getInet4Addresses()).thenReturn(addresses);
|
||||
assertThat(enigma2DiscoveryParticipant.getThingUID(requireNonNull(serviceInfo)),
|
||||
is(new ThingUID(Enigma2BindingConstants.THING_TYPE_DEVICE, "192_168_10_3")));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user