annotate mcserver/mcserver.py @ 40:7656f048bbdf moodplay

Added DMX send functionality into MovingBlob.draw, added globals for DMX universe, number of lighting fixtures, ambient lighting colour.
author JWoodbridge <j.woodbridge@se12.qmul.ac.uk>
date Thu, 07 May 2015 14:56:42 +0100
parents fe04ff3547c7
children 4455a77435b0 c0b34039917a
rev   line source
gyorgyf@0 1 #!/usr/bin/env python
gyorgyf@0 2 # encoding: utf-8
gyorgyf@0 3 """
gyorgyf@0 4 mcserver.py
gyorgyf@0 5
gyorgyf@0 6 Created by George Fazekas on 2012-06-16.
gyorgyf@0 7 Copyright (c) 2012 . All rights reserved.
gyorgyf@0 8 """
gyorgyf@0 9
gyorgyf@12 10 import os,sys,optparse,signal,time,math
gyorgyf@0 11 import cherrypy as cp
gyorgyf@0 12
gyorgyf@0 13 from cherrypy.lib import static
gyorgyf@0 14 import subprocess as sp
gyorgyf@0 15 from subprocess import Popen as spopen
gyorgyf@0 16
gyorgyf@0 17
gyorgyf@0 18 op = optparse.OptionParser()
gyorgyf@0 19 op.add_option('-u', '--user', action="store", dest="USER", default="server", type="str")
gyorgyf@0 20 options, args = op.parse_args()
gyorgyf@0 21 CONFIG_FILE = "mc%(USER)s.cfg" %options.__dict__
gyorgyf@0 22
gyorgyf@0 23 if not os.path.isfile(CONFIG_FILE) :
gyorgyf@4 24 print >> sys.stderr, "Config file not found: %s" %CONFIG_FILE
gyorgyf@0 25 sys.exit(-1)
gyorgyf@0 26
gyorgyf@0 27
gyorgyf@12 28 class Input(object):
gyorgyf@12 29
gyorgyf@27 30 def __init__(self,x,y,age,dist):
gyorgyf@12 31 self.time = time.time()
gyorgyf@12 32 self.x=float(x)
gyorgyf@12 33 self.y=float(y)
gyorgyf@12 34 self.count = 1
gyorgyf@27 35 self.age = age
gyorgyf@27 36 self.dist = dist
gyorgyf@12 37
gyorgyf@12 38 def __cmp__(self,other):
gyorgyf@12 39 d = math.sqrt( math.pow((self.x-other.x),2) + math.pow((self.y-other.y),2) )
gyorgyf@27 40 if d < self.dist :
gyorgyf@12 41 return 0
gyorgyf@12 42 else :
gyorgyf@12 43 return -1
gyorgyf@12 44
gyorgyf@12 45 def dead(self):
gyorgyf@27 46 return time.time()-self.time > self.age
gyorgyf@12 47
gyorgyf@12 48 def __repr__(self):
gyorgyf@27 49 # return (self.x,self.y,self.count).__repr__()
gyorgyf@27 50 return "(%.4f,%.4f,%i)" %(self.x,self.y,self.count)
gyorgyf@12 51
gyorgyf@12 52 def inc(self):
gyorgyf@12 53 self.time = time.time()
gyorgyf@12 54 self.count += 1
gyorgyf@27 55 # print self.count
gyorgyf@12 56
gyorgyf@12 57
gyorgyf@0 58 class MoodConductor:
gyorgyf@0 59
gyorgyf@5 60 def __init__(self):
gyorgyf@12 61 self.inputs = []
gyorgyf@27 62 self.age = 3
gyorgyf@27 63 self.dist = 0.1
gyorgyf@29 64 self.ninp = 18
gyorgyf@5 65
gyorgyf@27 66 # def index(self):
gyorgyf@27 67 # return str()
gyorgyf@0 68
gyorgyf@0 69 @cp.expose
gyorgyf@33 70 def test(self):
gyorgyf@33 71 print "Server test function accessed."
gyorgyf@33 72 cp.log.error("Server test function accessed.")
gyorgyf@33 73 return "Server: Test passed."
gyorgyf@33 74
gyorgyf@33 75 @cp.expose
gyorgyf@0 76 def mood(self,x,y):
gyorgyf@33 77 print "Received coordinates", x,y
gyorgyf@27 78 i = Input(x,y,self.age,self.dist)
gyorgyf@12 79 if i in self.inputs :
gyorgyf@12 80 self.inputs[self.inputs.index(i)].inc()
gyorgyf@12 81 else :
gyorgyf@12 82 self.inputs.insert(0,i)
gyorgyf@27 83 self.inputs = self.inputs[:self.ninp]
gyorgyf@29 84 cp.log.error("%s,%.6s,%.6s,%s" %(str(cp.request.remote.ip),x,y,i.time))
gyorgyf@12 85 return str()
gyorgyf@5 86
gyorgyf@5 87 @cp.expose
gyorgyf@5 88 def result(self):
gyorgyf@12 89 for i in self.inputs :
gyorgyf@12 90 if i.dead() : self.inputs.remove(i)
gyorgyf@12 91 return self.inputs.__repr__()
gyorgyf@27 92
gyorgyf@27 93 @cp.expose
gyorgyf@27 94 def config(self,**kwargs):
gyorgyf@27 95 if kwargs.has_key('age') :
gyorgyf@27 96 self.age = float(kwargs['age'])
gyorgyf@27 97 if kwargs.has_key('dist') :
gyorgyf@27 98 self.dist = float(kwargs['dist'])
gyorgyf@27 99 if kwargs.has_key('ninp') :
gyorgyf@27 100 self.ninp = int(kwargs['ninp'])
gyorgyf@29 101 # cp.log.error("Config changed...")
gyorgyf@32 102 print "New configuration received from visual client."
gyorgyf@27 103 return str()
gyorgyf@27 104
gyorgyf@27 105 @cp.expose
gyorgyf@27 106 def getconf(self):
gyorgyf@27 107 self.config_list = ['age','dist','ninp']
gyorgyf@29 108 cp.log.error(str(map(lambda x: (x,"%.3f" % self.__dict__[x]),self.config_list)))
gyorgyf@27 109 return str(map(lambda x: (x,"%.3f" % self.__dict__[x]),self.config_list)) #+ " Sessions: " + str(cp.tools.sessions)
gyorgyf@5 110
gyorgyf@0 111
gyorgyf@0 112
gyorgyf@0 113
gyorgyf@0 114 def getProcessPids(port,kill=False):
gyorgyf@0 115 '''Get the pid of the offending Python process given a port after an unsuccessful restart.'''
gyorgyf@0 116 print "Running lsof -i :"+str(port)," ...\n\n"
gyorgyf@0 117 command = "lsof -i :"+str(port)
gyorgyf@0 118 w = spopen(command,stdout=sp.PIPE,stderr=sp.PIPE,shell=True)
gyorgyf@0 119 se = w.stderr.readlines()
gyorgyf@0 120 result = w.stdout.readlines()
gyorgyf@0 121 exitcode = w.wait()
gyorgyf@0 122 if not result :
gyorgyf@33 123 print "getProcessPid:: Unable to obtain process pid. (lsof returned nothing. exitcode: %s) This is fine in most cases..." %str(exitcode)
gyorgyf@0 124 return False
gyorgyf@0 125 import pprint
gyorgyf@0 126 pprint.pprint(result)
gyorgyf@0 127
gyorgyf@0 128 # get heading:
gyorgyf@0 129 ix = None
gyorgyf@0 130 head = result[0].upper()
gyorgyf@0 131 if 'PID' in head:
gyorgyf@0 132 head = filter(lambda x: x != str(), head.split(' '))
gyorgyf@0 133 head = map(lambda x: x.strip().replace(' ',''), head)
gyorgyf@0 134 if 'PID' in head : ix = head.index('PID')
gyorgyf@0 135 # get process pid
gyorgyf@0 136 pids = []
gyorgyf@0 137 for line in result :
gyorgyf@0 138 if 'python' in line.lower() :
gyorgyf@0 139 line = filter(lambda x: x != str(), line.split(' '))
gyorgyf@0 140 line = map(lambda x: x.strip().replace(' ',''), line)
gyorgyf@0 141 try :
gyorgyf@0 142 if ix :
gyorgyf@0 143 pids.append(int(line[ix]))
gyorgyf@0 144 else:
gyorgyf@0 145 numbers = filter(lambda x: x.isdigit(), line)
gyorgyf@0 146 pids.append(int(numbers[0]))
gyorgyf@0 147 except:
gyorgyf@0 148 print 'Error parsing lsof results.'
gyorgyf@0 149 return False
gyorgyf@0 150 print 'Pids found: ',pids
gyorgyf@0 151 # kill if specified
gyorgyf@0 152 if kill :
gyorgyf@0 153 pids_killed = []
gyorgyf@0 154 import signal
gyorgyf@0 155 for pid in pids:
gyorgyf@0 156 print 'Killing process: ',pid
gyorgyf@0 157 try :
gyorgyf@0 158 os.kill(pid,signal.SIGKILL)
gyorgyf@0 159 pids_killed.append(pid)
gyorgyf@0 160 except :
gyorgyf@0 161 print 'Failed: ',pid
gyorgyf@0 162 if pids_killed :
gyorgyf@0 163 print 'Processes killed:',pids_killed,' Waiting 10 secods...'
gyorgyf@0 164 import time
gyorgyf@0 165 time.sleep(10)
gyorgyf@32 166 print "Starting..."
gyorgyf@0 167 return True
gyorgyf@0 168 return False
gyorgyf@0 169
gyorgyf@0 170
gyorgyf@0 171 def main(argv=None):
gyorgyf@0 172
gyorgyf@0 173 # Configure and start
gyorgyf@3 174 cp.config.update(CONFIG_FILE)
gyorgyf@0 175 cp.config.update({'tools.staticdir.root': os.getcwd()})
gyorgyf@3 176 cp.tree.mount(MoodConductor(),script_name="/moodconductor",config=CONFIG_FILE)
gyorgyf@2 177 port = int(cp.server.socket_port)
gyorgyf@3 178 ip = cp.server.socket_host
gyorgyf@3 179 print "Trying to bind: %(ip)s:%(port)s" %locals()
gyorgyf@0 180 getProcessPids(port,kill=True)
gyorgyf@33 181 print "Starting..."
gyorgyf@0 182 cp.quickstart()
gyorgyf@0 183
gyorgyf@0 184 if __name__ == "__main__":
gyorgyf@0 185 main()