Here is a quick home automation project: controlling a LG smart TV over the Internet using a Raspberry Pi computer. There is a Python script already developed for that, so getting all this working was a 5 minute effort. The original script uses graphical UI (hence requires a display attached, or running the script in X), while I wanted to run the commands from the shell. I stripped out the GUI part of the script and was left with this:
#!/usr/bin/env python3 #Full list of commands #http://developer.lgappstv.com/TV_HELP/index.jsp?topic=%2Flge.tvsdk.references.book%2Fhtml%2FUDAP%2FUDAP%2FAnnex+A+Table+of+virtual+key+codes+on+remote+Controller.htm import http.client 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"] = "939781" 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 = "AuthKeyReq" 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 = http.client.HTTPConnection( lgtv["ipaddress"], port=8080) pairCmd = "AuthReq" \ + lgtv["pairingKey"] + "" 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 getPairingKey(): displayKey() def handleCommand(cmdcode): conn = http.client.HTTPConnection( lgtv["ipaddress"], port=8080) cmdText = "" \ + "HandleKeyInput" \ + cmdcode \ + "" conn.request("POST", "/roap/api/command", cmdText, headers=headers) httpResponse = conn.getresponse() #main() lgtv["ipaddress"] = getip() theSessionid = getSessionid() while theSessionid == "Unauthorized" : getPairingKey() theSessionid = getSessionid() if len(theSessionid) < 8 : sys.exit("Could not get Session Id: " + theSessionid) lgtv["session"] = theSessionid #Uncomment the line below the first time to invoke pairing menu #displayKey() result = str(sys.argv[1]) handleCommand(result)
Both the TV and the Raspberry Pi need to be on the same network for this to work. You can then SSH to your Pi from anywhere and remotely control the TV. To pair the Raspberry Pi with the TV, you should run the script:
python3 lg.py
The pairing key will be displayed on the TV , write it in the line that reads:
lgtv["pairingKey"] = "939781"
That’s basically it, now you can use the script by passing a command number as a parameter, the below will switch off the TV:
python3 lg.py 1
Few popular codes:
POWER_OFF=1 3D=400 ARROW_DOWN=2 ARROW_LEFT=3 ARROW_RIGHT=4 BACK=23 BLUE=29 BTN_1=5 BTN_2=6 BTN_3=7 BTN_4=8 CH_DOWN=28 CH_UP=27 ENTER=20 EXIT=412 EXTERNAL_INPUT=47 GREEN=30 HOME=21 MUTE=26 MYAPPS=417 NETCAST=408 PAUSE=34 PLAY=33 PREV_CHANNEL=403 RED=31 STOP=35 VOL_DOWN=25 VOL_UP=24 YELLOW=32
A full list of the command codes is available here
My TV is a 2012 model, the keys may be different for older models. Check the original script for older key codes.
A possible use of this would be to briefly switch TV’s input to the Raspberry Pi upon certain events like showing the picture of the person ringing my doorbell or displaying home automation alerts when my my attention is needed. I can imagine people using the script for pranks as well