diff service/frontDoorLock/front_door_lock.py @ 379:67cebf7a14de

frontdoor autolock. logging improvements. use simpler mqtt interface. Ignore-this: e2bf5262a89ebb898108a634679fdec7
author drewp@bigasterisk.com
date Wed, 12 Dec 2018 01:11:54 -0800
parents 5b690bfc31b2
children d495d4382a07
line wrap: on
line diff
--- a/service/frontDoorLock/front_door_lock.py	Wed Dec 12 01:10:48 2018 -0800
+++ b/service/frontDoorLock/front_door_lock.py	Wed Dec 12 01:11:54 2018 -0800
@@ -2,16 +2,14 @@
 from patchablegraph import PatchableGraph, CycloneGraphHandler, CycloneGraphEventsHandler
 from rdflib import Namespace, URIRef, Literal, Graph
 from rdflib.parser import StringInputSource
-from twisted.internet import reactor
+from twisted.internet import reactor, task
 import cyclone.web
-import sys, logging
+import sys, logging, time
 from mqtt_client import MqttClient
+from logsetup import log, enableTwistedLog
 
 ROOM = Namespace('http://projects.bigasterisk.com/room/')
 
-logging.basicConfig()
-log = logging.getLogger()
-
 ctx = ROOM['frontDoorControl']
 
 def rdfGraphBody(body, headers):
@@ -44,15 +42,44 @@
             assert len(g) == 1, len(g)
             stmt = g.triples((None, None, None)).next()
         self._onStatement(stmt)
-            
+    post = put
+    
     def _onStatement(self, stmt):
         if stmt[0:2] == (ROOM['frontDoorLock'], ROOM['state']):
             self.settings.mqtt.publish("frontdoor/switch/strike/command",
                                        mqttMessageFromState(stmt[2]))
-            self.settings.masterGraph.patchObject(ctx,
-                                                  stmt[0], stmt[1], stmt[2])
             return
         log.warn("ignoring %s", stmt)
+
+
+class AutoLock(object):
+    def __init__(self, masterGraph, mqtt):
+        self.masterGraph = masterGraph
+        self.mqtt = mqtt
+        self.timeUnlocked = None
+        self.autoLockSec = 5
+        self.subj = ROOM['frontDoorLock']
+        task.LoopingCall(self.check).start(1)
+
+    def check(self):
+        now = time.time()
+        state = self.masterGraph._graph.value(self.subj, ROOM['state'])
+        if state == ROOM['unlocked']:
+            if self.timeUnlocked is None:
+                self.timeUnlocked = now
+            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']))
+        else:
+            self.timeUnlocked = None
+            self.masterGraph.patchObject(ctx, self.subj, ROOM['unlockedForSec'], None)
+            self.masterGraph.patchObject(ctx, self.subj, ROOM['autoLockInSec'], None)
+
             
 if __name__ == '__main__':
     arg = docopt("""
@@ -60,23 +87,25 @@
 
     -v   Verbose
     """)
-    log.setLevel(logging.WARN)
+    log.setLevel(logging.INFO)
     if arg['-v']:
-        from twisted.python import log as twlog
-        twlog.startLogging(sys.stdout)
+        enableTwistedLog()
         log.setLevel(logging.DEBUG)
 
     masterGraph = PatchableGraph()
     mqtt = MqttClient(brokerPort=10010)
+    autoclose = AutoLock(masterGraph, mqtt)
 
     def toGraph(payload):
-        log.debug('toGraph %r', payload)
+        log.info('mqtt->graph %r', payload)
         masterGraph.patchObject(ctx, ROOM['frontDoorLock'], ROOM['state'],
                                 stateFromMqtt(payload))
 
     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}),