changeset 467:56af0ca2db10

last version of nim attempt for pn532 rfid reader. adds simple nim lib for RDF Ignore-this: 7bc9a248f49f57dd0a08c849b807a586
author drewp@bigasterisk.com
date Sat, 20 Apr 2019 23:41:34 -0700
parents 1122016d16eb
children 756ff1170342
files service/rfid_pn532/graphserver.nim service/rfid_pn532/makefile service/rfid_pn532/rfid.nim
diffstat 3 files changed, 131 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
--- 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()