LGWebOS Binding (for LG WebOS TVs)

ok, found in the log on your google drive: “Connect SDK - onServiceRemoved: friendlyName: [LG] webOS TV”

DiscoveryProvider interface defines these constants:

public final static int RESCAN_INTERVAL = 10000;
public final static int RESCAN_ATTEMPTS = 6;
public final static int TIMEOUT = RESCAN_INTERVAL * RESCAN_ATTEMPTS;

So TIMEOUT is set to 60 seconds (or 60 000 Milliseconds). I think one minute and then disconnect corresponds with the time in the log entries.

TIMEOUT is then used in SSDPDiscoveryProvider:

SSDPDiscoveryProvider

@Override
public void start() {
if (isRunning)
return;

    isRunning = true;
    openSocket();
    scanTimer = new Timer();
    scanTimer.schedule(new TimerTask() {
        @Override
        public void run() {
            sendSearch();
        }
    }, 100, RESCAN_INTERVAL);
    responseThread = new Thread(mResponseHandler);
    notifyThread = new Thread(mRespNotifyHandler);
    responseThread.start();
    notifyThread.start();
}
public void sendSearch() {
    List<String> killKeys = new ArrayList<String>();
    long killPoint = new Date().getTime() - TIMEOUT;
    for (String key : foundServices.keySet()) {
        ServiceDescription service = foundServices.get(key);
        if (service == null || service.getLastDetection() < killPoint) {
            killKeys.add(key);
        }
    }
    for (String key : killKeys) {
        final ServiceDescription service = foundServices.get(key);
        if (service != null) {
            notifyListenersOfLostService(service);
        }
        if (foundServices.containsKey(key))
            foundServices.remove(key);
    }
    rescan();
}

So I suspect that service.getLastDetection() < killPoint is true and thus our service gets removed… now the question is, why is the last detection timestamp not updated.

It is supposted to be updated in SSDPDiscoveryProvider handleSSDPPacket. I have now created a version with a log statement added to debug all ssdp packets received. We need at least one packet of type HTTP/1.1 200 OK with a location key in the data map and a matching urn (webos-second-screen:1)… every minute when the TV is on.

Example:

14:52:41.060 [DEBUG] [openhab.binding.connectsdk.Log:23 ] - Connect SDK Socket - Packet received | type = HTTP/1.1 200 OK data = {LOCATION=http://192.168.1.128:1702/, CACHE-CONTROL=max-age=1800, EXT=, USN=uuid:6da62662-1369-a82d-95c7-353c235ed503::urn:lge-com:service:webos-second-screen:1, ST=urn:lge-com:service:webos-second-screen:1, DATE=Sun, 17 Jan 2016 13:52:40 GMT, SERVER=WebOS/4.1.0 UPnP/1.0}

If you do not find this, could you please check if there are maybe any settings on your network that prevents UPnP?

Updated the binding, the problem stays the same, no HTTP/1.1 200 OK found, will check for router settings soon. Log is here.

Hi,

I can’t find any HTTP/1.1 200 OK data messages in the log (after upgrading to your latest binding). I have checked my router and the UPnP settings are enabled. I can also successfully telnet to the UPnP port shown in the logs (2555).
I have uploaded my log here

Ok, that is pretty interesting. We can see the NOTIFY message from your TV. It announces its service and that is why the connection works initially.

But then not a single M-SEARCH for the search target "ST=urn:lge-com:service:webos-second-screen:1"
Like this:
14:56:51.109 [DEBUG] [openhab.binding.connectsdk.Log:23 ] - Connect SDK Socket - Packet received | type = M-SEARCH * HTTP/1.1 data = {ST=urn:lge-com:service:webos-second-screen:1, HOST=239.255.255.250:1900, MAN="ssdp:discover", MX=5}

Connect SDK should normally send this to the broadcast address, but I don’t find it in your logs.
And, thats probably the reason why we never get the 200 OK, response, and thus the timeout.
There are many other M-SEARCH requests in the log, but they are probably stem from other devices on your network.

Maybe the request goes out via the wrong network interface. The code does the following to auto-detect the IP on the network: Inet4Address.getLocalHost().getAddress();
This should hopefully give your IP on the network and not the 127.0.0.1 (loopback)

To verify, can you please run on your commandline:

  1. `hostname
  2. nslookup on whatever result hostname gave you.

example:
sprehn ~/openhab-runtime $ hostname
desktop
sprehn ~/openhab-runtime $ nslookup desktop
Server: 192.168.1.1
Address: 192.168.1.1#53

Name:	desktop.fritz.box
Address: 192.168.1.117

sprehn ~/openhab-runtime $ `

Check your /etc/hosts file if you resolve your hostname to 127.0.0.1 (which should not be the case for this to work).
If this is the problem, then I guess I have to detect this situation in code and/or make the interface configurable.

Success!!!
The hostname was set to 127.0.1.1. I changed this to my raspberrypi static ip, rebooted the pi and it all started working. Loads more logs and can see other devices on my network too.

Nice :smile:

Hi! Finally
Connect SDK Socket - Packet received | type = HTTP/1.1 200 OK data :joy:
and everything works just fine! Was fixed according to your advice, just like @Glenn_Bignell did.
Many thanks! You are awesome!:grinning:

Glad to say all still working well. Maybe add a line about the loopback address in the Binding Configuration section on the other page.

One other thing I am working on is Voice Control. Ideally I want to be able to write a rule to change the input to HDMI_1 and set the volume to a certain level. Do you think this is possible and any pointers on how to achieve? I am able to voice control Switch items OK (only lights in my house at the moment) but can’t workout the TV controls.

Quick update: I managed to get the Input working by using

LG_TV0_Input.sendCommand({“HDMI_1”})

In the rule. Just need to see if the Volume level can be set to a specific level rather than sending up or down commands.

Yes Volume can be set to absolute values. See VolumeControl:volume
However, I learned this only works when you use the internal speakers of the TV. I have a receiver connected and in this case only the up and down control makes sense, as the TV does not know what level of volume the receiver is set to.

btw. I am working on the next version, with improved auto-detection for the network interface. Additionally the local ip will be made configurable via openhab.cfg.

Awesome, wish I had your knowledge to fully understand what i’m doing!!

Can’t believe I missed that one. Rule now working as I want. Voice command switching input and turning the volume down to preset level (I only use the internal speakers).

Finally I found the solution. At the moment the binding is not compatible with java 1.7.
There are 3 problems:

  • android.util.Base64 uses java.util.Base64, which is not available in java 1.7.
  • org.openhab.binding.connectsdk.internal.bridges.ToastControlToast.java uses java.util.Base64, which is not available in java 1.7.
  • com.connectsdk.discovery.DiscoveryManager, Line 369 has to be for (Map.Entry<String, String> entry : devicesList.entrySet()) { instead of
    for (HashMap.Entry<String, String> entry : devicesList.entrySet()) {

For the moment I switched to java 1.8. which is fine for me, but might be not accetable when merging into upstream. I think solving this issues for java 1.7. should not be a problem (more are less you would need to introduce a base64-Encoder for java 7).

I am glad you found the issue. No problem to replace this with javax.xml.bind.DatatypeConverter. This is used also in other bindings, and it comes with standard java, no extra libs required.

You are right. HashMap.Entry is in effect the same as Map.Entry, has HashMap does not override Entry. This is code belongs to the connect sdk library. Since it won’t hurt I’ll leave it as is. I just touch the abosolute necessary, so that we are able to upgrade as LG releases newer versions.

New built - changelog:

  • removed ssdp debugging
  • made localIp configurable and improved auto detection
  • removed java 1.8 dependencies

Thanks for the quick work.
I did a quick test, in the new version toasts are working with java 1.7.

…btw, since I have installed java 1.8 now I decided to stick to it :slight_smile:

Hi again,

finally I have some spare time again to test your binding.
First of all, thanks for adding a check for each TV that there an item configuration for it!

Some more comment advance: do you really need to ship libs httpclient and httpcore? IIRC, openhab already ships these, at least the client in version 4.1.3. Please try in your manifest to simply import e.g. package ‘org.apache.http.client’.
Getting rid of these two libs would decrease your binding size by another 400k :smile:

Hi Sebastian,

i tested the ConnectSDK binding and it works really well.
It would be nice to get the opportunity to set the Icon in Toast Messages, but the other things are working well.
Keep up the good work!

Hi
I am on a business trip right now and cannot code. will test that when I return

yes. thought of this as well. but can anyone give me a hint how this could be achieved via the bus. my only interface is the command received and update received method.

should I add the ability to add icon configuration to an item … and then all toast messages sent to the item are displayed with it.

or interpret some sort of markup in the received value. like. “actual toast text”

or implement as action… never done this. and hope I would be able to include this in the same binding jar

???

I think it would be nice if we could set the icons for every single Mesage, i mean if you get a call than you could display a telephone icon. But if this is not possible it would be nice if we could set a icon for a item at least.

A other thing i noticed is that everytime you turn on the tv you get the message:“Welcome to openHAB!”. It would be nice to set the Message for that for example:“Connected to openHAB” or in a other language like “Verbindung zu openHAB hergestellt”.