annotate service/reasoning/reasoning.py @ 45:5b0f970e3d52

/status page, errors on failed graphs, time reports of successful fetches Ignore-this: 14742f2a6237f996d7024ff4454a8057
author drewp@bigasterisk.com
date Sun, 30 Dec 2012 03:02:25 -0800
parents c3c203100e06
children f5623d9b07fd
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
1 #!bin/python
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
2 """
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
3 gather subgraphs from various services, run them through a rules
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
4 engine, and make http requests with the conclusions.
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
5
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
6 E.g. 'when drew's phone is near the house, and someone is awake,
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
7 unlock the door when the door's motion sensor is activated'
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
8
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
9 When do we gather? The services should be able to trigger us, perhaps
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
10 with PSHB, that their graph has changed.
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
11 """
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
12
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
13
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
14 from twisted.internet import reactor, task
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
15 from twisted.web.client import getPage
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
16 import time, traceback, sys, json
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
17 from rdflib.Graph import Graph, ConjunctiveGraph
45
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
18 from rdflib import Namespace, URIRef, Literal, RDF
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
19 import restkit
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
20 from FuXi.Rete.RuleStore import N3RuleStore
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
21 import cyclone.web
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
22 from inference import addTrig, infer
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
23
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
24 sys.path.append("../../lib")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
25 from logsetup import log
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
26
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
27 ROOM = Namespace("http://projects.bigasterisk.com/room/")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
28 DEV = Namespace("http://projects.bigasterisk.com/device/")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
29
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
30 def gatherGraph():
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
31 g = ConjunctiveGraph()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
32 for source in ["http://bang:9069/graph", # arduino watchpins
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
33 "http://bang:9070/graph", # wifi usage
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
34 "http://bang:9075/graph", # env
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
35 "http://slash:9050/graph", # garageArduino for front motion
33
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
36 "http://dash:9095/graph", # dash monitor
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
37 "http://bang:9095/graph", # bang monitor
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
38 ]:
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
39 try:
45
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
40 fetchTime = addTrig(g, source)
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
41 except Exception, e:
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
42 log.error("adding source %s: %s", source, e)
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
43 g.add((URIRef(source), ROOM['graphLoadError'], Literal(str(e))))
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
44 g.add((URIRef(source), RDF.type, ROOM['FailedGraphLoad']))
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
45 else:
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
46 g.add((URIRef(source), ROOM['graphLoadSecs'], Literal(fetchTime)))
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
47 return g
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
48
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
49 def graphWithoutMetadata(g, ignorePredicates=[]):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
50 """
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
51 graph filter that removes any statements whose subjects are
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
52 contexts in the graph and also any statements with the given
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
53 predicates
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
54 """
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
55 ctxs = map(URIRef, set(g.contexts())) # weird they turned to strings
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
56
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
57 out = ConjunctiveGraph()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
58 for stmt in g.quads((None, None, None)):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
59 if stmt[0] not in ctxs and stmt[1] not in ignorePredicates:
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
60 out.addN([stmt])
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
61 return out
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
62
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
63 def graphEqual(a, b, ignorePredicates=[]):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
64 """
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
65 compare graphs, omitting any metadata statements about contexts
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
66 (especially modification times) and also any statements using the
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
67 given predicates
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
68 """
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
69 stmtsA = graphWithoutMetadata(a, ignorePredicates)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
70 stmtsB = graphWithoutMetadata(b, ignorePredicates)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
71 return set(stmtsA) == set(stmtsB)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
72
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
73 class Reasoning(object):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
74 def __init__(self):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
75 self.prevGraph = None
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
76 self.lastPollTime = 0
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
77 self.lastError = ""
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
78
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
79 self.deviceGraph = Graph()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
80 self.deviceGraph.parse("/my/proj/room/devices.n3", format="n3")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
81
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
82 self.rulesN3 = "(not read yet)"
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
83 self.inferred = Graph() # gets replaced in each graphChanged call
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
84
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
85 def readRules(self):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
86 self.rulesN3 = open('rules.n3').read() # for web display
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
87 self.ruleStore = N3RuleStore()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
88 self.ruleGraph = Graph(self.ruleStore)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
89 self.ruleGraph.parse('rules.n3', format='n3') # for inference
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
90
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
91 def poll(self):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
92 try:
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
93 self._poll()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
94 self.lastPollTime = time.time()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
95 except Exception, e:
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
96 log.error(traceback.format_exc())
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
97 self.lastError = str(e)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
98
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
99 def _poll(self):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
100 g = gatherGraph()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
101 if (self.prevGraph is None or
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
102 not graphEqual(g, self.prevGraph,
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
103 ignorePredicates=[ROOM.signalStrength])):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
104 self.graphChanged(g)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
105
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
106 self.prevGraph = g
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
107
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
108 def graphChanged(self, g):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
109 # i guess these are getting consumed each inference
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
110 try:
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
111 t1 = time.time()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
112 self.readRules()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
113 ruleParseTime = time.time() - t1
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
114 except ValueError, e:
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
115 # this is so if you're just watching the inferred output,
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
116 # you'll see the error too
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
117 self.inferred = Graph()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
118 self.inferred.add((ROOM['reasoner'], ROOM['ruleParseError'],
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
119 Literal(traceback.format_exc())))
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
120 raise
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
121
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
122 t1 = time.time()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
123 self.inferred = infer(g, self.ruleStore)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
124 inferenceTime = time.time() - t1
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
125
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
126 self.inferred.add((ROOM['reasoner'], ROOM['ruleParseTime'],
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
127 Literal(ruleParseTime)))
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
128 self.inferred.add((ROOM['reasoner'], ROOM['inferenceTime'],
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
129 Literal(inferenceTime)))
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
130
33
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
131 self.putResults(self.inferred)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
132
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
133 try:
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
134 inputGraphNt = g.serialize(format="nt")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
135 inferredNt = self.inferred.serialize(format="nt")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
136 body = json.dumps({"input": inputGraphNt,
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
137 "inferred": inferredNt})
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
138 restkit.Resource("http://bang:8014/").post(
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
139 "reasoningChange", payload=body,
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
140 headers={"content-type" : "application/json"})
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
141 except Exception, e:
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
142 traceback.print_exc()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
143 log.error("while sending changes to magma:")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
144 log.error(e)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
145
33
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
146
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
147 def putResults(self, inferred):
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
148 """
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
149 some conclusions in the inferred graph lead to PUT requests
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
150 getting made
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
151
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
152 if the graph contains (?d ?p ?o) and ?d and ?p are a device
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
153 and predicate we support PUTs for, then we look up
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
154 (?d :putUrl ?url) and (?o :putValue ?val) and call
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
155 PUT ?url <- ?val
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
156
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
157 If the graph doesn't contain any matches, we use (?d
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
158 :zeroValue ?val) for the value and PUT that.
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
159 """
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
160
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
161 for dev, pred in [
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
162 # the config of each putUrl should actually be in the
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
163 # context of a dev and predicate pair, and then that would
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
164 # be the source of this list
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
165 (DEV.theaterDoorLock, ROOM.state),
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
166 (URIRef('http://bigasterisk.com/host/bang/monitor'), ROOM.powerState),
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
167 ]:
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
168 url = self.deviceGraph.value(dev, ROOM.putUrl)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
169
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
170 if dev == DEV.theaterDoorLock: # ew
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
171 restkit.request(url=url+"/mode", method="PUT", body="output")
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
172
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
173 inferredObjects = list(inferred.objects(dev, pred))
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
174 if len(inferredObjects) == 0:
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
175 self.putZero(dev, pred, url)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
176 elif len(inferredObjects) == 1:
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
177 self.putInferred(dev, pred, url, inferredObjects[0])
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
178 elif len(inferredObjects) > 1:
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
179 log.info("conflict, ignoring: %s has %s of %s" %
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
180 (dev, pred, inferredObjects))
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
181 # write about it to the inferred graph?
45
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
182
33
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
183 self.frontDoorPuts(inferred)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
184
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
185 def putZero(self, dev, pred, putUrl):
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
186 # zerovalue should be a function of pred as well.
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
187 value = self.deviceGraph.value(dev, ROOM.zeroValue)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
188 if value is not None:
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
189 log.info("put zero (%r) to %s", value, putUrl)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
190 restkit.request(url=putUrl, method="PUT", body=value)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
191 # this should be written back into the inferred graph
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
192 # for feedback
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
193
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
194 def putInferred(self, dev, pred, putUrl, obj):
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
195 value = self.deviceGraph.value(obj, ROOM.putValue)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
196 if value is not None:
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
197 log.info("put %s to %s", value, putUrl)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
198 restkit.request(url=putUrl, method="PUT", body=value)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
199 else:
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
200 log.warn("%s %s %s has no :putValue" %
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
201 (dev, pred, obj))
45
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
202
33
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
203 def frontDoorPuts(self, inferred):
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
204 # todo: shouldn't have to be a special case
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
205 brt = inferred.value(DEV.frontDoorLcd, ROOM.brightness)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
206 url = self.deviceGraph.value(DEV.frontDoorLcdBrightness,
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
207 ROOM.putUrl)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
208 log.info("put lcd %s brightness %s", url, brt)
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
209 getPage(str(url) + "?brightness=%s" % str(brt), method="PUT")
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
210
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
211 msg = "open %s motion %s" % (inferred.value(DEV['frontDoorOpenIndicator'], ROOM.text),
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
212 inferred.value(DEV['frontDoorMotionIndicator'], ROOM.text))
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
213 # this was meant to be 2 chars in the bottom row, but the
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
214 # easier test was to replace the whole top msg
c3c203100e06 redo the http PUT request part of the reasoner
drewp@bigasterisk.com
parents: 20
diff changeset
215 #restkit.Resource("http://slash:9080/").put("lcd", message=msg)
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
216
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
217
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
218 class Index(cyclone.web.RequestHandler):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
219 def get(self):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
220 # make sure GET / fails if our poll loop died
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
221 ago = time.time() - self.settings.reasoning.lastPollTime
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
222 if ago > 2:
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
223 self.set_status(500)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
224 self.finish("last poll was %s sec ago. last error: %s" %
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
225 (ago, self.settings.reasoning.lastError))
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
226 return
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
227 self.set_header("Content-Type", "application/xhtml+xml")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
228 self.write(open('index.html').read())
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
229
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
230 # for reuse
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
231 class GraphResource(cyclone.web.RequestHandler):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
232 def get(self, which):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
233 self.set_header("Content-Type", "application/json")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
234 r = self.settings.reasoning
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
235 g = {'lastInput': r.prevGraph,
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
236 'lastOutput': r.inferred,
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
237 }[which]
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
238 self.write(self.jsonRdf(g))
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
239
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
240 def jsonRdf(self, g):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
241 return json.dumps(sorted(list(g)))
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
242
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
243 class NtGraphs(cyclone.web.RequestHandler):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
244 """same as what gets posted above"""
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
245 def get(self):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
246 r = self.settings.reasoning
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
247 inputGraphNt = r.prevGraph.serialize(format="nt")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
248 inferredNt = r.inferred.serialize(format="nt")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
249 self.set_header("Content-Type", "application/json")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
250 self.write(json.dumps({"input": inputGraphNt,
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
251 "inferred": inferredNt}))
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
252
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
253 class Rules(cyclone.web.RequestHandler):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
254 def get(self):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
255 self.set_header("Content-Type", "text/plain")
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
256 self.write(self.settings.reasoning.rulesN3)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
257
45
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
258 class Status(cyclone.web.RequestHandler):
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
259 def get(self):
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
260 self.set_header("Content-Type", "text/plain")
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
261 g = self.settings.reasoning.prevGraph
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
262 msg = ""
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
263 for badSource in g.subjects(RDF.type, ROOM['FailedGraphLoad']):
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
264 msg += "GET %s failed (%s). " % (
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
265 badSource, g.value(badSource, ROOM['graphLoadError']))
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
266 if not msg:
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
267 self.write("all inputs ok")
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
268 self.set_status(500)
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
269 self.finish(msg)
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
270
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
271 class Static(cyclone.web.RequestHandler):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
272 def get(self, p):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
273 self.write(open(p).read())
45
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
274
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
275 class Application(cyclone.web.Application):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
276 def __init__(self, reasoning):
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
277 handlers = [
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
278 (r"/", Index),
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
279 (r'/(jquery.min.js)', Static),
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
280 (r'/(lastInput|lastOutput)Graph', GraphResource),
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
281 (r'/ntGraphs', NtGraphs),
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
282 (r'/rules', Rules),
45
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
283 (r'/status', Status),
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
284 ]
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
285 cyclone.web.Application.__init__(self, handlers, reasoning=reasoning)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
286
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
287 if __name__ == '__main__':
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
288 r = Reasoning()
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
289 #import twisted.python.log
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
290 #twisted.python.log.startLogging(sys.stdout)
45
5b0f970e3d52 /status page, errors on failed graphs, time reports of successful fetches
drewp@bigasterisk.com
parents: 33
diff changeset
291
20
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
292 task.LoopingCall(r.poll).start(1.0)
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
293 reactor.listenTCP(9071, Application(r))
3f0dd03112b5 move reasoning from /my/proj/room, new integration with magma
drewp@bigasterisk.com
parents:
diff changeset
294 reactor.run()