aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LightInstallation.py52
-rw-r--r--ResponseMover.py15
-rw-r--r--behaviors/Accelerate.xml8
-rw-r--r--behaviors/BehaviorChain.py8
-rw-r--r--behaviors/DebugBehavior.py3
-rw-r--r--behaviors/LoopAndDie.xml6
-rw-r--r--behaviors/PixelDecay.xml9
-rw-r--r--behaviors/RandomColor.xml8
-rw-r--r--behaviors/RandomWalk.py5
-rw-r--r--behaviors/RunningBehavior.xml8
-rw-r--r--config/Outdoor.xml100
-rw-r--r--inputs/MouseFollower.xml8
-rw-r--r--inputs/RandomLocs.py13
-rw-r--r--inputs/TCPInput.py5
-rw-r--r--layouts/50PixelStrip.xml8
-rw-r--r--layouts/BasicSixStrip.xml42
-rw-r--r--operationscore/Input.py8
-rw-r--r--operationscore/SmootCoreObject.py2
-rw-r--r--pixelmappers/SimpleMapper.py2
-rw-r--r--renderers/IndoorRenderer.py9
-rw-r--r--renderers/Pygame.xml7
-rw-r--r--renderers/SixStripUDP.xml18
-rw-r--r--renderers/SixStripUDPPygame.xml27
-rw-r--r--tests/testdata/compositeTESTout.xml10
-rw-r--r--tests/testdata/compositeTRUTH.xml10
-rw-r--r--tests/testdata/inheritanceTEST.xml21
-rw-r--r--tests/testdata/inheritanceTESTout.xml14
-rw-r--r--tests/testdata/inheritanceTRUTH.xml14
-rw-r--r--tests/testdata/override.xml2
-rw-r--r--util/Config.py60
-rw-r--r--util/Geo.py6
-rw-r--r--util/NetworkOps.py9
-rw-r--r--util/PacketComposition.py2
-rw-r--r--util/Search.py14
34 files changed, 360 insertions, 173 deletions
diff --git a/LightInstallation.py b/LightInstallation.py
index 168983b..db7b808 100644
--- a/LightInstallation.py
+++ b/LightInstallation.py
@@ -11,8 +11,7 @@ from logger import main_log
#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))
+ main_log.info("System Initialization began based on: " + str(configFileName))
self.timer = clock.Stopwatch()
self.timer.start()
self.inputs = {} #dict of inputs and their bound behaviors, keyed by InputId
@@ -41,6 +40,7 @@ class LightInstallation:
self.initializeInputs(inputConfig)
self.initializeBehaviors(behaviorConfig)
self.initializeMapper(mapperConfig)
+ main_log.info('All components initialized')
#registration in dict
self.registerComponents(self.renderers)
self.registerComponents(self.inputs)
@@ -49,7 +49,7 @@ class LightInstallation:
self.configureInstallation(installationConfig)
#Done initializing. Lets start this thing!
self.timer.stop()
- print 'Initialization done. Time: ', self.timer.elapsed(), 'ms'
+ #main_log.info('Initialization done. Time: ', self.timer.elapsed(), 'ms')
self.mainLoop()
def configureInstallation(self, installationConfig):
defaults = configGetter.generateArgDict(installationConfig.find('Defaults'))
@@ -57,6 +57,8 @@ class LightInstallation:
componentToMap = compReg.getComponent(defaults[defaultSelection])
compReg.registerComponent(compReg.getComponent(defaults[defaultSelection]),\
'Default'+defaultSelection)
+ main_log.debug('Default Set: ' + defaultSelection + 'set to ' +\
+ defaults[defaultSelection])
def initializeMapper(self, mapperConfig):
self.mappers = self.initializeComponent(mapperConfig)
@@ -78,21 +80,40 @@ class LightInstallation:
def registerComponents(self, components):
for component in components:
cid = component['Id']
- if cid == None:
- raise Exception('Components must have Ids!')
- compReg.registerComponent(component)
+ if cid == None: #TODO: determine if componenent is critical, and if so, die
+ main_log.error('Components must be registered with Ids. Component not registered')
+ else:
+ compReg.registerComponent(component)
+ main_log.debug(cid + ' registered')
def initializeComponent(self, config):
components = []
if config != None:
- config = configGetter.resolveConfigInheritance(config)
for configItem in config.getchildren():
- [module,className] = configItem.find('Class').text.split('.')
- exec('from ' + module+'.'+className + ' import *')
- args = configGetter.generateArgDict(configItem.find('Args'))
+ try:
+ [module,className] = configItem.find('Class').text.split('.')
+ except:
+ main_log.error('Module must have Class element')
+ main_log.warn('Module without class element. Module not initialized')
+ continue
+ try:
+ exec('from ' + module+'.'+className + ' import *')
+ main_log.debug(module +'.' +className + 'imported')
+ except Exception as inst:
+ pdb.set_trace()
+ main_log.error('Error importing ' + module+'.'+'.className. Component not\
+ initialized.')
+ continue #TODO: verify functions as expected
+ args = configGetter.pullArgsFromItem(configItem)
args['parentScope'] = self #TODO: we shouldn't give away scope
#like this, find another way.
- components.append(eval(className+'(args)')) #TODO: doesn't error
+ try:
+ components.append(eval(className+'(args)')) #TODO: doesn't error
+ main_log.debug(className + 'initialized with args ' + str(args))
#right
+ except Exception as inst:
+ main_log.error('Failure while initializing ' + className + ' with ' + str(args))
+ #main_log.error(inst) TODO: exception logging
+
return components
def alive(self):
return True
@@ -100,7 +121,7 @@ class LightInstallation:
#self.screen.allOn()
lastLoopTime = clock.time()
refreshInterval = 30
- runCount = 150
+ runCount = 3000
while runCount > 0:
runCount -= 1
loopStart = clock.time()
@@ -149,11 +170,12 @@ class LightInstallation:
pass
#print 'Behaviors not initialized yet. WAIT!'
def main(argv):
- print argv
if len(argv) == 1:
l = LightInstallation('LightInstallationConfig.xml')
else:
l = LightInstallation(argv[1])
if __name__ == "__main__":
- main(sys.argv)
-
+ try:
+ main(sys.argv)
+ except KeyboardInterrupt:
+ main_log.info('Terminated by keyboard.')
diff --git a/ResponseMover.py b/ResponseMover.py
new file mode 100644
index 0000000..718400d
--- /dev/null
+++ b/ResponseMover.py
@@ -0,0 +1,15 @@
+from operationscore.Behavior import *
+import util.ComponentRegistry as compReg
+#ResponseMover is a scaffold for behaviors that spawn 'walkers' which act autonomously on input.
+#Add a recursive hook to control the movement.
+class ResponseMover(Behavior):
+ def processResponse(self, sensorInputs, recursiveInputs):
+ newResponses = sensorInputs
+ ret = []
+ ret += newResponses
+ for recurInput in recursiveInputs:
+ outDict = dict(recurInput)
+ ret.append(outDict)
+ ret += newResponses
+ return (ret, ret)
+
diff --git a/behaviors/Accelerate.xml b/behaviors/Accelerate.xml
new file mode 100644
index 0000000..2a3d7ac
--- /dev/null
+++ b/behaviors/Accelerate.xml
@@ -0,0 +1,8 @@
+<Behavior>
+ <Class>behaviors.ModifyParam</Class>
+ <Args>
+ <ParamType>Sensor</ParamType>
+ <ParamName>StepSize</ParamName>
+ <ParamOp>{val}*1.05</ParamOp>
+ </Args>
+</Behavior>
diff --git a/behaviors/BehaviorChain.py b/behaviors/BehaviorChain.py
index 98585c9..ce161f9 100644
--- a/behaviors/BehaviorChain.py
+++ b/behaviors/BehaviorChain.py
@@ -1,5 +1,6 @@
from operationscore.Behavior import *
import util.ComponentRegistry as compReg
+import logging as main_log
import pdb
class BehaviorChain(Behavior):
def behaviorInit(self):
@@ -20,11 +21,12 @@ class BehaviorChain(Behavior):
if behaviorId in self.hooks: #process recursive hook if there is one
hookBehavior = compReg.getComponent(self.hooks[behaviorId])
-#we feed its recurrence in as input to the behavior.
+ #we feed its recurrence in as input to the behavior.
(recurrence, hookRecurrence) = \
hookBehavior.immediateProcessInput(recurrence, \
[])
if hookRecurrence != []:
- print 'Hook recurrences are not currently supported. Implement it yourself or bug russell'
- self.feedback[behaviorId] = recurrence
+ main_log.warn('Hook recurrences are not currently supported. Implement it\
+ yourself or bug russell')
+ self.feedback[behaviorId] = recurrence
return response
diff --git a/behaviors/DebugBehavior.py b/behaviors/DebugBehavior.py
index a00346b..2f8db80 100644
--- a/behaviors/DebugBehavior.py
+++ b/behaviors/DebugBehavior.py
@@ -1,7 +1,8 @@
from operationscore.Behavior import *
+from logger import main_log
import pdb
class DebugBehavior(Behavior):
def processResponse(self, sensorInputs, recursiveInputs):
if sensorInputs != []:
- print 'Sensor Inputs: ', sensorInputs
+ main_log.debug('Sensor Inputs: ', sensorInputs)
return []
diff --git a/behaviors/LoopAndDie.xml b/behaviors/LoopAndDie.xml
new file mode 100644
index 0000000..af26562
--- /dev/null
+++ b/behaviors/LoopAndDie.xml
@@ -0,0 +1,6 @@
+<Behavior>
+ <Class>behaviors.RecursiveDecay</Class>
+ <Args>
+ <InitialResponseCount>70</InitialResponseCount>
+ </Args>
+</Behavior>
diff --git a/behaviors/PixelDecay.xml b/behaviors/PixelDecay.xml
new file mode 100644
index 0000000..f9eee0d
--- /dev/null
+++ b/behaviors/PixelDecay.xml
@@ -0,0 +1,9 @@
+<Behavior>
+ <Class>behaviors.DecayBehavior</Class>
+ <Args>
+ <DecayType>Exponential</DecayType>
+ <Coefficient>.01</Coefficient>
+ <z-index>0</z-index>
+ <RenderToScreen>False</RenderToScreen>
+ </Args>
+</Behavior>
diff --git a/behaviors/RandomColor.xml b/behaviors/RandomColor.xml
new file mode 100644
index 0000000..afac09c
--- /dev/null
+++ b/behaviors/RandomColor.xml
@@ -0,0 +1,8 @@
+<Behavior>
+ <Class>behaviors.ColorChangerBehavior</Class>
+ <Args>
+ <Id>colorchange</Id>
+ <z-index>0</z-index>
+ <RenderToScreen>False</RenderToScreen>
+ </Args>
+</Behavior>
diff --git a/behaviors/RandomWalk.py b/behaviors/RandomWalk.py
new file mode 100644
index 0000000..8254430
--- /dev/null
+++ b/behaviors/RandomWalk.py
@@ -0,0 +1,5 @@
+from operationscore.Behavior import *
+import util.ComponentRegistry as compReg
+class RandomWalk(Behavior):
+ def processResponse(self, sensors, recursives):
+
diff --git a/behaviors/RunningBehavior.xml b/behaviors/RunningBehavior.xml
new file mode 100644
index 0000000..2a7bf37
--- /dev/null
+++ b/behaviors/RunningBehavior.xml
@@ -0,0 +1,8 @@
+<Behavior>
+ <Class>behaviors.RunningBehavior</Class>
+ <Args>
+ <Id>running</Id>
+ <StepSize>1</StepSize>
+ <RenderToScreen>False</RenderToScreen>
+ </Args>
+</Behavior>
diff --git a/config/Outdoor.xml b/config/Outdoor.xml
index 67958d7..9ca33e9 100644
--- a/config/Outdoor.xml
+++ b/config/Outdoor.xml
@@ -28,29 +28,10 @@
</PixelMapperConfiguration>
<RendererConfiguration>
<Renderer>
- <Class>renderers.PygameRenderer</Class>
- <Args>
- <Id>pygamerender</Id>
- <displaySize>(1300,50)</displaySize>
- </Args>
+ <InheritsFrom>renderers/SixStripUDP.xml</InheritsFrom>
</Renderer>
<Renderer>
- <Class>renderers.IndoorRenderer</Class>
- <Args>
- <Id>indoorRenderer</Id>
- <PowerSupply>
- <IP>10.31.255.233</IP>
- <PortMapping>{'strip1':1, 'strip2':2}</PortMapping>
- </PowerSupply>
- <PowerSupply>
- <IP>10.32.97.17</IP>
- <PortMapping>{'strip3':1, 'strip4':2}</PortMapping>
- </PowerSupply>
- <PowerSupply>
- <IP>10.32.96.211</IP>
- <PortMapping>{'strip5':1, 'strip6':2}</PortMapping>
- </PowerSupply>
- </Args>
+ <InheritsFrom>renderers/Pygame.xml</InheritsFrom>
</Renderer>
</RendererConfiguration>
<InputConfiguration>
@@ -61,20 +42,13 @@
<RefreshInterval>100</RefreshInterval>
</Args>
</InputElement>
- <InputElement>
- <Class>inputs.PygameInput</Class>
- <Args>
- <Id>followmouse</Id>
- <RefreshInterval>50</RefreshInterval>
- <FollowMouse>True</FollowMouse>
- </Args>
+ <InputElement Id="followmouse">
+ <InheritsFrom>inputs/MouseFollower.xml</InheritsFrom>
</InputElement>
<InputElement>
- <Class>inputs.UDPInput</Class>
+ <Class>inputs.RandomLocs</Class>
<Args>
- <Id>UDP</Id>
- <Port>6038</Port>
- <RefreshInterval>100</RefreshInterval>
+ <Id>randomLoc</Id>
</Args>
</InputElement>
</InputConfiguration>
@@ -85,35 +59,13 @@
<Id>echo</Id>
<z-index>0</z-index>
<RenderToScreen>False</RenderToScreen>
- <Inputs>
- </Inputs>
</Args>
</Behavior>
- <Behavior>
- <Class>behaviors.ColorChangerBehavior</Class>
- <Args>
- <Id>colorchange</Id>
- <z-index>0</z-index>
- <RenderToScreen>False</RenderToScreen>
- <!--<ColorList>
- <Color>(255,0,0)</Color>
- </ColorList>-->
- <Inputs>
- <Id>pygame</Id>
- </Inputs>
- </Args>
+ <Behavior Id="colorchange">
+ <InheritsFrom>behaviors/RandomColor.xml</InheritsFrom>
</Behavior>
- <Behavior>
- <Class>behaviors.DecayBehavior</Class>
- <Args>
- <Id>decay</Id>
- <DecayType>Exponential</DecayType>
- <Coefficient>.01</Coefficient>
- <z-index>0</z-index>
- <RenderToScreen>False</RenderToScreen>
- <Inputs>
- </Inputs>
- </Args>
+ <Behavior Id="decay">
+ <InheritsFrom>behaviors/PixelDecay.xml</InheritsFrom>
</Behavior>
<Behavior>
<Class>behaviors.DebugBehavior</Class>
@@ -131,12 +83,8 @@
<Id>pixelsleft</Id>
</Args>
</Behavior>
- <Behavior>
- <Class>behaviors.RecursiveDecay</Class>
- <Args>
- <Id>recursivedecay</Id>
- <InitialResponseCount>70</InitialResponseCount>
- </Args>
+ <Behavior Id="recursivedecay">
+ <InheritsFrom>behaviors/LoopAndDie.xml</InheritsFrom>
</Behavior>
<Behavior>
<Class>behaviors.BehaviorChain</Class>
@@ -144,6 +92,7 @@
<Id>runcolordecay</Id>
<Inputs>
<Id>pygame</Id>
+ <Id>randomLoc</Id>
</Inputs>
<ChainedBehaviors>
<Id>colorchange</Id>
@@ -155,14 +104,8 @@
<Mapper>gaussmap</Mapper>
</Args>
</Behavior>
- <Behavior>
- <Class>behaviors.ModifyParam</Class>
- <Args>
- <Id>accelerate</Id>
- <ParamType>Sensor</ParamType>
- <ParamName>StepSize</ParamName>
- <ParamOp>{val}*1.05</ParamOp>
- </Args>
+ <Behavior Id="accelerate">
+ <InheritsFrom>behaviors/Accelerate.xml</InheritsFrom>
</Behavior>
<Behavior>
<Class>behaviors.BehaviorChain</Class>
@@ -184,22 +127,13 @@
<ChainedBehaviors>
<Id>echo</Id>
<Id>pixelsleft</Id>
- <Id>colorchange</Id>
<Id>decay</Id>
</ChainedBehaviors>
<RenderToScreen>False</RenderToScreen>
</Args>
</Behavior>
- <Behavior>
- <Class>behaviors.RunningBehavior</Class>
- <Args>
- <Id>running</Id>
- <Inputs>
- <Id>pygame</Id>
- </Inputs>
- <StepSize>1</StepSize>
- <RenderToScreen>False</RenderToScreen>
- </Args>
+ <Behavior Id="running">
+ <InheritsFrom>behaviors/RunningBehavior.xml</InheritsFrom>
</Behavior>
</BehaviorConfiguration>
</LightInstallation>
diff --git a/inputs/MouseFollower.xml b/inputs/MouseFollower.xml
new file mode 100644
index 0000000..7d7963d
--- /dev/null
+++ b/inputs/MouseFollower.xml
@@ -0,0 +1,8 @@
+<InputElement>
+ <Class>inputs.PygameInput</Class>
+ <Args>
+ <Id>followmouse</Id>
+ <RefreshInterval>50</RefreshInterval>
+ <FollowMouse>True</FollowMouse>
+ </Args>
+</InputElement>
diff --git a/inputs/RandomLocs.py b/inputs/RandomLocs.py
new file mode 100644
index 0000000..d1ce1c7
--- /dev/null
+++ b/inputs/RandomLocs.py
@@ -0,0 +1,13 @@
+import util.TimeOps as clock
+import random
+import util.Geo as Geo
+import util.Strings as Strings
+from operationscore.Input import *
+class RandomLocs(Input):
+ def inputInit(self):
+ self['LastEvent'] = clock.time()
+ def sensingLoop(self): #TODO: move to params
+ currentTime = clock.time()
+ if currentTime - self['LastEvent'] > 2000:
+ self.respond({Strings.LOCATION: Geo.randomLoc((50,50))})
+ self['LastEvent'] = currentTime
diff --git a/inputs/TCPInput.py b/inputs/TCPInput.py
index 1517afa..197045f 100644
--- a/inputs/TCPInput.py
+++ b/inputs/TCPInput.py
@@ -1,6 +1,7 @@
import util.Strings as Strings
from operationscore.Input import *
import socket, json, time
+import logging as main_log
class TCPInput(Input):
def inputInit(self):
self.HOST = '' # Symbolic name meaning all available interfaces
@@ -16,9 +17,9 @@ class TCPInput(Input):
def sensingLoop(self):
data = self.conn.recv(self.BUFFER_SIZE)
- print data
+ main_log.debug('Incoming data', data)
if not data or 'end' in data: # data end, close socket
- print 'END!!'
+ main_log.debug('End in data')
self.IS_RESPONDING = 0
self.sock.close()
diff --git a/layouts/50PixelStrip.xml b/layouts/50PixelStrip.xml
new file mode 100644
index 0000000..beabb97
--- /dev/null
+++ b/layouts/50PixelStrip.xml
@@ -0,0 +1,8 @@
+<PixelStrip>
+ <Class>layouts.LineLayout</Class>
+ <Args>
+ <pixelToPixelSpacing>4</pixelToPixelSpacing>
+ <spacing>4</spacing>
+ <numPixels>50</numPixels>
+ </Args>
+</PixelStrip>
diff --git a/layouts/BasicSixStrip.xml b/layouts/BasicSixStrip.xml
index 38c50d4..0d2d277 100644
--- a/layouts/BasicSixStrip.xml
+++ b/layouts/BasicSixStrip.xml
@@ -1,61 +1,43 @@
<PixelConfiguration>
<PixelStrip>
- <Class>layouts.LineLayout</Class>
- <Args>
+ <InheritsFrom>layouts/50PixelStrip.xml</InheritsFrom>
+ <Args OverrideBehavior="Merge">
<Id>strip1</Id>
- <pixelToPixelSpacing>4</pixelToPixelSpacing>
- <spacing>4</spacing>
- <numPixels>50</numPixels>
<originLocation>(10,20)</originLocation>
</Args>
</PixelStrip>
<PixelStrip>
- <Class>layouts.LineLayout</Class>
- <Args>
+ <InheritsFrom>layouts/50PixelStrip.xml</InheritsFrom>
+ <Args OverrideBehavior="Merge">
<Id>strip2</Id>
- <pixelToPixelSpacing>4</pixelToPixelSpacing>
- <spacing>4</spacing>
- <numPixels>50</numPixels>
<originLocation>(10,24)</originLocation>
</Args>
</PixelStrip>
<PixelStrip>
- <Class>layouts.LineLayout</Class>
- <Args>
+ <InheritsFrom>layouts/50PixelStrip.xml</InheritsFrom>
+ <Args OverrideBehavior="Merge">
<Id>strip3</Id>
- <pixelToPixelSpacing>4</pixelToPixelSpacing>
- <spacing>4</spacing>
- <numPixels>50</numPixels>
<originLocation>(10,28)</originLocation>
</Args>
</PixelStrip>
<PixelStrip>
- <Class>layouts.LineLayout</Class>
- <Args>
+ <InheritsFrom>layouts/50PixelStrip.xml</InheritsFrom>
+ <Args OverrideBehavior="Merge">
<Id>strip4</Id>
- <pixelToPixelSpacing>4</pixelToPixelSpacing>
- <spacing>4</spacing>
- <numPixels>50</numPixels>
<originLocation>(10,32)</originLocation>
</Args>
</PixelStrip>
<PixelStrip>
- <Class>layouts.LineLayout</Class>
- <Args>
+ <InheritsFrom>layouts/50PixelStrip.xml</InheritsFrom>
+ <Args OverrideBehavior="Merge">
<Id>strip5</Id>
- <pixelToPixelSpacing>4</pixelToPixelSpacing>
- <spacing>4</spacing>
- <numPixels>50</numPixels>
<originLocation>(10,36)</originLocation>
</Args>
</PixelStrip>
<PixelStrip>
- <Class>layouts.LineLayout</Class>
- <Args>
+ <InheritsFrom>layouts/50PixelStrip.xml</InheritsFrom>
+ <Args OverrideBehavior="Merge">
<Id>strip6</Id>
- <pixelToPixelSpacing>4</pixelToPixelSpacing>
- <spacing>4</spacing>
- <numPixels>50</numPixels>
<originLocation>(10,40)</originLocation>
</Args>
</PixelStrip>
diff --git a/operationscore/Input.py b/operationscore/Input.py
index 6b56cd5..3dd74cf 100644
--- a/operationscore/Input.py
+++ b/operationscore/Input.py
@@ -1,5 +1,5 @@
import threading,time
-from operationscore.SmootCoreObject import *
+from logger import main_log, exception_log
from operationscore.ThreadedSmootCoreObject import ThreadedSmootCoreObject
#Abstract class for inputs. Inheriting classes should call "respond" to raise
#their event. Inheriting classes MUST define sensingLoop. Called at the
@@ -34,7 +34,11 @@ class Input(ThreadedSmootCoreObject):
except:
return False
def run(self):
- while self.parentAlive():
+ while 1:
+ try:
+ die = self.parentAlive()
+ except:
+ break
time.sleep(self.argDict['RefreshInterval']/float(1000))
self.acquireLock()
self.sensingLoop()
diff --git a/operationscore/SmootCoreObject.py b/operationscore/SmootCoreObject.py
index 7e3c8bd..291519a 100644
--- a/operationscore/SmootCoreObject.py
+++ b/operationscore/SmootCoreObject.py
@@ -18,7 +18,7 @@ class SmootCoreObject(object):
def releaseLock(self):
self.lock.release()
def className(self):
- return str(self.__class__).split('.')[-1] #TODO: this doesn't work.
+ return self.__class__.__name__
def __setitem__(self,k, item):
self.argDict[k] = item
def __getitem__(self, item):
diff --git a/pixelmappers/SimpleMapper.py b/pixelmappers/SimpleMapper.py
index bc51cf9..5d4dceb 100644
--- a/pixelmappers/SimpleMapper.py
+++ b/pixelmappers/SimpleMapper.py
@@ -23,7 +23,7 @@ class SimpleMapper(PixelMapper):
#optimizations possible. This might be slow in the long run
if pixelValid:
ret.append((pixel, 1))
- except:
+ except Exception as exp:
raise Exception('Bad event condition')
return ret
diff --git a/renderers/IndoorRenderer.py b/renderers/IndoorRenderer.py
index c13d11f..0ee566a 100644
--- a/renderers/IndoorRenderer.py
+++ b/renderers/IndoorRenderer.py
@@ -2,7 +2,7 @@ from operationscore.Renderer import *
import util.PacketComposition as composer
import util.NetworkOps as network
import socket,pdb
-port = 6038
+sock_port = 6038
#Renderer for a Specific Light System.
class IndoorRenderer(Renderer):
def initRenderer(self):
@@ -26,9 +26,10 @@ class IndoorRenderer(Renderer):
(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)
+ self.sockets[ip] = network.getConnectedSocket(ip,sock_port)
packet = composer.composePixelStripPacket(pixelStrip, port)
self.sockets[ip].send(packet, 0x00)
- except:
- pass #Rendering error. Log it. LOG
+ #pdb.set_trace()
+ except Exception as inst:
+ print inst
diff --git a/renderers/Pygame.xml b/renderers/Pygame.xml
new file mode 100644
index 0000000..e37739d
--- /dev/null
+++ b/renderers/Pygame.xml
@@ -0,0 +1,7 @@
+<Renderer>
+ <Class>renderers.PygameRenderer</Class>
+ <Args>
+ <Id>pygamerender</Id>
+ <displaySize>(1300,50)</displaySize>
+ </Args>
+</Renderer>
diff --git a/renderers/SixStripUDP.xml b/renderers/SixStripUDP.xml
new file mode 100644
index 0000000..f3c9e75
--- /dev/null
+++ b/renderers/SixStripUDP.xml
@@ -0,0 +1,18 @@
+<Renderer>
+ <Class>renderers.IndoorRenderer</Class>
+ <Args>
+ <Id>indoorRenderer</Id>
+ <PowerSupply>
+ <IP>10.31.255.233</IP>
+ <PortMapping>{'strip1':1, 'strip2':2}</PortMapping>
+ </PowerSupply>
+ <PowerSupply>
+ <IP>10.32.97.17</IP>
+ <PortMapping>{'strip3':1, 'strip4':2}</PortMapping>
+ </PowerSupply>
+ <PowerSupply>
+ <IP>10.32.96.211</IP>
+ <PortMapping>{'strip5':1, 'strip6':2}</PortMapping>
+ </PowerSupply>
+ </Args>
+</Renderer>
diff --git a/renderers/SixStripUDPPygame.xml b/renderers/SixStripUDPPygame.xml
new file mode 100644
index 0000000..9a5dfa8
--- /dev/null
+++ b/renderers/SixStripUDPPygame.xml
@@ -0,0 +1,27 @@
+<RendererConfiguration>
+ <Renderer>
+ <Class>renderers.IndoorRenderer</Class>
+ <Args>
+ <Id>indoorRenderer</Id>
+ <PowerSupply>
+ <IP>10.31.255.233</IP>
+ <PortMapping>{'strip1':1, 'strip2':2}</PortMapping>
+ </PowerSupply>
+ <PowerSupply>
+ <IP>10.32.97.17</IP>
+ <PortMapping>{'strip3':1, 'strip4':2}</PortMapping>
+ </PowerSupply>
+ <PowerSupply>
+ <IP>10.32.96.211</IP>
+ <PortMapping>{'strip5':1, 'strip6':2}</PortMapping>
+ </PowerSupply>
+ </Args>
+ </Renderer>
+ <Renderer>
+ <Class>renderers.PygameRenderer</Class>
+ <Args>
+ <Id>pygamerender</Id>
+ <displaySize>(1300,50)</displaySize>
+ </Args>
+ </Renderer>
+</RendererConfiguration>
diff --git a/tests/testdata/compositeTESTout.xml b/tests/testdata/compositeTESTout.xml
index 435b75a..a306190 100644
--- a/tests/testdata/compositeTESTout.xml
+++ b/tests/testdata/compositeTESTout.xml
@@ -1,11 +1,11 @@
<Override>
<A>
- <override>overide parameter</override>
+ <blah>test</blah>
+ <foo>bar</foo>
+<override>overide parameter</override>
</A>
-<B OverrideBehavior="Merge">
- <this>taht</this>
- <that>this</that>
-<SomeNewParam>blah</SomeNewParam>
+<B OverrideBehavior="Replace">
+ <SomeNewParam>blah</SomeNewParam>
</B>
<A>
<someparam>appenedA</someparam>
diff --git a/tests/testdata/compositeTRUTH.xml b/tests/testdata/compositeTRUTH.xml
index 435b75a..a306190 100644
--- a/tests/testdata/compositeTRUTH.xml
+++ b/tests/testdata/compositeTRUTH.xml
@@ -1,11 +1,11 @@
<Override>
<A>
- <override>overide parameter</override>
+ <blah>test</blah>
+ <foo>bar</foo>
+<override>overide parameter</override>
</A>
-<B OverrideBehavior="Merge">
- <this>taht</this>
- <that>this</that>
-<SomeNewParam>blah</SomeNewParam>
+<B OverrideBehavior="Replace">
+ <SomeNewParam>blah</SomeNewParam>
</B>
<A>
<someparam>appenedA</someparam>
diff --git a/tests/testdata/inheritanceTEST.xml b/tests/testdata/inheritanceTEST.xml
index c2efd71..d90e9af 100644
--- a/tests/testdata/inheritanceTEST.xml
+++ b/tests/testdata/inheritanceTEST.xml
@@ -1,3 +1,22 @@
<A>
- <InheritsFrom>tests/testdata/aParent.xml</InheritsFrom>
+ <B>
+ <SubB>
+ <SubSubB>
+ <A>
+ <InheritsFrom>tests/testdata/aParent.xml</InheritsFrom>
+ </A>
+ </SubSubB>
+ </SubB>
+ <A>
+ <InheritsFrom>tests/testdata/aParent.xml</InheritsFrom>
+ </A>
+ </B>
</A>
+
+<!--
+<Parent>
+ <A>
+ <InheritsFrom>tests/testdata/aParent.xml</InheritsFrom>
+ </A>
+</Parent>
+-->
diff --git a/tests/testdata/inheritanceTESTout.xml b/tests/testdata/inheritanceTESTout.xml
index ffa6667..e8fb228 100644
--- a/tests/testdata/inheritanceTESTout.xml
+++ b/tests/testdata/inheritanceTESTout.xml
@@ -1,4 +1,16 @@
<A>
- <param1>1</param1>
+ <B>
+ <SubB>
+ <SubSubB>
+ <A>
+ <param1>1</param1>
<param2>2</param2>
+</A>
+ </SubSubB>
+ </SubB>
+ <A>
+ <param1>1</param1>
+ <param2>2</param2>
+</A>
+ </B>
</A> \ No newline at end of file
diff --git a/tests/testdata/inheritanceTRUTH.xml b/tests/testdata/inheritanceTRUTH.xml
index ffa6667..e8fb228 100644
--- a/tests/testdata/inheritanceTRUTH.xml
+++ b/tests/testdata/inheritanceTRUTH.xml
@@ -1,4 +1,16 @@
<A>
- <param1>1</param1>
+ <B>
+ <SubB>
+ <SubSubB>
+ <A>
+ <param1>1</param1>
<param2>2</param2>
+</A>
+ </SubSubB>
+ </SubB>
+ <A>
+ <param1>1</param1>
+ <param2>2</param2>
+</A>
+ </B>
</A> \ No newline at end of file
diff --git a/tests/testdata/override.xml b/tests/testdata/override.xml
index 1108fb0..722554a 100644
--- a/tests/testdata/override.xml
+++ b/tests/testdata/override.xml
@@ -2,7 +2,7 @@
<A>
<override>overide parameter</override>
</A>
-<B OverrideBehavior="Merge">
+<B OverrideBehavior="Replace">
<SomeNewParam>blah</SomeNewParam>
</B>
<APPEND>
diff --git a/util/Config.py b/util/Config.py
index 33e6fee..4c1eb1e 100644
--- a/util/Config.py
+++ b/util/Config.py
@@ -1,25 +1,29 @@
from xml.etree.ElementTree import *
+import sys
import xml
import pdb
import util.Strings as Strings
+import util.Search as Search
+from logger import main_log, exception_log
classArgsMem = {}
CONFIG_PATH = 'config/'
+DEFAULT_OVERRIDE_MODE = 'Merge'
def loadParamRequirementDict(className):
if not className in classArgsMem: #WOO CACHING
classArgsMem[className] = fileToDict(CONFIG_PATH + className)
return classArgsMem[className]
#Loads a config file. If its an xml file, inheritances are automatically resolved.
def loadConfigFile(fileName): #TODO: error handling etc.
- #try:
- #fileName = CONFIG_PATH + fileName
+ try:
if '.params' in fileName:
return fileToDict(fileName)
if '.xml' in fileName:
- config = ElementTree() #use .fromstring, and resolve xincludes
+ config = ElementTree()
config.parse(fileName)
- config = ElementTree(resolveConfigInheritance(config.getroot()))
+ resolveDocumentInheritances(config.getroot())
return config
- #except:
+ except Exception as inst:
+ main_log.error('Error loading config file ' + fileName)#, inst) TODO: log exception too
return None
#Takes an Element or an ElementTree. If it is a tree, it returns its root. Otherwise, just returns
#it
@@ -28,9 +32,15 @@ def getElement(el):
return el
elif el.__class__ == ElementTree:
return el.getroot()
+#XML tree composition. Returns the resulting tree, but happens in-place in the overriding tree.
def compositeXMLTrees(parentTree, overridingTree): #TODO: break up into sub-methods, change it to
#use .find()
#type checking -- convert ElementTrees to their root elements
+ if parentTree == None:
+ return overridingTree
+ if overridingTree == None:
+ return parentTree #TODO: this will probably cause a bug since it isn't in-place on
+ #overridingTree
parentTree = getElement(parentTree)
overridingTree = getElement(overridingTree)
parentItems = parentTree.getchildren()
@@ -44,13 +54,14 @@ def compositeXMLTrees(parentTree, overridingTree): #TODO: break up into sub-meth
#do we merge or replace?
intersectingElements = findElementsByTag(item.tag, overrideItems)
if len(intersectingElements) > 1:
- print 'ABUSE!'
+ main_log.warn('ABUSE! Override of multiple items isn\'t well defined. Don\'t do\
+ it!')
interEl = intersectingElements[0]
- mode = 'Replace'
+ mode = DEFAULT_OVERRIDE_MODE
if Strings.OVERRIDE_BEHAVIOR in interEl.attrib:
mode = interEl.attrib[Strings.OVERRIDE_BEHAVIOR]
if mode != 'Replace' and mode != 'Merge':
- print 'Bad Mode. Choosing to replace.'
+ main_log.warn('Bad Override Mode. Choosing to replace.')
mode = 'Replace'
if mode == 'Replace':
pass #we don't need to do anything
@@ -68,16 +79,31 @@ def findElementsByTag(tag, eList):
def fileToDict(fileName):
fileText = ''
try:
- print 'File Read'
with open(fileName) as f:
for line in f:
fileText += line.rstrip('\n').lstrip('\t') + ' '
except IOError:
+ exception_log.exception('Failure reading ' + fileName)
return {}
if fileText == '':
return {}
+ try:
+ resultDict = eval(fileText)
+ main_log.info(fileName + ' read and parsed')
+ return resultDict
+ except:
+ exception_log.info(fileName + ' is not a well formed python dict. Parsing failed')
return eval(fileText)
#parses arguments into python objects if possible, otherwise leaves as strings
+def pullArgsFromItem(parentNode):
+ attribArgs = {}
+ for arg in parentNode.attrib: #automatically pull attributes into the argdict
+ attribArgs[arg] = parentNode.attrib[arg]
+ argNode = parentNode.find('Args')
+ args = generateArgDict(argNode)
+ for key in attribArgs:
+ args[key] = attribArgs[key]
+ return args
def generateArgDict(parentNode, recurse=False):
args = {}
for arg in parentNode.getchildren():
@@ -100,11 +126,19 @@ def generateArgDict(parentNode, recurse=False):
if len(args.keys()) == 1 and recurse:
return args[args.keys()[0]]
return args
-
-def resolveConfigInheritance(el):
+#In place resolution of document inheritances. Doesn't return anything.
+def resolveDocumentInheritances(el):
+ abstractMembers = Search.parental_tree_search(el, '.getchildren()', '.tag==\'InheritsFrom\'')
+ for subel in abstractMembers:
+ subel = resolveInheritance(subel)
+#In place resolution of inheritence. Doesn't return anything.
+def resolveInheritance(el):
parentClass = el.find('InheritsFrom')
if parentClass != None:
parentTree = loadConfigFile(parentClass.text)
- el = compositeXMLTrees(el, parentTree)
+ if parentTree == None:
+ main_log.warn('Inheritance Failed. ' + parentClass.text + 'does not exist')
+ main_log.error('Inheritance Failed. ' + parentClass.text + 'does not exist')
+ return el
+ el = compositeXMLTrees(parentTree, el)
el.remove(parentClass) #get rid of the inheritance flag
- return el
diff --git a/util/Geo.py b/util/Geo.py
index 885c585..a9243de 100644
--- a/util/Geo.py
+++ b/util/Geo.py
@@ -1,6 +1,7 @@
#Geometry code
import math
from bisect import *
+import random
def pointWithinBoundingBox(point, bb): #this could be in 4 lines, but I'm lazy.
return sum([(point[i % 2] <= bb[i]) == (i>1) for i in range(4)]) == 4
print pointWithinBoundingBox((118,21), (10,8,298,42))
@@ -13,3 +14,8 @@ def gaussian(x,height,center,width):
return a*math.exp(-((x-b)**2)/(2*c**2))
def dist(l1, l2):
return math.sqrt(sum([(l1[i]-l2[i])**2 for i in range(len(l1))]))
+def randomLoc(boundingBox): #TODO: make less shitty
+ loc = []
+ loc.append(random.randint(0, boundingBox[0]))
+ loc.append(random.randint(0, boundingBox[1]))
+ return tuple(loc)
diff --git a/util/NetworkOps.py b/util/NetworkOps.py
index 0404975..6c50c6d 100644
--- a/util/NetworkOps.py
+++ b/util/NetworkOps.py
@@ -1,8 +1,11 @@
import socket
+from logger import main_log, exception_log
def getConnectedSocket(ip,port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
sock.connect((ip, port))
- except:
- print 'network down'
- return sock
+ return sock
+ except Exception as inst:
+ main_log.error('Network down. All network based renderers and sensors will not function.',
+ inst)
+ print (ip, port)
diff --git a/util/PacketComposition.py b/util/PacketComposition.py
index 2563c61..73eefff 100644
--- a/util/PacketComposition.py
+++ b/util/PacketComposition.py
@@ -6,6 +6,7 @@ DEEPMAGIC = 0xc001d00d
MAGICHASH = 0x69000420
PORTOUT = 0x0108
UNI = 0
+import pdb
kinetDict = {'flags': 0, 'startcode': 0, 'pad':0}
def composePixelStripData(pixelStrip):
packet = bytearray()
@@ -44,7 +45,6 @@ def kinetPortOut():
def kinetPortOutPayload(argDict):
payload = bytearray()
payload.extend(struct.pack('B', argDict['port']))
- #payload.append(0x00) #somepadding? lolwtf.
payload.extend(struct.pack('H', argDict['flags']))
#payload.append(0x00) #somepadding? lolwtf.
payload.extend(struct.pack('H', argDict['len']))
diff --git a/util/Search.py b/util/Search.py
index 25882da..f7e4b81 100644
--- a/util/Search.py
+++ b/util/Search.py
@@ -6,3 +6,17 @@ def find_le(a, x):
def find_ge(a, x):
'Find leftmost value greater than x'
return bisect_left(a, x)
+#returns parents of nodes that meed a given condition
+def parental_tree_search(root, childrenstr, conditionstr):
+ ret = []
+ queue = [root]
+ while queue:
+ current = queue.pop()
+ children = eval('current'+childrenstr)
+ for child in children:
+ if eval('child'+conditionstr):
+ ret.append(current)
+ #we know have a tree, so there are no back-edges etc, so no checking of that kind is
+ #necessary
+ queue += children
+ return ret