# HG changeset patch # User drewp # Date 1554369382 25200 # Node ID 02e4b84821d515157c21c952372bb09946cef4b0 # Parent a72e9245cc72cee3263cd32c6de7586772e416a2 talk to store graph, second button for holding unlocked, etc Ignore-this: c2ae7d756e743c26e5e01d99772899bd darcs-hash:a0750d0bbc4dc7c0f65f63f3e7342b35a175141b diff -r a72e9245cc72 -r 02e4b84821d5 service/frontDoorLock/front_door_lock.py --- a/service/frontDoorLock/front_door_lock.py Thu Apr 04 02:14:48 2019 -0700 +++ b/service/frontDoorLock/front_door_lock.py Thu Apr 04 02:16:22 2019 -0700 @@ -12,7 +12,7 @@ from rdflib.parser import StringInputSource from twisted.internet import reactor, task import cyclone.web -import sys, logging, time +import logging, time, json from mqtt_client import MqttClient from logsetup import log, enableTwistedLog @@ -39,6 +39,12 @@ class OutputPage(cyclone.web.RequestHandler): def put(self): + try: + user = URIRef(self.request.headers['x-foaf-agent']) + except KeyError: + log.warn('request without x-foaf-agent: %s', self.request.headers) + self.set_status(403, 'need x-foaf-agent') + return arg = self.request.arguments if arg.get('s') and arg.get('p'): subj = URIRef(arg['s'][-1]) @@ -49,11 +55,17 @@ g = rdfGraphBody(self.request.body, self.request.headers) assert len(g) == 1, len(g) stmt = g.triples((None, None, None)).next() - self._onStatement(stmt) + self._onStatement(user, stmt) post = put - def _onStatement(self, stmt): + def _onStatement(self, user, stmt): + log.info('put statement %r', stmt) if stmt[0:2] == (ROOM['frontDoorLock'], ROOM['state']): + if stmt[2] == ROOM['unlocked']: + log.info('unlock for %r', user) + self.settings.autoLock.onUnlockedStmt() + if stmt[2] == ROOM['locked']: + self.settings.autoLock.onLockedStmt() self.settings.mqtt.publish("frontdoor/switch/strike/command", mqttMessageFromState(stmt[2])) return @@ -65,24 +77,44 @@ self.masterGraph = masterGraph self.mqtt = mqtt self.timeUnlocked = None - self.autoLockSec = 5 + self.autoLockSec = 6 self.subj = ROOM['frontDoorLock'] task.LoopingCall(self.check).start(1) + def relock(self): + log.info('autolock is up: requesting lock') + self.mqtt.publish("frontdoor/switch/strike/command", + mqttMessageFromState(ROOM['locked'])) + + def reportTimes(self, unlockedFor): + g = self.masterGraph + lockIn = self.autoLockSec - int(unlockedFor) + if lockIn < 0: + tu = self.timeUnlocked + log.warn("timeUnlocked %(tu)r, state %(state)s, " + "unlockedFor %(unlockedFor)r, lockIn %(lockIn)r", vars()) + lockIn = 0 + g.patchObject(ctx, self.subj, ROOM['unlockedForSec'], + Literal(int(unlockedFor))) + g.patchObject(ctx, self.subj, ROOM['autoLockInSec'], + Literal(lockIn)) + + def clearReport(self): + g = self.masterGraph + g.patchObject(ctx, self.subj, ROOM['unlockedForSec'], None) + g.patchObject(ctx, self.subj, ROOM['autoLockInSec'], None) + def check(self): + g = self.masterGraph now = time.time() - state = self.masterGraph._graph.value(self.subj, ROOM['state']) + state = g._graph.value(self.subj, ROOM['state']) if state == ROOM['unlocked']: if self.timeUnlocked is None: self.timeUnlocked = now + # *newly* unlocked- this resets on every input stmt unlockedFor = now - self.timeUnlocked - self.masterGraph.patchObject(ctx, self.subj, ROOM['unlockedForSec'], - Literal(int(unlockedFor))) - self.masterGraph.patchObject(ctx, self.subj, ROOM['autoLockInSec'], - Literal(self.autoLockSec - int(unlockedFor))) if unlockedFor > self.autoLockSec: - self.mqtt.publish("frontdoor/switch/strike/command", - mqttMessageFromState(ROOM['locked'])) + self.relock() else: self.timeUnlocked = None self.masterGraph.patchObject(ctx, self.subj, ROOM['unlockedForSec'], None) @@ -111,14 +143,21 @@ mqtt.subscribe("frontdoor/switch/strike/state").subscribe(on_next=toGraph) port = 10011 - reactor.listenTCP(port, cyclone.web.Application([ - (r"/()", cyclone.web.StaticFileHandler, - {"path": ".", "default_filename": "index.html"}), - (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}), - (r"/graph/events", CycloneGraphEventsHandler, - {'masterGraph': masterGraph}), - (r'/output', OutputPage), - ], mqtt=mqtt, masterGraph=masterGraph, debug=arg['-v']), interface='::') + reactor.listenTCP(port, cyclone.web.Application( + [ + (r"/()", cyclone.web.StaticFileHandler, + {"path": ".", "default_filename": "index.html"}), + (r"/graph", CycloneGraphHandler, {'masterGraph': masterGraph}), + (r"/graph/events", CycloneGraphEventsHandler, + {'masterGraph': masterGraph}), + (r'/output', OutputPage), + (r'/bluetoothButton', BluetoothButton), + ], + mqtt=mqtt, + masterGraph=masterGraph, + autoLock=autoclose, + debug=arg['-v']), + interface='::') log.warn('serving on %s', port) reactor.run() diff -r a72e9245cc72 -r 02e4b84821d5 service/frontDoorLock/index.html --- a/service/frontDoorLock/index.html Thu Apr 04 02:14:48 2019 -0700 +++ b/service/frontDoorLock/index.html Thu Apr 04 02:16:22 2019 -0700 @@ -58,6 +58,7 @@ diff -r a72e9245cc72 -r 02e4b84821d5 service/frontDoorLock/makefile --- a/service/frontDoorLock/makefile Thu Apr 04 02:14:48 2019 -0700 +++ b/service/frontDoorLock/makefile Thu Apr 04 02:16:22 2019 -0700 @@ -15,5 +15,8 @@ shell: docker run --rm -it --cap-add SYS_PTRACE --net=host bang6:5000/$(JOB)_x86:latest /bin/sh -local_run: - docker run --rm -it --net=host -v `pwd`/index.html:/opt/index.html bang6:5000/$(JOB)_x86:latest python ./front_door_lock.py +local_run: build_image + docker run --rm -it --net=host -v `pwd`/index.html:/opt/index.html bang6:5000/$(JOB)_x86:latest python ./front_door_lock.py -v + +redeploy: build_image + supervisorctl restart $(JOB)_$(PORT) diff -r a72e9245cc72 -r 02e4b84821d5 service/frontDoorLock/requirements.txt --- a/service/frontDoorLock/requirements.txt Thu Apr 04 02:14:48 2019 -0700 +++ b/service/frontDoorLock/requirements.txt Thu Apr 04 02:16:22 2019 -0700 @@ -2,5 +2,5 @@ rdflib-jsonld==0.4.0 rdflib==4.2.2 twisted-mqtt==0.3.6 -https://projects.bigasterisk.com/rdfdb/rdfdb-0.6.0.tar.gz +https://projects.bigasterisk.com/rdfdb/rdfdb-0.7.0.tar.gz rx==1.6.1