Mercurial > code > home > repos > homeauto
comparison service/arduinoNode/arduinoNode.py @ 456:12f9f1838fb5
arduinoNode: build updates, stats support, etc
Ignore-this: 39386eb7644e3cf522e0f72a874eadba
author | drewp@bigasterisk.com |
---|---|
date | Sat, 20 Apr 2019 23:28:29 -0700 |
parents | 13b2a61650c1 |
children | 5c750342604d |
comparison
equal
deleted
inserted
replaced
455:7e09c0d0a86e | 456:12f9f1838fb5 |
---|---|
9 from twisted.internet import reactor, task | 9 from twisted.internet import reactor, task |
10 from twisted.internet.defer import inlineCallbacks | 10 from twisted.internet.defer import inlineCallbacks |
11 from twisted.internet.threads import deferToThread | 11 from twisted.internet.threads import deferToThread |
12 from docopt import docopt | 12 from docopt import docopt |
13 import etcd3 | 13 import etcd3 |
14 from greplin import scales | |
15 from greplin.scales.cyclonehandler import StatsHandler | |
14 | 16 |
15 import devices | 17 import devices |
16 import write_arduino_code | 18 import write_arduino_code |
17 import dotrender | 19 import dotrender |
18 import rdflib_patch | 20 import rdflib_patch |
39 | 41 |
40 ACTION_BASE = 10 # higher than any of the fixed command numbers | 42 ACTION_BASE = 10 # higher than any of the fixed command numbers |
41 | 43 |
42 hostname = socket.gethostname() | 44 hostname = socket.gethostname() |
43 CTX = ROOM['arduinosOn%s' % hostname] | 45 CTX = ROOM['arduinosOn%s' % hostname] |
44 etcd = etcd3.client(host='bang6') | 46 |
47 STATS = scales.collection('/root', | |
48 ) | |
49 | |
50 | |
51 etcd = etcd3.client(host='bang6', port=9022) | |
45 | 52 |
46 class Config(object): | 53 class Config(object): |
47 def __init__(self, masterGraph, slowMode=False): | 54 def __init__(self, masterGraph, slowMode=False): |
48 self.masterGraph = masterGraph | 55 self.masterGraph = masterGraph |
49 self.slowMode = slowMode | 56 self.slowMode = slowMode |
121 self.uri = uri | 128 self.uri = uri |
122 self.configGraph = configGraph | 129 self.configGraph = configGraph |
123 self.masterGraph = masterGraph | 130 self.masterGraph = masterGraph |
124 self.dev = dev | 131 self.dev = dev |
125 | 132 |
126 self.masterGraph.patch(Patch(addQuads=self.staticStmts())) | 133 self.masterGraph.setToGraph(self.staticStmts()) |
127 | 134 |
128 # The order of this list needs to be consistent between the | 135 # The order of this list needs to be consistent between the |
129 # deployToArduino call and the poll call. | 136 # deployToArduino call and the poll call. |
130 self._devs = devices.makeDevices(configGraph, self.uri) | 137 self._devs = devices.makeDevices(configGraph, self.uri) |
131 self._devCommandNum = dict((dev.uri, ACTION_BASE + devIndex) | 138 self._devCommandNum = dict((dev.uri, ACTION_BASE + devIndex) |
179 if isinstance(new, dict): # new style | 186 if isinstance(new, dict): # new style |
180 oneshot = new['oneshot'] | 187 oneshot = new['oneshot'] |
181 new = new['latest'] | 188 new = new['latest'] |
182 else: | 189 else: |
183 oneshot = None | 190 oneshot = None |
184 prev = self._statementsFromInputs.get(i.uri, []) | 191 |
185 if new or prev: | 192 self._updateMasterWithNewPollStatements(i.uri, new) |
186 self._statementsFromInputs[i.uri] = new | 193 |
187 # it's important that quads from different devices | |
188 # don't clash, since that can lead to inconsistent | |
189 # patches (e.g. | |
190 # dev1 changes value from 1 to 2; | |
191 # dev2 changes value from 2 to 3; | |
192 # dev1 changes from 2 to 4 but this patch will | |
193 # fail since the '2' statement is gone) | |
194 self.masterGraph.patch(Patch.fromDiff(inContext(prev, i.uri), | |
195 inContext(new, i.uri))) | |
196 if oneshot: | 194 if oneshot: |
197 self._sendOneshot(oneshot) | 195 self._sendOneshot(oneshot) |
198 self._lastPollTime[i.uri] = now | 196 self._lastPollTime[i.uri] = now |
199 except: | 197 except: |
200 log.warn('while polling %r:', i.uri) | 198 log.warn('while polling %r:', i.uri) |
216 stmts = set() | 214 stmts = set() |
217 for v in self._statementsFromInputs.values(): | 215 for v in self._statementsFromInputs.values(): |
218 stmts.update(v) | 216 stmts.update(v) |
219 self._influx.exportToInflux(stmts) | 217 self._influx.exportToInflux(stmts) |
220 | 218 |
219 def _updateMasterWithNewPollStatements(self, dev, new): | |
220 prev = self._statementsFromInputs.get(dev, set()) | |
221 | |
222 # it's important that quads from different devices | |
223 # don't clash, since that can lead to inconsistent | |
224 # patches (e.g. | |
225 # dev1 changes value from 1 to 2; | |
226 # dev2 changes value from 2 to 3; | |
227 # dev1 changes from 2 to 4 but this patch will | |
228 # fail since the '2' statement is gone) | |
229 self.masterGraph.patch(Patch.fromDiff(inContext(prev, dev), | |
230 inContext(new, dev))) | |
231 self._statementsFromInputs[dev] = new | |
232 | |
221 def _sendOneshot(self, oneshot): | 233 def _sendOneshot(self, oneshot): |
222 body = (' '.join('%s %s %s .' % (s.n3(), p.n3(), o.n3()) | 234 body = (' '.join('%s %s %s .' % (s.n3(), p.n3(), o.n3()) |
223 for s,p,o in oneshot)).encode('utf8') | 235 for s,p,o in oneshot)).encode('utf8') |
224 fetch(method='POST', | 236 fetch(method='POST', |
225 url='http://bang6:9071/oneShot', | 237 url='http://bang6:9071/oneShot', |
253 self.syncMasterGraphToHostStatements(dev) | 265 self.syncMasterGraphToHostStatements(dev) |
254 log.info("output and masterGraph sync complete") | 266 log.info("output and masterGraph sync complete") |
255 if unused: | 267 if unused: |
256 log.info("Board %s doesn't care about these statements:", self.uri) | 268 log.info("Board %s doesn't care about these statements:", self.uri) |
257 for s in unused: | 269 for s in unused: |
258 log.warn("%r", s) | 270 log.info("%r", s) |
259 | 271 |
260 def syncMasterGraphToHostStatements(self, dev): | 272 def syncMasterGraphToHostStatements(self, dev): |
261 hostStmtCtx = URIRef(dev.uri + '/host') | 273 hostStmtCtx = URIRef(dev.uri + '/host') |
262 newQuads = inContext(dev.hostStatements(), hostStmtCtx) | 274 newQuads = inContext(dev.hostStatements(), hostStmtCtx) |
263 p = self.masterGraph.patchSubgraph(hostStmtCtx, newQuads) | 275 p = self.masterGraph.patchSubgraph(hostStmtCtx, newQuads) |
412 | 424 |
413 reactor.listenTCP(9059, cyclone.web.Application([ | 425 reactor.listenTCP(9059, cyclone.web.Application([ |
414 (r"/()", cyclone.web.StaticFileHandler, { | 426 (r"/()", cyclone.web.StaticFileHandler, { |
415 "path": "static", "default_filename": "index.html"}), | 427 "path": "static", "default_filename": "index.html"}), |
416 (r'/static/(.*)', cyclone.web.StaticFileHandler, {"path": "static"}), | 428 (r'/static/(.*)', cyclone.web.StaticFileHandler, {"path": "static"}), |
429 (r'/stats/(.*)', StatsHandler, {'serverName': 'arduinoNode'}), | |
417 (r'/boards', Boards), | 430 (r'/boards', Boards), |
418 (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}), | 431 (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}), |
419 (r"/graph/events", CycloneGraphEventsHandler, {'masterGraph': masterGraph}), | 432 (r"/graph/events", CycloneGraphEventsHandler, {'masterGraph': masterGraph}), |
420 (r'/output', OutputPage), | 433 (r'/output', OutputPage), |
421 (r'/arduinoCode', ArduinoCode), | 434 (r'/arduinoCode', ArduinoCode), |