Mercurial > code > home > repos > homeauto
comparison service/reasoning/actions.py @ 1197:d8acab2b01f5
mqtt has two devices now. various older cleanups.
Ignore-this: 67ca3acc5dc6aa672d0c896c9f5ae48e
darcs-hash:964511475873219e6bc4725388a8d2e54a3c4e28
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sat, 19 Jan 2019 12:08:59 -0800 |
parents | 114ca7fd9d01 |
children | 1ceb26846eca |
comparison
equal
deleted
inserted
replaced
1196:ef15d8915d09 | 1197:d8acab2b01f5 |
---|---|
24 PUT ?url <- ?val | 24 PUT ?url <- ?val |
25 | 25 |
26 If the graph doesn't contain any matches, we use (?d | 26 If the graph doesn't contain any matches, we use (?d |
27 :zeroValue ?val) for the value and PUT that. | 27 :zeroValue ?val) for the value and PUT that. |
28 """ | 28 """ |
29 | 29 self._putDevices(deviceGraph, inferred) |
30 self._oneShotPostActions(deviceGraph, inferred) | 30 self._oneShotPostActions(deviceGraph, inferred) |
31 for dev, pred in [ | 31 for dev, pred in [ |
32 # the config of each putUrl should actually be in the | |
33 # context of a dev and predicate pair, and then that would | |
34 # be the source of this list | |
35 #(DEV.theaterDoorLock, ROOM.state), | |
36 #(URIRef('http://bigasterisk.com/host/bang/monitor'), ROOM.powerState), | 32 #(URIRef('http://bigasterisk.com/host/bang/monitor'), ROOM.powerState), |
37 (URIRef('http://bigasterisk.com/host/dash/monitor'), ROOM.powerState), | 33 (URIRef('http://bigasterisk.com/host/dash/monitor'), ROOM.powerState), |
34 (URIRef('http://bigasterisk.com/host/frontdoor/monitor'), ROOM.powerState), | |
38 (ROOM['storageCeilingLedLong'], ROOM.brightness), | 35 (ROOM['storageCeilingLedLong'], ROOM.brightness), |
39 (ROOM['storageCeilingLedCross'], ROOM.brightness), | 36 (ROOM['storageCeilingLedCross'], ROOM.brightness), |
37 (ROOM['garageOverhead'], ROOM.brightness), | |
40 (ROOM['headboardWhite'], ROOM.brightness), | 38 (ROOM['headboardWhite'], ROOM.brightness), |
41 (ROOM['changingWhite'], ROOM.brightness), | 39 (ROOM['changingWhite'], ROOM.brightness), |
42 (ROOM['starTrekLight'], ROOM.brightness), | 40 (ROOM['starTrekLight'], ROOM.brightness), |
41 (ROOM['kitchenLight'], ROOM.brightness), | |
42 (ROOM['kitchenCounterLight'], ROOM.brightness), | |
43 (ROOM['livingRoomLamp1'], ROOM.brightness), | 43 (ROOM['livingRoomLamp1'], ROOM.brightness), |
44 (ROOM['livingRoomLamp2'], ROOM.brightness), | 44 (ROOM['livingRoomLamp2'], ROOM.brightness), |
45 (ROOM['bedLedStrip'], ROOM.color), | 45 (ROOM['bedLedStrip'], ROOM.color), |
46 ]: | 46 ]: |
47 url = deviceGraph.value(dev, ROOM.putUrl) | 47 url = deviceGraph.value(dev, ROOM.putUrl) |
48 | 48 |
49 if url and dev == DEV.theaterDoorLock: # ew | 49 log.debug('inferredObjects of dev=%s pred=%s', |
50 self._put(url+"/mode", payload="output") | 50 deviceGraph.qname(dev), |
51 | 51 deviceGraph.qname(pred)) |
52 inferredObjects = list(inferred.objects(dev, pred)) | 52 inferredObjects = list(inferred.objects(dev, pred)) |
53 if len(inferredObjects) == 0: | 53 if len(inferredObjects) == 0: |
54 self._putZero(deviceGraph, dev, pred, url) | 54 self._putZero(deviceGraph, dev, pred, url) |
55 elif len(inferredObjects) == 1: | 55 elif len(inferredObjects) == 1: |
56 log.debug('inferredObject: %s %s %r', | 56 log.debug(' inferredObject: %s %s %r', |
57 deviceGraph.qname(dev), | 57 deviceGraph.qname(dev), |
58 deviceGraph.qname(pred), | 58 deviceGraph.qname(pred), |
59 inferredObjects[0]) | 59 inferredObjects[0].toPython()) |
60 self._putInferred(deviceGraph, url, inferredObjects[0]) | 60 self._putInferred(deviceGraph, url, inferredObjects[0]) |
61 elif len(inferredObjects) > 1: | 61 elif len(inferredObjects) > 1: |
62 log.info("conflict, ignoring: %s has %s of %s" % | 62 log.info(" conflict, ignoring: %s has %s of %s" % |
63 (dev, pred, inferredObjects)) | 63 (dev, pred, inferredObjects)) |
64 # write about it to the inferred graph? | 64 # write about it to the inferred graph? |
65 | 65 |
66 #self._frontDoorPuts(deviceGraph, inferred) | |
67 | |
68 def _oneShotPostActions(self, deviceGraph, inferred): | 66 def _oneShotPostActions(self, deviceGraph, inferred): |
69 """ | 67 """ |
70 Inferred graph may contain some one-shot statements. We'll send | 68 Inferred graph may contain some one-shot statements. We'll send |
71 statement objects to anyone on web sockets, and also generate | 69 statement objects to anyone on web sockets, and also generate |
72 POST requests as described in the graph. | 70 POST requests as described in the graph. |
86 for osp in deviceGraph.subjects(RDF.type, ROOM['OneShotPost']): | 84 for osp in deviceGraph.subjects(RDF.type, ROOM['OneShotPost']): |
87 s = deviceGraph.value(osp, ROOM['subject']) | 85 s = deviceGraph.value(osp, ROOM['subject']) |
88 p = deviceGraph.value(osp, ROOM['predicate']) | 86 p = deviceGraph.value(osp, ROOM['predicate']) |
89 if s is None or p is None: | 87 if s is None or p is None: |
90 continue | 88 continue |
91 log.info("checking for %s %s", s, p) | 89 #log.info("checking for %s %s", s, p) |
92 for postTarget in inferred.objects(s, p): | 90 for postTarget in inferred.objects(s, p): |
93 log.info("post target %r", postTarget) | 91 log.info("post target %r", postTarget) |
94 # this packet ought to have 'oneShot' in it somewhere | 92 # this packet ought to have 'oneShot' in it somewhere |
95 self.sendToLiveClients({"s":s, "p":p, "o":postTarget}) | 93 self.sendToLiveClients({"s":s, "p":p, "o":postTarget}) |
96 | 94 |
97 log.info(" POST %s", postTarget) | 95 log.info(" POST %s", postTarget) |
98 fetch(postTarget, method="POST", timeout=2).addErrback(err) | 96 fetch(postTarget, method="POST", timeout=2).addErrback(err) |
99 self._postMpdCommands(inferred) | |
100 | |
101 def _postMpdCommands(self, inferred): | |
102 """special case to be eliminated. mpd play urls are made of an | |
103 mpd service and a song/album/playlist uri to be played. | |
104 Ideally the graph rules would assemble these like | |
105 http://{mpd}/addAndPlay?uri={toPlay} or maybe toPlay as the payload | |
106 which would be fairly general but still allow toPlay uris to | |
107 be matched with any player.""" | |
108 | 97 |
109 rootSkippingAuth = "http://brace:9009/" | 98 def _putDevices(self, deviceGraph, inferred): |
110 for mpd in [URIRef("http://bigasterisk.com/host/brace/mpd")]: | 99 agentFor = {} |
111 | 100 for stmt in inferred: |
112 for song in inferred.objects(mpd, ROOM['startMusic']): | 101 if stmt[1] == ROOM['putAgent']: |
113 log.info("mpd statement: %r" % song) | 102 agentFor[stmt[0]] = stmt[2] |
114 assert song.startswith('http://bigasterisk.com/music/') | 103 for stmt in inferred: |
115 self.post(rootSkippingAuth + "addAndPlay" + urllib.quote(song[len("http://bigasterisk.com/music"):])) | 104 putUrl = deviceGraph.value(stmt[0], ROOM['putUrl']) |
116 | 105 putPred = deviceGraph.value(stmt[0], ROOM['putPredicate']) |
117 for state in inferred.objects(mpd, ROOM['playState']): | 106 if putUrl and putPred == stmt[1]: |
118 log.info('hello playstate %s', state) | 107 self._put(putUrl + '?' + urllib.urlencode([ |
119 if state == ROOM['pause']: | 108 ('s', str(stmt[0])), |
120 log.info("mpd %s %s", mpd, state) | 109 ('p', str(stmt[1]))]), |
121 self.post(rootSkippingAuth + "mpd/pause") | 110 str(stmt[2].toPython()), |
122 for vol in inferred.objects(mpd, ROOM['audioState']): | 111 agent=agentFor.get(stmt[0], None)) |
123 if vol == ROOM['volumeStepUp']: | |
124 self.post(rootSkippingAuth + "volumeAdjust?amount=6&max=70") | |
125 if vol == ROOM['volumeStepDown']: | |
126 self.post(rootSkippingAuth + "volumeAdjust?amount=-6&min=10") | |
127 | |
128 def _frontDoorPuts(self, deviceGraph, inferred): | |
129 # todo: shouldn't have to be a special case | |
130 brt = inferred.value(DEV.frontDoorLcd, ROOM.brightness) | |
131 if brt is None: | |
132 return | |
133 url = deviceGraph.value(DEV.frontDoorLcdBrightness, ROOM.putUrl) | |
134 log.info("put lcd %s brightness %s", url, brt) | |
135 self._put(str(url) + "?brightness=%s" % str(brt), payload='') | |
136 | |
137 msg = "open %s motion %s" % ( | |
138 inferred.value(DEV['frontDoorOpenIndicator'], ROOM.text), | |
139 inferred.value(DEV['frontDoorMotionIndicator'], ROOM.text)) | |
140 # this was meant to be 2 chars in the bottom row, but the | |
141 # easier test was to replace the whole top msg | |
142 #restkit.Resource("http://slash:9080/").put("lcd", message=msg) | |
143 | |
144 | |
145 | |
146 | |
147 def _put(self, url, payload): | |
148 def err(e): | |
149 log.warn(" put %s failed (%r)", url, e) | |
150 log.info(" PUT %s payload=%r", url, payload) | |
151 fetch(url, method="PUT", postdata=payload, timeout=2).addErrback(err) | |
152 | |
153 def post(self, postTarget): | |
154 log.info("special mpd POST %s", postTarget) | |
155 def err(e): | |
156 log.warn("post %s failed", postTarget) | |
157 fetch(postTarget, method="POST", timeout=2).addErrback(err) | |
158 | |
159 def _putZero(self, deviceGraph, dev, pred, putUrl): | |
160 # zerovalue should be a function of pred as well. | |
161 value = deviceGraph.value(dev, ROOM.zeroValue) | |
162 if value is not None: | |
163 log.info("put zero (%r) to %s", value, putUrl) | |
164 self._put(putUrl, payload=str(value)) | |
165 # this should be written back into the inferred graph | |
166 # for feedback | |
167 | 112 |
168 def _putInferred(self, deviceGraph, putUrl, obj): | 113 def _putInferred(self, deviceGraph, putUrl, obj): |
169 """ | 114 """ |
170 HTTP PUT to putUrl, with a payload that's either obj's :putValue | 115 HTTP PUT to putUrl, with a payload that's either obj's :putValue |
171 or obj itself. | 116 or obj itself. |
174 if value is not None: | 119 if value is not None: |
175 self._put(putUrl, payload=str(value)) | 120 self._put(putUrl, payload=str(value)) |
176 elif isinstance(obj, Literal): | 121 elif isinstance(obj, Literal): |
177 self._put(putUrl, payload=str(obj)) | 122 self._put(putUrl, payload=str(obj)) |
178 else: | 123 else: |
179 log.warn("don't know what payload to put for %s. obj=%r", | 124 log.warn(" don't know what payload to put for %s. obj=%r", |
180 putUrl, obj) | 125 putUrl, obj) |
126 | |
127 def _putZero(self, deviceGraph, dev, pred, putUrl): | |
128 # zerovalue should be a function of pred as well. | |
129 value = deviceGraph.value(dev, ROOM.zeroValue) | |
130 if value is not None: | |
131 log.info(" put zero (%r) to %s", value.toPython(), putUrl) | |
132 self._put(putUrl, payload=str(value)) | |
133 # this should be written back into the inferred graph | |
134 # for feedback | |
135 | |
136 def _put(self, url, payload, agent=None): | |
137 assert isinstance(payload, bytes) | |
138 def err(e): | |
139 log.warn(" put %s failed (%r)", url, e) | |
140 log.info(" PUT %s payload=%s agent=%s", url, payload, agent) | |
141 headers = {} | |
142 if agent is not None: | |
143 headers['x-foaf-agent'] = [str(agent)] | |
144 fetch(url, method="PUT", postdata=payload, timeout=2, | |
145 headers=headers).addErrback(err) |