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()