Mercurial > code > home > repos > homeauto
annotate service/piNode/piNode.py @ 1025:f58b5536f683
ipv6 and some refactor
Ignore-this: 8ae5a78848fac996ad777eb74a48e656
darcs-hash:f0b1959fdda425f82cb1bb1581eb46dc909f3c36
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sun, 03 Jan 2016 02:32:46 -0800 |
parents | 065fc9e07c10 |
children | 666e0e756ce6 |
rev | line source |
---|---|
987 | 1 from __future__ import division |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
2 import sys, logging, socket, json |
987 | 3 import cyclone.web |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
4 from rdflib import Namespace, URIRef, Literal, Graph, RDF |
989
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
5 from rdflib.parser import StringInputSource |
987 | 6 from twisted.internet import reactor, task |
7 from docopt import docopt | |
8 logging.basicConfig(level=logging.DEBUG) | |
9 sys.path.append("/my/site/magma") | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
10 sys.path.append("../../../../site/magma") |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
11 |
987 | 12 from stategraph import StateGraph |
13 sys.path.append('/home/pi/dim/PIGPIO') | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
14 try: |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
15 import pigpio |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
16 except ImportError: |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
17 class pigpio(object): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
18 @staticmethod |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
19 def pi(): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
20 return None |
987 | 21 |
22 import devices | |
23 | |
24 log = logging.getLogger() | |
25 logging.getLogger('serial').setLevel(logging.WARN) | |
26 ROOM = Namespace('http://projects.bigasterisk.com/room/') | |
27 HOST = Namespace('http://bigasterisk.com/ruler/host/') | |
28 | |
29 hostname = socket.gethostname() | |
30 | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
31 class Config(object): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
32 def __init__(self): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
33 self.graph = Graph() |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
34 log.info('read config') |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
35 self.graph.parse('config.n3', format='n3') |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
36 self.graph.bind('', ROOM) # not working |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
37 self.graph.bind('rdf', RDF) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
38 |
987 | 39 class GraphPage(cyclone.web.RequestHandler): |
40 def get(self): | |
41 g = StateGraph(ctx=ROOM['pi/%s' % hostname]) | |
42 | |
43 for stmt in self.settings.board.currentGraph(): | |
44 g.add(stmt) | |
45 | |
46 if self.get_argument('config', 'no') == 'yes': | |
47 for stmt in self.settings.config.graph: | |
48 g.add(stmt) | |
49 | |
50 self.set_header('Content-type', 'application/x-trig') | |
51 self.write(g.asTrig()) | |
52 | |
53 class Board(object): | |
54 """similar to arduinoNode.Board but without the communications stuff""" | |
55 def __init__(self, graph, uri, onChange): | |
56 self.graph, self.uri = graph, uri | |
57 self.pi = pigpio.pi() | |
58 self._devs = devices.makeDevices(graph, self.uri, self.pi) | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
59 log.debug('found %s devices', len(self._devs)) |
987 | 60 self._statementsFromInputs = {} # input device uri: latest statements |
61 | |
62 def startPolling(self): | |
63 task.LoopingCall(self._poll).start(.5) | |
64 | |
65 def _poll(self): | |
66 for i in self._devs: | |
67 self._statementsFromInputs[i.uri] = i.poll() | |
68 | |
69 def outputStatements(self, stmts): | |
70 unused = set(stmts) | |
71 for dev in self._devs: | |
72 stmtsForDev = [] | |
73 for pat in dev.outputPatterns(): | |
74 if [term is None for term in pat] != [False, False, True]: | |
75 raise NotImplementedError | |
76 for stmt in stmts: | |
77 if stmt[:2] == pat[:2]: | |
78 stmtsForDev.append(stmt) | |
79 unused.discard(stmt) | |
80 if stmtsForDev: | |
81 log.info("output goes to action handler for %s" % dev.uri) | |
82 dev.sendOutput(stmtsForDev) | |
83 log.info("success") | |
84 if unused: | |
85 log.warn("No devices cared about these statements:") | |
86 for s in unused: | |
87 log.warn(repr(s)) | |
88 | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
89 def currentGraph(self): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
90 g = Graph() |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
91 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
92 g.add((HOST[socket.gethostname()], ROOM['connectedTo'], self.uri)) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
93 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
94 for si in self._statementsFromInputs.values(): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
95 for s in si: |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
96 g.add(s) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
97 return g |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
98 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
99 def description(self): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
100 """for web page""" |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
101 return { |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
102 'uri': self.uri, |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
103 'devices': [d.description() for d in self._devs], |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
104 'graph': 'http://sticker:9059/graph', #todo |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
105 } |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
106 |
989
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
107 def rdfGraphBody(body, headers): |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
108 g = Graph() |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
109 g.parse(StringInputSource(body), format='nt') |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
110 return g |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
111 |
987 | 112 class OutputPage(cyclone.web.RequestHandler): |
113 def put(self): | |
989
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
114 arg = self.request.arguments |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
115 if arg.get('s') and arg.get('p'): |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
116 subj = URIRef(arg['s'][-1]) |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
117 pred = URIRef(arg['p'][-1]) |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
118 turtleLiteral = self.request.body |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
119 try: |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
120 obj = Literal(float(turtleLiteral)) |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
121 except ValueError: |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
122 obj = Literal(turtleLiteral) |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
123 stmt = (subj, pred, obj) |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
124 else: |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
125 g = rdfGraphBody(self.request.body, self.request.headers) |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
126 assert len(g) == 1, len(g) |
065fc9e07c10
piNode allow nt graphs as the body of a PUT /output
drewp <drewp@bigasterisk.com>
parents:
988
diff
changeset
|
127 stmt = g.triples((None, None, None)).next() |
987 | 128 |
129 self.settings.board.outputStatements([stmt]) | |
130 | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
131 class Boards(cyclone.web.RequestHandler): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
132 def get(self): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
133 self.set_header('Content-type', 'application/json') |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
134 self.write(json.dumps({ |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
135 'boards': [self.settings.board.description()] |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
136 }, indent=2)) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
137 |
987 | 138 def main(): |
139 arg = docopt(""" | |
140 Usage: piNode.py [options] | |
141 | |
142 -v Verbose | |
143 """) | |
144 log.setLevel(logging.WARN) | |
145 if arg['-v']: | |
146 from twisted.python import log as twlog | |
147 twlog.startLogging(sys.stdout) | |
148 | |
149 log.setLevel(logging.DEBUG) | |
150 | |
151 config = Config() | |
152 | |
153 def onChange(): | |
154 # notify reasoning | |
155 pass | |
156 | |
157 thisBoard = URIRef('http://bigasterisk.com/homeauto/node2') | |
158 | |
159 board = Board(config.graph, thisBoard, onChange) | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
160 board.startPolling() |
987 | 161 |
162 reactor.listenTCP(9059, cyclone.web.Application([ | |
163 (r"/()", cyclone.web.StaticFileHandler, { | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
164 "path": "../arduinoNode/static", "default_filename": "index.html"}), |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
165 (r'/static/(.*)', cyclone.web.StaticFileHandler, {"path": "../arduinoNode/static"}), |
987 | 166 (r"/graph", GraphPage), |
167 (r'/output', OutputPage), | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
168 (r'/boards', Boards), |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
169 #(r'/dot', Dot), |
1025 | 170 ], config=config, board=board, debug=arg['-v']), interface='::') |
987 | 171 reactor.run() |
172 | |
173 main() |