Mercurial > code > home > repos > homeauto
comparison service/rfid/rfid.py @ 1264:c5b13d630d90
last version of rc522 reader; i moved onto pn532 now
Ignore-this: 37d50691ffec46f984a66c185cc27445
darcs-hash:9485271388fd30918eaf27d71e3af9bbfc52d61c
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sat, 20 Apr 2019 23:33:39 -0700 |
parents | ee9cbe5817a4 |
children | a93fbf0d0daa |
comparison
equal
deleted
inserted
replaced
1263:82fe44eadf00 | 1264:c5b13d630d90 |
---|---|
4 from rdflib import Namespace, URIRef, Literal, Graph | 4 from rdflib import Namespace, URIRef, Literal, Graph |
5 from rdflib.parser import StringInputSource | 5 from rdflib.parser import StringInputSource |
6 from twisted.internet import reactor, task | 6 from twisted.internet import reactor, task |
7 import cyclone.web | 7 import cyclone.web |
8 from cyclone.httpclient import fetch | 8 from cyclone.httpclient import fetch |
9 import logging, time | 9 import logging, time, json, random, string |
10 from MFRC522.SimpleMFRC522 import SimpleMFRC522 | 10 from MFRC522.SimpleMFRC522 import SimpleMFRC522 |
11 from logsetup import log, enableTwistedLog | 11 from logsetup import log, enableTwistedLog |
12 import private | |
13 from greplin import scales | |
14 from greplin.scales.cyclonehandler import StatsHandler | |
12 | 15 |
13 ROOM = Namespace('http://projects.bigasterisk.com/room/') | 16 ROOM = Namespace('http://projects.bigasterisk.com/room/') |
14 | 17 |
15 ctx = ROOM['frontDoorWindowRfidCtx'] | 18 ctx = ROOM['frontDoorWindowRfidCtx'] |
16 | 19 |
20 cardOwner = { | |
21 URIRef('http://bigasterisk.com/rfidCard/93a7591a77'): | |
22 URIRef('http://bigasterisk.com/foaf.rdf#drewp'), | |
23 } | |
24 | |
25 STATS = scales.collection('/web', | |
26 scales.PmfStat('cardReadPoll'), | |
27 ) | |
17 def rdfGraphBody(body, headers): | 28 def rdfGraphBody(body, headers): |
18 g = Graph() | 29 g = Graph() |
19 g.parse(StringInputSource(body), format='nt') | 30 g.parse(StringInputSource(body), format='nt') |
20 return g | 31 return g |
21 | 32 |
39 # write rfid to new key, etc. | 50 # write rfid to new key, etc. |
40 if stmt[1] == ROOM['keyContents']: | 51 if stmt[1] == ROOM['keyContents']: |
41 return | 52 return |
42 log.warn("ignoring %s", stmt) | 53 log.warn("ignoring %s", stmt) |
43 | 54 |
55 def uidUri(card_id): | |
56 return URIRef('http://bigasterisk.com/rfidCard/%010x' % card_id) | |
57 | |
58 def uidArray(uri): | |
59 prefix, h = uri.rsplit('/', 1) | |
60 if prefix != 'http://bigasterisk.com/rfidCard': | |
61 raise ValueError(uri) | |
62 return [int(h[i * 2: i * 2 + 2], 16) for i in range(0, len(h), 2)] | |
63 | |
64 class Rewrite(cyclone.web.RequestHandler): | |
65 def post(self): | |
66 agent = URIRef(self.request.headers['x-foaf-agent']) | |
67 body = json.loads(self.request.body) | |
68 | |
69 _, uid = reader.read_id() | |
70 log.info('current card id: %r %r', _, uid) | |
71 if uid is None: | |
72 self.set_status(404, "no card present") | |
73 # maybe retry a few more times since the card might be nearby | |
74 return | |
75 | |
76 text = ''.join(random.choice(string.uppercase) for n in range(32)) | |
77 log.info('%s rewrites %s to %s, to be owned by %s', | |
78 agent, uid, text, body['user']) | |
79 | |
80 #reader.KEY = private.rfid_key | |
81 reader.write(uid, text) | |
82 log.info('done with write') | |
83 | |
84 | |
44 sensor = ROOM['frontDoorWindowRfid'] | 85 sensor = ROOM['frontDoorWindowRfid'] |
45 | 86 |
46 class ReadLoop(object): | 87 class ReadLoop(object): |
47 def __init__(self, reader, masterGraph): | 88 def __init__(self, reader, masterGraph): |
48 self.reader = reader | 89 self.reader = reader |
49 self.masterGraph = masterGraph | 90 self.masterGraph = masterGraph |
50 self.log = {} # cardIdUri : most recent seentime | 91 self.log = {} # cardIdUri : most recent seentime |
51 | 92 |
52 self.pollPeriodSecs = .2 | 93 self.pollPeriodSecs = .1 |
53 self.expireSecs = 2 | 94 self.expireSecs = 2 |
54 | 95 |
55 task.LoopingCall(self.poll).start(self.pollPeriodSecs) | 96 task.LoopingCall(self.poll).start(self.pollPeriodSecs) |
56 | 97 |
98 @STATS.cardReadPoll.time() | |
57 def poll(self): | 99 def poll(self): |
58 now = time.time() | 100 now = time.time() |
59 | 101 |
60 self.flushOldReads(now) | 102 self.flushOldReads(now) |
61 | 103 |
62 card_id, text = self.reader.read() | 104 card_id, text = self.reader.read() |
63 if card_id is None: | 105 if card_id is None or text == '': |
106 # text=='' could be legit, but it's probably a card that's | |
107 # still being read. | |
64 return | 108 return |
65 | 109 |
66 cardIdUri = URIRef('http://bigasterisk.com/rfidCard/%s' % card_id) | 110 cardIdUri = uidUri(card_id) |
67 textLit = Literal(text.rstrip()) | 111 textLit = Literal(text.rstrip().decode('ascii', 'replace')) |
68 | 112 |
69 is_new = cardIdUri not in self.log | 113 is_new = cardIdUri not in self.log |
70 self.log[cardIdUri] = now | 114 self.log[cardIdUri] = now |
71 if is_new: | 115 if is_new: |
72 self.startCardRead(cardIdUri, textLit) | 116 self.startCardRead(cardIdUri, textLit) |
77 self.endCardRead(uri) | 121 self.endCardRead(uri) |
78 del self.log[uri] | 122 del self.log[uri] |
79 | 123 |
80 def startCardRead(self, cardUri, text): | 124 def startCardRead(self, cardUri, text): |
81 p = Patch(addQuads=[(sensor, ROOM['reading'], cardUri, ctx), | 125 p = Patch(addQuads=[(sensor, ROOM['reading'], cardUri, ctx), |
82 (cardUri, ROOM['cardText'], text, ctx)], delQuads=[]) | 126 (cardUri, ROOM['cardText'], text, ctx)], |
127 delQuads=[]) | |
83 self.masterGraph.patch(p) | 128 self.masterGraph.patch(p) |
129 log.info('read card: id=%s %r', cardUri, str(text)) | |
84 self._sendOneshot([(sensor, ROOM['startReading'], cardUri), | 130 self._sendOneshot([(sensor, ROOM['startReading'], cardUri), |
85 (cardUri, ROOM['cardText'], text)]) | 131 (cardUri, ROOM['cardText'], text)]) |
86 | 132 |
87 def endCardRead(self, cardUri): | 133 def endCardRead(self, cardUri): |
88 delQuads = [] | 134 delQuads = [] |
89 for spo in self.masterGraph._graph.triples((sensor, ROOM['reading'], cardUri)): | 135 for spo in self.masterGraph._graph.triples( |
136 (sensor, ROOM['reading'], cardUri)): | |
90 delQuads.append(spo + (ctx,)) | 137 delQuads.append(spo + (ctx,)) |
91 for spo in self.masterGraph._graph.triples((cardUri, ROOM['cardText'], None)): | 138 for spo in self.masterGraph._graph.triples( |
139 (cardUri, ROOM['cardText'], None)): | |
92 delQuads.append(spo + (ctx,)) | 140 delQuads.append(spo + (ctx,)) |
93 | 141 |
94 self.masterGraph.patch(Patch(addQuads=[], delQuads=delQuads)) | 142 self.masterGraph.patch(Patch(addQuads=[], delQuads=delQuads)) |
95 | 143 |
96 def _sendOneshot(self, oneshot): | 144 def _sendOneshot(self, oneshot): |
119 if arg['-v']: | 167 if arg['-v']: |
120 enableTwistedLog() | 168 enableTwistedLog() |
121 log.setLevel(logging.DEBUG) | 169 log.setLevel(logging.DEBUG) |
122 | 170 |
123 masterGraph = PatchableGraph() | 171 masterGraph = PatchableGraph() |
124 reader = SimpleMFRC522() | 172 reader = SimpleMFRC522(gain=0x07) |
125 | 173 |
126 loop = ReadLoop(reader, masterGraph) | 174 loop = ReadLoop(reader, masterGraph) |
127 | 175 |
128 port = 10012 | 176 port = 10012 |
129 reactor.listenTCP(port, cyclone.web.Application([ | 177 reactor.listenTCP(port, cyclone.web.Application([ |
131 {"path": ".", "default_filename": "index.html"}), | 179 {"path": ".", "default_filename": "index.html"}), |
132 (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}), | 180 (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}), |
133 (r"/graph/events", CycloneGraphEventsHandler, | 181 (r"/graph/events", CycloneGraphEventsHandler, |
134 {'masterGraph': masterGraph}), | 182 {'masterGraph': masterGraph}), |
135 (r'/output', OutputPage), | 183 (r'/output', OutputPage), |
184 (r'/rewrite', Rewrite), | |
185 (r'/stats/(.*)', StatsHandler, {'serverName': 'rfid'}), | |
136 ], masterGraph=masterGraph, debug=arg['-v']), interface='::') | 186 ], masterGraph=masterGraph, debug=arg['-v']), interface='::') |
137 log.warn('serving on %s', port) | 187 log.warn('serving on %s', port) |
138 | 188 |
139 reactor.run() | 189 reactor.run() |