Mercurial > code > home > repos > homeauto
comparison service/arduinoNode/devices.py @ 170:376599552a4c
polymer board debug page with working output widgets
Ignore-this: 3157d0c47a91afe47b30a5f182629d93
author | drewp@bigasterisk.com |
---|---|
date | Mon, 13 Apr 2015 23:30:12 -0700 |
parents | d228105749ac |
children | 715c1c42185e |
comparison
equal
deleted
inserted
replaced
169:d228105749ac | 170:376599552a4c |
---|---|
34 | 34 |
35 # subclasses may add args to this | 35 # subclasses may add args to this |
36 def __init__(self, graph, uri, pinNumber): | 36 def __init__(self, graph, uri, pinNumber): |
37 self.graph, self.uri = graph, uri | 37 self.graph, self.uri = graph, uri |
38 self.pinNumber = pinNumber | 38 self.pinNumber = pinNumber |
39 | |
40 def description(self): | |
41 return { | |
42 'uri': self.uri, | |
43 'className': self.__class__.__name__, | |
44 'pinNumber': self.pinNumber, | |
45 'outputPatterns': self.outputPatterns(), | |
46 'watchPrefixes': self.watchPrefixes(), | |
47 'outputWidgets': self.outputWidgets(), | |
48 } | |
39 | 49 |
40 def readFromPoll(self, read): | 50 def readFromPoll(self, read): |
41 """ | 51 """ |
42 read an update message returned as part of a poll bundle. This may | 52 read an update message returned as part of a poll bundle. This may |
43 consume a varying number of bytes depending on the type of | 53 consume a varying number of bytes depending on the type of |
44 input (e.g. IR receiver). | 54 input (e.g. IR receiver). |
45 Returns rdf statements. | 55 Returns rdf statements. |
46 """ | 56 """ |
47 raise NotImplementedError('readFromPoll in %s' % self.__class__) | 57 raise NotImplementedError('readFromPoll in %s' % self.__class__) |
48 | 58 |
59 def watchPrefixes(self): | |
60 """ | |
61 subj,pred pairs of the statements that might be returned from | |
62 readFromPoll, so the dashboard knows what it should | |
63 watch. This should be eliminated, as the dashboard should just | |
64 always watch the whole tree of statements starting self.uri | |
65 """ | |
66 return [] | |
67 | |
49 def generateIncludes(self): | 68 def generateIncludes(self): |
69 """filenames of .h files to #include""" | |
50 return [] | 70 return [] |
51 | 71 |
52 def generateArduinoLibs(self): | 72 def generateArduinoLibs(self): |
73 """names of libraries for the ARDUINO_LIBS line in the makefile""" | |
53 return [] | 74 return [] |
54 | 75 |
55 def generateGlobalCode(self): | 76 def generateGlobalCode(self): |
77 """C code to emit in the global section""" | |
56 return '' | 78 return '' |
57 | 79 |
58 def generateSetupCode(self): | 80 def generateSetupCode(self): |
81 """C code to emit in setup()""" | |
59 return '' | 82 return '' |
60 | 83 |
61 def generatePollCode(self): | 84 def generatePollCode(self): |
62 """if this returns nothing, we don't try to poll this device""" | 85 """ |
86 C code to run a poll update. This should Serial.write its output | |
87 for readFromPoll to consume. If this returns nothing, we don't | |
88 try to poll this device. | |
89 """ | |
63 return '' | 90 return '' |
64 | 91 |
65 def generateActionCode(self): | 92 def generateActionCode(self): |
66 """ | 93 """ |
67 If the host side runs sendOutput, this C code will be run on the | 94 If the host side runs sendOutput, this C code will be run on the |
76 Triple patterns, using None as a wildcard, that should be routed | 103 Triple patterns, using None as a wildcard, that should be routed |
77 to sendOutput | 104 to sendOutput |
78 """ | 105 """ |
79 return [] | 106 return [] |
80 | 107 |
108 def outputWidgets(self): | |
109 """ | |
110 structs to make output widgets on the dashboard. ~1 of these per | |
111 handler you have in sendOutput | |
112 """ | |
113 return [] | |
114 | |
81 def sendOutput(self, statements, write, read): | 115 def sendOutput(self, statements, write, read): |
82 """ | 116 """ |
83 If we got statements that match this class's outputPatterns, this | 117 If we got statements that match this class's outputPatterns, this |
84 will be called with the statements that matched, and a serial | 118 will be called with the statements that matched, and a serial |
85 write method. What you write here will be available as | 119 write method. What you write here will be available as |
101 def findInstances(cls, graph, board): | 135 def findInstances(cls, graph, board): |
102 return [cls(graph, board, None)] | 136 return [cls(graph, board, None)] |
103 | 137 |
104 def generatePollCode(self): | 138 def generatePollCode(self): |
105 return "Serial.write('k');" | 139 return "Serial.write('k');" |
140 | |
106 def readFromPoll(self, read): | 141 def readFromPoll(self, read): |
107 if read(1) != 'k': | 142 if read(1) != 'k': |
108 raise ValueError('invalid ping response') | 143 raise ValueError('invalid ping response') |
109 return [(self.uri, ROOM['ping'], ROOM['ok'])] | 144 return [(self.uri, ROOM['ping'], ROOM['ok'])] |
145 | |
146 def watchPrefixes(self): | |
147 return [(self.uri, ROOM['ping'])] | |
110 | 148 |
111 @register | 149 @register |
112 class MotionSensorInput(DeviceType): | 150 class MotionSensorInput(DeviceType): |
113 deviceType = ROOM['MotionSensor'] | 151 deviceType = ROOM['MotionSensor'] |
114 def generateSetupCode(self): | 152 def generateSetupCode(self): |
127 raise ValueError('unexpected response %r' % b) | 165 raise ValueError('unexpected response %r' % b) |
128 motion = b == 'y' | 166 motion = b == 'y' |
129 return [(self.uri, ROOM['sees'], | 167 return [(self.uri, ROOM['sees'], |
130 ROOM['motion'] if motion else ROOM['noMotion'])] | 168 ROOM['motion'] if motion else ROOM['noMotion'])] |
131 | 169 |
170 def watchPrefixes(self): | |
171 return [(self.uri, ROOM['sees'])] | |
172 | |
132 @register | 173 @register |
133 class OneWire(DeviceType): | 174 class OneWire(DeviceType): |
175 """ | |
176 A OW bus with temperature sensors (and maybe other devices, which | |
177 are also to be handled under this object) | |
178 """ | |
134 deviceType = ROOM['OneWire'] | 179 deviceType = ROOM['OneWire'] |
135 | 180 |
136 def generateIncludes(self): | 181 def generateIncludes(self): |
137 return ['OneWire.h', 'DallasTemperature.h'] | 182 return ['OneWire.h', 'DallasTemperature.h'] |
138 | 183 |
174 ''' | 219 ''' |
175 | 220 |
176 def readFromPoll(self, read): | 221 def readFromPoll(self, read): |
177 newTemp = readLine(read) | 222 newTemp = readLine(read) |
178 retries = ord(read(1)) | 223 retries = ord(read(1)) |
224 # uri will change; there could (likely) be multiple connected sensors | |
179 return [ | 225 return [ |
180 (self.uri, ROOM['temperatureF'], | 226 (self.uri, ROOM['temperatureF'], |
181 Literal(newTemp, datatype=XSD['decimal'])), | 227 Literal(newTemp, datatype=XSD['decimal'])), |
182 (self.uri, ROOM['temperatureRetries'], Literal(retries)), | 228 (self.uri, ROOM['temperatureRetries'], Literal(retries)), |
183 ] | 229 ] |
230 | |
231 def watchPrefixes(self): | |
232 # these uris will become dynamic! see note on watchPrefixes | |
233 # about eliminating it. | |
234 return [(self.uri, ROOM['temperatureF']), | |
235 (self.uri, ROOM['temperatureRetries']), | |
236 ] | |
184 | 237 |
185 def byteFromFloat(f): | 238 def byteFromFloat(f): |
186 return chr(int(min(255, max(0, f * 255)))) | 239 return chr(int(min(255, max(0, f * 255)))) |
187 | 240 |
188 @register | 241 @register |
207 def generateActionCode(self): | 260 def generateActionCode(self): |
208 return r''' | 261 return r''' |
209 while(Serial.available() < 1) NULL; | 262 while(Serial.available() < 1) NULL; |
210 analogWrite(%(pin)d, Serial.read()); | 263 analogWrite(%(pin)d, Serial.read()); |
211 ''' % dict(pin=self.pinNumber) | 264 ''' % dict(pin=self.pinNumber) |
265 | |
266 def outputWidgets(self): | |
267 return [{ | |
268 'element': 'output-slider', | |
269 'min': 0, | |
270 'max': 1, | |
271 'step': 1 / 255, | |
272 'subj': self.uri, | |
273 'pred': ROOM['brightness'], | |
274 }] | |
275 | |
276 @register | |
277 class DigitalOutput(DeviceType): | |
278 deviceType = ROOM['DigitalOutput'] | |
279 def generateSetupCode(self): | |
280 return 'pinMode(%(pin)d, OUTPUT); digitalWrite(%(pin)d, LOW);' % { | |
281 'pin': self.pinNumber, | |
282 } | |
283 | |
284 def outputPatterns(self): | |
285 return [(self.uri, ROOM['level'], None)] | |
286 | |
287 def sendOutput(self, statements, write, read): | |
288 assert len(statements) == 1 | |
289 assert statements[0][:2] == (self.uri, ROOM['level']) | |
290 value = {"high": 1, "low": 0}[str(statements[0][2])] | |
291 write(chr(value)) | |
292 | |
293 def generateActionCode(self): | |
294 return r''' | |
295 while(Serial.available() < 1) NULL; | |
296 digitalWrite(%(pin)d, Serial.read()); | |
297 ''' % dict(pin=self.pinNumber) | |
298 | |
299 def outputWidgets(self): | |
300 return [{ | |
301 'element': 'output-switch', | |
302 'subj': self.uri, | |
303 'pred': ROOM['level'], | |
304 }] | |
212 | 305 |
213 @register | 306 @register |
214 class ST7576Lcd(DeviceType): | 307 class ST7576Lcd(DeviceType): |
215 deviceType = ROOM['ST7565Lcd'] | 308 deviceType = ROOM['ST7565Lcd'] |
216 @classmethod | 309 @classmethod |
271 assert statements[0][:2] == (self.uri, ROOM['text']) | 364 assert statements[0][:2] == (self.uri, ROOM['text']) |
272 value = str(statements[0][2]) | 365 value = str(statements[0][2]) |
273 assert len(value) < 254, repr(value) | 366 assert len(value) < 254, repr(value) |
274 write(chr(len(value)) + value) | 367 write(chr(len(value)) + value) |
275 | 368 |
369 def outputWidgets(self): | |
370 return [{ | |
371 'element': 'output-fixed-text', | |
372 'cols': 21, | |
373 'rows': 8, | |
374 'subj': self.uri, | |
375 'pred': ROOM['text'], | |
376 }] | |
377 | |
276 def generateActionCode(self): | 378 def generateActionCode(self): |
277 return ''' | 379 return ''' |
278 while(Serial.available() < 1) NULL; | 380 while(Serial.available() < 1) NULL; |
279 byte bufSize = Serial.read(); | 381 byte bufSize = Serial.read(); |
280 for (byte i = 0; i < bufSize; i++) { | 382 for (byte i = 0; i < bufSize; ++i) { |
281 while(Serial.available() < 1) NULL; | 383 while(Serial.available() < 1) NULL; |
282 newtxt[i] = Serial.read(); | 384 newtxt[i] = Serial.read(); |
385 } | |
386 for (byte i = bufSize; i < sizeof(newtxt); ++i) { | |
387 newtxt[i] = 0; | |
283 } | 388 } |
284 glcd.clear(); | 389 glcd.clear(); |
285 glcd.drawstring(0,0, newtxt); | 390 glcd.drawstring(0,0, newtxt); |
286 glcd.display(); | 391 glcd.display(); |
287 ''' | 392 ''' |