Skip to content

Commit

Permalink
[lgwebos] Detection of power on/off with UPnP
Browse files Browse the repository at this point in the history
Also fix #7119

Signed-off-by: Laurent Garnier <[email protected]>
  • Loading branch information
lolodomo committed Apr 10, 2020
1 parent 8a99893 commit c884e1b
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.smarthome.config.discovery.DiscoveryServiceRegistry;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory;
Expand All @@ -43,17 +44,19 @@ public class LGWebOSHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(LGWebOSHandlerFactory.class);

private final WebSocketClient webSocketClient;

private final DiscoveryServiceRegistry discoveryServiceRegistry;
private final LGWebOSStateDescriptionOptionProvider stateDescriptionProvider;

@Activate
public LGWebOSHandlerFactory(final @Reference WebSocketFactory webSocketFactory,
final @Reference DiscoveryServiceRegistry discoveryServiceRegistry,
final @Reference LGWebOSStateDescriptionOptionProvider stateDescriptionProvider) {
/*
* Cannot use openHAB's shared web socket client (webSocketFactory.getCommonWebSocketClient()) as we have to
* change client settings.
*/
this.webSocketClient = webSocketFactory.createWebSocketClient("lgwebos");
this.discoveryServiceRegistry = discoveryServiceRegistry;
this.stateDescriptionProvider = stateDescriptionProvider;
}

Expand All @@ -66,7 +69,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(THING_TYPE_WEBOSTV)) {
return new LGWebOSHandler(thing, webSocketClient, stateDescriptionProvider);
return new LGWebOSHandler(thing, webSocketClient, discoveryServiceRegistry, stateDescriptionProvider);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.jupnp.model.meta.RemoteDevice;
import org.jupnp.model.types.DeviceType;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -41,6 +42,9 @@ public class LGWebOSUpnpDiscoveryParticipant implements UpnpDiscoveryParticipant

private final Logger logger = LoggerFactory.getLogger(LGWebOSUpnpDiscoveryParticipant.class);

private static final DeviceType UPNP_MEDIARENDERER_DEVICE_TYPE = new DeviceType("schemas-upnp-org", "MediaRenderer",
1);

@Override
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
return SUPPORTED_THING_TYPES_UIDS;
Expand All @@ -58,15 +62,20 @@ public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
.withProperty(PROPERTY_DEVICE_ID, device.getIdentity().getUdn().getIdentifierString())
.withProperty(CONFIG_HOST, device.getIdentity().getDescriptorURL().getHost())
.withLabel(device.getDetails().getFriendlyName())
.withProperty(PROPERTY_MODEL_NAME, device.getDetails().getModelDetails().getModelName())
.withProperty(PROPERTY_MODEL_NAME, device.getDetails().getFriendlyName())
.withProperty(PROPERTY_MANUFACTURER, device.getDetails().getManufacturerDetails().getManufacturer())
.withRepresentationProperty(PROPERTY_DEVICE_ID).withThingType(THING_TYPE_WEBOSTV).build();
}

@Override
public @Nullable ThingUID getThingUID(RemoteDevice device) {
logger.trace("Discovered remote device {}", device);
if (device.findService(UPNP_SERVICE_TYPE) != null) {
if (UPNP_MEDIARENDERER_DEVICE_TYPE.equals(device.getType())
&& device.getDetails().getManufacturerDetails().getManufacturer() != null
&& device.getDetails().getManufacturerDetails().getManufacturer().toUpperCase()
.contains("LG ELECTRONICS")
&& device.getDetails().getModelDetails().getModelDescription() != null
&& device.getDetails().getModelDetails().getModelDescription().toUpperCase().contains("WEBOSTV")) {
logger.debug("Found LG WebOS TV: {}", device);
return new ThingUID(THING_TYPE_WEBOSTV, device.getIdentity().getUdn().getIdentifierString());
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public int getPort() {

@Override
public String toString() {
return "WebOSConfiguration [host=" + host + ", port=" + port + ", key.length=" + getKey().length() + "]";
return "WebOSConfiguration [host=" + getHost() + ", port=" + getPort() + ", key.length=" + getKey().length()
+ "]";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.config.discovery.DiscoveryListener;
import org.eclipse.smarthome.config.discovery.DiscoveryResult;
import org.eclipse.smarthome.config.discovery.DiscoveryService;
import org.eclipse.smarthome.config.discovery.DiscoveryServiceRegistry;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
import org.eclipse.smarthome.core.thing.binding.ThingHandlerService;
import org.eclipse.smarthome.core.types.Command;
Expand Down Expand Up @@ -61,7 +67,8 @@
* @author Sebastian Prehn - initial contribution
*/
@NonNullByDefault
public class LGWebOSHandler extends BaseThingHandler implements LGWebOSTVSocket.ConfigProvider, WebOSTVSocketListener {
public class LGWebOSHandler extends BaseThingHandler
implements LGWebOSTVSocket.ConfigProvider, WebOSTVSocketListener, DiscoveryListener {

/*
* constants for device polling
Expand All @@ -82,21 +89,24 @@ public class LGWebOSHandler extends BaseThingHandler implements LGWebOSTVSocket.
private final Map<String, ChannelHandler> channelHandlers;

private final LauncherApplication appLauncher = new LauncherApplication();

private @Nullable LGWebOSTVSocket socket;
private final WebSocketClient webSocketClient;

private final DiscoveryServiceRegistry discoveryServiceRegistry;
private final LGWebOSStateDescriptionOptionProvider stateDescriptionProvider;

private @Nullable ScheduledFuture<?> reconnectJob;
private @Nullable ScheduledFuture<?> keepAliveJob;

private @Nullable LGWebOSConfiguration config;

private String udn = "";

public LGWebOSHandler(Thing thing, WebSocketClient webSocketClient,
DiscoveryServiceRegistry discoveryServiceRegistry,
LGWebOSStateDescriptionOptionProvider stateDescriptionProvider) {
super(thing);
this.webSocketClient = webSocketClient;
this.discoveryServiceRegistry = discoveryServiceRegistry;
this.stateDescriptionProvider = stateDescriptionProvider;

Map<String, ChannelHandler> handlers = new HashMap<>();
Expand Down Expand Up @@ -138,6 +148,8 @@ public void initialize() {

updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "TV is off");

discoveryServiceRegistry.addDiscoveryListener(this);

startReconnectJob();
}

Expand All @@ -147,6 +159,8 @@ public void dispose() {
stopKeepAliveJob();
stopReconnectJob();

discoveryServiceRegistry.removeDiscoveryListener(this);

LGWebOSTVSocket s = socket;
if (s != null) {
s.setListener(null);
Expand Down Expand Up @@ -322,6 +336,7 @@ public void setOptions(String channelId, List<StateOption> options) {
}

public void postUpdate(String channelId, State state) {
logger.debug("postUpdate channelId {} state {}", channelId, state);
if (isLinked(channelId)) {
updateState(channelId, state);
}
Expand All @@ -336,4 +351,52 @@ public void postUpdate(String channelId, State state) {
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Collections.singleton(LGWebOSActions.class);
}

@Override
public void thingDiscovered(DiscoveryService source, DiscoveryResult result) {
if (THING_TYPE_WEBOSTV.equals(result.getThingTypeUID())) {
Map<String, Object> properties = result.getProperties();
String host = (String) properties.get(CONFIG_HOST);
if (host != null && host.equals(getLGWebOSConfig().getHost())) {
// Thing matching the discovery
logger.debug("thingDiscovered: discovery with UID {} matching thing {}", result.getThingUID(),
getThing().getUID());

channelHandlers.get(CHANNEL_POWER).onDeviceReady(CHANNEL_POWER, this);

// Update the thing properties from the discovery result
Map<String, String> map = new HashMap<>();
String deviceId = (String) properties.get(PROPERTY_DEVICE_ID);
if (deviceId != null && !deviceId.isEmpty()) {
udn = deviceId;
logger.debug("UDN {} considered", udn);
map.put(PROPERTY_DEVICE_ID, deviceId);
}
String manufacturer = (String) properties.get(PROPERTY_MANUFACTURER);
if (manufacturer != null && !manufacturer.isEmpty()) {
map.put(PROPERTY_MANUFACTURER, manufacturer);
}
String modelName = (String) properties.get(PROPERTY_MODEL_NAME);
if (modelName != null && !modelName.isEmpty()) {
map.put(PROPERTY_MODEL_NAME, modelName);
}
storeProperties(map);
}
}
}

@Override
public void thingRemoved(DiscoveryService source, ThingUID thingUID) {
if (!udn.isEmpty() && thingUID.getId().equals(udn)) {
logger.debug("thingRemoved: discovery with UID {} matching thing {}", thingUID, getThing().getUID());
channelHandlers.get(CHANNEL_POWER).onDeviceRemoved(CHANNEL_POWER, this);
}
}

@Override
public @Nullable Collection<ThingUID> removeOlderResults(DiscoveryService source, long timestamp,
@Nullable Collection<ThingTypeUID> thingTypeUIDs, @Nullable ThingUID bridgeUID) {
return null;
}

}

0 comments on commit c884e1b

Please sign in to comment.