comparison service/bedroomArduino/bedroomArduino.py @ 842:1f69e77411ba

add shiftbrites to bedroom arduino Ignore-this: c0ce65f20b52679af58b9e31bcc3cf2e darcs-hash:20120825212045-312f9-46f810a9229b60efb4db1200b17397c60c17c178
author drewp <drewp@bigasterisk.com>
date Sat, 25 Aug 2012 14:20:45 -0700
parents a87cae710556
children 1fada3a61c5f
comparison
equal deleted inserted replaced
841:ddc2cdbfde50 842:1f69e77411ba
3 talks to bed.pde on an arduino 3 talks to bed.pde on an arduino
4 """ 4 """
5 5
6 from __future__ import division 6 from __future__ import division
7 7
8 import cyclone.web, json, traceback, os, sys, time, logging 8 import cyclone.web, json, traceback, os, sys, time, logging, bitstring
9 from twisted.internet import reactor, task 9 from twisted.internet import reactor, task
10 from twisted.web.client import getPage 10 from twisted.web.client import getPage
11 sys.path.append("/my/proj/house/frontdoor") 11 sys.path.append("/my/proj/house/frontdoor")
12 from loggingserial import LoggingSerial 12 from loggingserial import LoggingSerial
13 sys.path.append("/my/proj/homeauto/lib") 13 sys.path.append("/my/proj/homeauto/lib")
14 from cycloneerr import PrettyErrorHandler 14 from cycloneerr import PrettyErrorHandler
15 from logsetup import log 15 from logsetup import log
16
17 sys.path.append("/my/proj/pixel/shiftweb")
18 from shiftweb import hexFromRgb, rgbFromHex
16 19
17 sys.path.append("/my/site/magma") 20 sys.path.append("/my/site/magma")
18 from stategraph import StateGraph 21 from stategraph import StateGraph
19 from rdflib import Namespace 22 from rdflib import Namespace
20 23
32 assert msg == {"ok":True}, msg 35 assert msg == {"ok":True}, msg
33 36
34 def poll(self): 37 def poll(self):
35 self.ser.write("\x60\x01\x00") 38 self.ser.write("\x60\x01\x00")
36 ret = self.ser.readJson() 39 ret = self.ser.readJson()
40 ret['motion'] = int(ret['motion'] > 100)
37 return ret 41 return ret
38 42
39 def setSpeakerChoice(self, pillow): 43 def setSpeakerChoice(self, pillow):
40 self.ser.write("\x60\x02" + chr(pillow)) 44 self.ser.write("\x60\x02" + chr(pillow))
41 return self.ser.readJson() 45 return self.ser.readJson()
46
47 def setLeds(self, colors):
48 """
49 shift out this sequence of (r,g,b) triples of 10-bit ints
50 The nearest led gets color[0], etc.
51 """
52 resetCurrent = "".join(bitstring.pack("0b01, uint:10, uint:10, uint:10",
53 127, 127, 127).bytes
54 for loop in range(len(colors)))
55 out = "".join(bitstring.pack("0b00, uint:10, uint:10, uint:10",
56 b, r, g).bytes
57 for r,g,b in reversed(colors))
58 out = resetCurrent + out
59 self.ser.write("\x60\x03" + chr(len(out)) + out)
60 msg = self.ser.readJson()
61 assert msg == {"ok":1}, msg
42 62
43 class Index(PrettyErrorHandler, cyclone.web.RequestHandler): 63 class Index(PrettyErrorHandler, cyclone.web.RequestHandler):
44 def get(self): 64 def get(self):
45 """ 65 """
46 this is an acceptable status check since it makes a round-trip 66 this is an acceptable status check since it makes a round-trip
53 73
54 class SpeakerChoice(PrettyErrorHandler, cyclone.web.RequestHandler): 74 class SpeakerChoice(PrettyErrorHandler, cyclone.web.RequestHandler):
55 def put(self): 75 def put(self):
56 ret = self.settings.arduino.setSpeakerChoice(int(self.get_argument('pillow'))) 76 ret = self.settings.arduino.setSpeakerChoice(int(self.get_argument('pillow')))
57 self.write(ret) 77 self.write(ret)
78
79 class Brite(PrettyErrorHandler, cyclone.web.RequestHandler):
80 def put(self, which):
81 which = int(which)
82 brites = self.settings.brites
83 if which + 1 > len(brites):
84 brites.extend([(0,0,0)] * (which + 1 - len(brites)))
85 brites[which] = rgbFromHex(self.request.body)
86
87 self.settings.arduino.setLeds(brites)
88 self.set_header("Content-Type", "text/plain")
89 self.write("ok")
58 90
59 class GraphPage(PrettyErrorHandler, cyclone.web.RequestHandler): 91 class GraphPage(PrettyErrorHandler, cyclone.web.RequestHandler):
60 def get(self): 92 def get(self):
61 self.set_header("Content-Type", "application/x-trig") 93 self.set_header("Content-Type", "application/x-trig")
62 g = StateGraph(ROOM['bedroomArduino']) 94 g = StateGraph(ROOM['bedroomArduino'])
73 def __init__(self, config, ard, period): 105 def __init__(self, config, ard, period):
74 self.config, self.ard = config, ard 106 self.config, self.ard = config, ard
75 self.period = period 107 self.period = period
76 self.lastValues = None 108 self.lastValues = None
77 self.lastPollTime = 0 109 self.lastPollTime = 0
78 self.lastMotion = False 110 self.lastMotion = None
79 111
80 def assertIsCurrent(self): 112 def assertIsCurrent(self):
81 """raise an error if the poll data is not fresh""" 113 """raise an error if the poll data is not fresh"""
82 dt = time.time() - self.lastPollTime 114 dt = time.time() - self.lastPollTime
83 if dt > period * 2: 115 if dt > period * 2:
89 try: 121 try:
90 newData = ard.poll() 122 newData = ard.poll()
91 except ValueError, e: 123 except ValueError, e:
92 print e 124 print e
93 else: 125 else:
94 print newData 126 #print newData # for testing
95 return 127
96 self.lastPollTime = now 128 self.lastPollTime = now
97 self.lastValues = newData # for other data besides the blinks 129 self.lastValues = newData # for other data besides the blinks
98 self.processMotion(newData['motion']) 130 self.processMotion(newData['motion'])
99 131
100 except (IOError, OSError): 132 except (IOError, OSError):
119 print "post error", msg, args 151 print "post error", msg, args
120 152
121 if __name__ == '__main__': 153 if __name__ == '__main__':
122 154
123 config = { # to be read from a file 155 config = { # to be read from a file
124 'arduinoPort': '/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A4001lVK-if00-port0', 156 'arduinoPort': '/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A4001nIu-if00-port0',
125 'servePort' : 9088, 157 'servePort' : 9088,
126 'pollFrequency' : 6, 158 'pollFrequency' : 6,
127 'boardName' : 'bedroom', # gets sent with updates 159 'boardName' : 'bedroom', # gets sent with updates
128 } 160 }
129 161
140 172
141 reactor.listenTCP(config['servePort'], cyclone.web.Application([ 173 reactor.listenTCP(config['servePort'], cyclone.web.Application([
142 (r"/", Index), 174 (r"/", Index),
143 (r"/graph", GraphPage), 175 (r"/graph", GraphPage),
144 (r'/speakerChoice', SpeakerChoice), 176 (r'/speakerChoice', SpeakerChoice),
145 ], arduino=ard, poller=p)) 177 (r'/brite/(\d+)', Brite),
178 ], arduino=ard, poller=p, brites=[]))
146 reactor.run() 179 reactor.run()