Mercurial > code > home > repos > homeauto
comparison service/arduinoNode/arduinoNode.py @ 233:4ebb5cc30002
server/browser graph sync. cut dependency on the WS version. merge some changes between arduino/pi code.
Ignore-this: cf7d20d54e134e8ff33a9ee405610846
author | drewp@bigasterisk.com |
---|---|
date | Sat, 30 Jan 2016 06:40:00 -0800 |
parents | 0aa54404df19 |
children | 141079644c45 |
comparison
equal
deleted
inserted
replaced
232:4e91f3ec460b | 233:4ebb5cc30002 |
---|---|
39 ROOM = Namespace('http://projects.bigasterisk.com/room/') | 39 ROOM = Namespace('http://projects.bigasterisk.com/room/') |
40 HOST = Namespace('http://bigasterisk.com/ruler/host/') | 40 HOST = Namespace('http://bigasterisk.com/ruler/host/') |
41 | 41 |
42 ACTION_BASE = 10 # higher than any of the fixed command numbers | 42 ACTION_BASE = 10 # higher than any of the fixed command numbers |
43 | 43 |
44 CTX = ROOM['arduinosOn%s' % socket.gethostname()] | 44 hostname = socket.gethostname() |
45 CTX = ROOM['arduinosOn%s' % hostname] | |
45 | 46 |
46 class Config(object): | 47 class Config(object): |
47 def __init__(self, masterGraph): | 48 def __init__(self, masterGraph): |
48 self.graph = ConjunctiveGraph() | 49 self.graph = ConjunctiveGraph() |
49 log.info('read config') | 50 log.info('read config') |
72 self.uri = uri | 73 self.uri = uri |
73 self.configGraph = configGraph | 74 self.configGraph = configGraph |
74 self.masterGraph = masterGraph | 75 self.masterGraph = masterGraph |
75 self.dev = dev | 76 self.dev = dev |
76 | 77 |
77 self.masterGraph.patch(Patch(addQuads=[ | 78 self.masterGraph.patch(Patch(addQuads=self.staticStmts())) |
78 (HOST[socket.gethostname()], ROOM['connectedTo'], self.uri, CTX), | 79 |
79 ])) | |
80 | |
81 # The order of this list needs to be consistent between the | 80 # The order of this list needs to be consistent between the |
82 # deployToArduino call and the poll call. | 81 # deployToArduino call and the poll call. |
83 self._devs = devices.makeDevices(configGraph, self.uri) | 82 self._devs = devices.makeDevices(configGraph, self.uri) |
84 self._devCommandNum = dict((dev.uri, ACTION_BASE + devIndex) | 83 self._devCommandNum = dict((dev.uri, ACTION_BASE + devIndex) |
85 for devIndex, dev in enumerate(self._devs)) | 84 for devIndex, dev in enumerate(self._devs)) |
96 return { | 95 return { |
97 'uri': self.uri, | 96 'uri': self.uri, |
98 'dev': self.dev, | 97 'dev': self.dev, |
99 'baudrate': self.baudrate, | 98 'baudrate': self.baudrate, |
100 'devices': [d.description() for d in self._devs], | 99 'devices': [d.description() for d in self._devs], |
101 'graph': 'http://%s6:9059/graph' % socket.gethostname(), #todo | |
102 } | 100 } |
103 | 101 |
104 def open(self): | 102 def open(self): |
105 self.ser = LoggingSerial(port=self.dev, baudrate=self.baudrate, | 103 self.ser = LoggingSerial(port=self.dev, baudrate=self.baudrate, |
106 timeout=2) | 104 timeout=2) |
141 self._exportToGraphite() | 139 self._exportToGraphite() |
142 | 140 |
143 def _exportToGraphite(self): | 141 def _exportToGraphite(self): |
144 # note this is writing way too often- graphite is storing at a lower res | 142 # note this is writing way too often- graphite is storing at a lower res |
145 now = time.time() | 143 now = time.time() |
144 # 20 sec is not precise; just trying to reduce wifi traffic | |
145 if getattr(self, 'lastGraphiteExport', 0) + 20 > now: | |
146 return | |
147 self.lastGraphiteExport = now | |
148 log.debug('graphite export:') | |
146 # objects of these statements are suitable as graphite values. | 149 # objects of these statements are suitable as graphite values. |
147 graphitePredicates = {ROOM['temperatureF']} | 150 graphitePredicates = {ROOM['temperatureF']} |
151 # bug: one sensor can have temp and humid- this will be ambiguous | |
148 for s, graphiteName in self.configGraph.subject_objects(ROOM['graphiteName']): | 152 for s, graphiteName in self.configGraph.subject_objects(ROOM['graphiteName']): |
149 for group in self._statementsFromInputs.values(): | 153 for group in self._statementsFromInputs.values(): |
150 for stmt in group: | 154 for stmt in group: |
151 if stmt[0] == s and stmt[1] in graphitePredicates: | 155 if stmt[0] == s and stmt[1] in graphitePredicates: |
156 log.debug(' sending %s -> %s', stmt[0], graphiteName) | |
152 self._carbon.send(graphiteName, stmt[2].toPython(), now) | 157 self._carbon.send(graphiteName, stmt[2].toPython(), now) |
153 | 158 |
154 def outputStatements(self, stmts): | 159 def outputStatements(self, stmts): |
155 unused = set(stmts) | 160 unused = set(stmts) |
156 for dev in self._devs: | 161 for dev in self._devs: |
157 stmtsForDev = [] | 162 stmtsForDev = [] |
158 for pat in dev.outputPatterns(): | 163 for pat in dev.outputPatterns(): |
174 # we're not currently tracking that, but the usual is | 179 # we're not currently tracking that, but the usual is |
175 # to change them in response to sendOutput so this | 180 # to change them in response to sendOutput so this |
176 # should be good enough. The right answer is to give | 181 # should be good enough. The right answer is to give |
177 # each dev the masterGraph for it to write to. | 182 # each dev the masterGraph for it to write to. |
178 self.syncMasterGraphToHostStatements(dev) | 183 self.syncMasterGraphToHostStatements(dev) |
179 log.info("success") | 184 log.info("output and masterGraph sync complete") |
180 if unused: | 185 if unused: |
181 log.info("Board %s doesn't care about these statements:", self.uri) | 186 log.info("Board %s doesn't care about these statements:", self.uri) |
182 for s in unused: | 187 for s in unused: |
183 log.info("%r", s) | 188 log.warn("%r", s) |
184 | 189 |
185 def syncMasterGraphToHostStatements(self, dev): | 190 def syncMasterGraphToHostStatements(self, dev): |
186 hostStmtCtx = URIRef(dev.uri + '/host') | 191 hostStmtCtx = URIRef(dev.uri + '/host') |
187 newQuads = inContext(dev.hostStatements(), hostStmtCtx) | 192 newQuads = inContext(dev.hostStatements(), hostStmtCtx) |
188 self.masterGraph.patchSubgraph(hostStmtCtx, newQuads) | 193 p = self.masterGraph.patchSubgraph(hostStmtCtx, newQuads) |
189 | 194 log.debug("patch master with these host stmts %s", p) |
195 | |
196 def staticStmts(self): | |
197 return [(HOST[hostname], ROOM['connectedTo'], self.uri, CTX)] | |
198 | |
190 def generateArduinoCode(self): | 199 def generateArduinoCode(self): |
191 code = write_arduino_code.writeCode(self.baudrate, self._devs, self._devCommandNum) | 200 code = write_arduino_code.writeCode(self.baudrate, self._devs, |
201 self._devCommandNum) | |
192 code = write_arduino_code.indent(code) | 202 code = write_arduino_code.indent(code) |
193 cksum = hashlib.sha1(code).hexdigest() | 203 cksum = hashlib.sha1(code).hexdigest() |
194 code = code.replace('CODE_CHECKSUM', cksum) | 204 code = code.replace('CODE_CHECKSUM', cksum) |
195 return code, cksum | 205 return code, cksum |
196 | 206 |
298 b.outputStatements([stmt]) | 308 b.outputStatements([stmt]) |
299 | 309 |
300 | 310 |
301 class Boards(cyclone.web.RequestHandler): | 311 class Boards(cyclone.web.RequestHandler): |
302 def get(self): | 312 def get(self): |
303 | |
304 self.set_header('Content-type', 'application/json') | 313 self.set_header('Content-type', 'application/json') |
305 self.write(json.dumps({ | 314 self.write(json.dumps({ |
306 'host': socket.gethostname(), | 315 'host': hostname, |
307 'boards': [b.description() for b in self.settings.boards] | 316 'boards': [b.description() for b in self.settings.boards] |
308 }, indent=2)) | 317 }, indent=2)) |
309 | 318 |
310 def currentSerialDevices(): | 319 def currentSerialDevices(): |
311 log.info('find connected boards') | 320 log.info('find connected boards') |
342 log.info('open boards') | 351 log.info('open boards') |
343 for b in boards: | 352 for b in boards: |
344 b.startPolling() | 353 b.startPolling() |
345 | 354 |
346 | 355 |
347 app = cyclone.web.Application([ | 356 reactor.listenTCP(9059, cyclone.web.Application([ |
348 (r"/()", cyclone.web.StaticFileHandler, { | 357 (r"/()", cyclone.web.StaticFileHandler, { |
349 "path": "static", "default_filename": "index.html"}), | 358 "path": "static", "default_filename": "index.html"}), |
350 (r'/static/(.*)', cyclone.web.StaticFileHandler, {"path": "static"}), | 359 (r'/static/(.*)', cyclone.web.StaticFileHandler, {"path": "static"}), |
351 (r'/boards', Boards), | 360 (r'/boards', Boards), |
352 (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}), | 361 (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}), |
353 (r"/graph/events", CycloneGraphEventsHandler, {'masterGraph': masterGraph}), | 362 (r"/graph/events", CycloneGraphEventsHandler, {'masterGraph': masterGraph}), |
354 (r'/output', OutputPage), | 363 (r'/output', OutputPage), |
355 (r'/arduinoCode', ArduinoCode), | 364 (r'/arduinoCode', ArduinoCode), |
356 (r'/dot', Dot), | 365 (r'/dot', Dot), |
357 ], config=config, boards=boards) | 366 ], config=config, boards=boards), interface='::') |
358 reactor.listenTCP(9059, app, interface='::') | |
359 reactor.run() | 367 reactor.run() |
360 | 368 |
361 main() | 369 main() |