Mercurial > code > home > repos > homeauto
annotate service/piNode/devices.py @ 183:634d6e477953
get piNode working, for motionsensor at least
Ignore-this: 53f16373acb0613e01fdf3e98d8425f2
author | drewp@bigasterisk.com |
---|---|
date | Sun, 31 May 2015 22:53:21 -0700 |
parents | 9fff29ebca71 |
children | 40000fafad94 |
rev | line source |
---|---|
182 | 1 from __future__ import division |
183
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
2 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
3 import time, logging |
182 | 4 from rdflib import Namespace, RDF, URIRef, Literal |
5 | |
183
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
6 try: |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
7 import pigpio |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
8 except ImportError: |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
9 pigpio = None |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
10 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
11 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
12 log = logging.getLogger() |
182 | 13 ROOM = Namespace('http://projects.bigasterisk.com/room/') |
14 | |
15 class DeviceType(object): | |
16 deviceType = None | |
17 @classmethod | |
18 def findInstances(cls, graph, board, pi): | |
19 """ | |
20 return any number of instances of this class for all the separately | |
21 controlled devices on the board. Two LEDS makes two instances, | |
22 but two sensors on the same onewire bus makes only one device | |
23 (which yields more statements). | |
24 """ | |
183
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
25 for row in graph.query("""SELECT ?dev ?gpioNumber WHERE { |
182 | 26 ?board :hasPin ?pin . |
183
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
27 ?pin :gpioNumber ?gpioNumber; |
182 | 28 :connectedTo ?dev . |
29 ?dev a ?thisType . | |
30 } ORDER BY ?dev""", | |
31 initBindings=dict(board=board, | |
32 thisType=cls.deviceType), | |
33 initNs={'': ROOM}): | |
183
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
34 yield cls(graph, row.dev, pi, int(row.gpioNumber)) |
182 | 35 |
36 def __init__(self, graph, uri, pi, pinNumber): | |
37 self.graph, self.uri, self.pi = graph, uri, pi | |
38 self.pinNumber = pinNumber | |
39 | |
40 def description(self): | |
41 return { | |
42 'uri': self.uri, | |
43 'className': self.__class__.__name__, | |
183
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
44 'pinNumber': getattr(self, 'pinNumber', None), |
182 | 45 'outputPatterns': self.outputPatterns(), |
46 'watchPrefixes': self.watchPrefixes(), | |
47 'outputWidgets': self.outputWidgets(), | |
48 } | |
49 | |
50 def watchPrefixes(self): | |
51 """ | |
52 subj,pred pairs of the statements that might be returned from | |
53 readFromPoll, so the dashboard knows what it should | |
54 watch. This should be eliminated, as the dashboard should just | |
55 always watch the whole tree of statements starting self.uri | |
56 """ | |
57 return [] | |
58 | |
59 def poll(self): | |
60 return [] # statements | |
61 | |
62 def outputPatterns(self): | |
63 """ | |
64 Triple patterns, using None as a wildcard, that should be routed | |
65 to sendOutput | |
66 """ | |
67 return [] | |
68 | |
69 def outputWidgets(self): | |
70 """ | |
71 structs to make output widgets on the dashboard. ~1 of these per | |
72 handler you have in sendOutput | |
73 """ | |
74 return [] | |
75 | |
76 def sendOutput(self, statements): | |
77 """ | |
78 If we got statements that match this class's outputPatterns, this | |
79 will be called with the statements that matched. | |
80 | |
81 Todo: it would be fine to read back confirmations or | |
82 whatever. Just need a way to collect them into graph statements. | |
83 """ | |
84 raise NotImplementedError | |
85 | |
86 _knownTypes = set() | |
87 def register(deviceType): | |
88 _knownTypes.add(deviceType) | |
89 return deviceType | |
90 | |
91 @register | |
92 class MotionSensorInput(DeviceType): | |
93 deviceType = ROOM['MotionSensor'] | |
94 | |
95 def setup(self): | |
96 self.pi.set_mode(17, pigpio.INPUT) | |
97 self.pi.set_pull_up_down(17, pigpio.PUD_DOWN) | |
98 | |
99 def poll(self): | |
100 motion = self.pi.read(17) | |
101 | |
102 return [ | |
103 (self.uri, ROOM['sees'], | |
104 ROOM['motion'] if motion else ROOM['noMotion']), | |
105 self.recentMotionStatement(motion), | |
106 ] | |
107 | |
108 def recentMotionStatement(self, motion): | |
109 if not hasattr(self, 'lastMotionTime'): | |
110 self.lastMotionTime = 0 | |
111 now = time.time() | |
112 if motion: | |
113 self.lastMotionTime = now | |
114 recentMotion = now - self.lastMotionTime < 60 * 10 | |
115 return (self.uri, ROOM['seesRecently'], | |
116 ROOM['motion'] if recentMotion else ROOM['noMotion']) | |
117 | |
118 def watchPrefixes(self): | |
119 return [ | |
120 (self.uri, ROOM['sees']), | |
121 (self.uri, ROOM['seesRecently']), | |
122 ] | |
123 | |
183
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
124 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
125 @register |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
126 class RgbStrip(DeviceType): |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
127 deviceType = ROOM['RgbStrip'] |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
128 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
129 @classmethod |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
130 def findInstances(cls, graph, board, pi): |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
131 for row in graph.query("""SELECT DISTINCT ?dev ?r ?g ?b WHERE { |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
132 ?board |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
133 :hasPin ?rpin; |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
134 :hasPin ?gpin; |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
135 :hasPin ?bpin . |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
136 ?dev a :RgbStrip; |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
137 :redChannel ?rpin; |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
138 :greenChannel ?gpin; |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
139 :blueChannel ?bpin . |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
140 ?rpin :gpioNumber ?r . |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
141 ?gpin :gpioNumber ?g . |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
142 ?bpin :gpioNumber ?b . |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
143 } ORDER BY ?dev""", |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
144 initBindings=dict(board=board), |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
145 initNs={'': ROOM}): |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
146 log.debug('found rgb %r', row) |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
147 yield cls(graph, row.dev, pi, row.r, row.g, row.b) |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
148 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
149 def __init__(self, graph, uri, pi, r, g, b): |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
150 self.graph, self.uri, self.pi = graph, uri, pi |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
151 self.rgb = map(int, [r, g, b]) |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
152 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
153 def setup(self): |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
154 for i in self.rgb: |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
155 self.pi.set_mode(i, pigpio.OUTPUT) |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
156 self.pi.set_PWM_frequency(i, 200) |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
157 self.pi.set_PWM_dutycycle(i, 0) |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
158 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
159 def outputPatterns(self): |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
160 return [(self.uri, ROOM['color'], None)] |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
161 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
162 def sendOutput(self, statements): |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
163 assert len(statements) == 1 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
164 assert statements[0][:2] == (self.uri, ROOM['color']) |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
165 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
166 rrggbb = statements[0][2].lstrip('#') |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
167 rgb = [int(x, 16) for x in [rrggbb[0:2], rrggbb[2:4], rrggbb[4:6]]] |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
168 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
169 for (i, v) in zip(self.rgb, rgb): |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
170 self.pi.set_PWM_dutycycle(i, v) |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
171 |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
172 def outputWidgets(self): |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
173 return [{ |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
174 'element': 'output-rgb', |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
175 'subj': self.uri, |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
176 'pred': ROOM['color'], |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
177 }] |
634d6e477953
get piNode working, for motionsensor at least
drewp@bigasterisk.com
parents:
182
diff
changeset
|
178 |
182 | 179 def makeDevices(graph, board, pi): |
180 out = [] | |
181 for dt in sorted(_knownTypes, key=lambda cls: cls.__name__): | |
182 out.extend(dt.findInstances(graph, board, pi)) | |
183 return out | |
184 |