comparison service/garageArduino/garageArduino.py @ 839:9cf01cee74f6

garage: videoselect and shiftbrite move from parallel to arduino Ignore-this: 45c791caa87d4c054826020eeae8298b darcs-hash:20120625075033-312f9-fe2b5088e638e008dd194bd450aa1bac3d48c233.gz
author drewp <drewp@bigasterisk.com>
date Mon, 25 Jun 2012 00:50:33 -0700
parents ccbff2a4b8ce
children 62b3bb861e35
comparison
equal deleted inserted replaced
838:36dbbb01d689 839:9cf01cee74f6
3 talks to frontdoordriver.pde on an arduino 3 talks to frontdoordriver.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, defer 9 from twisted.internet import reactor, task, defer
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")
16 sys.path.append("../../../room") 16 sys.path.append("../../../room")
17 from carbondata import CarbonClient 17 from carbondata import CarbonClient
18 sys.path.append("/my/site/magma") 18 sys.path.append("/my/site/magma")
19 from stategraph import StateGraph 19 from stategraph import StateGraph
20 from rdflib import Namespace, RDF, Literal 20 from rdflib import Namespace, RDF, Literal
21 from webcolors import hex_to_rgb, rgb_to_hex
22
23 def rgbFromHex(h):
24 """returns tuple of 0..1023"""
25 norm = hex_to_rgb(h)
26 return tuple([x * 4 for x in norm])
27
28 def hexFromRgb(rgb):
29 return rgb_to_hex(tuple([x // 4 for x in rgb]))
21 30
22 31
23 ROOM = Namespace("http://projects.bigasterisk.com/room/") 32 ROOM = Namespace("http://projects.bigasterisk.com/room/")
24 DEV = Namespace("http://projects.bigasterisk.com/device/") 33 DEV = Namespace("http://projects.bigasterisk.com/device/")
25 34
50 def setGarage(self, level): 59 def setGarage(self, level):
51 """set garage door opener pin""" 60 """set garage door opener pin"""
52 self.ser.write("\x60\x04"+chr(int(bool(level)))) 61 self.ser.write("\x60\x04"+chr(int(bool(level))))
53 return self.ser.readJson()['garage'] 62 return self.ser.readJson()['garage']
54 63
64 def setVideoSelect(self, chan):
65 """set video select bits from 0..3"""
66 self.ser.write("\x60\x05"+chr(chan))
67 return self.ser.readJson()['videoSelect']
68
69 def shiftbrite(self, colors):
70 """
71 shift out this sequence of (r,g,b) triples of 10-bit ints
72 """
73 current = "".join(bitstring.pack("0b01, uint:10, uint:10, uint:10",
74 127, 127, 127).bytes
75 for loop in range(len(colors)))
76 out = "".join(bitstring.pack("0b00, uint:10, uint:10, uint:10",
77 b, r, g).bytes
78 for r,g,b in colors)
79 out = current + out
80 self.ser.write("\x60\x06" + chr(len(out)) + out)
81 msg = self.ser.readJson()
82 assert msg == {"ok":1}, msg
55 83
56 class Index(PrettyErrorHandler, cyclone.web.RequestHandler): 84 class Index(PrettyErrorHandler, cyclone.web.RequestHandler):
57 def get(self): 85 def get(self):
58 """ 86 """
59 this is an acceptable status check since it makes a round-trip 87 this is an acceptable status check since it makes a round-trip
130 self.write("pin low. Done") 158 self.write("pin low. Done")
131 d.callback(None) 159 d.callback(None)
132 reactor.callLater(1.5, finish) # this time depends on the LP circuit 160 reactor.callLater(1.5, finish) # this time depends on the LP circuit
133 return d 161 return d
134 162
163 class VideoSelect(PrettyErrorHandler, cyclone.web.RequestHandler):
164 def post(self):
165 self.set_header("Content-Type", "application/javascript")
166 v = self.settings.arduino.setVideoSelect(int(self.request.body))
167 self.write(json.dumps({"videoSelect" : v}))
168
169 class Brite(PrettyErrorHandler, cyclone.web.RequestHandler):
170 def get(self, chan):
171 self.set_header("Content-Type", "text/plain")
172 self.write(hexFromRgb(self.settings.colors[int(chan)]))
173
174 def put(self, chan):
175 s = self.settings
176 s.colors[int(chan)] = rgbFromHex(self.request.body)
177 s.arduino.shiftbrite(s.colors)
178 post = put
179
135 class Application(cyclone.web.Application): 180 class Application(cyclone.web.Application):
136 def __init__(self, ard, poller): 181 def __init__(self, ard, poller):
137 handlers = [ 182 handlers = [
138 (r"/", Index), 183 (r"/", Index),
139 (r"/graph", GraphPage), 184 (r"/graph", GraphPage),
140 (r"/frontDoorMotion", FrontDoorMotion), 185 (r"/frontDoorMotion", FrontDoorMotion),
141 (r'/housePower', HousePower), 186 (r'/housePower', HousePower),
142 (r'/housePower/raw', HousePowerRaw), 187 (r'/housePower/raw', HousePowerRaw),
143 (r'/housePower/threshold', HousePowerThreshold), 188 (r'/housePower/threshold', HousePowerThreshold),
144 (r'/garageDoorOpen', GarageDoorOpen), 189 (r'/garageDoorOpen', GarageDoorOpen),
190 (r'/videoSelect', VideoSelect),
191 (r"/brite/(\d+)", Brite),
145 ] 192 ]
146 settings = {"arduino" : ard, "poller" : poller} 193 colors = [(0,0,0)] * 1 # stored 10-bit
194 settings = {"arduino" : ard, "poller" : poller, "colors" : colors}
147 cyclone.web.Application.__init__(self, handlers, **settings) 195 cyclone.web.Application.__init__(self, handlers, **settings)
148
149 196
150 class Poller(object): 197 class Poller(object):
151 """ 198 """
152 times the blinks to estimate power usage. Captures the other 199 times the blinks to estimate power usage. Captures the other
153 returned sensor values too in self.lastValues 200 returned sensor values too in self.lastValues