Mercurial > code > home > repos > homeauto
changeset 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 | 82fe44eadf00 |
children | 1ddd1f057749 |
files | service/rfid/index.html service/rfid/requirements.txt service/rfid/rfid.py |
diffstat | 3 files changed, 183 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/service/rfid/index.html Sat Apr 20 23:32:36 2019 -0700 +++ b/service/rfid/index.html Sat Apr 20 23:33:39 2019 -0700 @@ -1,14 +1,128 @@ <!doctype html> <html> <head> - <title></title> + <title>rfid</title> <meta charset="utf-8" /> + <meta name="mobile-web-app-capable" content="yes"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <script src="/lib/polymer/1.0.9/webcomponentsjs/webcomponents.min.js"></script> + <script src="/lib/require/require-2.3.3.js"></script> + <script> + requirejs.config({ + paths: { + "streamed-graph": "/rdf/streamed-graph", + "quadstore": "/rdf/quadstore", + "async-module": "/lib/async/80f1793/async", + "async": "/lib/async/80f1793/async", + "jsonld-module": "/lib/jsonld.js/0.4.11/js/jsonld", + "jsonld": "/lib/jsonld.js/0.4.11/js/jsonld", + "rdfstore": "/lib/rdf_store/0.9.7/dist/rdfstore", + "moment": "/lib/moment.min", + "underscore": "/lib/underscore-1.5.2.min", + } + }); + </script> + <script> + window.NS = { + dev: 'http://projects.bigasterisk.com/device/', + room: 'http://projects.bigasterisk.com/room/', + rdfs: 'http://www.w3.org/2000/01/rdf-schema#', + sensor: 'http://bigasterisk.com/homeauto/sensor/', + }; + </script> + <link rel="import" href="/lib/polymer/1.0.9/iron-ajax/iron-ajax.html"> + <link rel="import" href="/rdf/streamed-graph.html"> + <link rel="import" href="/lib/polymer/1.0.9/polymer/polymer.html"> + <link rel="import" href="/rdf/rdf-oneshot.html"> + <link rel="import" href="/rdf/rdf-uri.html"> </head> <body> - - Current read: graph.sensor.card graph.sensor.card.text + <dom-module id="rfid-control"> + <style> + button { + min-width: 60px; + min-height: 40px; + } + table { + border-collapse: collapse; + } + + td, th { + border: 1px solid gray; + } + </style> + <template> + <div> + <streamed-graph url="graph/events" graph="{{graph}}"></streamed-graph> + <!-- also get a graph of users so we can look up cards --> + </div> + + <iron-ajax id="rewrite" url="rewrite" method="POST"></iron-ajax> + + Current reads: + <table> + <tr><th>Card UID</th><th>Card text</th><th></th></tr> + <template is="dom-repeat" items="{{currentReads}}"> + <tr> + <td>{{item.uidDisplay}}</td> + <td>{{item.text}}</td> + <td> + <div id="form"> + <button on-click="rewrite">Rewrite</button> + </div> + </td> + </tr> + </template> + </table> + + </template> + <script> + HTMLImports.whenReady(function () { + Polymer({ + is: 'rfid-control', + properties: { + graph: { type: Object, notify: true, observer: "_onGraph" }, + currentReads: { type: Array, value: [] }, + }, + behaviors: [BigastUri], + _onGraph: function(graph) { + if (!graph.graph) return; + const env = graph.graph.store.rdf; - Write new key: [random id] [Write] - + this.splice('currentReads', 0, this.currentReads.length); + graph.graph.quadStore.quads( + {subject: env.createNamedNode('room:frontDoorWindowRfid'), + predicate: env.createNamedNode('room:reading'), + }, + (q) => { + graph.graph.quadStore.quads( + {subject: q.object, + predicate: env.createNamedNode('room:cardText'), + }, + (q2) => { + this.push( + 'currentReads', { + 'cardUid': q.object, + 'uidDisplay': q.object.toString().replace(/.*\//, ""), + 'text': q2.object.toString() + }); + }); + }); + }, + rewrite: function(ev) { + const cardUid = ev.model.item.cardUid; + + // ask for user first + + this.$.rewrite.contentType = "application/json"; + this.$.rewrite.body = {'cardUid': cardUid.toString(), + 'user': "some foaf"}; + this.$.rewrite.generateRequest(); + } + }); + }); + </script> + </dom-module> + <rfid-control></rfid-control> </body> </html>
--- a/service/rfid/requirements.txt Sat Apr 20 23:32:36 2019 -0700 +++ b/service/rfid/requirements.txt Sat Apr 20 23:33:39 2019 -0700 @@ -1,6 +1,7 @@ cyclone +docopt rdflib-jsonld==0.4.0 rdflib==4.2.2 -https://projects.bigasterisk.com/rdfdb/rdfdb-0.6.0.tar.gz -https://github.com/drewp/MFRC522-python/archive/drewp/m4.zip - +https://projects.bigasterisk.com/rdfdb/rdfdb-0.7.0.tar.gz +https://github.com/drewp/MFRC522-python/archive/877f5568627b5e67d622c08191aae0f4ffd6dd32.zip +git+http://github.com/drewp/scales.git@448d59fb491b7631877528e7695a93553bfaaa93#egg=scales
--- a/service/rfid/rfid.py Sat Apr 20 23:32:36 2019 -0700 +++ b/service/rfid/rfid.py Sat Apr 20 23:33:39 2019 -0700 @@ -6,14 +6,25 @@ from twisted.internet import reactor, task import cyclone.web from cyclone.httpclient import fetch -import logging, time +import logging, time, json, random, string from MFRC522.SimpleMFRC522 import SimpleMFRC522 from logsetup import log, enableTwistedLog +import private +from greplin import scales +from greplin.scales.cyclonehandler import StatsHandler ROOM = Namespace('http://projects.bigasterisk.com/room/') ctx = ROOM['frontDoorWindowRfidCtx'] +cardOwner = { + URIRef('http://bigasterisk.com/rfidCard/93a7591a77'): + URIRef('http://bigasterisk.com/foaf.rdf#drewp'), +} + +STATS = scales.collection('/web', + scales.PmfStat('cardReadPoll'), +) def rdfGraphBody(body, headers): g = Graph() g.parse(StringInputSource(body), format='nt') @@ -41,6 +52,36 @@ return log.warn("ignoring %s", stmt) +def uidUri(card_id): + return URIRef('http://bigasterisk.com/rfidCard/%010x' % card_id) + +def uidArray(uri): + prefix, h = uri.rsplit('/', 1) + if prefix != 'http://bigasterisk.com/rfidCard': + raise ValueError(uri) + return [int(h[i * 2: i * 2 + 2], 16) for i in range(0, len(h), 2)] + +class Rewrite(cyclone.web.RequestHandler): + def post(self): + agent = URIRef(self.request.headers['x-foaf-agent']) + body = json.loads(self.request.body) + + _, uid = reader.read_id() + log.info('current card id: %r %r', _, uid) + if uid is None: + self.set_status(404, "no card present") + # maybe retry a few more times since the card might be nearby + return + + text = ''.join(random.choice(string.uppercase) for n in range(32)) + log.info('%s rewrites %s to %s, to be owned by %s', + agent, uid, text, body['user']) + + #reader.KEY = private.rfid_key + reader.write(uid, text) + log.info('done with write') + + sensor = ROOM['frontDoorWindowRfid'] class ReadLoop(object): @@ -49,22 +90,25 @@ self.masterGraph = masterGraph self.log = {} # cardIdUri : most recent seentime - self.pollPeriodSecs = .2 + self.pollPeriodSecs = .1 self.expireSecs = 2 task.LoopingCall(self.poll).start(self.pollPeriodSecs) - + + @STATS.cardReadPoll.time() def poll(self): now = time.time() self.flushOldReads(now) card_id, text = self.reader.read() - if card_id is None: + if card_id is None or text == '': + # text=='' could be legit, but it's probably a card that's + # still being read. return - cardIdUri = URIRef('http://bigasterisk.com/rfidCard/%s' % card_id) - textLit = Literal(text.rstrip()) + cardIdUri = uidUri(card_id) + textLit = Literal(text.rstrip().decode('ascii', 'replace')) is_new = cardIdUri not in self.log self.log[cardIdUri] = now @@ -79,16 +123,20 @@ def startCardRead(self, cardUri, text): p = Patch(addQuads=[(sensor, ROOM['reading'], cardUri, ctx), - (cardUri, ROOM['cardText'], text, ctx)], delQuads=[]) + (cardUri, ROOM['cardText'], text, ctx)], + delQuads=[]) self.masterGraph.patch(p) + log.info('read card: id=%s %r', cardUri, str(text)) self._sendOneshot([(sensor, ROOM['startReading'], cardUri), (cardUri, ROOM['cardText'], text)]) def endCardRead(self, cardUri): delQuads = [] - for spo in self.masterGraph._graph.triples((sensor, ROOM['reading'], cardUri)): + for spo in self.masterGraph._graph.triples( + (sensor, ROOM['reading'], cardUri)): delQuads.append(spo + (ctx,)) - for spo in self.masterGraph._graph.triples((cardUri, ROOM['cardText'], None)): + for spo in self.masterGraph._graph.triples( + (cardUri, ROOM['cardText'], None)): delQuads.append(spo + (ctx,)) self.masterGraph.patch(Patch(addQuads=[], delQuads=delQuads)) @@ -121,7 +169,7 @@ log.setLevel(logging.DEBUG) masterGraph = PatchableGraph() - reader = SimpleMFRC522() + reader = SimpleMFRC522(gain=0x07) loop = ReadLoop(reader, masterGraph) @@ -133,6 +181,8 @@ (r"/graph/events", CycloneGraphEventsHandler, {'masterGraph': masterGraph}), (r'/output', OutputPage), + (r'/rewrite', Rewrite), + (r'/stats/(.*)', StatsHandler, {'serverName': 'rfid'}), ], masterGraph=masterGraph, debug=arg['-v']), interface='::') log.warn('serving on %s', port)