annotate service/rfid/rfid.py @ 1194:ee9cbe5817a4

rfid reader service Ignore-this: 26df9a4be891c26722311cf89d1d7cf7 darcs-hash:80ff40afce46a1429309421b1db52aefd5b675a8
author drewp <drewp@bigasterisk.com>
date Thu, 03 Jan 2019 21:52:27 -0800
parents
children cebc0134254a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1194
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
1 from docopt import docopt
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
2 from rdfdb.patch import Patch
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
3 from patchablegraph import PatchableGraph, CycloneGraphHandler, CycloneGraphEventsHandler
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
4 from rdflib import Namespace, URIRef, Literal, Graph
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
5 from rdflib.parser import StringInputSource
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
6 from twisted.internet import reactor, task
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
7 import cyclone.web
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
8 from cyclone.httpclient import fetch
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
9 import logging, time
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
10 from MFRC522.SimpleMFRC522 import SimpleMFRC522
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
11 from logsetup import log, enableTwistedLog
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
12
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
13 ROOM = Namespace('http://projects.bigasterisk.com/room/')
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
14
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
15 ctx = ROOM['frontDoorWindowRfidCtx']
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
16
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
17 def rdfGraphBody(body, headers):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
18 g = Graph()
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
19 g.parse(StringInputSource(body), format='nt')
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
20 return g
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
21
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
22 class OutputPage(cyclone.web.RequestHandler):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
23 def put(self):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
24 user = URIRef(self.request.headers['x-foaf-agent'])
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
25 arg = self.request.arguments
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
26 if arg.get('s') and arg.get('p'):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
27 subj = URIRef(arg['s'][-1])
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
28 pred = URIRef(arg['p'][-1])
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
29 obj = URIRef(self.request.body)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
30 stmt = (subj, pred, obj)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
31 else:
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
32 g = rdfGraphBody(self.request.body, self.request.headers)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
33 assert len(g) == 1, len(g)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
34 stmt = g.triples((None, None, None)).next()
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
35 self._onStatement(user, stmt)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
36 post = put
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
37
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
38 def _onStatement(self, user, stmt):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
39 # write rfid to new key, etc.
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
40 if stmt[1] == ROOM['keyContents']:
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
41 return
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
42 log.warn("ignoring %s", stmt)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
43
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
44 sensor = ROOM['frontDoorWindowRfid']
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
45
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
46 class ReadLoop(object):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
47 def __init__(self, reader, masterGraph):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
48 self.reader = reader
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
49 self.masterGraph = masterGraph
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
50 self.log = {} # cardIdUri : most recent seentime
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
51
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
52 self.pollPeriodSecs = .2
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
53 self.expireSecs = 2
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
54
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
55 task.LoopingCall(self.poll).start(self.pollPeriodSecs)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
56
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
57 def poll(self):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
58 now = time.time()
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
59
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
60 self.flushOldReads(now)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
61
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
62 card_id, text = self.reader.read()
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
63 if card_id is None:
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
64 return
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
65
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
66 cardIdUri = URIRef('http://bigasterisk.com/rfidCard/%s' % card_id)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
67 textLit = Literal(text.rstrip())
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
68
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
69 is_new = cardIdUri not in self.log
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
70 self.log[cardIdUri] = now
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
71 if is_new:
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
72 self.startCardRead(cardIdUri, textLit)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
73
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
74 def flushOldReads(self, now):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
75 for uri in self.log.keys():
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
76 if self.log[uri] < now - self.expireSecs:
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
77 self.endCardRead(uri)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
78 del self.log[uri]
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
79
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
80 def startCardRead(self, cardUri, text):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
81 p = Patch(addQuads=[(sensor, ROOM['reading'], cardUri, ctx),
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
82 (cardUri, ROOM['cardText'], text, ctx)], delQuads=[])
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
83 self.masterGraph.patch(p)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
84 self._sendOneshot([(sensor, ROOM['startReading'], cardUri),
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
85 (cardUri, ROOM['cardText'], text)])
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
86
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
87 def endCardRead(self, cardUri):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
88 delQuads = []
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
89 for spo in self.masterGraph._graph.triples((sensor, ROOM['reading'], cardUri)):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
90 delQuads.append(spo + (ctx,))
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
91 for spo in self.masterGraph._graph.triples((cardUri, ROOM['cardText'], None)):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
92 delQuads.append(spo + (ctx,))
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
93
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
94 self.masterGraph.patch(Patch(addQuads=[], delQuads=delQuads))
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
95
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
96 def _sendOneshot(self, oneshot):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
97 body = (' '.join('%s %s %s .' % (s.n3(), p.n3(), o.n3())
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
98 for s,p,o in oneshot)).encode('utf8')
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
99 url = 'http://bang6:9071/oneShot'
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
100 d = fetch(method='POST',
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
101 url=url,
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
102 headers={'Content-Type': ['text/n3']},
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
103 postdata=body,
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
104 timeout=5)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
105 def err(e):
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
106 log.info('oneshot post to %r failed: %s',
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
107 url, e.getErrorMessage())
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
108 d.addErrback(err)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
109
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
110
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
111
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
112 if __name__ == '__main__':
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
113 arg = docopt("""
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
114 Usage: rfid.py [options]
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
115
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
116 -v Verbose
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
117 """)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
118 log.setLevel(logging.INFO)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
119 if arg['-v']:
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
120 enableTwistedLog()
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
121 log.setLevel(logging.DEBUG)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
122
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
123 masterGraph = PatchableGraph()
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
124 reader = SimpleMFRC522()
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
125
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
126 loop = ReadLoop(reader, masterGraph)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
127
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
128 port = 10012
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
129 reactor.listenTCP(port, cyclone.web.Application([
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
130 (r"/()", cyclone.web.StaticFileHandler,
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
131 {"path": ".", "default_filename": "index.html"}),
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
132 (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}),
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
133 (r"/graph/events", CycloneGraphEventsHandler,
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
134 {'masterGraph': masterGraph}),
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
135 (r'/output', OutputPage),
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
136 ], masterGraph=masterGraph, debug=arg['-v']), interface='::')
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
137 log.warn('serving on %s', port)
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
138
ee9cbe5817a4 rfid reader service
drewp <drewp@bigasterisk.com>
parents:
diff changeset
139 reactor.run()