annotate service/piNode/devices.py @ 987:cc79d092e136

start pinode Ignore-this: bfafd9994f7f9a61919d49274417ebbb darcs-hash:20150531075655-312f9-15aefdee47756afdbde1b6c83f8797b5f0bb3a88
author drewp <drewp@bigasterisk.com>
date Sun, 31 May 2015 00:56:55 -0700
parents
children 634d6e477953
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
987
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
1 from __future__ import division
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
2 import pigpio
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
3 import time
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
4 from rdflib import Namespace, RDF, URIRef, Literal
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
5
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
6 ROOM = Namespace('http://projects.bigasterisk.com/room/')
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
7
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
8 class DeviceType(object):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
9 deviceType = None
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
10 @classmethod
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
11 def findInstances(cls, graph, board, pi):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
12 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
13 return any number of instances of this class for all the separately
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
14 controlled devices on the board. Two LEDS makes two instances,
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
15 but two sensors on the same onewire bus makes only one device
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
16 (which yields more statements).
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
17 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
18 for row in graph.query("""SELECT ?dev ?pinNumber WHERE {
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
19 ?board :hasPin ?pin .
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
20 ?pin :pinNumber ?pinNumber;
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
21 :connectedTo ?dev .
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
22 ?dev a ?thisType .
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
23 } ORDER BY ?dev""",
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
24 initBindings=dict(board=board,
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
25 thisType=cls.deviceType),
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
26 initNs={'': ROOM}):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
27 yield cls(graph, row.dev, pi, int(row.pinNumber))
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
28
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
29 def __init__(self, graph, uri, pi, pinNumber):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
30 self.graph, self.uri, self.pi = graph, uri, pi
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
31 self.pinNumber = pinNumber
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
32
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
33 def description(self):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
34 return {
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
35 'uri': self.uri,
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
36 'className': self.__class__.__name__,
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
37 'pinNumber': self.pinNumber,
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
38 'outputPatterns': self.outputPatterns(),
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
39 'watchPrefixes': self.watchPrefixes(),
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
40 'outputWidgets': self.outputWidgets(),
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
41 }
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
42
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
43 def watchPrefixes(self):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
44 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
45 subj,pred pairs of the statements that might be returned from
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
46 readFromPoll, so the dashboard knows what it should
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
47 watch. This should be eliminated, as the dashboard should just
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
48 always watch the whole tree of statements starting self.uri
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
49 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
50 return []
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
51
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
52 def poll(self):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
53 return [] # statements
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
54
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
55 def outputPatterns(self):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
56 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
57 Triple patterns, using None as a wildcard, that should be routed
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
58 to sendOutput
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
59 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
60 return []
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
61
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
62 def outputWidgets(self):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
63 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
64 structs to make output widgets on the dashboard. ~1 of these per
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
65 handler you have in sendOutput
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
66 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
67 return []
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
68
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
69 def sendOutput(self, statements):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
70 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
71 If we got statements that match this class's outputPatterns, this
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
72 will be called with the statements that matched.
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
73
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
74 Todo: it would be fine to read back confirmations or
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
75 whatever. Just need a way to collect them into graph statements.
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
76 """
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
77 raise NotImplementedError
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
78
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
79 _knownTypes = set()
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
80 def register(deviceType):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
81 _knownTypes.add(deviceType)
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
82 return deviceType
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
83
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
84 @register
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
85 class MotionSensorInput(DeviceType):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
86 deviceType = ROOM['MotionSensor']
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
87
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
88 def setup(self):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
89 self.pi.set_mode(17, pigpio.INPUT)
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
90 self.pi.set_pull_up_down(17, pigpio.PUD_DOWN)
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
91
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
92 def poll(self):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
93 motion = self.pi.read(17)
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
94
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
95 return [
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
96 (self.uri, ROOM['sees'],
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
97 ROOM['motion'] if motion else ROOM['noMotion']),
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
98 self.recentMotionStatement(motion),
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
99 ]
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
100
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
101 def recentMotionStatement(self, motion):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
102 if not hasattr(self, 'lastMotionTime'):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
103 self.lastMotionTime = 0
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
104 now = time.time()
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
105 if motion:
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
106 self.lastMotionTime = now
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
107 recentMotion = now - self.lastMotionTime < 60 * 10
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
108 return (self.uri, ROOM['seesRecently'],
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
109 ROOM['motion'] if recentMotion else ROOM['noMotion'])
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
110
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
111 def watchPrefixes(self):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
112 return [
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
113 (self.uri, ROOM['sees']),
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
114 (self.uri, ROOM['seesRecently']),
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
115 ]
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
116
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
117 def makeDevices(graph, board, pi):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
118 out = []
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
119 for dt in sorted(_knownTypes, key=lambda cls: cls.__name__):
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
120 out.extend(dt.findInstances(graph, board, pi))
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
121 return out
cc79d092e136 start pinode
drewp <drewp@bigasterisk.com>
parents:
diff changeset
122