From 71c339f5f6b74f05f4c9b2d9c60a8c12399b5da3 Mon Sep 17 00:00:00 2001 From: Sebastian Prehn Date: Sun, 29 Nov 2015 22:14:47 +0100 Subject: [PATCH] New feature ToastControl:Toast and MediaControl:PlayState --- .../internal/ConnectSDKBinding.java | 6 +- ...stractOpenhabConnectSDKPropertyBridge.java | 40 ++++++---- .../bridges/ExternalInputControlInput.java | 2 +- .../bridges/MediaControlPlayState.java | 78 +++++++++++++++++++ .../internal/bridges/ToastControlToast.java | 63 +++++++++++++++ 5 files changed, 173 insertions(+), 16 deletions(-) create mode 100644 bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/MediaControlPlayState.java create mode 100644 bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/ToastControlToast.java diff --git a/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/ConnectSDKBinding.java b/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/ConnectSDKBinding.java index 71fb42d0f10..0e83a5d4c4d 100644 --- a/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/ConnectSDKBinding.java +++ b/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/ConnectSDKBinding.java @@ -24,6 +24,7 @@ import org.openhab.binding.connectsdk.internal.bridges.MediaControlForward; import org.openhab.binding.connectsdk.internal.bridges.MediaControlPause; import org.openhab.binding.connectsdk.internal.bridges.MediaControlPlay; +import org.openhab.binding.connectsdk.internal.bridges.MediaControlPlayState; import org.openhab.binding.connectsdk.internal.bridges.MediaControlRewind; import org.openhab.binding.connectsdk.internal.bridges.MediaControlStop; import org.openhab.binding.connectsdk.internal.bridges.OpenhabConnectSDKPropertyBridge; @@ -33,6 +34,7 @@ import org.openhab.binding.connectsdk.internal.bridges.TVControlDown; import org.openhab.binding.connectsdk.internal.bridges.TVControlProgram; import org.openhab.binding.connectsdk.internal.bridges.TVControlUp; +import org.openhab.binding.connectsdk.internal.bridges.ToastControlToast; import org.openhab.binding.connectsdk.internal.bridges.VolumeControlDown; import org.openhab.binding.connectsdk.internal.bridges.VolumeControlMute; import org.openhab.binding.connectsdk.internal.bridges.VolumeControlUp; @@ -68,7 +70,8 @@ public class ConnectSDKBinding extends AbstractBinding implements OpenhabConnectSDKPropertyBridge { private static final Logger logger = LoggerFactory.getLogger(AbstractOpenhabConnectSDKPropertyBridge.class); - private Map> subscriptions = new ConcurrentHashMap>(); + private Map> subscriptions; + private synchronized Map> getSubscriptions() { + if (subscriptions == null) { + subscriptions = new ConcurrentHashMap>(); + } + return subscriptions; + } @Override public final void updateSubscription(final ConnectableDevice device, @@ -26,27 +32,33 @@ public final void updateSubscription(final ConnectableDevice device, removeAnySubscription(device); ServiceSubscription listener = getSubscription(device, providers, eventPublisher); - if (listener != null) { - logger.debug("Subscribed {}:{} listener on IP: {}", getItemClass(), getItemProperty(), device.getIpAddress()); - subscriptions.put(device.getIpAddress(), listener); + if (listener != null) { + logger.debug("Subscribed {}:{} listener on IP: {}", getItemClass(), getItemProperty(), + device.getIpAddress()); + getSubscriptions().put(device.getIpAddress(), listener); } } /** * Creates a subscription instance for this device. + * * @param device * @param providers * @param eventPublisher * @return instance or null if no subscription is possible or required */ - protected abstract ServiceSubscription getSubscription(final ConnectableDevice device, final Collection providers, final EventPublisher eventPublisher); + protected abstract ServiceSubscription getSubscription(final ConnectableDevice device, + final Collection providers, final EventPublisher eventPublisher); + @Override - public final void removeAnySubscription(final ConnectableDevice device) { // here - ServiceSubscription l = subscriptions.remove(device.getIpAddress()); - if (l != null) { - l.unsubscribe(); - logger.debug("Unsubscribed {}:{} listener on IP: {}", getItemClass(), getItemProperty(), - device.getIpAddress()); + public final synchronized void removeAnySubscription(final ConnectableDevice device) { // here + if (subscriptions != null) { + ServiceSubscription l = subscriptions.remove(device.getIpAddress()); + if (l != null) { + l.unsubscribe(); + logger.debug("Unsubscribed {}:{} listener on IP: {}", getItemClass(), getItemProperty(), + device.getIpAddress()); + } } } @@ -65,19 +77,19 @@ public final void removeAnySubscription(final ConnectableDevice device) { // her protected boolean matchClassAndProperty(String clazz, String property) { return getItemClass().equals(clazz) && getItemProperty().equals(property); } - + protected ResponseListener createDefaultResponseListener() { return new ResponseListener() { @Override public void onError(ServiceCommandError error) { - logger.error("Error setting {}:{}: {}.", getItemClass(), getItemProperty(),error.getMessage()); + logger.error("Error setting {}:{}: {}.", getItemClass(), getItemProperty(), error.getMessage()); } @Override public void onSuccess(O object) { - logger.debug("Successfully set {}:{}: {}.", getItemClass(), getItemProperty(),object); + logger.debug("Successfully set {}:{}: {}.", getItemClass(), getItemProperty(), object); } }; diff --git a/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/ExternalInputControlInput.java b/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/ExternalInputControlInput.java index 5ffc819b202..0683fc113ac 100644 --- a/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/ExternalInputControlInput.java +++ b/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/ExternalInputControlInput.java @@ -46,7 +46,7 @@ public void onReceiveCommand(final ConnectableDevice d, final String clazz, fina control.getExternalInputList(new ExternalInputListListener() { @Override public void onError(ServiceCommandError error) { - logger.error("error requesting channel list: {}.", error.getMessage()); + logger.error("error requesting external input list: {}.", error.getMessage()); } @Override diff --git a/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/MediaControlPlayState.java b/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/MediaControlPlayState.java new file mode 100644 index 00000000000..51c73a6b727 --- /dev/null +++ b/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/MediaControlPlayState.java @@ -0,0 +1,78 @@ +package org.openhab.binding.connectsdk.internal.bridges; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Collection; + +import org.openhab.binding.connectsdk.ConnectSDKBindingProvider; +import org.openhab.core.events.EventPublisher; +import org.openhab.core.library.types.StringType; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.connectsdk.device.ConnectableDevice; +import com.connectsdk.service.capability.MediaControl; +import com.connectsdk.service.capability.MediaControl.PlayStateListener; +import com.connectsdk.service.capability.MediaControl.PlayStateStatus; +import com.connectsdk.service.command.ServiceCommandError; +import com.connectsdk.service.command.ServiceSubscription; +// TODO: somehow this does not work with LG 60UF7709 spotify app or netflix +public class MediaControlPlayState extends AbstractOpenhabConnectSDKPropertyBridge { + private static final Logger logger = LoggerFactory.getLogger(MediaControlPlayState.class); + @Override + protected String getItemClass() { + return "MediaControl"; + } + + @Override + protected String getItemProperty() { + return "playState"; + } + + private MediaControl getControl(final ConnectableDevice device) { + return device.getCapability(MediaControl.class); + } + + @Override + public void onReceiveCommand(final ConnectableDevice d, final String clazz, final String property, Command command) { + + } + + @Override + protected ServiceSubscription getSubscription(final ConnectableDevice device, + final Collection providers, final EventPublisher eventPublisher) { + if (device.hasCapability(MediaControl.PlayState_Subscribe)) { + return getControl(device).subscribePlayState(new PlayStateListener() { + + @Override + public void onError(ServiceCommandError error) { + logger.error("error: {} {} {}", error.getCode(), error.getPayload(), error.getMessage()); + } + + @Override + public void onSuccess(PlayStateStatus status) { + for (ConnectSDKBindingProvider provider : providers) { + for (String itemName : provider.getItemNames()) { + try { + if (matchClassAndProperty(provider.getClassForItem(itemName),provider.getPropertyForItem(itemName)) + && device.getIpAddress().equals( + InetAddress.getByName(provider.getDeviceForItem(itemName)) + .getHostAddress())) { + if (eventPublisher != null) { + eventPublisher.postUpdate(itemName, + new StringType(status.name())); + } + } + } catch (UnknownHostException e) { + logger.error("Failed to resolve {} to IP address. Skipping update on item {}.", + device, itemName); + } + } + } + } + }); + } else return null; + } + +} \ No newline at end of file diff --git a/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/ToastControlToast.java b/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/ToastControlToast.java new file mode 100644 index 00000000000..60195f3ae43 --- /dev/null +++ b/bundles/binding/org.openhab.binding.connectsdk/src/main/java/org/openhab/binding/connectsdk/internal/bridges/ToastControlToast.java @@ -0,0 +1,63 @@ +package org.openhab.binding.connectsdk.internal.bridges; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Base64; +import java.util.Collection; + +import javax.imageio.ImageIO; + +import org.openhab.binding.connectsdk.ConnectSDKBindingProvider; +import org.openhab.core.events.EventPublisher; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.connectsdk.device.ConnectableDevice; +import com.connectsdk.service.capability.ToastControl; +import com.connectsdk.service.command.ServiceSubscription; + +public class ToastControlToast extends AbstractOpenhabConnectSDKPropertyBridge { + private static final Logger logger = LoggerFactory.getLogger(ToastControlToast.class); + + @Override + protected String getItemClass() { + return "ToastControl"; + } + + @Override + protected String getItemProperty() { + return "toast"; + } + + private ToastControl getControl(final ConnectableDevice device) { + return device.getCapability(ToastControl.class); + } + + @Override + public void onReceiveCommand(final ConnectableDevice d, final String clazz, final String property, Command command) { + if (matchClassAndProperty(clazz, property) + && d.hasCapabilities(ToastControl.Show_Toast)) { + final String value = command.toString(); + final ToastControl control = getControl(d); + try { + BufferedImage bi = ImageIO.read(getClass().getResource("/openhab-logo-square.png")); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OutputStream b64 = Base64.getEncoder().wrap(os); + ImageIO.write(bi, "png", b64); + control.showToast(value, os.toString("UTF-8"), "png", createDefaultResponseListener() ); + } catch (IOException ex) { + logger.error(ex.getMessage(), ex); + } + } + } + + @Override + protected ServiceSubscription getSubscription(final ConnectableDevice device, + final Collection providers, final EventPublisher eventPublisher) { + return null; + } + +} \ No newline at end of file