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