aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar rcoh <rcoh@mit.edu>2010-12-25 14:07:18 -0500
committerGravatar rcoh <rcoh@mit.edu>2010-12-25 14:07:18 -0500
commit1b84f44faacfe83d4f3603b4df913ed01bf79d09 (patch)
tree5c8af28f71d44d6fb234e3c9f4b9b1f2a2be0006
parent2113f5363022e4ccb2b14d0a7ebd6765de820411 (diff)
parent9e1e0f0c0b6835cc3755bbaa6a364475133ce848 (diff)
Merge branch 'master' into configimprovements
Conflicts: util/Strings.py
-rw-r--r--.gitignore2
-rw-r--r--LightInstallation.py33
-rw-r--r--behaviors/AllPixelsLeft.py11
-rw-r--r--behaviors/BehaviorChain.py1
-rw-r--r--behaviors/DebugBehavior.py1
-rw-r--r--behaviors/DecayBehavior.py1
-rw-r--r--behaviors/EchoBehavior.py1
-rw-r--r--behaviors/ModifyParam.py1
-rw-r--r--behaviors/RunningBehavior.py1
-rw-r--r--config/Outdoor.xml17
-rw-r--r--inputs/PygameInput.py2
-rw-r--r--inputs/TCPInput.py1
-rw-r--r--inputs/TCPInput_backup.py1
-rw-r--r--inputs/UDPInput.py1
-rw-r--r--logger/Logger.py19
-rw-r--r--logger/UTF8LogFormatter.py8
-rw-r--r--logger/__init__.py1
-rw-r--r--logger/loggingConfig.ini61
-rw-r--r--operationscore/Behavior.py21
-rw-r--r--operationscore/Input.py6
-rw-r--r--operationscore/PixelAssembler.py1
-rw-r--r--operationscore/PixelMapper.py1
-rw-r--r--operationscore/SmootCoreObject.py2
-rw-r--r--pixelcore/PixelStrip.py1
-rw-r--r--pixelcore/Screen.py14
-rw-r--r--pixelmappers/GaussianMapper.py1
-rw-r--r--pixelmappers/SimpleMapper.py35
-rw-r--r--renderers/IndoorRenderer.py19
-rw-r--r--tests/TestConfigLoaders.py10
-rw-r--r--tests/__init__.py0
-rw-r--r--util/ComponentRegistry.py36
-rw-r--r--util/Config.py34
-rw-r--r--util/NetworkOps.py6
-rw-r--r--util/PacketComposition.py2
-rw-r--r--util/Strings.py5
35 files changed, 282 insertions, 75 deletions
diff --git a/.gitignore b/.gitignore
index c9b568f..9d4e9cb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
*.pyc
*.swp
+*.swo
+*.pyo
diff --git a/LightInstallation.py b/LightInstallation.py
index e6e5a26..5882806 100644
--- a/LightInstallation.py
+++ b/LightInstallation.py
@@ -1,15 +1,18 @@
from xml.etree.ElementTree import ElementTree
from pixelcore.Screen import *
from pixelcore.PixelStrip import *
-import pdb, sys, time, Util, thread
+import pdb, sys, time, thread
from pygame.locals import *
import util.TimeOps as clock
import util.Config as configGetter
import util.ComponentRegistry as compReg
+from logger import main_log
#Python class to instantiate and drive a Screen through different patterns,
#and effects.
class LightInstallation:
def __init__(self, configFileName):
+ main_log.critical("hi russell, i'm sending info to the log files")
+ main_log.critical("initializing based on file: " + str(configFileName))
self.timer = clock.Stopwatch()
self.timer.start()
self.inputs = {} #dict of inputs and their bound behaviors, keyed by InputId
@@ -20,11 +23,8 @@ class LightInstallation:
self.componentDict = {}
self.inputBehaviorRegistry = {} #inputid -> behaviors listening to that
#input
- #give Util a pointer to our componentRegistry and screen so that everyone can use
- #it
- #Util.setComponentDict(self.componentDict)
self.screen = Screen()
- #Util.setScreen(self.screen)
+ compReg.initRegistry()
compReg.registerComponent(self.screen, 'Screen') #TODO: move to constants file
config = configGetter.loadConfigFile(configFileName)
#read configs from xml
@@ -33,25 +33,33 @@ class LightInstallation:
inputConfig = config.find('InputConfiguration')
behaviorConfig = config.find('BehaviorConfiguration')
mapperConfig = config.find('PixelMapperConfiguration')
+
+ installationConfig = config.find('InstallationConfiguration')
#inits
self.initializeScreen(pixelConfig)
self.initializeRenderers(rendererConfig)
self.initializeInputs(inputConfig)
self.initializeBehaviors(behaviorConfig)
self.initializeMapper(mapperConfig)
-
- self.screen.setMapper(self.mapper)
#registration in dict
self.registerComponents(self.renderers)
self.registerComponents(self.inputs)
self.registerComponents(self.behaviors)
+ self.registerComponents(self.mappers)
+ self.configureInstallation(installationConfig)
#Done initializing. Lets start this thing!
self.timer.stop()
print 'Initialization done. Time: ', self.timer.elapsed(), 'ms'
self.mainLoop()
+ def configureInstallation(self, installationConfig):
+ defaults = configGetter.generateArgDict(installationConfig.find('Defaults'))
+ for defaultSelection in defaults:
+ componentToMap = compReg.getComponent(defaults[defaultSelection])
+ compReg.registerComponent(compReg.getComponent(defaults[defaultSelection]),\
+ 'Default'+defaultSelection)
+
def initializeMapper(self, mapperConfig):
- self.mapper = self.initializeComponent(mapperConfig)[0] #TODO: support
- #multiple mappers
+ self.mappers = self.initializeComponent(mapperConfig)
def initializeScreen(self, layoutConfig):
pixelAssemblers = self.initializeComponent(layoutConfig)
[self.addPixelStrip(l) for l in pixelAssemblers]
@@ -72,7 +80,6 @@ class LightInstallation:
cid = component['Id']
if cid == None:
raise Exception('Components must have Ids!')
- #self.componentDict[cid] = component
compReg.registerComponent(component)
def initializeComponent(self, config):
components = []
@@ -125,9 +132,6 @@ class LightInstallation:
self.behaviors = self.initializeComponent(behaviorConfig)
for behavior in self.behaviors:
self.addBehavior(behavior)
- #TODO: we probably don't need this anymore :(
- def topologicalBehaviorSort(self):
- return Util.topologicalSort(self.behaviorDependencies)
#Does work needed to add a behavior: currently -- maps behavior inputs into
#the input behavior registry.
def addBehavior(self, behavior):
@@ -141,7 +145,8 @@ class LightInstallation:
try:
[compReg.getComponent(b).addInput(responseDict) for b in boundBehaviorIds]
except:
- print 'Behaviors not initialized yet. WAIT!'
+ pass
+ #print 'Behaviors not initialized yet. WAIT!'
def main(argv):
print argv
if len(argv) == 1:
diff --git a/behaviors/AllPixelsLeft.py b/behaviors/AllPixelsLeft.py
new file mode 100644
index 0000000..7f731e9
--- /dev/null
+++ b/behaviors/AllPixelsLeft.py
@@ -0,0 +1,11 @@
+from operationscore.Behavior import *
+import util.ComponentRegistry as compReg
+import pdb
+class AllPixelsLeft(Behavior):
+ def processResponse(self, sensorInputs, recursiveInputs):
+ for sensory in sensorInputs:
+ xLoc = sensory['Location'][0]
+ if type(xLoc) == type(tuple()):
+ pdb.set_trace()
+ sensory['Location'] = '[{x}<' + str(xLoc) + ']'
+ return (sensorInputs, recursiveInputs)
diff --git a/behaviors/BehaviorChain.py b/behaviors/BehaviorChain.py
index 65f5c9d..98585c9 100644
--- a/behaviors/BehaviorChain.py
+++ b/behaviors/BehaviorChain.py
@@ -1,6 +1,5 @@
from operationscore.Behavior import *
import util.ComponentRegistry as compReg
-import Util
import pdb
class BehaviorChain(Behavior):
def behaviorInit(self):
diff --git a/behaviors/DebugBehavior.py b/behaviors/DebugBehavior.py
index 4c8550a..a00346b 100644
--- a/behaviors/DebugBehavior.py
+++ b/behaviors/DebugBehavior.py
@@ -1,5 +1,4 @@
from operationscore.Behavior import *
-import Util
import pdb
class DebugBehavior(Behavior):
def processResponse(self, sensorInputs, recursiveInputs):
diff --git a/behaviors/DecayBehavior.py b/behaviors/DecayBehavior.py
index 56e1686..c1f6f92 100644
--- a/behaviors/DecayBehavior.py
+++ b/behaviors/DecayBehavior.py
@@ -1,7 +1,6 @@
from operationscore.Behavior import *
from pixelevents.DecayEvent import *
import util.Strings as Strings
-import Util
import pdb
class DecayBehavior(Behavior):
def processResponse(self, sensorInputs, recursiveInputs):
diff --git a/behaviors/EchoBehavior.py b/behaviors/EchoBehavior.py
index 002f8fb..be0ed14 100644
--- a/behaviors/EchoBehavior.py
+++ b/behaviors/EchoBehavior.py
@@ -1,6 +1,5 @@
from operationscore.Behavior import *
import util.Strings as Strings
-import Util
import pdb
class EchoBehavior(Behavior):
def processResponse(self, sensorInputs, recursiveInputs):
diff --git a/behaviors/ModifyParam.py b/behaviors/ModifyParam.py
index 38b8cd5..3701013 100644
--- a/behaviors/ModifyParam.py
+++ b/behaviors/ModifyParam.py
@@ -1,5 +1,4 @@
from operationscore.Behavior import *
-import Util
import pdb
#Class to perform a given operation on some element of an argDict. Designed to be used a recursive hook, but can serve sensor-based functions as well. Specify ParamType (Sensor or Recurse), ParamName, and ParamOp, (a valid python statement with the old value represented as {val})
class ModifyParam(Behavior):
diff --git a/behaviors/RunningBehavior.py b/behaviors/RunningBehavior.py
index 1969162..92db69b 100644
--- a/behaviors/RunningBehavior.py
+++ b/behaviors/RunningBehavior.py
@@ -2,7 +2,6 @@ from operationscore.Behavior import *
import util.ComponentRegistry as compReg
import util.Geo as Geo
import pdb
-import Util
class RunningBehavior(Behavior):
def processResponse(self, sensorInputs, recursiveInputs):
newResponses = sensorInputs
diff --git a/config/Outdoor.xml b/config/Outdoor.xml
index 10274b2..1cf00e4 100644
--- a/config/Outdoor.xml
+++ b/config/Outdoor.xml
@@ -1,5 +1,10 @@
<!---All configuration items contain a "Class" tag specifying the python class they represent, and an "Args" tag specifying the args to be passed in.-->
<LightInstallation>
+ <InstallationConfiguration>
+ <Defaults>
+ <PixelMapper>simplemap</PixelMapper>
+ </Defaults>
+ </InstallationConfiguration>
<PixelConfiguration>
<PixelStrip>
<Class>layouts.LineLayout</Class>
@@ -62,15 +67,13 @@
</Args>
</PixelStrip>
</PixelConfiguration>
- <!--<PixelMapperConfiguration>
+ <PixelMapperConfiguration>
<PixelMapper>
<Class>pixelmappers.SimpleMapper</Class>
<Args>
<Id>simplemap</Id>
</Args>
</PixelMapper>
- </PixelMapperConfiguration>-->
- <PixelMapperConfiguration>
<PixelMapper>
<Class>pixelmappers.GaussianMapper</Class>
<Args>
@@ -181,6 +184,12 @@
</Args>
</Behavior>
<Behavior>
+ <Class>behaviors.AllPixelsLeft</Class>
+ <Args>
+ <Id>pixelsleft</Id>
+ </Args>
+ </Behavior>
+ <Behavior>
<Class>behaviors.RecursiveDecay</Class>
<Args>
<Id>recursivedecay</Id>
@@ -201,6 +210,7 @@
</ChainedBehaviors>
<RecursiveHooks>{'running':'acceleratedie'}</RecursiveHooks>
<RenderToScreen>True</RenderToScreen>
+ <Mapper>gaussmap</Mapper>
</Args>
</Behavior>
<Behavior>
@@ -231,6 +241,7 @@
</Inputs>
<ChainedBehaviors>
<Id>echo</Id>
+ <Id>pixelsleft</Id>
<Id>colorchange</Id>
<Id>decay</Id>
</ChainedBehaviors>
diff --git a/inputs/PygameInput.py b/inputs/PygameInput.py
index f69d0f5..6779a20 100644
--- a/inputs/PygameInput.py
+++ b/inputs/PygameInput.py
@@ -1,4 +1,4 @@
-import time, Util
+import time
import util.Strings as Strings
from operationscore.Input import *
import pygame
diff --git a/inputs/TCPInput.py b/inputs/TCPInput.py
index 9f62825..1517afa 100644
--- a/inputs/TCPInput.py
+++ b/inputs/TCPInput.py
@@ -1,4 +1,3 @@
-import Util
import util.Strings as Strings
from operationscore.Input import *
import socket, json, time
diff --git a/inputs/TCPInput_backup.py b/inputs/TCPInput_backup.py
index 01b6a99..d2c4087 100644
--- a/inputs/TCPInput_backup.py
+++ b/inputs/TCPInput_backup.py
@@ -1,5 +1,4 @@
import SocketServer
-import Util
from operationscore.Input import *
"""
diff --git a/inputs/UDPInput.py b/inputs/UDPInput.py
index 5b83792..7d5609e 100644
--- a/inputs/UDPInput.py
+++ b/inputs/UDPInput.py
@@ -1,4 +1,3 @@
-import Util
from operationscore.Input import *
import socket
class UDPInput(Input):
diff --git a/logger/Logger.py b/logger/Logger.py
new file mode 100644
index 0000000..7115e47
--- /dev/null
+++ b/logger/Logger.py
@@ -0,0 +1,19 @@
+import logging
+import logging.config
+
+logging.config.fileConfig("logger/loggingConfig.ini")
+
+# create logger
+screen_log = logging.getLogger("root")
+main_log = logging.getLogger("smoot_light")
+exception_log = logging.getLogger("exception")
+
+#test code -- won't work unless file is imported by a file from the directory above this "logger" directory
+#main_log.debug("debug mesage")
+#main_log.info("info message")
+#main_log.warn("warn message")
+#main_log.error("error message")
+#main_log.critical("critical message")
+#exception_log.critical("hi")
+#screen_log.error("whoa hello")
+
diff --git a/logger/UTF8LogFormatter.py b/logger/UTF8LogFormatter.py
new file mode 100644
index 0000000..2d3fae5
--- /dev/null
+++ b/logger/UTF8LogFormatter.py
@@ -0,0 +1,8 @@
+from logging import Formatter
+
+class UTF8LogFormatter(Formatter):
+ def format(self, record):
+ try:
+ return Formatter.format(self, record)
+ except Exception, e:
+ return Formatter.format(self, record).encode('utf8')
diff --git a/logger/__init__.py b/logger/__init__.py
new file mode 100644
index 0000000..ff356f4
--- /dev/null
+++ b/logger/__init__.py
@@ -0,0 +1 @@
+from Logger import screen_log, main_log, exception_log
diff --git a/logger/loggingConfig.ini b/logger/loggingConfig.ini
new file mode 100644
index 0000000..ee35749
--- /dev/null
+++ b/logger/loggingConfig.ini
@@ -0,0 +1,61 @@
+# Logging configuration
+# Add additional loggers, handlers, formatters here
+# Uses pythons logging config file format
+# http://docs.python.org/lib/logging-config-fileformat.html
+[loggers]
+keys = root, smoot_light, exception
+
+[handlers]
+keys = console, file, exception
+
+[formatters]
+keys = generic, utf8encode
+
+####################################################################
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_smoot_light]
+level = INFO
+handlers = file
+qualname = smoot_light
+propagate = 0
+
+[logger_exception]
+level = DEBUG
+handlers = exception
+qualname = exception
+propagate = 0
+
+####################################################################
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[handler_file]
+class = FileHandler
+args = ('/var/log/smoot_light/main.log', 'a')
+level = INFO
+formatter = generic
+
+[handler_exception]
+class = FileHandler
+args = ('/var/log/smoot_light/exception.log', 'a')
+level = DEBUG
+formatter = utf8encode
+
+####################################################################
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-8s [%(name)s] %(message)s
+#datefmt = %H:%M:%S
+
+[formatter_utf8encode]
+format = %(asctime)s %(levelname)-8s [%(name)s] %(message)s
+class = logger.UTF8LogFormatter.UTF8LogFormatter
+#datefmt = %H:%M:%S
diff --git a/operationscore/Behavior.py b/operationscore/Behavior.py
index 3bdf1ec..d48c1d5 100644
--- a/operationscore/Behavior.py
+++ b/operationscore/Behavior.py
@@ -33,14 +33,26 @@ class Behavior(SmootCoreObject):
recursiveInputs)
if type(output) != type([]):
output = [output]
- return (output, recursions)
- except:
+ return self.addMapperToResponse((output, recursions)) #TODO: use a decorator for this?
+ except: #deal with behaviors that don't return a tuple.
+ responses = self.processResponse(sensorInputs, recursiveInputs)
return (self.processResponse(sensorInputs, recursiveInputs),[])
def addInputs(self, sensorInputs):
if type(sensorInputs) == type([]):
[self.addInput(sensorInput) for sensorInput in sensorInputs]
else:
self.addInput(sensorInputs)
+ #private
+ def addMapperToResponse(self, responses):
+ if self['Mapper'] != None:
+ if type(responses) == type(tuple):
+ (out, recurs) = responses
+ return (self.addMapperToResponse(out), self.addMapperToResponse(recurs))
+ if type(responses) == type([]):
+ for r in responses:
+ r['Mapper'] = self['Mapper']
+ return responses
+ return responses
def timeStep(self): #TODO: type checking. clean this up
responses = self.processResponse(self.sensorResponseQueue, \
self.recursiveResponseQueue)
@@ -54,8 +66,7 @@ class Behavior(SmootCoreObject):
if type(outputs) != type([]):
outputs = [outputs]
try:
- return outputs
+ return self.addMapperToResponse(outputs) #TODO: WTF is up with this?
except:
pass
- #pdb.set_trace()
- return outputs
+ return self.addMapperToResponse(outputs)
diff --git a/operationscore/Input.py b/operationscore/Input.py
index 2144678..62c4682 100644
--- a/operationscore/Input.py
+++ b/operationscore/Input.py
@@ -1,4 +1,4 @@
-import threading,time,Util
+import threading,time
from operationscore.SmootCoreObject import *
#Abstract class for inputs. Inheriting classes should call "respond" to raise
#their event. Inheriting classes MUST define sensingLoop. Called at the
@@ -22,14 +22,10 @@ class Input(SmootCoreObject):
self.daemon = True #This kills this thread when the main thread stops
def respond(self, eventDict):
#if eventDict != []:
- #pdb.set_trace()
self.parentScope.lock.acquire()
self.parentScope.processResponse(self.argDict, eventDict)
self.parentScope.lock.release()
time.sleep(.001)
- def newEvent(self, event): #Mostly just useful for grabbing events from the
- #computer running the sim (key presses, clicks etc.)
- self.eventQueue.append(event)
def parentAlive(self):
try:
parentAlive = self.parentScope.alive()
diff --git a/operationscore/PixelAssembler.py b/operationscore/PixelAssembler.py
index c8563fb..6878f8a 100644
--- a/operationscore/PixelAssembler.py
+++ b/operationscore/PixelAssembler.py
@@ -1,6 +1,5 @@
from operationscore.SmootCoreObject import *
import util.Geo as Geo
-import Util
import pdb
class PixelAssembler(SmootCoreObject):
def init(self):
diff --git a/operationscore/PixelMapper.py b/operationscore/PixelMapper.py
index bbbfcf4..e3f2515 100644
--- a/operationscore/PixelMapper.py
+++ b/operationscore/PixelMapper.py
@@ -1,5 +1,4 @@
from operationscore.SmootCoreObject import *
-import Util
import pdb
class PixelMapper(SmootCoreObject):
def init(self):
diff --git a/operationscore/SmootCoreObject.py b/operationscore/SmootCoreObject.py
index 10df299..9784aab 100644
--- a/operationscore/SmootCoreObject.py
+++ b/operationscore/SmootCoreObject.py
@@ -1,4 +1,3 @@
-import Util
import pdb
import threading
import thread
@@ -8,6 +7,7 @@ class SmootCoreObject(threading.Thread):
self.argDict = argDict
self.validateArgs(self.className()+'.params')
self.lock = thread.allocate_lock()
+ threading.Thread.__init__(self)
self.init() #call init of inheriting class
# self.__setitem__ = self.argDict.__setitem__
# self.__getitem__ = self.argDict.__getitem__
diff --git a/pixelcore/PixelStrip.py b/pixelcore/PixelStrip.py
index cfab948..fceff8e 100644
--- a/pixelcore/PixelStrip.py
+++ b/pixelcore/PixelStrip.py
@@ -4,7 +4,6 @@ import util.Geo as Geo
from pixelevents.StepEvent import *
import pygame
import math
-import Util
import pdb
#Python class representing a single Pixel strip (usually 50 Pixels)
class PixelStrip:
diff --git a/pixelcore/Screen.py b/pixelcore/Screen.py
index a20cc72..da03ad2 100644
--- a/pixelcore/Screen.py
+++ b/pixelcore/Screen.py
@@ -1,7 +1,10 @@
from pixelcore.Pixel import *
from pixelcore.PixelStrip import *
from operationscore.PixelEvent import *
+from operationscore.PixelMapper import *
import util.Search as Search
+import util.ComponentRegistry as compReg
+import util.Strings as Strings
import itertools
#Class representing a collection of Pixels grouped into PixelStrips. Needs a
#PixelMapper, currently set via setMapper by may be migrated into the argDict.
@@ -29,8 +32,6 @@ class Screen:
self.xPixelLocs = [p[0] for p in self.xSortedPixels]
def render(self, surface):
[lS.render(surface) for lS in self.pixelStrips]
- def setMapper(self, mapper):
- self.mapper = mapper
def allOn(self):
[lS.allOn(-1) for lS in self.pixelStrips]
def __iter__(self): #the iterator of all our pixel strips chained togther
@@ -70,8 +71,13 @@ class Screen:
#[strip.respond(dict(responseInfo)) for strip in self.pixelStrips]
if type(responseInfo) != type(dict()):
pass
- #pdb.set_trace()
- pixelWeightList = self.mapper.mapEvent(responseInfo['Location'], self)
+ if 'Mapper' in responseInfo:
+ mapper = compReg.getComponent(responseInfo['Mapper'])
+ else:
+ mapper = compReg.getComponent(Strings.DEFAULT_MAPPER)
+ #if type(mapper) != type(PixelMapper):
+ # raise Exception('No default mapper specified.')
+ pixelWeightList = mapper.mapEvent(responseInfo['Location'], self)
PixelEvent.addPixelEventIfMissing(responseInfo)
for (pixel, weight) in pixelWeightList:
pixel.processInput(responseInfo['PixelEvent'].scale(weight), 0) #TODO: z-index
diff --git a/pixelmappers/GaussianMapper.py b/pixelmappers/GaussianMapper.py
index e94235e..8755acf 100644
--- a/pixelmappers/GaussianMapper.py
+++ b/pixelmappers/GaussianMapper.py
@@ -1,6 +1,5 @@
from operationscore.PixelMapper import *
import util.Geo as Geo
-import Util
class GaussianMapper(PixelMapper):
def mappingFunction(self, eventLocation, screen):
returnPixels = [] #TODO: consider preallocation and trimming
diff --git a/pixelmappers/SimpleMapper.py b/pixelmappers/SimpleMapper.py
index 4b5377d..bc51cf9 100644
--- a/pixelmappers/SimpleMapper.py
+++ b/pixelmappers/SimpleMapper.py
@@ -1,14 +1,29 @@
from operationscore.PixelMapper import *
-import Util
+import util.Geo as Geo
class SimpleMapper(PixelMapper):
def mappingFunction(self, eventLocation, screen):
- bestDist = 10**10 #don't kill me, I'm lazy
- bestPixel = None
- for pixel in screen:
- pixelDist = Geo.dist(pixel.location, eventLocation)
- if pixelDist < bestDist:
- bestPixel = pixel
- bestDist = pixelDist
- return [(bestPixel,1)]
-
+ if type(eventLocation) == type(tuple()):
+ bestDist = 10**10 #don't kill me, I'm lazy
+ bestPixel = None
+ for pixel in screen:
+ pixelDist = Geo.dist(pixel.location, eventLocation)
+ if pixelDist < bestDist:
+ bestPixel = pixel
+ bestDist = pixelDist
+ return [(bestPixel,1)]
+ elif type(type(str)):
+ #[{x}>5,{y}<k]
+ #TODO: we should probably encapsulate this somewhere
+ ret = []
+ eventLocation = eventLocation.replace('{x}', 'pixel.location[0]')
+ eventLocation = eventLocation.replace('{y}', 'pixel.location[1]')
+ for pixel in screen:
+ try:
+ pixelValid = sum(eval(eventLocation)) == len(eval(eventLocation)) #TODO: some
+ #optimizations possible. This might be slow in the long run
+ if pixelValid:
+ ret.append((pixel, 1))
+ except:
+ raise Exception('Bad event condition')
+ return ret
diff --git a/renderers/IndoorRenderer.py b/renderers/IndoorRenderer.py
index 2eac162..c13d11f 100644
--- a/renderers/IndoorRenderer.py
+++ b/renderers/IndoorRenderer.py
@@ -20,12 +20,15 @@ class IndoorRenderer(Renderer):
self.stripLocations[stripId] = (ip, \
stripsInPowerSupply[stripId])
def render(self, lightSystem):
- for pixelStrip in lightSystem.pixelStrips:
- stripId = pixelStrip.argDict['Id']
- (ip, port) = self.stripLocations[stripId]
- if not ip in self.sockets: #do we have a socket to this
- #strip? if not, spin off a new one
- self.sockets[ip] = network.getConnectedSocket(ip,port)
- packet = composer.composePixelStripPacket(pixelStrip, port)
- self.sockets[ip].send(packet, 0x00)
+ try:
+ for pixelStrip in lightSystem.pixelStrips:
+ stripId = pixelStrip.argDict['Id']
+ (ip, port) = self.stripLocations[stripId]
+ if not ip in self.sockets: #do we have a socket to this
+ #strip? if not, spin off a new one
+ self.sockets[ip] = network.getConnectedSocket(ip,port)
+ packet = composer.composePixelStripPacket(pixelStrip, port)
+ self.sockets[ip].send(packet, 0x00)
+ except:
+ pass #Rendering error. Log it. LOG
diff --git a/tests/TestConfigLoaders.py b/tests/TestConfigLoaders.py
new file mode 100644
index 0000000..6ea4f59
--- /dev/null
+++ b/tests/TestConfigLoaders.py
@@ -0,0 +1,10 @@
+import unittest
+class TestConfigLoaders(unittest.TestCase):
+ def setUp(self):
+ pass
+ def tearDown(self):
+ pass
+ def test_something(self):
+ pass
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/__init__.py
diff --git a/util/ComponentRegistry.py b/util/ComponentRegistry.py
index f8fe00d..119ce18 100644
--- a/util/ComponentRegistry.py
+++ b/util/ComponentRegistry.py
@@ -1,17 +1,43 @@
import pdb
+#component registry, a singleton
+import thread
+#class ComponentRegistry:
+# def __init__(self):
+# self.regDict = {}
+# @staticmethod
+# def getRegistry(self):
+# if self.instance == None:
+# self.instance = self.__class__()
+# return self.instance
+# def registerComponent(component, cid=None):
+# if cid != None:
+# globals()['Registry'][cid] = component
+# else:
+# try:
+# cid = component['Id']
+# globals()['Registry'][cid] = component
+# except:
+# raise Exception('Must specify Id, component did not store it')
+#def registerDefault(
+def removeComponent(cid):
+ globals()['Registry'].pop(cid)
+def getComponent(cid):
+ return globals()['Registry'][cid]
#Registry of all components of the light system
#TODO: pick a graceful failure behavior and implement it
-registry = {}
+def initRegistry():
+ globals()['Registry'] = {}
def registerComponent(component, cid=None):
if cid != None:
- registry[cid] = component
+ globals()['Registry'][cid] = component
else:
try:
cid = component['Id']
- registry[cid] = component
+ globals()['Registry'][cid] = component
except:
raise Exception('Must specify Id, component did not store it')
+#def registerDefault(
def removeComponent(cid):
- registry.pop(cid)
+ globals()['Registry'].pop(cid)
def getComponent(cid):
- return registry[cid]
+ return globals()['Registry'][cid]
diff --git a/util/Config.py b/util/Config.py
index 746350d..0349e3e 100644
--- a/util/Config.py
+++ b/util/Config.py
@@ -1,4 +1,5 @@
from xml.etree.ElementTree import ElementTree
+import util.Strings as Strings
classArgsMem = {}
CONFIG_PATH = 'config/'
def loadParamRequirementDict(className):
@@ -6,7 +7,7 @@ def loadParamRequirementDict(className):
classArgsMem[className] = fileToDict(CONFIG_PATH + className)
return classArgsMem[className]
def loadConfigFile(fileName): #TODO: error handling etc.
- try:
+ #try:
fileName = CONFIG_PATH + fileName
if '.params' in fileName:
return fileToDict(fileName)
@@ -14,8 +15,37 @@ def loadConfigFile(fileName): #TODO: error handling etc.
config = ElementTree() #use .fromstring, and resolve xincludes
config.parse(fileName)
return config
- except:
+ #except:
return None
+def compositeXMLTrees(parentTree, overridingTree):
+ #type checking -- convert ElementTrees to their root elements
+ parentItems = parentTree.getchildren()
+ overrideItems = overridingTree.getchildren()
+ #first, lets figure out what tags we have in the override tree:
+ tagCollection = [el.tag for el in overrideItems] #we can speed this up with a dict if necessary
+ overrideRoot = overridingTree.getroot()
+ for item in parentItems:
+ if not item.tag in tagCollection: #no override
+ overrideRoot.insert(-1, item) #insert the new item at the end
+ else:
+ #do we merge or replace?
+ intersectingElements = findElementsByTag(item.tag, overrideItems)
+ if len(intersectingItems) > 1:
+ print 'ABUSE!'
+ interEl = intersectingElements[0]
+ mode = 'Replace'
+ if Strings.OVERRIDE_BEHAVIOR in interEl.attrib:
+ mode = interEl.attrib[Strings.OVERRIDE_BEHAVIOR]
+ if mode != 'Replace' and mode != 'Merge':
+ print 'Bad Mode. Replacing'
+ mode = 'Replace'
+ if mode == 'Replace':
+ pass #we don't need to do anything
+ if mode == 'Merge':
+ pass #TODO: code this
+
+def findElementsByTag(tag, eList):
+ return [el for el in eList if el.tag == tag]
def fileToDict(fileName):
fileText = ''
try:
diff --git a/util/NetworkOps.py b/util/NetworkOps.py
index a247090..0404975 100644
--- a/util/NetworkOps.py
+++ b/util/NetworkOps.py
@@ -1,6 +1,8 @@
import socket
def getConnectedSocket(ip,port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- print (ip, port)
- sock.connect((ip, port))
+ try:
+ sock.connect((ip, port))
+ except:
+ print 'network down'
return sock
diff --git a/util/PacketComposition.py b/util/PacketComposition.py
index 5133459..2563c61 100644
--- a/util/PacketComposition.py
+++ b/util/PacketComposition.py
@@ -26,7 +26,6 @@ def composePixelStripPacket(pixelStrip,port):
subDict = dict(kinetDict)
subDict['len'] = 38000 #I have no idea why this works.
subDict['port'] = port
- #pdb.set_trace()
packet.extend(kinetPortOutPacket(subDict))
packet.append(0x0)
packet.extend(data)
@@ -50,7 +49,6 @@ def kinetPortOutPayload(argDict):
#payload.append(0x00) #somepadding? lolwtf.
payload.extend(struct.pack('H', argDict['len']))
payload.extend(struct.pack('H', argDict['startcode']))
- #pdb.set_trace()
return payload
def kinetPortOutPacket(payloadArgs):
packet = bytearray()
diff --git a/util/Strings.py b/util/Strings.py
index d58202d..40ad86b 100644
--- a/util/Strings.py
+++ b/util/Strings.py
@@ -1,2 +1,7 @@
LOCATION = 'Location'
+DEFAULT_MAPPER = 'DefaultPixelMapper'
+
+
+
+#XMLStuff
OVERRIDE_BEHAVIOR = 'OverrideBehavior'