987
|
1 from __future__ import division
|
|
2 import glob, sys, logging, subprocess, socket, os, hashlib, time, tempfile
|
|
3 import shutil, json, socket
|
|
4 import cyclone.web
|
|
5 from rdflib import Graph, Namespace, URIRef, Literal, RDF
|
|
6 from rdflib.parser import StringInputSource
|
|
7 from twisted.internet import reactor, task
|
|
8 from docopt import docopt
|
|
9 logging.basicConfig(level=logging.DEBUG)
|
|
10 sys.path.append("/my/site/magma")
|
|
11 from stategraph import StateGraph
|
|
12 sys.path.append('/home/pi/dim/PIGPIO')
|
|
13 import pigpio
|
|
14
|
|
15 import devices
|
|
16
|
|
17 log = logging.getLogger()
|
|
18 logging.getLogger('serial').setLevel(logging.WARN)
|
|
19 ROOM = Namespace('http://projects.bigasterisk.com/room/')
|
|
20 HOST = Namespace('http://bigasterisk.com/ruler/host/')
|
|
21
|
|
22 hostname = socket.gethostname()
|
|
23
|
|
24 class GraphPage(cyclone.web.RequestHandler):
|
|
25 def get(self):
|
|
26 g = StateGraph(ctx=ROOM['pi/%s' % hostname])
|
|
27
|
|
28 for stmt in self.settings.board.currentGraph():
|
|
29 g.add(stmt)
|
|
30
|
|
31 if self.get_argument('config', 'no') == 'yes':
|
|
32 for stmt in self.settings.config.graph:
|
|
33 g.add(stmt)
|
|
34
|
|
35 self.set_header('Content-type', 'application/x-trig')
|
|
36 self.write(g.asTrig())
|
|
37
|
|
38 class Board(object):
|
|
39 """similar to arduinoNode.Board but without the communications stuff"""
|
|
40 def __init__(self, graph, uri, onChange):
|
|
41 self.graph, self.uri = graph, uri
|
|
42 self.pi = pigpio.pi()
|
|
43 self._devs = devices.makeDevices(graph, self.uri, self.pi)
|
|
44 self._statementsFromInputs = {} # input device uri: latest statements
|
|
45
|
|
46 def startPolling(self):
|
|
47 task.LoopingCall(self._poll).start(.5)
|
|
48
|
|
49 def _poll(self):
|
|
50 for i in self._devs:
|
|
51 self._statementsFromInputs[i.uri] = i.poll()
|
|
52
|
|
53 def outputStatements(self, stmts):
|
|
54 unused = set(stmts)
|
|
55 for dev in self._devs:
|
|
56 stmtsForDev = []
|
|
57 for pat in dev.outputPatterns():
|
|
58 if [term is None for term in pat] != [False, False, True]:
|
|
59 raise NotImplementedError
|
|
60 for stmt in stmts:
|
|
61 if stmt[:2] == pat[:2]:
|
|
62 stmtsForDev.append(stmt)
|
|
63 unused.discard(stmt)
|
|
64 if stmtsForDev:
|
|
65 log.info("output goes to action handler for %s" % dev.uri)
|
|
66 dev.sendOutput(stmtsForDev)
|
|
67 log.info("success")
|
|
68 if unused:
|
|
69 log.warn("No devices cared about these statements:")
|
|
70 for s in unused:
|
|
71 log.warn(repr(s))
|
|
72
|
|
73 class OutputPage(cyclone.web.RequestHandler):
|
|
74
|
|
75 def put(self):
|
|
76 subj = URIRef(self.get_argument('s'))
|
|
77 pred = URIRef(self.get_argument('p'))
|
|
78
|
|
79 turtleLiteral = self.request.body
|
|
80 try:
|
|
81 obj = Literal(float(turtleLiteral))
|
|
82 except TypeError:
|
|
83 obj = Literal(turtleLiteral)
|
|
84
|
|
85 stmt = (subj, pred, obj)
|
|
86 self.settings.board.outputStatements([stmt])
|
|
87
|
|
88
|
|
89 def main():
|
|
90 arg = docopt("""
|
|
91 Usage: piNode.py [options]
|
|
92
|
|
93 -v Verbose
|
|
94 """)
|
|
95 log.setLevel(logging.WARN)
|
|
96 if arg['-v']:
|
|
97 from twisted.python import log as twlog
|
|
98 twlog.startLogging(sys.stdout)
|
|
99
|
|
100 log.setLevel(logging.DEBUG)
|
|
101
|
|
102 config = Config()
|
|
103
|
|
104 def onChange():
|
|
105 # notify reasoning
|
|
106 pass
|
|
107
|
|
108 thisBoard = URIRef('http://bigasterisk.com/homeauto/node2')
|
|
109
|
|
110 board = Board(config.graph, thisBoard, onChange)
|
|
111
|
|
112 reactor.listenTCP(9059, cyclone.web.Application([
|
|
113 (r"/()", cyclone.web.StaticFileHandler, {
|
|
114 "path": "static", "default_filename": "index.html"}),
|
|
115 (r'/static/(.*)', cyclone.web.StaticFileHandler, {"path": "static"}),
|
|
116 (r"/graph", GraphPage),
|
|
117 (r'/output', OutputPage),
|
|
118 (r'/dot', Dot),
|
|
119 ], config=config, board=board))
|
|
120 reactor.run()
|
|
121
|
|
122 main()
|