# HG changeset patch # User drewp # Date 1555828894 25200 # Node ID 114d20be3314c4502a054b858b3e4a9ab6eb9df4 # Parent 73b6ed12bae67835705e32d291bee0f67617c834 last version of nim attempt for pn532 rfid reader. adds simple nim lib for RDF Ignore-this: 7bc9a248f49f57dd0a08c849b807a586 darcs-hash:0972a0a0a58feee13f536cb4352919138e350d71 diff -r 73b6ed12bae6 -r 114d20be3314 service/rfid_pn532/graphserver.nim --- a/service/rfid_pn532/graphserver.nim Sat Apr 20 23:40:29 2019 -0700 +++ b/service/rfid_pn532/graphserver.nim Sat Apr 20 23:41:34 2019 -0700 @@ -1,4 +1,7 @@ import asynchttpserver, asyncdispatch, asyncnet, strtabs, sequtils, times, os, strutils, strformat +import sets +import rdf +import rdf_nodes type GraphServer* = ref object of RootObj @@ -7,6 +10,20 @@ previousUpdateTime: int httpServer: AsyncHttpServer serverReady: Future[void] + graph: Graph + +proc ssePayload(eventType: string, body: string): string = + eventType & ": " & body & "\n\n" + +proc sendEvent(client: AsyncSocket, eventType: string, body: string) {.async.} = + if not client.isClosed(): + asyncCheck client.send(ssePayload(eventType, body)) + +proc sendEventToAll(self: GraphServer, eventType: string, body: string) {.async.} = + let payload = ssePayload(eventType, body) + for client in self.clients: + if not client.isClosed(): + asyncCheck client.send(payload) proc handleCORS(req: Request) {.async.} = await req.respond(Http204, "", newHttpHeaders({ @@ -29,6 +46,7 @@ await req.client.send("HTTP/1.1 200 OK\c\L") await req.sendHeaders(headers) await req.client.send("\c\L:ok\n\n") + await sendEvent(req.client, "fullGraph", Patch(addQuads: self.graph.stmts).toJson()) self.clients.add(req.client) proc handleConnections(self: GraphServer, req: Request) {.async.} = @@ -41,26 +59,52 @@ await req.respond(Http200, $clientCount, headers) req.client.close() +proc handleGraph(self: GraphServer, req: Request) {.async.} = + await req.respond(Http200, self.graph.toNquads(), newHttpHeaders({ + "Content-Type": "application/n-quads", + })) + req.client.close() + +proc applyPatch*(self: GraphServer, p: Patch) {.async.} = + self.graph.applyPatch(p) + let body = p.toJson() + echo "emitpatch " & body + asyncCheck self.sendEventToAll("patch", body) + +# Replace graph contents. +proc setGraph*(self: GraphServer, quads: HashSet[Quad]) {.async.} = + let p = Patch(addQuads: quads - self.graph.stmts, + delQuads: self.graph.stmts - quads) + asyncCheck self.graph.applyPatch(p) + +proc handleCurrentGraph(self: GraphServer, req: Request) {.async.} = + let quad = HashSet[Quad]([]) + self.setGraph(quads) + + proc requestCallback(self: GraphServer, req: Request) {.async.} = if req.reqMethod == HttpOptions: asyncCheck handleCORS(req) else: case req.url.path of "/connections": asyncCheck self.handleConnections(req) - of "/sse": asyncCheck self.handleSSE(req) + of "/graph": asyncCheck self.handleGraph(req) + of "/graph/events": asyncCheck self.handleSSE(req) + of "/currentGraph": asyncCheck self.handleCurrentGraph(req) else: asyncCheck handle404(req) proc newGraphServer*(port: int): GraphServer = new(result) result.port = port result.previousUpdateTime = toInt(epochTime() * 1000) + result.graph = initGraph() result.httpServer = newAsyncHttpServer(true) let self = result - self.serverReady = self.httpServer.serve( - Port(self.port), - proc (req: Request): Future[void] = self.requestCallback(req), - address="0.0.0.0") + # https://github.com/dom96/nim-in-action-code/issues/6#issuecomment-446956468 has been applied to ./nim-0.19.4/lib/pure/asynchttpserver.nim + proc handler(req: Request): Future[void] {.async.} = + asyncCheck self.requestCallback(req) + self.serverReady = self.httpServer.serve(Port(self.port), handler, address="0.0.0.0") asyncCheck self.serverReady echo "Listening on " & $self.port @@ -74,20 +118,17 @@ if currentTime - self.previousUpdateTime < 1000: return - for client in self.clients: - if not client.isClosed(): - asyncCheck client.send("data: " & $currentTime & "\n\n") - + asyncCheck self.sendEventToAll("data", $currentTime) self.previousUpdateTime = toInt(epochTime() * 1000) + proc run*(self: GraphServer) = while true: self.checkClients() asyncCheck self.pingClients() poll() + -# Replace graph contents -proc setGraph*(self: GraphServer) = - echo "graph replaced" - +let server = newGraphServer(port = 10012) +server.run() \ No newline at end of file diff -r 73b6ed12bae6 -r 114d20be3314 service/rfid_pn532/makefile --- a/service/rfid_pn532/makefile Sat Apr 20 23:40:29 2019 -0700 +++ b/service/rfid_pn532/makefile Sat Apr 20 23:41:34 2019 -0700 @@ -12,12 +12,15 @@ freefare_demo_run: freefare_demo ./freefare_demo -rfid: rfid.nim graphserver.nim nfc-nim/nfc.nim nfc-nim/freefare.nim +rfid: rfid.nim graphserver.nim nfc-nim/nfc.nim nfc-nim/freefare.nim rdf.nim rdf_nodes.nim nim-0.19.4/bin/nim c -d:nimDebugDlOpen rfid.nim rfid_local_run: rfid ./rfid +test_rdf: + nim-0.19.4/bin/nim c -r rdf_test.nim + build_image: rm -rf tmp_ctx @@ -41,3 +44,24 @@ local_run: build_image docker run --name rfid_local --rm -it --net=host bang6:5000/$(SERVICE)_x86:latest + + + +build_graphserver: + rm -rf tmp_ctx + mkdir -p tmp_ctx + cp -a Dockerfile.graphserver *.py *.html require* ../../lib/*.py tmp_ctx + docker build --file Dockerfile.graphserver --network=host -t bang6:5000/rfid_graphserver_x86:latest tmp_ctx + docker push bang6:5000/rfid_graphserver_x86:latest + rm -rf tmp_ctx + +build_graphserver_pi: + rm -rf tmp_ctx + mkdir -p tmp_ctx + cp -a Dockerfile.graphserver.pi *.py *.html require* ../../lib/*.py tmp_ctx + docker build --file Dockerfile.graphserver.pi --network=host -t bang6:5000/rfid_graphserver_pi:latest tmp_ctx + docker push bang6:5000/rfid_graphserver_pi:latest + rm -rf tmp_ctx + +local_run_graphserver: build_graphserver + docker run --name rfid_local_graphserver --rm -it --net=host bang6:5000/rfid_graphserver_x86:latest diff -r 73b6ed12bae6 -r 114d20be3314 service/rfid_pn532/rfid.nim --- a/service/rfid_pn532/rfid.nim Sat Apr 20 23:40:29 2019 -0700 +++ b/service/rfid_pn532/rfid.nim Sat Apr 20 23:41:34 2019 -0700 @@ -1,16 +1,21 @@ # make rfid && make build_image_pi # docker pull bang6:5000/rfid_pn532_pi && docker run --rm -it --name rfid --net=host --privileged bang6:5000/rfid_pn532_pi -# i2c keeps dropping. kernel from 1.20180313 to 1.201811112.1 - -import nfc-nim/freefare +#import asyncdispatch +import os +import parseutils +import sets import strformat import strutils -import graphserver +import threadpool +import httpclient + +import nfc-nim/freefare + +#import graphserver +import rdf +import rdf_nodes import tags -import threadpool -import os -import sets type CardEvent = object of RootObj uid: cstring @@ -90,19 +95,50 @@ except IOError: echo "IOError: restarting nfc now" - -type TtgArgs = tuple[events: ptr CardEventChannel, server: GraphServer] +proc uidUri(card_id: cstring): Uri = + let id10 = align($card_id, 10, '0') + initUri(&"http://bigasterisk.com/rfidCard/{id10}") + +proc graphChanged(newGraph: openArray[Quad]) = + let client = newHttpClient() + let response = client.request("http://localhost:10012/currentGraph", + httpMethod = HttpPut, body = toSet(newGraph).toJsonLd()) + if response.status != "200 OK": + raise new IOError + +proc sendOneshot(graph: openArray[Quad]) = + let client = newHttpClient() + let response = client.request("http://10.2.0.1:9071/oneShot", + httpMethod = HttpPost, + body = graph.toNtriples(), + headers=newHttpHeaders({ + "Content-Type":"text/n3"})) + if response.status != "200 OK": + raise new IOError + + +type TtgArgs = tuple[events: ptr CardEventChannel,] proc tagsToGraph(args: TtgArgs) {.thread.} = + let ROOM = initNamespace("http://projects.bigasterisk.com/room/") + let sensor = ROOM["frontDoorWindowRfid"] + let ctx = ROOM["frontDoorWindowRfidCtx"] + while true: - echo "wait for event" let ev = args.events[].recv() if ev.appeared: - args.server.setGraph() + let cardUri = uidUri(ev.uid) + graphChanged([ + Quad((sensor, ROOM["reading"], cardUri, ctx)), + Quad((cardUri, ROOM["cardText"], initLiteral(ev.body), ctx)), + ]) + sendOneshot([ + Quad((sensor, ROOM["startReading"], cardUri, ctx)), + Quad((cardUri, ROOM["cardText"], initLiteral(ev.body), ctx)) + ]) else: - args.server.setGraph() + graphChanged([]) proc main() = - var events: CardEventChannel events.open() @@ -110,11 +146,10 @@ var thr: Thread[tw.type] thr.createThread(watchForever, tw) - let server = newGraphServer(port = 10012) - var t2: Thread[TtgArgs] - t2.createThread(tagsToGraph, (addr events, server)) + t2.createThread(tagsToGraph, (addr events,)) - server.run() + joinThread(thr) + joinThread(t2) main()