Mercurial > code > home > repos > homeauto
annotate service/frontDoorArduino/frontDoorArduino.py @ 323:e2865f1034a9
frontbed config
Ignore-this: 615b26b5f518db98d2f53f7777755bf2
author | drewp@bigasterisk.com |
---|---|
date | Mon, 15 Jan 2018 02:59:52 -0800 |
parents | 0fa988159bb3 |
children |
rev | line source |
---|---|
0 | 1 """ |
2 talks to the arduino outside the front door. Don't write straight to | |
3 this LCD; use frontDoorMessage for that. | |
4 | |
5 lcd is this wide | |
6 |-------------------| | |
7 22:05 85F in, 71F out | |
8 | |
17 | 9 pin 11 senses the door |
10 pin 12 activates the front yard lights ('out yard') | |
11 | |
0 | 12 """ |
13 | |
14 from __future__ import division | |
15 | |
16 import cyclone.web, json, traceback, os, sys | |
17 from twisted.python import log | |
18 from twisted.internet import reactor, task | |
19 from twisted.web.client import getPage | |
55
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
20 from rdflib import Namespace, Literal, URIRef |
0 | 21 |
22 sys.path.append("/my/proj/house/frontdoor") | |
23 from loggingserial import LoggingSerial | |
24 | |
25 sys.path.append("/my/proj/homeauto/lib") | |
26 from cycloneerr import PrettyErrorHandler | |
27 | |
55
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
28 sys.path.append("/my/site/magma") |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
29 from stategraph import StateGraph |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
30 |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
31 DEV = Namespace("http://projects.bigasterisk.com/device/") |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
32 ROOM = Namespace("http://projects.bigasterisk.com/room/") |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
33 |
0 | 34 class Board(object): |
35 """ | |
36 arduino board actions, plus the last values we wrote to it | |
37 """ | |
38 def __init__(self, port): | |
39 self.ser = LoggingSerial(port=port) | |
40 self.ser.flush() | |
41 | |
17 | 42 self.setLcd("") |
43 self.setLcdBrightness(0) | |
44 self.setYardLight(0) | |
0 | 45 |
46 def ping(self): | |
47 self.getDoor() | |
48 | |
49 def getDoor(self): | |
50 self.ser.write("\xff\x01") | |
51 ret = self.ser.readJson() | |
52 return ret['door'] | |
53 | |
17 | 54 def setYardLight(self, level): |
55 self.currentYardLight = bool(level) | |
56 self.ser.write("\xff\x04" + chr(bool(self.currentYardLight))) | |
57 | |
58 def getYardLight(self): | |
59 return self.currentYardLight | |
60 | |
0 | 61 def getLcd(self): |
62 return self.currentText | |
63 | |
64 def setLcd(self, txt): | |
65 """ | |
66 up to 8*21 chars | |
67 """ | |
68 self.currentText = txt | |
69 self.ser.write("\xff\x00" + txt + "\x00") | |
70 | |
71 def getLcdBrightness(self): | |
72 return self.currentBrightness | |
73 | |
74 def setLcdBrightness(self, b): | |
75 """b in 0 to 255""" | |
76 self.currentBrightness = b | |
77 self.ser.write("\xff\x03" + chr(b)) | |
78 | |
79 def getTemperature(self): | |
80 """returns parsed json from the board""" | |
81 self.ser.write("\xff\x02") | |
82 # this can take 1.25 seconds per retry | |
83 f = self.ser.readJson() | |
84 | |
85 if f['temp'] > 184 or f['temp'] < -100: | |
86 # this fails a lot, maybe 50% of the time. retry if | |
87 # you want | |
88 raise ValueError("out of range temp value (%s)" % f) | |
89 return f | |
90 | |
91 class index(PrettyErrorHandler, cyclone.web.RequestHandler): | |
92 def get(self): | |
93 self.settings.board.ping() | |
94 | |
95 self.set_header("Content-Type", "application/xhtml+xml") | |
96 self.write(open("index.html").read()) | |
97 | |
55
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
98 class GraphResource(PrettyErrorHandler, cyclone.web.RequestHandler): |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
99 def get(self): |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
100 g = StateGraph(ctx=DEV['frontDoorArduino']) |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
101 |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
102 board = self.settings.board |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
103 g.add((DEV['frontDoorOpen'], ROOM['state'], |
78
0fa988159bb3
old fix to frontDoorArduino for door state. i think this is unused
drewp@bigasterisk.com
parents:
55
diff
changeset
|
104 ROOM['open'] if board.getDoor() == 'open' else ROOM['closed'])) |
55
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
105 g.add((DEV['frontYardLight'], ROOM['state'], |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
106 ROOM['on'] if board.getYardLight() else ROOM['off'])) |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
107 g.add((DEV['frontDoorLcd'], ROOM['text'], |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
108 Literal(board.getLcd()))) |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
109 g.add((DEV['frontDoorLcd'], ROOM['brightness'], |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
110 Literal(board.getLcdBrightness()))) |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
111 |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
112 # not temperature yet because it's slow and should be cached from |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
113 # the last poll |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
114 |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
115 self.set_header('Content-type', 'application/x-trig') |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
116 self.write(g.asTrig()) |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
117 |
0 | 118 class Lcd(PrettyErrorHandler, cyclone.web.RequestHandler): |
119 def get(self): | |
120 self.set_header("Content-Type", "text/plain") | |
121 self.write(self.settings.board.getLcd()) | |
122 | |
123 def put(self): | |
124 self.settings.board.setLcd(self.request.body) | |
125 self.set_status(204) | |
126 | |
127 class Backlight(PrettyErrorHandler, cyclone.web.RequestHandler): | |
128 def get(self): | |
129 self.set_header("Content-Type", "application/json") | |
130 self.write(json.dumps({ | |
131 "backlight" : self.settings.board.getLcdBrightness()})) | |
132 | |
133 def put(self): | |
134 """param brightness=0 to brightness=255""" | |
135 self.settings.board.setLcdBrightness( | |
136 int(self.get_argument('brightness'))) | |
137 self.write("ok") | |
138 post = put | |
139 | |
17 | 140 |
141 class YardLight(PrettyErrorHandler, cyclone.web.RequestHandler): | |
142 def get(self): | |
143 self.set_header("Content-Type", "application/json") | |
144 self.write(json.dumps({ | |
145 "yardLight" : self.settings.board.getYardLight()})) | |
146 | |
147 def put(self): | |
148 """text true or false or 0 or 1""" | |
149 self.settings.board.setYardLight( | |
150 self.request.body.strip() in ['true', '1']) | |
151 self.write("ok") | |
152 post = put | |
153 | |
154 | |
0 | 155 class Door(PrettyErrorHandler, cyclone.web.RequestHandler): |
156 def get(self): | |
157 self.set_header("Content-Type", "text/plain") | |
158 self.write(self.settings.board.getDoor()) | |
159 | |
160 class Temperature(PrettyErrorHandler, cyclone.web.RequestHandler): | |
161 def get(self): | |
162 f = self.settings.board.getTemperature() | |
163 self.set_header("Content-Type", "application/json") | |
164 self.write(f) | |
165 | |
166 class Application(cyclone.web.Application): | |
167 def __init__(self, board): | |
168 handlers = [ | |
169 (r"/", index), | |
55
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
170 (r"/graph", GraphResource), |
0 | 171 (r'/lcd', Lcd), |
172 (r'/door', Door), | |
173 (r'/temperature', Temperature), | |
174 (r'/lcd/backlight', Backlight), | |
17 | 175 (r'/yardLight', YardLight), |
0 | 176 ] |
177 settings = {"board" : board} | |
178 cyclone.web.Application.__init__(self, handlers, **settings) | |
179 | |
180 | |
181 class Poller(object): | |
182 def __init__(self, board, postUrl, boardName): | |
183 self.board = board | |
184 self.postUrl = postUrl | |
185 self.boardName = boardName | |
186 self.last = None | |
187 | |
188 def poll(self): | |
189 try: | |
55
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
190 # this should be fetching everything and pinging reasoning |
0cffbf171a97
frontdoorarduino can return an rdf graph
drewp@bigasterisk.com
parents:
18
diff
changeset
|
191 # if anything is new |
0 | 192 new = self.board.getDoor() |
193 if new != self.last: | |
194 msg = json.dumps(dict(board=self.boardName, | |
195 name="frontDoor", state=new)) | |
196 getPage(self.postUrl, | |
197 method="POST", | |
198 postdata=msg, | |
199 headers={'Content-Type' : 'application/json'} | |
200 ).addErrback(self.reportError, msg) | |
201 | |
202 self.last = new | |
203 except (IOError, OSError): | |
204 os.abort() | |
205 except Exception, e: | |
206 print "poll error", e | |
207 traceback.print_exc() | |
208 | |
209 def reportError(self, msg, *args): | |
210 print "post error", msg, args | |
211 | |
212 if __name__ == '__main__': | |
213 | |
214 config = { # to be read from a file | |
18
84af13435de7
move more ports to use /dev/serial/by-id/
drewp@bigasterisk.com
parents:
17
diff
changeset
|
215 'arduinoPort': '/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A6004bUG-if00-port0', |
0 | 216 'servePort' : 9080, |
217 'pollFrequency' : 1, | |
218 'boardName' : 'frontDoor', # gets sent with updates | |
219 'doorChangePost' : 'http://bang.bigasterisk.com:9069/inputChange', | |
220 # todo: need options to preset inputs/outputs at startup | |
221 } | |
222 | |
17 | 223 #log.startLogging(sys.stdout) |
0 | 224 |
225 board = Board(port=config['arduinoPort']) | |
226 | |
227 p = Poller(board, config['doorChangePost'], config['boardName']) | |
228 task.LoopingCall(p.poll).start(1/config['pollFrequency']) | |
229 reactor.listenTCP(config['servePort'], Application(board)) | |
230 reactor.run() |