LG TV control over Ethernet - here's a possibility?

Questions and comments specific to a particular plugin should go here.
Post Reply
peterhjalmarsson
Posts: 6
Joined: Sun Mar 31, 2013 2:49 pm

LG TV control over Ethernet - here's a possibility?

Post by peterhjalmarsson » Mon May 05, 2014 8:48 pm

I've been looking for a way to control my LG TV from EG; HDMI-CEC seems a no-go since it does not support such basic stuff as switching to Antenna or changing channels. IR is just too messy.

However, I've just found a Python script that claims to be able to do such things over Ethernet, at https://github.com/ubaransel/lgcommander. Being Python, it should be fairly easy(?) to integrate with EG, I presume? I have zero programming experience in neither Python or EG, but the language itself should not be much of a problem (I have learned VBA, C++ and some others over the years). However, creating a EG plugin is, or even using the script from within EG.

Here's some official info about the protocol from LG (search for UDAP) http://developer.lge.com/resource/tv/Re ... ibrary.dev, hopefully that should include the rest of the key codes that are missing from the above link.
[Edit: the key codes are here: http://developer.lgappstv.com/TV_HELP/i ... roller.htm]

Can anyone give me some pointers on where to start, and I can see if I can develop this into a proper plugin, or at least document how it can be run as a script from EG to send commands. Or even better if someone wants to start from the linked script and develop the plugin for the community?
Last edited by peterhjalmarsson on Mon May 05, 2014 11:01 pm, edited 1 time in total.

peterhjalmarsson
Posts: 6
Joined: Sun Mar 31, 2013 2:49 pm

Re: LG TV control over Ethernet - here's a possibility?

Post by peterhjalmarsson » Mon May 05, 2014 10:50 pm

Update: The script ran beautifully on Python 3.0, letting me change to live TV, etc, just like a regular remote.
However, if I try to run it as a script in EG, it hangs on line 3 ("import http.client"), with "Importerror: No module named http.client".

Mucking about further gives me a similar error for line 4 ("from tkinter import *"), but Tk seems to be for scren interactivity, so once I removed those parts of the script, I could remove the whole "tkinter" import as well.

On the other hand, the "xml.etree.ElementTree", "socket", "re", and "sys" imports work fine. Could this be a difference between Python 3 (which the script is written in) and 2.7, which I sem to recall EG is written in? If so, how do I "backport" the http code from "http.client" to "httplib", which I think is used by Python 2.7?

peterhjalmarsson
Posts: 6
Joined: Sun Mar 31, 2013 2:49 pm

Re: LG TV control over Ethernet - here's a possibility?

Post by peterhjalmarsson » Mon May 05, 2014 10:58 pm

Another update: Ooops the http lib thingy was easier than I thought; I just changed the references from "http.client" to "httplib"! With the other changes, here is the result for the time being. Note that if you test it, a box with a code will pop up on the TV screen the first time. Take the code from that box and enter it on line 12 and run the script again.

Code: Select all

#!/usr/bin/env python3

import httplib
# from tkinter import *
import xml.etree.ElementTree as etree
import socket
import re
import sys
lgtv = {}
dialogMsg =""
headers = {"Content-Type": "application/atom+xml"}
lgtv["pairingKey"] = "xxxxxx"

class MyDialog:
    def __init__(self, parent, dialogMsg):
        top = self.top = Toplevel(parent)
        Label(top, text = dialogMsg, justify="left").pack()
        self.e = Entry(top)
        self.e.pack(padx=5)
        self.e.focus_set()
        b = Button(top, text="Ok", command=self.ok)
        b.pack(pady=5)
        top.bind("<Return>", self.ok)
        top.title("Lg Commander")
        top.geometry("410x280+10+10")
    def ok(self,dummy=None):
        global result
        result = self.e.get()
        self.top.destroy()


def getip():
    strngtoXmit =   'M-SEARCH * HTTP/1.1' + '\r\n' + \
                    'HOST: 239.255.255.250:1900'  + '\r\n' + \
                    'MAN: "ssdp:discover"'  + '\r\n' + \
                    'MX: 2'  + '\r\n' + \
                    'ST: urn:schemas-upnp-org:device:MediaRenderer:1'  + '\r\n' +  '\r\n'

    bytestoXmit = strngtoXmit.encode()
    sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
    sock.settimeout(3)
    found = False
    gotstr = 'notyet'
    i = 0
    ipaddress = None
    sock.sendto( bytestoXmit,  ('239.255.255.250', 1900 ) )
    while not found and i <= 5 and gotstr == 'notyet':
        try:
            gotbytes, addressport = sock.recvfrom(512)
            gotstr = gotbytes.decode()
        except:
            i += 1
            sock.sendto( bytestoXmit, ( '239.255.255.250', 1900 ) )
        if re.search('LG', gotstr):
            ipaddress, _ = addressport
            found = True
        else:
            gotstr = 'notyet'
        i += 1
    sock.close()
    if not found : sys.exit("Lg TV not found")
    return ipaddress


def displayKey():
    conn = http.client.HTTPConnection( lgtv["ipaddress"], port=8080)
    reqKey = "<?xml version=\"1.0\" encoding=\"utf-8\"?><auth><type>AuthKeyReq</type></auth>"
    conn.request("POST", "/roap/api/auth", reqKey, headers=headers)
    httpResponse = conn.getresponse()
    if httpResponse.reason != "OK" : sys.exit("Network error")
    return httpResponse.reason


def getSessionid():
    conn = httplib.HTTPConnection( lgtv["ipaddress"], port=8080)
    pairCmd = "<?xml version=\"1.0\" encoding=\"utf-8\"?><auth><type>AuthReq</type><value>" \
            + lgtv["pairingKey"] + "</value></auth>"
    conn.request("POST", "/roap/api/auth", pairCmd, headers=headers)
    httpResponse = conn.getresponse()
    if httpResponse.reason != "OK" : return httpResponse.reason
    tree = etree.XML(httpResponse.read())
    return tree.find('session').text


def handleCommand(cmdcode):
    conn = httplib.HTTPConnection( lgtv["ipaddress"], port=8080)
    cmdText = "<?xml version=\"1.0\" encoding=\"utf-8\"?><command>" \
                + "<name>HandleKeyInput</name><value>" \
                + cmdcode \
                + "</value></command>"
    conn.request("POST", "/roap/api/command", cmdText, headers=headers)
    httpResponse = conn.getresponse()


#main()

lgtv["ipaddress"] = getip()
theSessionid = getSessionid()

if len(theSessionid) < 8 : sys.exit("Could not get Session Id: " + theSessionid)
if theSessionid == "Unauthorized" : sys.exit("Could not get Session Id: " + theSessionid)

lgtv["session"] = theSessionid


dialogMsg =""
for lgkey in lgtv :
    dialogMsg += lgkey + ": " + lgtv[lgkey] + "\n"

dialogMsg += "Success in establishing command session\n"
dialogMsg += "=" * 28 + "\n"
dialogMsg += "Enter command code i.e. a number between 0 and 1024\n"
dialogMsg += "Enter a number greater than 1024 to quit.\n"
dialogMsg += "Some useful codes (not working with 2012 models):\n"
dialogMsg += "for EZ_ADJUST     menu enter   255 \n"
dialogMsg += "for IN START        menu enter   251 \n"
dialogMsg += "for Installation     menu enter   207 \n"
dialogMsg += "for POWER_ONLY mode enter   254 \n"
dialogMsg += "Warning: do not enter 254 if you \ndo not know what POWER_ONLY mode is. "


result = "91"
handleCommand("22")
#while int(result) < 1024:
#    root = Tk()
#    root.withdraw()
#    d = MyDialog(root, dialogMsg)
#    root.wait_window(d.top)
#    handleCommand(result)
Note that the only thing the script can do right now is to bring the OSD menu up on the TV screen (keycode 22 on the 7th line from the bottom of the script). But parameterizing the function should be easy for someone more familiar with EG? Or even converting it to a plugin? Me, I'm off to bed for tonight!

kalia
Experienced User
Posts: 109
Joined: Wed Aug 12, 2009 1:10 am

Re: LG TV control over Ethernet - here's a possibility?

Post by kalia » Tue May 06, 2014 5:38 am

Thank you peterhjalmarsson.

This is a great start. I recently got an LG TV and was thinking about this.

Tested out the code above and was able to successfully get the pairing key.

Thanks,

kalia

peterhjalmarsson
Posts: 6
Joined: Sun Mar 31, 2013 2:49 pm

Re: LG TV control over Ethernet - here's a possibility?

Post by peterhjalmarsson » Wed May 07, 2014 1:18 am

Kalia and anyone else: I have posted a beta version of the plugin over at the development forum, at viewtopic.php?f=10&t=6144. Please check it out, and leave any comments over there. If I understood the "rules" correctly, this forum is for support of existing plugins. I'll start a new post when the plugin is ready for release.

Post Reply