Skip to content
Browse files

xbmc

  • Loading branch information...
1 parent 1a18902 commit f791c4610520764ade59d65dc65c911303d55389 @awentz awentz committed Mar 18, 2013
View
BIN src/python/xmas.sqlite
Binary file not shown.
View
0 src/xmbc/script.module.xmas/LICENSE.txt
No changes.
View
30 src/xmbc/script.module.xmas/addon.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addon
+ id="script.module.xmas"
+ name="Interactive Lighting Controller"
+ version="0.1.0"
+ provider-name="Interactive Lighting">
+ <requires>
+ <import addon="xbmc.python" version="2.1.0"/>
+ <import addon="xbmc.json" version="6.0.0"/>
+ <import addon="xbmc.gui" version="4.0.0"/>
+ <import addon="xbmc.addon" version="12.0.0"/>
+ <import addon="script.module.pysqlite" version="2.5.6"/>
+ <import addon="xbmc.metadata" version="2.1.0"/>
+ </requires>
+ <extension point="xbmc.python.script" library="xmas.py">
+ <provides>executable</provides>
+ </extension>
+ <extension point="xbmc.addon.metadata">
+ <summary lang="en">Adds a light show to your music!</summary>
+ <description lang="en">Created for Senior Design project at SDSMT.</description>
+ <disclaimer>Use at your own risk. Not responsible for electrical mishaps.</disclaimer>
+ <language></language>
+ <platform>all</platform>
+ <license>MIT License</license>
+ <forum></forum>
+ <website></website>
+ <email></email>
+ <source></source>
+ </extension>
+</addon>
View
0 src/xmbc/script.module.xmas/changelog.txt
No changes.
View
BIN src/xmbc/script.module.xmas/fanart.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN src/xmbc/script.module.xmas/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
116 src/xmbc/script.module.xmas/resources/lib/actions.py
@@ -0,0 +1,116 @@
+'''
+ ISY Browser for XBMC
+ Copyright (C) 2012 Ryan M. Kraus
+
+ LICENSE:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ DESCRIPTION:
+ This Python Module contains the variables and functions used by the
+ ISY Browser XBMC Addon to send commands to the ISY API.
+
+ WRITTEN: 11/2012
+'''
+
+import xbmc
+import xbmcgui
+import xbmcaddon
+
+import shared
+import actions as self
+
+# define ISY API actions
+__act_names__ = {
+ 'on': 'NodeOn',
+ 'off': 'NodeOff',
+ 'toggle': 'NodeToggle',
+ 'faston': 'NodeFastOn',
+ 'fastoff': 'NodeFastOff',
+ 'bright': 'NodeBright',
+ 'dim': 'NodeDim',
+ 'on25': 'NodeOn25',
+ 'on50': 'NodeOn50',
+ 'on75': 'NodeOn75',
+ 'on100': 'NodeOn100',
+ 'run': 'ProgramRun',
+ 'then': 'ProgramRunThen',
+ 'else': 'ProgramRunElse'
+ }
+# define local actions
+__act_names_local__ = {
+ 'info': 'ShowNodeInfo',
+ 'config': 'ShowAddonConfig'
+ }
+
+def DoAction(addr, cmd):
+ '''
+ DoAction(addr, cmd)
+
+ DESCRIPTION:
+ This function executes actions on a
+ given address. This is the function
+ that is called by the menu items.
+ '''
+ try:
+ fun = getattr(shared.isy, __act_names__[cmd])
+ except KeyError:
+ fun = getattr(self, __act_names_local__[cmd])
+ fun(addr)
+
+# local actions
+# these are actions that are performed
+# on the nodes that would not be
+# appropriate in the ISY API
+def ShowNodeInfo(addr):
+ '''
+ ShowNodeInfo(addr)
+
+ DESCRIPTION:
+ This action displays node information
+ on the screen.
+ '''
+ data = shared.isy.NodeInfo(addr)
+ name = data.keys()[0]
+ type = data[name][0]
+ status = data[name][2]
+
+ if type=='node':
+ output = name + ' (' + str(int(float(status)/255.0*100.0)) + '%)' + '\n' + shared.translate(33002) + ': ' + str(addr)
+ else:
+ output = name + '\n' + shared.translate(33002) + ': ' + str(addr)
+
+ dialog = xbmcgui.Dialog()
+ ok = dialog.ok(shared.translate(33001),output)
+
+def ShowAddonConfig(addr):
+ '''
+ ShowAddonConfig(addr)
+
+ DESCRIPTION:
+ This action opens the configuration for
+ an XBMC addon on the screen.
+ '''
+ xbmcaddon.Addon(id=addr).openSettings()
+
+def RefreshWindow(*args, **kwargs):
+ '''
+ RefreshWindow(*)
+
+ DESCRIPTION:
+ This function refreshes the active
+ window in XBMC. All inputs are ignored
+ so that it can be called like the
+ other actions that do require input.
+ '''
+ xbmc.executebuiltin('XBMC.Container.Refresh()')
View
57 src/xmbc/script.module.xmas/resources/lib/images.py
@@ -0,0 +1,57 @@
+'''
+ ISY Browser for XBMC
+ Copyright (C) 2012 Ryan M. Kraus
+
+ LICENSE:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ DESCRIPTION:
+ This Python Module contains variables and functions neccessary for
+ handling image requests for the ISY Browser XBMC Addon.
+
+ WRITTEN: 11/2012
+'''
+
+import shared
+
+# define image keys
+__images__ = {
+ 'folder': 'folder_2.png',
+ 'node_on': 'node_on_2.png',
+ 'node_off': 'node_off_2.png',
+ 'node_0': 'node_0.png',
+ 'node_20': 'node_20.png',
+ 'node_40': 'node_40.png',
+ 'node_60': 'node_60.png',
+ 'node_80': 'node_80.png',
+ 'node_100': 'node_100.png',
+ 'group': 'group.png',
+ 'program': 'program_2.png',
+ '__default__': 'DefaultFolder.png'
+ }
+
+def getImage(key):
+ '''
+ getImage(key)
+
+ DESCRIPTION:
+ This function parses an image key and
+ returns the path to the image.
+ '''
+ try:
+ img = shared.__media__ + __images__[key]
+ except:
+ img = __images__['__default__']
+
+ return img
View
255 src/xmbc/script.module.xmas/resources/lib/menus.py
@@ -0,0 +1,255 @@
+
+
+import xbmcgui
+import xbmcplugin
+
+
+
+class ilmenu(object):
+
+ listing = []
+ browsing = None
+ addr = ''
+ handle = -1
+ events_enabled = False
+
+ def __init__(self, handle, browsing, events_enabled, addr):
+ self.browsing = browsing
+ self.addr = addr
+ self.handle = handle
+ self.events_enabled = events_enabled
+
+ if browsing == None:
+ self._createRoot()
+ elif browsing == 'music':
+ self._createNodes()
+ elif browsing == 'light sequences':
+ self._createPrograms()
+
+ def _createRoot(self):
+ '''
+ _createRoot()
+
+ DESCRIPTION:
+ Creates the root directory.
+ '''
+ item = {'name': shared.translate(34001),
+ 'browsing': 'music',
+ 'node_type': 'folder',
+ 'context_menu': [],
+ 'image_key': 'folder',
+ 'node_addr': None,
+ 'node_action': None,
+ 'node_parent': None}
+ self.listing.append(item)
+ item = {'name': shared.translate(34002),
+ 'browsing': 'light sequences',
+ 'node_type': 'folder',
+ 'context_menu': [],
+ 'image_key': 'folder',
+ 'node_addr': None,
+ 'node_action': None,
+ 'node_parent': None}
+ self.listing.append(item)
+
+ if self.events_enabled:
+ item = {'name': shared.translate(34003),
+ 'browsing': None,
+ 'node_type': 'builtin',
+ 'context_menu': [],
+ 'image_key': 'folder',
+ 'node_addr': 'service.script.isyevents',
+ 'node_action': 'config',
+ 'node_parent': None}
+ self.listing.append(item)
+
+ def _createMusic(self):
+ '''
+ _createNodes()
+
+ DESCRIPTION:
+ Creates a menu displaying nodes and
+ folders of nodes.
+ '''
+ # get isy nodes
+ nodes = shared.isy.BrowseNodes(self.addr)
+
+ # assemble listing
+ for name in nodes.keys():
+ # pull node basic data
+ type = nodes[name][0]
+ child = nodes[name][1]
+ parent = self.addr
+
+ # compile the image key and action commands
+ image = type
+ action = None
+ if type == 'node':
+ action = 'toggle'
+ status = max([0, float(nodes[name][2])]) / 255.0 * 100
+ if status == 0:
+ image += '_0'
+ elif status < 20:
+ image += '_20'
+ elif status < 40:
+ image += '_40'
+ elif status < 60:
+ image += '_60'
+ elif status < 80:
+ image += '_80'
+ else:
+ image += '_100'
+ elif type == 'group':
+ action = 'on'
+
+ # compile the context menu
+ context = createContext(type != 'folder', type == 'node', type =='node', False)
+
+ self.listing.append({'name': name,
+ 'image_key': image,
+ 'node_addr': child,
+ 'node_type': type,
+ 'node_action': action,
+ 'node_parent': parent,
+ 'context_menu': context,
+ 'browsing': 'nodes'})
+
+ def _createLS(self):
+ '''
+ _createPrograms()
+
+ DESCRIPTION:
+ Creates a menu containing programs and
+ folders containing programs.
+ '''
+ # get isy programs
+ nodes = shared.isy.BrowsePrograms(self.addr)
+
+ # assemble listing
+ for name in nodes.keys():
+ # pull node basic data
+ type = nodes[name][0]
+ child = nodes[name][1]
+ parent = self.addr
+
+ # compile the image key and action commands
+ image = type
+ action = None
+ if type=='program':
+ action = 'run'
+
+ # compile the context menu
+ context = createContext(False, False, False, type != 'folder')
+
+ self.listing.append({'name': name,
+ 'image_key': image,
+ 'node_addr': child,
+ 'node_type': type,
+ 'node_action': action,
+ 'node_parent': parent,
+ 'context_menu': context,
+ 'browsing': 'programs'})
+
+ def sendToXbmc(self):
+ '''
+ sendToXbmc()
+
+ DESCRIPTION:
+ Sends the menu to XBMC.
+ '''
+ for item in self.listing:
+ # create item to add to menu
+ icon = images.getImage(item['image_key'])
+ listItem = xbmcgui.ListItem(item['name'], iconImage=icon)
+
+ # assemble link url
+ params = shared.__params__
+ params['addr'] = item['node_addr']
+ params['type'] = item['node_type']
+ params['cmd'] = item['node_action']
+ params['parent'] = item['node_parent']
+ params['browsing'] = item['browsing']
+ url = urls.CreateUrl(shared.__path__, **params)
+
+ # create the item's context menu
+ context = []
+ for context_item in item['context_menu']:
+ context_url = urls.CreateUrl(
+ shared.__path__,
+ addr=item['node_addr'],
+ type=item['node_type'],
+ cmd=context_item[1],
+ parent=item['node_parent'])
+ context.append((context_item[0], 'XBMC.RunPlugin(' + context_url + ')'))
+
+ listItem.addContextMenuItems(context, replaceItems=True)
+
+ # add item to menu
+ xbmcplugin.addDirectoryItem(
+ handle=self.handle,
+ url=url,
+ listitem=listItem,
+ isFolder=item['node_action']==None)
+
+ def show(self):
+ '''
+ show()
+
+ DESCRIPTION:
+ Shows the menu on the screen.
+ '''
+ xbmcplugin.endOfDirectory(handle=self.handle, updateListing=False, cacheToDisc=False)
+
+def createContext(onoff=False, toggle=False, dim=False, run=False):
+ '''
+ createContext(onoff, dim, run)
+
+ DESCRIPTION:
+ Creates a context menu for a menu item.
+ There are four sections to a context menu
+ that can be toggled by input. There is the
+ On/Off section, the Dim Controls section,
+ the Program Run section, and the Show Info
+ section.
+ '''
+ # max items = 10
+ menu = []
+
+ if onoff:
+ new_items = [
+ (shared.translate(32001), 'on'),
+ (shared.translate(32002), 'off'),
+ (shared.translate(32004), 'faston'),
+ (shared.translate(32005), 'fastoff')]
+ for item in new_items:
+ menu.append(item)
+
+ if toggle:
+ new_items = [
+ (shared.translate(32003), 'toggle')]
+ for item in new_items:
+ menu.append(item)
+
+ if dim:
+ new_items = [
+ #(shared.translate(32006), 'bright'),
+ #(shared.translate(32007), 'dim'),
+ (shared.translate(32008), 'on25'),
+ (shared.translate(32009), 'on50'),
+ (shared.translate(32010), 'on75'),
+ (shared.translate(32011), 'on100')]
+ for item in new_items:
+ menu.append(item)
+
+ if run:
+ new_items = [
+ (shared.translate(32013), 'run'),
+ (shared.translate(32014), 'then'),
+ (shared.translate(32015), 'else'),
+ (shared.translate(32016), 'info')]
+ for item in new_items:
+ menu.append(item)
+
+ menu.append((shared.translate(32012), 'info'))
+
+ return menu
View
349 src/xmbc/script.module.xmas/resources/lib/pyisy.py
@@ -0,0 +1,349 @@
+'''
+ PyISY
+ Copyright (C) 2012 Ryan M. Kraus
+
+ LICENSE:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ DESCRIPTION:
+ This Python Module is designed to interface directly with the REST
+ API interface of the ISY-99 Series of Home Automation Controllers
+ from Universal Devices Incorporated.
+
+ WRITTEN: 11/2012
+'''
+
+import urllib2
+import urllib
+from xml.dom.minidom import parseString
+
+def open(user, password, host='isy', port='80', usehttps=False):
+ out = isy(user, password, host, port, usehttps)
+ if not out.Ping():
+ out = dummy()
+
+ return out
+
+class isy(object):
+ __x10__ = { \
+ 'all_off': 1, \
+ 'all_on': 4, \
+ 'on': 3, \
+ 'off': 11, \
+ 'bright': 7, \
+ 'dim': 15 \
+ }
+
+ __dummy__ = False
+
+ def __init__(self, user, password, host='isy', port='80', usehttps=False):
+ self._user = user
+ self._password = password
+ self._host = host
+ self._port = port
+ self._usehttps = usehttps
+
+ self.Connect()
+
+ def Connect(self):
+ # create connection to ISY
+ url = self._BaseURL()
+ passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
+ passman.add_password(None, url, self._user, self._password)
+ authhandler = urllib2.HTTPBasicAuthHandler(passman)
+ opener = urllib2.build_opener(authhandler)
+ urllib2.install_opener(opener)
+
+ def Ping(self):
+ try:
+ theurl = self._BaseURL() + 'rest/nodes/'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ self._SendRequest(theurl)
+ return True
+ except urllib2.URLError:
+ return False
+
+ def _BaseURL(self):
+ if self._usehttps:
+ url = 'https://'
+ else:
+ url = 'http://'
+ url += self._host + ':' + str(self._port) + '/'
+ return url
+
+ def _SendRequest(self, url):
+ try:
+ pagehandle = urllib2.urlopen(url)
+ except urllib2.HTTPError:
+ self.Connect()
+ pagehandle = urllib2.urlopen(url)
+
+ data = pagehandle.read()
+ pagehandle.close()
+ return data
+
+ def _ParseNodeXML(self, data, return_node=None, return_parent=None):
+ dom = parseString(data)
+ node_types = ['folder', 'node', 'group']
+ child_dict = {}
+ for ntype in node_types:
+ nodes = dom.getElementsByTagName(ntype)
+ for node in nodes:
+ parent = node.getElementsByTagName('parent')
+ if len(parent) == 0:
+ paddr = None
+ else:
+ paddr = parent[0].toxml().replace('<parent type="1">','').replace('<parent type="3">','').replace('</parent>','')
+
+ if (return_node!=None) or (return_parent==paddr):
+ name = node.getElementsByTagName('name')[0].toxml().replace('<name>','').replace('</name>','')
+ addr = node.getElementsByTagName('address')[0].toxml().replace('<address>','').replace('</address>','')
+ properties = node.getElementsByTagName('property')
+ if len(properties)>0:
+ status = properties[0].toxml().split('"')
+ val_ind = status.index(' value=')+1
+ status = status[val_ind]
+ else:
+ status = '0'
+
+ if (return_node==None) or (addr in [return_node, return_node.replace('%20', ' ')]):
+ child_dict[name] = (ntype, addr, status)
+
+ return child_dict
+
+ def _ParseProgramXML(self, data, return_node=None, return_parent=None):
+ # read file
+ dom = parseString(data)
+ # look for children of addr
+ ntype = 'program'
+ child_dict = {}
+ nodes = dom.getElementsByTagName(ntype)
+ for node in nodes:
+ name = node.getElementsByTagName('name')[0].toxml().replace('<name>','').replace('</name>','')
+ properties = node.toxml().split('"')
+ new_addr_ind = properties.index(' id=')+1
+ new_addr = properties[new_addr_ind]
+ try:
+ properties.index('<program enabled=')
+ type = 'program'
+ except ValueError:
+ type ='folder'
+
+ if (return_parent==None) or (new_addr!=return_parent):
+ if (return_node==None) or (new_addr==return_node):
+ child_dict[name] = (type, new_addr)
+
+ return child_dict
+
+ def NodeOn(self, addr, val=None):
+ theurl = self._BaseURL() + 'rest/nodes/' + addr + '/cmd/DON'
+ if val != None:
+ if val > 255:
+ val = 255
+ if val < 0:
+ val = 0
+ theurl += '/' + str(int(val))
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ self._SendRequest(theurl)
+
+ def NodeOn25(self, addr):
+ self.NodeOn(addr, 25*255/100)
+
+ def NodeOn50(self, addr):
+ self.NodeOn(addr, 50*255/100)
+
+ def NodeOn75(self, addr):
+ self.NodeOn(addr, 75*255/100)
+
+ def NodeOn100(self, addr):
+ self.NodeOn(addr, 100*255/100)
+
+ def NodeOff(self, addr):
+ theurl = self._BaseURL() + 'rest/nodes/' + addr + '/cmd/DOF'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ self._SendRequest(theurl)
+
+ def NodeToggle(self, addr):
+ # get node information
+ info = self.NodeInfo(addr)
+
+ if len(info.keys()) > 0:
+ # parse node information
+ NodeName = info.keys()[0]
+ NodeValue = int(info[NodeName][2])
+
+ # decide on action
+ if NodeValue > 0:
+ self.NodeOff(addr)
+ else:
+ self.NodeOn(addr)
+
+ return True
+ else:
+ return False
+
+ def NodeFastOn(self, addr):
+ theurl = self._BaseURL() + 'rest/nodes/' + addr + '/cmd/DFON'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ self._SendRequest(theurl)
+
+ def NodeFastOff(self, addr):
+ theurl = self._BaseURL() + 'rest/nodes/' + addr + '/cmd/DFOF'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ self._SendRequest(theurl)
+
+ def NodeBright(self, addr):
+ theurl = self._BaseURL() + 'rest/nodes/' + addr + '/cmd/BRT'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ self._SendRequest(theurl)
+
+ def NodeDim(self, addr):
+ theurl = self._BaseURL() + 'rest/nodes/' + addr + '/cmd/DIM'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ self._SendRequest(theurl)
+
+ def NodeInfo(self, addr):
+ theurl = self._BaseURL() + 'rest/nodes/' + addr.replace(' ', '%20')
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ data = self._SendRequest(theurl)
+ # parse response
+ node = self._ParseNodeXML(data, return_node=addr)
+ return node
+
+ def BrowseNodes(self, addr = None):
+ theurl = self._BaseURL() + 'rest/nodes/'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ data = self._SendRequest(theurl)
+ children = self._ParseNodeXML(data, return_parent=addr)
+ return children
+
+ def X10cmd(self, addr, cmd):
+ theurl = self._BaseURL() + 'rest/X10/' + addr + '/' + self.__x10__[cmd]
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ self._SendRequest(theurl)
+
+ def BrowsePrograms(self, addr='0001'):
+ theurl = self._BaseURL() + 'rest/programs/'
+ if addr == None or addr=='':
+ addr = '0001'
+ theurl += addr.replace(' ', '%20')
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ data = self._SendRequest(theurl)
+ programs = self._ParseProgramXML(data, return_parent=addr)
+ return programs
+
+ def ProgramRun(self, addr):
+ theurl = self._BaseURL() + 'rest/programs/' + addr + '/run'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ data = self._SendRequest(theurl)
+
+ def ProgramRunThen(self, addr):
+ theurl = self._BaseURL() + 'rest/programs/' + addr + '/runThen'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ data = self._SendRequest(theurl)
+
+ def ProgramRunElse(self, addr):
+ theurl = self._BaseURL() + 'rest/programs/' + addr + '/runElse'
+ #normalize the URL
+ theurl = urllib.quote(theurl, safe="%/:=&?~#+!$,;'@()*[]")
+ data = self._SendRequest(theurl)
+
+class dummy(object):
+
+ __dummy__ = True
+
+ def __init__(self, *kargs, **kwargs):
+ pass
+
+ def Connect(self):
+ pass
+
+ def Ping(self):
+ return True
+
+ def NodeOn(self, *kargs, **kwargs):
+ pass
+
+ def NodeOn25(self, *kargs, **kwargs):
+ pass
+
+ def NodeOn50(self, *kargs, **kwargs):
+ pass
+
+ def NodeOn75(self, *kargs, **kwargs):
+ pass
+
+ def NodeOn100(self, *kargs, **kwargs):
+ pass
+
+ def NodeOff(self, *kargs, **kwargs):
+ pass
+
+ def NodeToggle(self, *kargs, **kwargs):
+ pass
+
+ def NodeFastOn(self, *kargs, **kwargs):
+ pass
+
+ def NodeFastOff(self, *kargs, **kwargs):
+ pass
+
+ def NodeBright(self, *kargs, **kwargs):
+ pass
+
+ def NodeDim(self, *kargs, **kwargs):
+ pass
+
+ def NodeInfo(self, addr):
+ return {'Dummy Node ' + str(addr):
+ ('node', addr, '255')}
+
+ def BrowseNodes(self, addr=None):
+ if addr==None:
+ nodes = {'Dummy Room 1': ('folder', '1', '0'),
+ 'Dummy Room 2': ('folder', '2', '0')}
+ elif int(addr)==1:
+ nodes = {'Dummy Switch 3': ('node', '3', '255')}
+ elif int(addr)==2:
+ nodes = {'Dummy Switch 4': ('node', '4', '255')}
+
+ return nodes
+
+ def X10cmd(self, *kargs, **kwargs):
+ pass
+
+ def BrowsePrograms(self, addr='0001'):
+ return {'Dummy Program 2': ('program', '2', '0')}
+
+ def ProgramRun(self, *kargs, **kwargs):
+ pass
+
+ def ProgramRunThen(self, *kargs, **kwargs):
+ pass
+
+ def ProgramRunElse(self, *kargs, **kwargs):
+ pass
View
94 src/xmbc/script.module.xmas/resources/lib/shared.py
@@ -0,0 +1,94 @@
+'''
+ ISY Browser for XBMC
+ Copyright (C) 2012 Ryan M. Kraus
+
+ LICENSE:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ DESCRIPTION:
+ This Python Module contains functions and variables that are
+ globally interesting to the ISY Browser XBMC addon.
+
+ WRITTEN: 11/2012
+'''
+# IMPORTS
+# xbmc
+import xbmc
+import xbmcaddon
+# custom
+import shared as self
+import pyisy
+import urls
+
+# addon classes
+events = None
+browser = None
+
+# connection to ISY controller
+isy = None
+
+# runtime parameters
+__path__ = ''
+__params__ = {}
+__id__ = -1
+
+# function shortcuts
+translate = None
+def events_enabled(): return events!=None
+
+# common paths
+__media__ = ''
+__lib__ = ''
+
+def initialize(args):
+ '''
+ initialize(args)
+
+ DESCRIPTION:
+ This function initialize the shared variable library.
+ The only input to this function is the program's
+ system arguments. There is no output.
+ '''
+ # check if events is available
+ try:
+ self.events = xbmcaddon.Addon('service.script.isyevents')
+ except:
+ self.events = None
+
+ # get this addon
+ self.browser = xbmcaddon.Addon('plugin.program.isybrowse')
+
+ # get plugin information
+ self.__path__ = args[0]
+ self.__id__ = int(args[1])
+ self.__params__ = urls.ParseUrl(args[2])['params']
+ self.translate = self.browser.getLocalizedString
+
+ # get common file paths
+ self.__media__ = self.browser.getAddonInfo('path') + '/resources/media/'
+ self.__lib__ = self.browser.getAddonInfo('path') + '/resources/lib/'
+
+ # connect to isy
+ username = self.browser.getSetting('username')
+ password = self.browser.getSetting('password')
+ host = self.browser.getSetting('host')
+ port = int(self.browser.getSetting('port'))
+ usehttps = self.browser.getSetting('usehttps') == 'true'
+ self.isy = pyisy.open(username, password, host, port, usehttps)
+
+ # verify isy opened correctly
+ if self.isy.__dummy__:
+ header = self.translate(35001)
+ message = self.translate(35002)
+ xbmc.executebuiltin('Notification(' + header + ',' + message + ', 15000)')
View
97 src/xmbc/script.module.xmas/resources/lib/urls.py
@@ -0,0 +1,97 @@
+'''
+ ISY Browser for XBMC
+ Copyright (C) 2012 Ryan M. Kraus
+
+ LICENSE:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ DESCRIPTION:
+ This Python Module contains functions for parsing and creating
+ XBMC Addon URLs.
+
+ WRITTEN: 11/2012
+'''
+
+# define default params
+__params__ = {
+ 'addr': None,
+ 'type': None,
+ 'cmd': None,
+ 'parent': None,
+ 'browsing': None
+ }
+
+def ParseUrl(url):
+ '''
+ ParseUrl(url)
+
+ DESCRIPTION:
+ This function reads a URL containing GET data and
+ seperates the path and each parameter. The input is
+ a string containing the URL and the output is a
+ dictionary with two keys, path and params. The params
+ entry contains a dictionary with an entry for each
+ parameter where the keys are the parameter names.
+ '''
+ # initialize
+ output = {}
+ url = url.split('?')
+
+ # store path
+ output['path'] = url[0]
+
+ # parse parameters
+ output['params'] = {}
+ if len(url)>1:
+ params = url[1].split('&')
+ for param in params:
+ param = param.split('=')
+ p_name = param[0].strip()
+ if len(param) > 0:
+ p_val = param[1].strip()
+ else:
+ p_val = ''
+ output['params'][p_name] = p_val
+
+ # set undefined params to default
+ for key in __params__.keys():
+ if key not in output['params'].keys():
+ output['params'][key] = __params__[key]
+
+ return output
+
+def CreateUrl(base, **params):
+ '''
+ CreateUrl(base, **params)
+
+ DESCRIPTION:
+ This function encodes GET data in a URL. The first
+ input is the base path. The rest of the inputs
+ should be input by name. The name used for input
+ will be the name assigned in the URL. The output
+ will be the complete URL.
+ '''
+ url = base
+ first = True
+
+ for param in params.keys():
+ if params[param] != None:
+ if first:
+ url += '?'
+ first = False
+ else:
+ url += '&'
+ url += param + '=' + str(params[param])
+
+ return url
View
10 src/xmbc/script.module.xmas/resources/settings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<settings>
+ <category label="31000">
+ <setting label="31001" type="text" id="command server" default="http://107.22.230.121"/>
+ <setting label="31002" type="text" id="port" default="5000"/>
+ <setting type="sep"/>
+ <setting label="31003" type="text" id="channel server" default="http://107.22.230.121"/>
+ <setting label="31004" type="text" id="port" default="50000"/>
+ </category>
+</settings>
View
87 src/xmbc/script.module.xmas/xmas.py
@@ -0,0 +1,87 @@
+import xbmc
+import xbmcgui
+import httplib2
+import json
+import serial
+import time
+#get actioncodes from https://github.com/xbmc/xbmc/blob/master/xbmc/guilib/Key.h
+ACTION_PREVIOUS_MENU = 10
+ACTION_SELECT_ITEM = 7
+ACTION_MOUSE_LEFT_CLICK = 100
+ACTION_MOUSE_RIGHT_CLICK = 101
+pb = 0x7D #pad byte
+sb = 0x7E #sync byte
+cb = 0x80 #command byte
+pad_offset = 100
+
+#url with ip address and port to access web service
+oscuri = 'http://107.22.230.121:50000/'
+
+h = httplib2.Http()
+
+def getlightvals():
+ resp, content = h.request(oscuri)
+ lightvals = []
+ if resp['status'] == '200':
+ lightvals = json.loads(content)
+ return lightvals
+
+
+def special_replace(n):
+ if n == 0x7D:
+ return 0x7C
+ elif n == 0x7E:
+ return 0x7C
+ elif n == 0x7F:
+ return 0x80
+ else:
+ return n
+
+def package_bytes(light_values, channels):
+ """Packages the light dimming values into a readable format for the renard controller"""
+ pv = map(special_replace, light_values)
+ #insert a pad byte every pad_offset byte
+ if len(pv) > pad_offset:
+ for i in range(pad_offset, len(pv), pad_offset):
+ pv.insert(i, pb)
+
+ if len(pv) > channels:
+ a = len(pv) - (len(pv) % channels)
+ for i in range(a, 0, -channels):
+ pv.insert(i,cb)
+ pv.insert(i,sb)
+
+ pv.insert(0, cb)
+ pv.insert(0, sb)
+
+ return pv
+
+
+
+class MyClass(xbmcgui.Window):
+ def __init__(self):
+ self.strActionInfo = xbmcgui.ControlLabel(100, 120, 200, 200, '', 'font13', '0xFFFF00FF')
+ self.addControl(self.strActionInfo)
+ self.strActionInfo.setLabel('Push BACK to quit - A to reset text')
+ self.strActionFade = xbmcgui.ControlFadeLabel(100, 300, 500, 200, 'font13', '0xFFFFFF00')
+ self.addControl(self.strActionFade)
+ self.strActionFade.addLabel(str(getlightvals()))
+ self.serport = serial.Serial('COM7', '57600', timeout=2)
+
+
+ def onAction(self, action):
+ if action == ACTION_PREVIOUS_MENU:
+ self.serport.close()
+ self.close()
+ if action == ACTION_SELECT_ITEM:
+ self.strActionFade.reset()
+ self.strActionFade.addLabel(str(getlightvals()))
+ while True:
+ self.lvals = getlightvals()
+ self.plvals = package_bytes(self.lvals, 32)
+ self.serport.write(bytearray(self.plvals))
+ time.sleep(0.1)
+
+mydisplay = MyClass()
+mydisplay .doModal()
+del mydisplay
View
0 src/xmbc/script.service.xmas/LICENSE.txt
No changes.
View
29 src/xmbc/script.service.xmas/addon.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addon
+ id="script.service.xmas"
+ name="Interactive Lighting Service"
+ version="0.1.0"
+ provider-name="Interactive Lighting">
+ <requires>
+ <import addon="xbmc.python" version="2.1.0"/>
+ <import addon="xbmc.json" version="6.0.0"/>
+ <import addon="xbmc.gui" version="4.0.0"/>
+ <import addon="xbmc.addon" version="12.0.0"/>
+ <import addon="script.module.pysqlite" version="2.5.6"/>
+ <import addon="script.module.xmas" version="0.1.0"/>
+ <import addon="xbmc.metadata" version="2.1.0"/>
+ </requires>
+ <extension point="xbmc.service" library="lightservice.py" start="startup"/>
+ <extension point="xbmc.addon.metadata">
+ <summary lang="en">Interactive Lighting Service</summary>
+ <description lang="en">Created for Senior Design project at SDSMT.</description>
+ <disclaimer>Use at your own risk. Not responsible for electrical mishaps.</disclaimer>
+ <language></language>
+ <platform>all</platform>
+ <license>MIT License</license>
+ <forum></forum>
+ <website></website>
+ <email></email>
+ <source></source>
+ </extension>
+</addon>
View
0 src/xmbc/script.service.xmas/changelog.txt
No changes.
View
BIN src/xmbc/script.service.xmas/fanart.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN src/xmbc/script.service.xmas/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
51 src/xmbc/script.service.xmas/resources/lib/event_actions.py
@@ -0,0 +1,51 @@
+'''
+ ISY Event Engine for XBMC (event_actions)
+ Copyright (C) 2012 Ryan M. Kraus
+
+ LICENSE:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ DESCRIPTION:
+ This Python Module translates the action names into functions for the
+ ISY Events addon for XBMC.
+
+ WRITTEN: 11/2012
+'''
+
+# dictionary to translate actions
+__act_names__ = {
+ 'On': 'NodeOn',
+ 'Off': 'NodeOff',
+ 'Toggle': 'NodeToggle',
+ 'Fast On': 'NodeFastOn',
+ 'Fast Off': 'NodeFastOff',
+ 'Bright': 'NodeBright',
+ 'Dim': 'NodeDim',
+ 'On To 25%': 'NodeOn25',
+ 'On To 50%': 'NodeOn50',
+ 'On To 75%': 'NodeOn75',
+ 'On To 100%': 'NodeOn100',
+ 'Run': 'ProgramRun',
+ 'Run Then': 'ProgramRunThen',
+ 'Run Else': 'ProgramRunElse'
+ }
+
+def ParseActionSettings(isy, addr, action):
+ if addr == '':
+ return None
+ elif action == 'None':
+ return None
+ else:
+ fun = getattr(isy, __act_names__[action])
+ return lambda: fun(addr)
View
35 src/xmbc/script.service.xmas/resources/lib/log.py
@@ -0,0 +1,35 @@
+'''
+ ISY Event Engine for XBMC (log)
+ Copyright (C) 2012 Ryan M. Kraus
+
+ LICENSE:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ DESCRIPTION:
+ This Python Module logs messages for the XBMC addon, ISY Events.
+
+ WRITTEN: 11/2012
+'''
+
+# imports
+# xbmc
+import xbmcaddon
+
+# get translator function
+self = xbmcaddon.Addon('service.script.isyevents')
+translator = self.getLocalizedString
+
+# function to record messages to log
+def log(msg):
+ print translator(33001) + msg
View
99 src/xmbc/script.service.xmas/resources/lib/myCollections.py
@@ -0,0 +1,99 @@
+'''
+ myCollections
+ Copyright (C) 2012 Ryan M. Kraus
+
+ LICENSE:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ DESCRIPTION:
+ This Python Module contains different data types that perform basic
+ functions to assist outside programs.
+
+ WRITTEN: 11/2012
+'''
+
+class histlist(object):
+ '''
+ histlist
+
+ The history list (histlist) is a list that tracks the history of a
+ value. The history list can also notify when the value is changed,
+ This is referred to as a step. There are two kinds of steps that can
+ be tracked. A regular step (value is changed) and a delayed step. A
+ delayed step requires that the value be changed a specified amount of
+ consecutive times.
+
+ On initialization, the hist list class requires either a set of initial
+ conditions of a single value that will be set for all the initial
+ conditions. If a single value is given, 4 steps of history will be
+ tracked. If initial conditions are given, one step will be tracked for
+ each entry in the array of initial conditions.
+ '''
+
+ __min_size__ = 4
+
+ def __init__(self, IC):
+ # create initial states
+ if type(IC) == int or type(IC) == float or type(IC) == bool:
+ # single value input, spread across all IC's
+ self.state = list()
+ self.state = [IC for ind in range(self.__min_size__)]
+
+ elif type(IC) == list or type(IC) == tuple:
+ # IC set was input
+ IC = list(IC)
+ if len(IC) < self.__min_size__:
+ raise ValueError('Input must be of at least length ' + str(self.__min_size__))
+ else:
+ self.state = IC
+
+ else:
+ raise ValueError('Input must be of type bool, int, float, list, or tuple')
+
+ self.__len__ = len(self.state)
+
+ def set(self, val):
+ self.state = [val] + [self.state[ind] for ind in xrange(0, self.__len__-1, 1)]
+
+ def get(self, step=0):
+ return self.state[step]
+
+ def __str__(self):
+ return "histlist(" + str(self.state) + ")"
+
+ def __iter__(self):
+ return self.state.__iter__()
+
+ def step(self):
+ return self.get(0) != self.get(1)
+
+ def delayed_step(self, inc=2):
+ step = True
+ ind = 1
+ while step and ind <= inc:
+ step = step and (self.get(ind-1) != self.get(ind))
+ ind += 1
+ return step
+
+ def step_on(self):
+ return self.step() and (self.get(0) > 0)
+
+ def delayed_step_on(self, inc=2):
+ return self.delayed_step(inc) and (self.get(0) > 0)
+
+ def step_off(self):
+ return self.step() and (self.get(0) == 0)
+
+ def delayed_step_off(self, inc=2):
+ return self.delayed_step(inc) and (self.get(0) == 0)
View
145 src/xmbc/script.service.xmas/resources/lib/xb_events.py
@@ -0,0 +1,145 @@
+'''
+ ISY Event Engine for XBMC (xb_events)
+ Copyright (C) 2012 Ryan M. Kraus
+
+ LICENSE:
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ DESCRIPTION:
+ This Python Module contains the event engine used by the
+ XBMC addon, ISY Events.
+
+ WRITTEN: 11/2012
+'''
+
+# imports
+# xbmc
+import xbmc
+# custom
+import myCollections as mc
+from log import log
+
+class xbmcEvents(object):
+ # settings
+ _wait = 0.5
+
+ # event definitions
+ _events = {'onStart': [], \
+ 'onQuit': [], \
+ 'onPlayMovie': [], \
+ 'onPlayMusic': [], \
+ 'onStopMovie': [], \
+ 'onStopMusic': [], \
+ 'onPauseMovie': [], \
+ 'onPauseMusic': [], \
+ 'onResumeMovie': [], \
+ 'onResumeMusic':[]}
+
+ # current status
+ _playingMovie = mc.histlist(False)
+ _playingMusic = mc.histlist(False)
+ _time = mc.histlist(-1.0)
+ _paused = mc.histlist(False)
+
+ def __init__(self):
+ pass
+
+ def ListEvents(self):
+ return self._events.keys()
+
+ def AddHandler(self, event, fun):
+ if fun != None:
+ if event in self._events.keys():
+ self._events[event].append(fun)
+ return len(self._events[event])-1
+ else:
+ raise InvalidEventName(event)
+
+ def AddHandlers(self, events):
+ for event in events.keys():
+ self.AddHandler(event, events[event])
+
+ def RemoveHandler(self, event, id):
+ if event in self._events.keys():
+ self._events[event].pop(id)
+ else:
+ raise InvalidEventName(event)
+
+ def RaiseEvent(self, event):
+ log(event)
+ for fun in self._events[event]:
+ fun()
+
+ def RunMainLoop(self, wait):
+ # set loop wait time
+ self._wait = wait
+
+ # connect to xbmc
+ player = xbmc.Player()
+
+ # raise xbmc started event
+ self.RaiseEvent('onStart')
+
+ while(not xbmc.abortRequested):
+ # check movie playing status
+ self._playingMovie.set(player.isPlayingVideo())
+
+ # check music playing status
+ self._playingMusic.set(player.isPlayingAudio())
+
+ # check paused status
+ try:
+ self._time.set(player.getTime())
+ self._paused.set(not self._time.delayed_step(3) and self._time.get(1) > -1 and self._time.get(2) > -1)
+ except Exception:
+ self._paused.set(False)
+ self._time.set(-1.0)
+
+ # check for events
+ if self._playingMovie.step_on():
+ # raise started playing movie
+ self.RaiseEvent('onPlayMovie')
+ elif self._playingMovie.step_off():
+ # raise stopped playing movie
+ self.RaiseEvent('onStopMovie')
+ elif self._paused.step_on() and self._playingMovie.get():
+ # raise movie paused
+ self.RaiseEvent('onPauseMovie')
+ elif self._paused.step_off() and self._playingMovie.get():
+ # raise movie resumed
+ self.RaiseEvent('onResumeMovie')
+
+ elif self._playingMusic.step_on():
+ # raise started playing music
+ self.RaiseEvent('onPlayMusic')
+ elif self._playingMusic.step_off():
+ # raise stopped playing music
+ self.RaiseEvent('onStopMusic')
+ elif self._paused.step_on() and self._playingMusic.get():
+ # raise music paused
+ self.RaiseEvent('onPauseMusic')
+ elif self._paused.step_off() and self._playingMusic.get():
+ # raise music resumed
+ self.RaiseEvent('onResumeMusic')
+
+ # wait sleep time
+ # time.sleep(self._wait)
+ xbmc.sleep(int(self._wait * 1000))
+
+ # raise xbmc quit event
+ self.RaiseEvent('onQuit')
+
+
+class InvalidEventName(Exception):
+ pass
View
58 src/xmbc/script.service.xmas/resources/settings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<settings>
+ <category label="32000">
+ <setting label="30001" type="lsep"/>
+ <setting label="32001" id="dev_xbmc_start" type="text" default=""/>
+ <setting label="32002" id="devact_xbmc_start" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+ <setting label="32003" id="dev_xbmc_quit" type="text" default=""/>
+ <setting label="32004" id="devact_xbmc_quit" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+
+ <setting label="30002" type="lsep"/>
+ <setting label="32005" id="dev_video_start" type="text" default=""/>
+ <setting label="32006" id="devact_video_start" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+ <setting label="32007" id="dev_video_end" type="text" default=""/>
+ <setting label="32008" id="devact_video_end" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+ <setting label="32009" id="dev_video_pause" type="text" default=""/>
+ <setting label="32010" id="devact_video_pause" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+ <setting label="32011" id="dev_video_resume" type="text" default=""/>
+ <setting label="32012" id="devact_video_resume" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+
+ <setting label="30003" type="lsep"/>
+ <setting label="32005" id="dev_audio_start" type="text" default=""/>
+ <setting label="32006" id="devact_audio_start" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+ <setting label="32007" id="dev_audio_end" type="text" default=""/>
+ <setting label="32008" id="devact_audio_end" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+ <setting label="32009" id="dev_audio_pause" type="text" default=""/>
+ <setting label="32010" id="devact_audio_pause" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+ <setting label="32011" id="dev_audio_resume" type="text" default=""/>
+ <setting label="32012" id="devact_audio_resume" type="labelenum" values="None|On|Off|Fast On|Fast Off|Bright|Dim|On To 25%|On To 50%|On To 75%|On To 100%" default="None"/>
+ </category>
+
+ <category label="32100">
+ <setting label="30001" type="lsep"/>
+ <setting label="32101" id="prog_xbmc_start" type="text" default=""/>
+ <setting label="32102" id="progact_xbmc_start" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+ <setting label="32103" id="prog_xbmc_quit" type="text" default=""/>
+ <setting label="32104" id="progact_xbmc_quit" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+
+ <setting label="30002" type="lsep"/>
+ <setting label="32105" id="prog_video_start" type="text" default=""/>
+ <setting label="32106" id="progact_video_start" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+ <setting label="32107" id="prog_video_end" type="text" default=""/>
+ <setting label="32108" id="progact_video_end" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+ <setting label="32109" id="prog_video_pause" type="text" default=""/>
+ <setting label="32110" id="progact_video_pause" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+ <setting label="32111" id="prog_video_resume" type="text" default=""/>
+ <setting label="32112" id="progact_video_resume" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+
+ <setting label="30003" type="lsep"/>
+ <setting label="32105" id="prog_audio_start" type="text" default=""/>
+ <setting label="32106" id="progact_audio_start" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+ <setting label="32107" id="prog_audio_end" type="text" default=""/>
+ <setting label="32108" id="progact_audio_end" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+ <setting label="32109" id="prog_audio_pause" type="text" default=""/>
+ <setting label="32110" id="progact_audio_pause" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+ <setting label="32111" id="prog_audio_resume" type="text" default=""/>
+ <setting label="32112" id="progact_audio_resume" type="labelenum" values="None|Run|Run Then|Run Else" default="None"/>
+ </category>
+</settings>
View
87 src/xmbc/script.service.xmas/xmas.py
@@ -0,0 +1,87 @@
+import xbmc
+import xbmcgui
+import httplib2
+import json
+import serial
+import time
+#get actioncodes from https://github.com/xbmc/xbmc/blob/master/xbmc/guilib/Key.h
+ACTION_PREVIOUS_MENU = 10
+ACTION_SELECT_ITEM = 7
+ACTION_MOUSE_LEFT_CLICK = 100
+ACTION_MOUSE_RIGHT_CLICK = 101
+pb = 0x7D #pad byte
+sb = 0x7E #sync byte
+cb = 0x80 #command byte
+pad_offset = 100
+
+#url with ip address and port to access web service
+oscuri = 'http://107.22.230.121:50000/'
+
+h = httplib2.Http()
+
+def getlightvals():
+ resp, content = h.request(oscuri)
+ lightvals = []
+ if resp['status'] == '200':
+ lightvals = json.loads(content)
+ return lightvals
+
+
+def special_replace(n):
+ if n == 0x7D:
+ return 0x7C
+ elif n == 0x7E:
+ return 0x7C
+ elif n == 0x7F:
+ return 0x80
+ else:
+ return n
+
+def package_bytes(light_values, channels):
+ """Packages the light dimming values into a readable format for the renard controller"""
+ pv = map(special_replace, light_values)
+ #insert a pad byte every pad_offset byte
+ if len(pv) > pad_offset:
+ for i in range(pad_offset, len(pv), pad_offset):
+ pv.insert(i, pb)
+
+ if len(pv) > channels:
+ a = len(pv) - (len(pv) % channels)
+ for i in range(a, 0, -channels):
+ pv.insert(i,cb)
+ pv.insert(i,sb)
+
+ pv.insert(0, cb)
+ pv.insert(0, sb)
+
+ return pv
+
+
+
+class MyClass(xbmcgui.Window):
+ def __init__(self):
+ self.strActionInfo = xbmcgui.ControlLabel(100, 120, 200, 200, '', 'font13', '0xFFFF00FF')
+ self.addControl(self.strActionInfo)
+ self.strActionInfo.setLabel('Push BACK to quit - A to reset text')
+ self.strActionFade = xbmcgui.ControlFadeLabel(100, 300, 500, 200, 'font13', '0xFFFFFF00')
+ self.addControl(self.strActionFade)
+ self.strActionFade.addLabel(str(getlightvals()))
+ self.serport = serial.Serial('COM7', '57600', timeout=2)
+
+
+ def onAction(self, action):
+ if action == ACTION_PREVIOUS_MENU:
+ self.serport.close()
+ self.close()
+ if action == ACTION_SELECT_ITEM:
+ self.strActionFade.reset()
+ self.strActionFade.addLabel(str(getlightvals()))
+ while True:
+ self.lvals = getlightvals()
+ self.plvals = package_bytes(self.lvals, 32)
+ self.serport.write(bytearray(self.plvals))
+ time.sleep(0.1)
+
+mydisplay = MyClass()
+mydisplay .doModal()
+del mydisplay

0 comments on commit f791c46

Please sign in to comment.
Something went wrong with that request. Please try again.