Mercurial > code > home > repos > homeauto
annotate service/piNode/devices.py @ 1012:d125a8c90f6c
fix temp init
Ignore-this: df4368c5bcb03af26b055c9a90ba7e61
darcs-hash:20151107180605-312f9-1bbea091b13fad80d17f4cb9c848fa1b82b78a3f
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sat, 07 Nov 2015 10:06:05 -0800 |
parents | f2d05b425dfa |
children | e203a7d075e6 |
rev | line source |
---|---|
987 | 1 from __future__ import division |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
2 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
3 import time, logging |
987 | 4 from rdflib import Namespace, RDF, URIRef, Literal |
5 | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
6 try: |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
7 import pigpio |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
8 except ImportError: |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
9 pigpio = None |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
10 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
11 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
12 log = logging.getLogger() |
987 | 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 """ | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
25 for row in graph.query("""SELECT ?dev ?gpioNumber WHERE { |
987 | 26 ?board :hasPin ?pin . |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
27 ?pin :gpioNumber ?gpioNumber; |
987 | 28 :connectedTo ?dev . |
29 ?dev a ?thisType . | |
30 } ORDER BY ?dev""", | |
31 initBindings=dict(board=board, | |
32 thisType=cls.deviceType), | |
33 initNs={'': ROOM}): | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
34 yield cls(graph, row.dev, pi, int(row.gpioNumber)) |
987 | 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__, | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
44 'pinNumber': getattr(self, 'pinNumber', None), |
987 | 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 | |
988
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
124 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
125 @register |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
126 class RgbStrip(DeviceType): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
127 deviceType = ROOM['RgbStrip'] |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
128 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
129 @classmethod |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
130 def findInstances(cls, graph, board, pi): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
131 for row in graph.query("""SELECT DISTINCT ?dev ?r ?g ?b WHERE { |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
132 ?board |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
133 :hasPin ?rpin; |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
134 :hasPin ?gpin; |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
135 :hasPin ?bpin . |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
136 ?dev a :RgbStrip; |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
137 :redChannel ?rpin; |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
138 :greenChannel ?gpin; |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
139 :blueChannel ?bpin . |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
140 ?rpin :gpioNumber ?r . |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
141 ?gpin :gpioNumber ?g . |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
142 ?bpin :gpioNumber ?b . |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
143 } ORDER BY ?dev""", |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
144 initBindings=dict(board=board), |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
145 initNs={'': ROOM}): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
146 log.debug('found rgb %r', row) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
147 yield cls(graph, row.dev, pi, row.r, row.g, row.b) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
148 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
149 def __init__(self, graph, uri, pi, r, g, b): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
150 self.graph, self.uri, self.pi = graph, uri, pi |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
151 self.rgb = map(int, [r, g, b]) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
152 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
153 def setup(self): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
154 for i in self.rgb: |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
155 self.pi.set_mode(i, pigpio.OUTPUT) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
156 self.pi.set_PWM_frequency(i, 200) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
157 self.pi.set_PWM_dutycycle(i, 0) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
158 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
159 def outputPatterns(self): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
160 return [(self.uri, ROOM['color'], None)] |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
161 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
162 def sendOutput(self, statements): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
163 assert len(statements) == 1 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
164 assert statements[0][:2] == (self.uri, ROOM['color']) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
165 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
166 rrggbb = statements[0][2].lstrip('#') |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
167 rgb = [int(x, 16) for x in [rrggbb[0:2], rrggbb[2:4], rrggbb[4:6]]] |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
168 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
169 for (i, v) in zip(self.rgb, rgb): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
170 self.pi.set_PWM_dutycycle(i, v) |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
171 |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
172 def outputWidgets(self): |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
173 return [{ |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
174 'element': 'output-rgb', |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
175 'subj': self.uri, |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
176 'pred': ROOM['color'], |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
177 }] |
63c172316239
get piNode working, for motionsensor at least
drewp <drewp@bigasterisk.com>
parents:
987
diff
changeset
|
178 |
1010 | 179 @register |
180 class OnboardTemperature(DeviceType): | |
181 deviceType = ROOM['OnboardTemperature'] | |
182 @classmethod | |
183 def findInstances(cls, graph, board, pi): | |
1012 | 184 for row in graph.query('''SELECT DISTINCT ?uri WHERE { |
1010 | 185 ?board :onboardDevice ?uri . |
186 ?uri a :OnboardTemperature . | |
187 }'''): | |
188 yield cls(graph, row.uri, pi, pinNumber=None) | |
189 | |
190 def readFromPoll(self): | |
191 milliC = open('/sys/class/thermal/thermal_zone0/temp').read().strip() | |
192 c = float(milliC) / 1000. | |
193 f = c * 1.8 + 32 | |
194 return [ | |
195 (self.uri, ROOM['temperatureF'], Literal(f, datatype=XSD['decimal'])), | |
196 ] | |
197 | |
198 def watchPrefixes(self): | |
199 # these uris will become dynamic! see note on watchPrefixes | |
200 # about eliminating it. | |
201 return [(self.uri, ROOM['temperatureF']), | |
202 ] | |
203 | |
987 | 204 def makeDevices(graph, board, pi): |
205 out = [] | |
206 for dt in sorted(_knownTypes, key=lambda cls: cls.__name__): | |
207 out.extend(dt.findInstances(graph, board, pi)) | |
208 return out | |
209 |