Mercurial > code > home > repos > homeauto
comparison service/piNode/devices.py @ 221:666e0e756ce6
piNode support for temp sensors. proper hostname lookup
Ignore-this: a68c3319bffb16c55cbb5f329118f0a4
author | drewp@bigasterisk.com |
---|---|
date | Mon, 18 Jan 2016 22:43:22 -0800 |
parents | fb23df31b642 |
children | 4e91f3ec460b |
comparison
equal
deleted
inserted
replaced
220:fb23df31b642 | 221:666e0e756ce6 |
---|---|
1 from __future__ import division | 1 from __future__ import division |
2 | 2 |
3 import time, logging | 3 import time, logging, os |
4 from rdflib import Namespace, RDF, URIRef, Literal | 4 from rdflib import Namespace, RDF, URIRef, Literal |
5 | 5 |
6 try: | 6 try: |
7 import pigpio | 7 import pigpio |
8 except ImportError: | 8 except ImportError: |
9 pigpio = None | 9 pigpio = None |
10 | 10 import w1thermsensor |
11 | |
12 import sys | |
11 | 13 |
12 log = logging.getLogger() | 14 log = logging.getLogger() |
13 ROOM = Namespace('http://projects.bigasterisk.com/room/') | 15 ROOM = Namespace('http://projects.bigasterisk.com/room/') |
14 XSD = Namespace('http://www.w3.org/2001/XMLSchema#') | 16 XSD = Namespace('http://www.w3.org/2001/XMLSchema#') |
17 RDFS = Namespace('http://www.w3.org/2000/01/rdf-schema#') | |
15 | 18 |
16 class DeviceType(object): | 19 class DeviceType(object): |
17 deviceType = None | 20 deviceType = NotImplementedError |
18 @classmethod | 21 @classmethod |
19 def findInstances(cls, graph, board, pi): | 22 def findInstances(cls, graph, board, pi): |
20 """ | 23 """ |
21 return any number of instances of this class for all the separately | 24 return any number of instances of this class for all the separately |
22 controlled devices on the board. Two LEDS makes two instances, | 25 controlled devices on the board. Two LEDS makes two instances, |
23 but two sensors on the same onewire bus makes only one device | 26 but two sensors on the same onewire bus makes only one device |
24 (which yields more statements). | 27 (which yields more statements). |
25 """ | 28 """ |
29 log.debug("graph has any connected devices of type %s?", cls.deviceType) | |
26 for row in graph.query("""SELECT ?dev ?gpioNumber WHERE { | 30 for row in graph.query("""SELECT ?dev ?gpioNumber WHERE { |
27 ?board :hasPin ?pin . | 31 ?board :hasPin ?pin . |
28 ?pin :gpioNumber ?gpioNumber; | 32 ?pin :gpioNumber ?gpioNumber; |
29 :connectedTo ?dev . | 33 :connectedTo ?dev . |
30 ?dev a ?thisType . | 34 ?dev a ?thisType . |
31 } ORDER BY ?dev""", | 35 } ORDER BY ?dev""", |
32 initBindings=dict(board=board, | 36 initBindings=dict(board=board, |
33 thisType=cls.deviceType), | 37 thisType=cls.deviceType)): |
34 initNs={'': ROOM}): | |
35 yield cls(graph, row.dev, pi, int(row.gpioNumber)) | 38 yield cls(graph, row.dev, pi, int(row.gpioNumber)) |
36 | 39 |
37 def __init__(self, graph, uri, pi, pinNumber): | 40 def __init__(self, graph, uri, pi, pinNumber): |
38 self.graph, self.uri, self.pi = graph, uri, pi | 41 self.graph, self.uri, self.pi = graph, uri, pi |
39 self.pinNumber = pinNumber | 42 self.pinNumber = pinNumber |
89 _knownTypes.add(deviceType) | 92 _knownTypes.add(deviceType) |
90 return deviceType | 93 return deviceType |
91 | 94 |
92 @register | 95 @register |
93 class MotionSensorInput(DeviceType): | 96 class MotionSensorInput(DeviceType): |
97 # compare motion sensor lib at http://pythonhosted.org/gpiozero/inputs/ | |
98 # which is a bit fancier | |
94 deviceType = ROOM['MotionSensor'] | 99 deviceType = ROOM['MotionSensor'] |
95 | 100 |
96 def setup(self): | 101 def setup(self): |
97 self.pi.set_mode(17, pigpio.INPUT) | 102 self.pi.set_mode(17, pigpio.INPUT) |
98 self.pi.set_pull_up_down(17, pigpio.PUD_DOWN) | 103 self.pi.set_pull_up_down(17, pigpio.PUD_DOWN) |
124 | 129 |
125 | 130 |
126 @register | 131 @register |
127 class RgbStrip(DeviceType): | 132 class RgbStrip(DeviceType): |
128 """3 PWMs for r/g/b on a strip""" | 133 """3 PWMs for r/g/b on a strip""" |
134 # pigpio daemon is working fine, but | |
135 # https://github.com/RPi-Distro/python-gpiozero/blob/59ba7154c5918745ac894ea03503667d6473c760/gpiozero/output_devices.py#L213 | |
136 # can also apparently do PWM | |
129 deviceType = ROOM['RgbStrip'] | 137 deviceType = ROOM['RgbStrip'] |
130 | 138 |
131 @classmethod | 139 @classmethod |
132 def findInstances(cls, graph, board, pi): | 140 def findInstances(cls, graph, board, pi): |
133 for row in graph.query("""SELECT DISTINCT ?dev ?r ?g ?b WHERE { | 141 for row in graph.query("""SELECT DISTINCT ?dev ?r ?g ?b WHERE { |
181 'pred': ROOM['color'], | 189 'pred': ROOM['color'], |
182 }] | 190 }] |
183 | 191 |
184 | 192 |
185 @register | 193 @register |
194 class TempHumidSensor(DeviceType): | |
195 deviceType = ROOM['TempHumidSensor'] | |
196 | |
197 def __init__(self, *a, **kw): | |
198 DeviceType.__init__(self, *a, **kw) | |
199 sys.path.append('/opt/pigpio/EXAMPLES/Python/DHT22_AM2302_SENSOR') | |
200 import DHT22 | |
201 self.sensor = DHT22.sensor(self.pi, self.pinNumber) | |
202 | |
203 def poll(self): | |
204 self.sensor.trigger() | |
205 humid, tempC = self.sensor.humidity(), self.sensor.temperature() | |
206 | |
207 stmts = set() | |
208 if humid is not None: | |
209 stmts.add((self.uri, ROOM['humidity'], Literal(humid))) | |
210 else: | |
211 stmts.add((self.uri, RDFS['comment'], | |
212 Literal('DHT read returned None'))) | |
213 if tempC is not None: | |
214 stmts.add((self.uri, ROOM['temperatureF'], | |
215 Literal(tempC * 9 / 5 + 32))) | |
216 else: | |
217 stmts.add((self.uri, RDFS['comment'], | |
218 Literal('DHT read returned None'))) | |
219 return stmts | |
220 | |
221 def watchPrefixes(self): | |
222 return [ | |
223 (self.uri, ROOM['temperatureF']), | |
224 (self.uri, ROOM['humidity']), | |
225 ] | |
226 | |
227 @register | |
228 class OneWire(DeviceType): | |
229 """ | |
230 Also see /my/proj/ansible/roles/raspi_io_node/tasks/main.yml for | |
231 some system config that contains the pin number that you want to | |
232 use for onewire. The pin number in this config is currently ignored. | |
233 """ | |
234 deviceType = ROOM['OneWire'] | |
235 # deliberately written like arduinoNode's one for an easier merge. | |
236 def __init__(self, *a, **kw): | |
237 DeviceType.__init__(self, *a, **kw) | |
238 log.info("scan for w1 devices") | |
239 self._sensors = w1thermsensor.W1ThermSensor.get_available_sensors() | |
240 for s in self._sensors: | |
241 # Something looks different about these ids | |
242 # ('000003a5a94c') vs the ones I get from arduino | |
243 # ('2813bea50300003d'). Not sure if I'm parsing them | |
244 # differently or what. | |
245 s.uri = URIRef(os.path.join(self.uri, 'dev-%s' % s.id)) | |
246 log.info(' found temperature sensor %s' % s.uri) | |
247 | |
248 def poll(self): | |
249 try: | |
250 stmts = [] | |
251 for sensor in self._sensors: | |
252 stmts.append((self.uri, ROOM['connectedTo'], sensor.uri)) | |
253 try: | |
254 tempF = sensor.get_temperature(sensor.DEGREES_F) | |
255 stmts.append((sensor.uri, ROOM['temperatureF'], | |
256 Literal(tempF))) | |
257 except w1thermsensor.core.SensorNotReadyError as e: | |
258 log.warning(e) | |
259 | |
260 return stmts | |
261 except Exception as e: | |
262 log.error(e) | |
263 os.abort() | |
264 | |
265 def watchPrefixes(self): | |
266 return [(s.uri, ROOM['temperatureF']) for s in self._sensors] | |
267 | |
268 | |
269 @register | |
186 class LedOutput(DeviceType): | 270 class LedOutput(DeviceType): |
187 deviceType = ROOM['LedOutput'] | 271 deviceType = ROOM['LedOutput'] |
188 | 272 |
189 def setup(self): | 273 def setup(self): |
190 self.pi.set_mode(self.pinNumber, pigpio.OUTPUT) | 274 self.pi.set_mode(self.pinNumber, pigpio.OUTPUT) |
217 @classmethod | 301 @classmethod |
218 def findInstances(cls, graph, board, pi): | 302 def findInstances(cls, graph, board, pi): |
219 for row in graph.query('''SELECT DISTINCT ?uri WHERE { | 303 for row in graph.query('''SELECT DISTINCT ?uri WHERE { |
220 ?board :onboardDevice ?uri . | 304 ?board :onboardDevice ?uri . |
221 ?uri a :OnboardTemperature . | 305 ?uri a :OnboardTemperature . |
222 }'''): | 306 }''', initBindings=dict(board=board)): |
223 yield cls(graph, row.uri, pi, pinNumber=None) | 307 yield cls(graph, row.uri, pi, pinNumber=None) |
224 | 308 |
225 def poll(self): | 309 def poll(self): |
226 milliC = open('/sys/class/thermal/thermal_zone0/temp').read().strip() | 310 milliC = open('/sys/class/thermal/thermal_zone0/temp').read().strip() |
227 c = float(milliC) / 1000. | 311 c = float(milliC) / 1000. |