annotate service/frontDoorArduino/frontDoorArduino.py @ 823:0aafd40e4afc

move more ports to use /dev/serial/by-id/ Ignore-this: 4d9bc18902dfe08897c3e03579c87b23 darcs-hash:20111204030320-312f9-da93888bb0e3b2bc898eb34f3126706d0ac3aefa.gz
author drewp <drewp@bigasterisk.com>
date Sat, 03 Dec 2011 19:03:20 -0800
parents b1c92ee20ff4
children 0cffbf171a97
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
805
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
1 """
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
2 talks to the arduino outside the front door. Don't write straight to
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
3 this LCD; use frontDoorMessage for that.
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
4
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
5 lcd is this wide
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
6 |-------------------|
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
7 22:05 85F in, 71F out
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
8
822
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
9 pin 11 senses the door
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
10 pin 12 activates the front yard lights ('out yard')
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
11
805
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
12 """
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
13
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
14 from __future__ import division
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
15
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
16 import cyclone.web, json, traceback, os, sys
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
17 from twisted.python import log
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
18 from twisted.internet import reactor, task
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
19 from twisted.web.client import getPage
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
20
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
21 sys.path.append("/my/proj/house/frontdoor")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
22 from loggingserial import LoggingSerial
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
23
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
24 sys.path.append("/my/proj/homeauto/lib")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
25 from cycloneerr import PrettyErrorHandler
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
26
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
27 class Board(object):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
28 """
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
29 arduino board actions, plus the last values we wrote to it
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
30 """
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
31 def __init__(self, port):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
32 self.ser = LoggingSerial(port=port)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
33 self.ser.flush()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
34
822
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
35 self.setLcd("")
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
36 self.setLcdBrightness(0)
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
37 self.setYardLight(0)
805
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
38
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
39 def ping(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
40 self.getDoor()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
41
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
42 def getDoor(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
43 self.ser.write("\xff\x01")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
44 ret = self.ser.readJson()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
45 return ret['door']
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
46
822
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
47 def setYardLight(self, level):
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
48 self.currentYardLight = bool(level)
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
49 self.ser.write("\xff\x04" + chr(bool(self.currentYardLight)))
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
50
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
51 def getYardLight(self):
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
52 return self.currentYardLight
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
53
805
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
54 def getLcd(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
55 return self.currentText
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
56
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
57 def setLcd(self, txt):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
58 """
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
59 up to 8*21 chars
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
60 """
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
61 self.currentText = txt
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
62 self.ser.write("\xff\x00" + txt + "\x00")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
63
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
64 def getLcdBrightness(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
65 return self.currentBrightness
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
66
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
67 def setLcdBrightness(self, b):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
68 """b in 0 to 255"""
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
69 self.currentBrightness = b
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
70 self.ser.write("\xff\x03" + chr(b))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
71
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
72 def getTemperature(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
73 """returns parsed json from the board"""
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
74 self.ser.write("\xff\x02")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
75 # this can take 1.25 seconds per retry
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
76 f = self.ser.readJson()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
77
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
78 if f['temp'] > 184 or f['temp'] < -100:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
79 # this fails a lot, maybe 50% of the time. retry if
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
80 # you want
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
81 raise ValueError("out of range temp value (%s)" % f)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
82 return f
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
83
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
84 class index(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
85 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
86 self.settings.board.ping()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
87
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
88 self.set_header("Content-Type", "application/xhtml+xml")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
89 self.write(open("index.html").read())
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
90
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
91 class Lcd(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
92 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
93 self.set_header("Content-Type", "text/plain")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
94 self.write(self.settings.board.getLcd())
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
95
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
96 def put(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
97 self.settings.board.setLcd(self.request.body)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
98 self.set_status(204)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
99
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
100 class Backlight(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
101 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
102 self.set_header("Content-Type", "application/json")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
103 self.write(json.dumps({
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
104 "backlight" : self.settings.board.getLcdBrightness()}))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
105
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
106 def put(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
107 """param brightness=0 to brightness=255"""
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
108 self.settings.board.setLcdBrightness(
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
109 int(self.get_argument('brightness')))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
110 self.write("ok")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
111 post = put
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
112
822
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
113
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
114 class YardLight(PrettyErrorHandler, cyclone.web.RequestHandler):
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
115 def get(self):
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
116 self.set_header("Content-Type", "application/json")
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
117 self.write(json.dumps({
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
118 "yardLight" : self.settings.board.getYardLight()}))
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
119
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
120 def put(self):
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
121 """text true or false or 0 or 1"""
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
122 self.settings.board.setYardLight(
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
123 self.request.body.strip() in ['true', '1'])
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
124 self.write("ok")
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
125 post = put
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
126
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
127
805
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
128 class Door(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
129 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
130 self.set_header("Content-Type", "text/plain")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
131 self.write(self.settings.board.getDoor())
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
132
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
133 class Temperature(PrettyErrorHandler, cyclone.web.RequestHandler):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
134 def get(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
135 f = self.settings.board.getTemperature()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
136 self.set_header("Content-Type", "application/json")
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
137 self.write(f)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
138
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
139 class Application(cyclone.web.Application):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
140 def __init__(self, board):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
141 handlers = [
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
142 (r"/", index),
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
143 (r'/lcd', Lcd),
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
144 (r'/door', Door),
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
145 (r'/temperature', Temperature),
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
146 (r'/lcd/backlight', Backlight),
822
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
147 (r'/yardLight', YardLight),
805
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
148 ]
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
149 settings = {"board" : board}
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
150 cyclone.web.Application.__init__(self, handlers, **settings)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
151
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
152
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
153 class Poller(object):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
154 def __init__(self, board, postUrl, boardName):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
155 self.board = board
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
156 self.postUrl = postUrl
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
157 self.boardName = boardName
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
158 self.last = None
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
159
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
160 def poll(self):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
161 try:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
162 new = self.board.getDoor()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
163 if new != self.last:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
164 msg = json.dumps(dict(board=self.boardName,
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
165 name="frontDoor", state=new))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
166 getPage(self.postUrl,
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
167 method="POST",
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
168 postdata=msg,
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
169 headers={'Content-Type' : 'application/json'}
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
170 ).addErrback(self.reportError, msg)
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
171
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
172 self.last = new
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
173 except (IOError, OSError):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
174 os.abort()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
175 except Exception, e:
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
176 print "poll error", e
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
177 traceback.print_exc()
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
178
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
179 def reportError(self, msg, *args):
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
180 print "post error", msg, args
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
181
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
182 if __name__ == '__main__':
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
183
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
184 config = { # to be read from a file
823
0aafd40e4afc move more ports to use /dev/serial/by-id/
drewp <drewp@bigasterisk.com>
parents: 822
diff changeset
185 'arduinoPort': '/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A6004bUG-if00-port0',
805
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
186 'servePort' : 9080,
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
187 'pollFrequency' : 1,
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
188 'boardName' : 'frontDoor', # gets sent with updates
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
189 'doorChangePost' : 'http://bang.bigasterisk.com:9069/inputChange',
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
190 # todo: need options to preset inputs/outputs at startup
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
191 }
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
192
822
b1c92ee20ff4 yard light toggle button
drewp <drewp@bigasterisk.com>
parents: 805
diff changeset
193 #log.startLogging(sys.stdout)
805
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
194
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
195 board = Board(port=config['arduinoPort'])
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
196
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
197 p = Poller(board, config['doorChangePost'], config['boardName'])
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
198 task.LoopingCall(p.poll).start(1/config['pollFrequency'])
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
199 reactor.listenTCP(config['servePort'], Application(board))
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
200 reactor.run()