comparison service/frontDoorLock/front_door_lock.py @ 1456:a81def58ecfb

index page rewrite. mqtt subscribe update. new store/events graph uri Ignore-this: f0e59d3487ebfc90f8f4a830a7084023 darcs-hash:45bd18fecdb41c90b786a9e5909111e4a17bfcbe
author drewp <drewp@bigasterisk.com>
date Wed, 25 Sep 2019 17:36:44 -0700
parents 7229daca9c9a
children a93fbf0d0daa
comparison
equal deleted inserted replaced
1455:1a7cd0cff3eb 1456:a81def58ecfb
42 42
43 def requestUser(req): 43 def requestUser(req):
44 # what happened to the case-insens dict? 44 # what happened to the case-insens dict?
45 h = dict((k.lower(), v) for k,v in req.headers.items()) 45 h = dict((k.lower(), v) for k,v in req.headers.items())
46 return URIRef(h['x-foaf-agent']) 46 return URIRef(h['x-foaf-agent'])
47 47
48 48
49 class OutputPage(cyclone.web.RequestHandler): 49 class OutputPage(cyclone.web.RequestHandler):
50 def put(self): 50 def put(self):
51 try: 51 try:
52 user = requestUser(self.request) 52 user = requestUser(self.request)
64 g = rdfGraphBody(self.request.body, self.request.headers) 64 g = rdfGraphBody(self.request.body, self.request.headers)
65 assert len(g) == 1, len(g) 65 assert len(g) == 1, len(g)
66 stmt = next(g.triples((None, None, None))) 66 stmt = next(g.triples((None, None, None)))
67 self._onStatement(user, stmt) 67 self._onStatement(user, stmt)
68 post = put 68 post = put
69 69
70 def _onStatement(self, user, stmt): 70 def _onStatement(self, user, stmt):
71 log.info('put statement %r', stmt) 71 log.info('put statement %r', stmt)
72 if stmt[0:2] == (ROOM['frontDoorLock'], ROOM['state']): 72 if stmt[0:2] == (ROOM['frontDoorLock'], ROOM['state']):
73 if stmt[2] == ROOM['unlocked']: 73 if stmt[2] == ROOM['unlocked']:
74 log.info('unlock for %r', user) 74 log.info('unlock for %r', user)
86 user = requestUser(self.request) 86 user = requestUser(self.request)
87 except KeyError: 87 except KeyError:
88 log.warn('request without x-foaf-agent: %s', h) 88 log.warn('request without x-foaf-agent: %s', h)
89 self.set_status(403, 'need x-foaf-agent') 89 self.set_status(403, 'need x-foaf-agent')
90 return 90 return
91 91
92 state = self.request.body.strip().decode('ascii') 92 state = self.request.body.strip().decode('ascii')
93 if state == 'unlock': 93 if state == 'unlock':
94 self.settings.autoLock.onUnlockedStmt() 94 self.settings.autoLock.onUnlockedStmt()
95 self.settings.mqtt.publish(espName + b"/switch/strike/command", b'ON') 95 self.settings.mqtt.publish(espName + b"/switch/strike/command", b'ON')
96 if state == 'lock': 96 if state == 'lock':
97 self.settings.autoLock.onLockedStmt() 97 self.settings.autoLock.onLockedStmt()
98 self.settings.mqtt.publish(espName + b"/switch/strike/command", b'OFF') 98 self.settings.mqtt.publish(espName + b"/switch/strike/command", b'OFF')
99 99
100 100
101 class AutoLock(object): 101 class AutoLock(object):
102 def __init__(self, masterGraph, mqtt): 102 def __init__(self, masterGraph, mqtt):
103 self.masterGraph = masterGraph 103 self.masterGraph = masterGraph
104 self.mqtt = mqtt 104 self.mqtt = mqtt
105 self.timeUnlocked = None 105 self.timeUnlocked = None
106 self.autoLockSec = 6 106 self.autoLockSec = 6
107 self.subj = ROOM['frontDoorLock'] 107 self.subj = ROOM['frontDoorLock']
108 task.LoopingCall(self.pollCheck).start(1) 108 task.LoopingCall(self.pollCheck).start(1)
109 109
110 def relock(self): 110 def relock(self):
111 log.info('autolock is up: requesting lock') 111 log.info('autolock is up: requesting lock')
133 def pollCheck(self): 133 def pollCheck(self):
134 try: 134 try:
135 self.check() 135 self.check()
136 except Exception: 136 except Exception:
137 log.exception('poll failed') 137 log.exception('poll failed')
138 138
139 def check(self): 139 def check(self):
140 g = self.masterGraph 140 g = self.masterGraph
141 now = time.time() 141 now = time.time()
142 state = g._graph.value(self.subj, ROOM['state']) 142 state = g._graph.value(self.subj, ROOM['state'])
143 if state == ROOM['unlocked']: 143 if state == ROOM['unlocked']:
158 else: 158 else:
159 self.clearReport() 159 self.clearReport()
160 160
161 def onUnlockedStmt(self): 161 def onUnlockedStmt(self):
162 self.timeUnlocked = None 162 self.timeUnlocked = None
163 163
164 def onLockedStmt(self): 164 def onLockedStmt(self):
165 pass 165 pass
166 166
167 class BluetoothButton(cyclone.web.RequestHandler): 167 class BluetoothButton(cyclone.web.RequestHandler):
168 def post(self): 168 def post(self):
171 if body['addr'] == 'zz:zz:zz:zz:zz:zz' and body['key'] == 'top': 171 if body['addr'] == 'zz:zz:zz:zz:zz:zz' and body['key'] == 'top':
172 log.info('unlock for %r', body['addr']) 172 log.info('unlock for %r', body['addr'])
173 self.settings.mqtt.publish( 173 self.settings.mqtt.publish(
174 espName + b"/switch/strike/command", b'ON') 174 espName + b"/switch/strike/command", b'ON')
175 175
176 176
177 if __name__ == '__main__': 177 if __name__ == '__main__':
178 arg = docopt(""" 178 arg = docopt("""
179 Usage: front_door_lock.py [options] 179 Usage: front_door_lock.py [options]
180 180
181 -v Verbose 181 -v Verbose
183 verboseLogging(arg['-v']) 183 verboseLogging(arg['-v'])
184 184
185 masterGraph = PatchableGraph() 185 masterGraph = PatchableGraph()
186 mqtt = MqttClient(brokerPort=10010) 186 mqtt = MqttClient(brokerPort=10010)
187 autoclose = AutoLock(masterGraph, mqtt) 187 autoclose = AutoLock(masterGraph, mqtt)
188
189 def toGraph(payload): 188 def toGraph(payload):
190 log.info('mqtt->graph %r', payload) 189 log.info('mqtt->graph %r', payload)
191 masterGraph.patchObject(ctx, ROOM['frontDoorLock'], ROOM['state'], 190 masterGraph.patchObject(ctx, ROOM['frontDoorLock'], ROOM['state'],
192 stateFromMqtt(payload)) 191 stateFromMqtt(payload))
193 192
194 mqtt.subscribe(espName + b"/switch/strike/state").subscribe(on_next=toGraph) 193 sub = mqtt.subscribe(espName + b"/switch/strike/state")
194 sub.subscribe(on_next=toGraph)
195 195
196 def setEspState(payload): 196 def setEspState(payload):
197 log.info('esp state change %r', payload) 197 log.info('esp state change %r', payload)
198 masterGraph.patchObject(ctx, ROOM['frontDoorLock'], ROOM['espMqttConnection'], 198 masterGraph.patchObject(ctx, ROOM['frontDoorLock'], ROOM['espMqttConnection'],
199 ROOM['mqtt' + payload.decode('ascii').capitalize()]) 199 ROOM['mqtt' + payload.decode('ascii').capitalize()])
200 200
201 mqtt.subscribe(espName + b"/status").subscribe(on_next=setEspState) 201 sub = mqtt.subscribe(espName + b"/status")
202 202 sub.subscribe(on_next=setEspState)
203
203 port = 10011 204 port = 10011
204 reactor.listenTCP(port, cyclone.web.Application( 205 reactor.listenTCP(port, cyclone.web.Application(
205 [ 206 [
206 (r"/()", cyclone.web.StaticFileHandler, 207 (r"/()", cyclone.web.StaticFileHandler,
207 {"path": ".", "default_filename": "index.html"}), 208 {"path": ".", "default_filename": "index.html"}),