Quantcast
Channel: OpenEnergyMonitor aggregator
Viewing all articles
Browse latest Browse all 328

mharizanov: Control LG smart TV over the Internet using a Raspberry Pi

$
0
0

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 :-)

 


Viewing all articles
Browse latest Browse all 328

Trending Articles