Advertisement
Guest User

Kodi plugin test

a guest
Aug 2nd, 2016
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.31 KB | None | 0 0
  1. import xbmc
  2. import xbmcaddon
  3. import xbmcgui
  4. import socket
  5. import httplib
  6. import time
  7. import re
  8.  
  9. #SDK Docs
  10. #http://developer.lgappstv.com/TV_HELP/index.jsp?topic=%2Flge.tvsdk.references.book%2Fhtml%2FUDAP%2FUDAP%2FUDAP+Specifications+For+Second+Screen+TV+and+Companion+Apps.htm
  11.  
  12. # Class to interface with LG TV
  13. class LGRemote:
  14.     # ctor - load settings from kodi
  15.     def __init__(self):
  16.         self.settings = xbmcaddon.Addon(id="script.lg_remote")
  17.         self.settings.getLocalizedString
  18.         self.pairing = self.settings.getSetting("pairing_key")
  19.         self.address = self.settings.getSetting("ip_address")
  20.         self.port = self.settings.getSetting("ip_port")
  21.         if ("" == self.address):
  22.             self.findTV()
  23.        
  24.     # Search the local network for a tv
  25.     # TODO: What if there are multiple TVs?
  26.     def findTV(self):
  27.         UDP_IP = "239.255.255.250"
  28.         UDP_PORT = 1900
  29.         cmd = ("M-SEARCH * HTTP/1.1\r\n"
  30.                 "HOST: 239.255.255.250:1900\r\n"
  31.                 "MAN: \"ssdp:discover\"\r\n"
  32.                 "MX: 3\r\n"
  33.                 "ST: udap:rootservice\r\n"
  34.                 "USER-AGENT: OpenELEC/1.0 UDAP/2.0 Kodi/15\r\n"
  35.                 "\r\n"
  36.             )
  37.         try:
  38.             # Use UDP to find it
  39.             sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  40.             sock.settimeout(1)
  41.             sock.sendto(cmd, (UDP_IP, UDP_PORT))
  42.             data, addr = sock.recvfrom(1024)
  43.             sock.close()
  44.             data = data.split("\r\n")
  45.  
  46.             # TV Found!
  47.             if "HTTP/1.1 200 OK" == data[0]:
  48.                 # Parse out IP address and port
  49.                 def loc(s): return s.startswith("LOCATION")
  50.                 data = filter(loc, data)
  51.                 if 1 == len(data):
  52.                     data = re.split("[\/:]", data[0]);
  53.                     self.address = data[4]
  54.                     self.port = data[5]
  55.                     self.saveSettings()
  56.                     # Pair-up with TV
  57.                     self.sendPairingCode()
  58.             else:
  59.                 self.tvLost()
  60.                    
  61.         except socket.timeout:
  62.             self.tvLost()
  63.  
  64.     # Connection to TV failed
  65.     def tvLost(self):
  66.         # Reset so next call re-fetches data
  67.         self.address = ""
  68.         self.port = 0
  69.         self.saveSettings()
  70.        
  71.     def saveSettings(self):
  72.         self.settings.setSetting("ip_address", self.address)
  73.         self.settings.setSetting("ip_port", str(self.port))
  74.            
  75.     # Send command to TV
  76.     def sendMsg(self, path, msg):
  77.         if ("" == self.address):
  78.             self.findTV()
  79.             if ("" == self.address):
  80.                 return;
  81.  
  82.         httpServ = httplib.HTTPConnection(self.address, self.port, timeout=1)
  83.         headers = {
  84.             "Content-Type": "text/xml; charset=utf-8",
  85.             "Connection": "Close",
  86.             "User-Agent": "OpenELEC/1.0 UDAP/2.0 Kodi/15"
  87.             }
  88.         httpServ.connect()
  89.  
  90.         httpServ.request("POST", "/udap/api/" + path, msg, headers)
  91.         response = httpServ.getresponse()
  92.         if response.status != httplib.OK:
  93.             print("***************ERROR: ", response.read())
  94.             self.tvLost()
  95.  
  96.         httpServ.close()
  97.  
  98.     # Fill in command and parameters of TV message
  99.     def formatMsg(self, cmd, params):
  100.         body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
  101.                 "<envelope>"
  102.                 "<api type=\"{}\">"
  103.                 "{}"
  104.                 "</api>"
  105.                 "</envelope>")
  106.         p = ""
  107.         for key, value in params.items():
  108.             p += "<{}>{}</{}>\n".format(key, value, key)
  109.         return body.format(cmd, p)
  110.    
  111.     # Below are helper functions to send commands
  112.     def showPairingCode(self):
  113.         self.sendMsg("pairing", self.formatMsg("pairing", {"name": "showKey"}))
  114.            
  115.     def sendPairingCode(self):
  116.         # Don't use return port, but I beleive it's required
  117.         self.sendMsg("pairing", self.formatMsg("pairing", {"name": "hello", "value": self.pairing, "port": 6161}))
  118.        
  119.     def endPairing(self):
  120.         self.sendMsg("pairing", self.formatMsg("pairing", {"name": "byebye", "port": 6161}))
  121.  
  122.     def sendKey(self, code):
  123.         self.sendMsg("command", self.formatMsg("command", {"name": "HandleKeyInput", "value": code}))
  124.        
  125.     def volumeUp(self):
  126.         self.sendKey(24)
  127.        
  128.     def volumeDown(self):
  129.         self.sendKey(25)
  130.        
  131.     def mute(self):
  132.         self.sendKey(26)
  133.    
  134.     def power(self):
  135.         self.sendKey(1)
  136.  
  137. # Create a connection
  138. remote = LGRemote()
  139. if (1 == len(sys.argv)):
  140.     # This never gets called. Is there a "Kodi just started up" callback?
  141.     print("****************init")
  142. elif (2 == len(sys.argv)):
  143.     param = sys.argv[1]
  144.     param.upper()
  145.     if ("K" == param):
  146.         # Display pairing code on the TV
  147.         remote.showPairingCode()
  148.     else:
  149.         # Send commands mapped to key presses on remote
  150.         remote.sendPairingCode()
  151.         if ("VU" == param):
  152.             remote.volumeUp()
  153.         elif ("VD" == param):
  154.             remote.volumeDown()
  155.         elif ("M" == param):
  156.             remote.mute()
  157.         elif ("P" == param):
  158.             remote.power()
  159.         #remote.endPairing()    <- apparently not required???
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement