Mercurial > code > home > repos > homeauto
diff service/arduinoNode/devices.py @ 975:f3023410d875
polymer board debug page with working output widgets
Ignore-this: 3157d0c47a91afe47b30a5f182629d93
darcs-hash:20150414063012-312f9-69ac15a9c7bab2b3b5ca00142fe4435ded7d6d0f
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Mon, 13 Apr 2015 23:30:12 -0700 |
parents | f707210c13bd |
children | 715c1c42185e |
line wrap: on
line diff
--- a/service/arduinoNode/devices.py Sun Apr 12 03:44:14 2015 -0700 +++ b/service/arduinoNode/devices.py Mon Apr 13 23:30:12 2015 -0700 @@ -36,6 +36,16 @@ def __init__(self, graph, uri, pinNumber): self.graph, self.uri = graph, uri self.pinNumber = pinNumber + + def description(self): + return { + 'uri': self.uri, + 'className': self.__class__.__name__, + 'pinNumber': self.pinNumber, + 'outputPatterns': self.outputPatterns(), + 'watchPrefixes': self.watchPrefixes(), + 'outputWidgets': self.outputWidgets(), + } def readFromPoll(self, read): """ @@ -46,20 +56,37 @@ """ raise NotImplementedError('readFromPoll in %s' % self.__class__) + def watchPrefixes(self): + """ + subj,pred pairs of the statements that might be returned from + readFromPoll, so the dashboard knows what it should + watch. This should be eliminated, as the dashboard should just + always watch the whole tree of statements starting self.uri + """ + return [] + def generateIncludes(self): + """filenames of .h files to #include""" return [] def generateArduinoLibs(self): + """names of libraries for the ARDUINO_LIBS line in the makefile""" return [] def generateGlobalCode(self): + """C code to emit in the global section""" return '' def generateSetupCode(self): + """C code to emit in setup()""" return '' def generatePollCode(self): - """if this returns nothing, we don't try to poll this device""" + """ + C code to run a poll update. This should Serial.write its output + for readFromPoll to consume. If this returns nothing, we don't + try to poll this device. + """ return '' def generateActionCode(self): @@ -78,6 +105,13 @@ """ return [] + def outputWidgets(self): + """ + structs to make output widgets on the dashboard. ~1 of these per + handler you have in sendOutput + """ + return [] + def sendOutput(self, statements, write, read): """ If we got statements that match this class's outputPatterns, this @@ -103,11 +137,15 @@ def generatePollCode(self): return "Serial.write('k');" + def readFromPoll(self, read): if read(1) != 'k': raise ValueError('invalid ping response') return [(self.uri, ROOM['ping'], ROOM['ok'])] + def watchPrefixes(self): + return [(self.uri, ROOM['ping'])] + @register class MotionSensorInput(DeviceType): deviceType = ROOM['MotionSensor'] @@ -129,8 +167,15 @@ return [(self.uri, ROOM['sees'], ROOM['motion'] if motion else ROOM['noMotion'])] + def watchPrefixes(self): + return [(self.uri, ROOM['sees'])] + @register class OneWire(DeviceType): + """ + A OW bus with temperature sensors (and maybe other devices, which + are also to be handled under this object) + """ deviceType = ROOM['OneWire'] def generateIncludes(self): @@ -176,12 +221,20 @@ def readFromPoll(self, read): newTemp = readLine(read) retries = ord(read(1)) + # uri will change; there could (likely) be multiple connected sensors return [ (self.uri, ROOM['temperatureF'], Literal(newTemp, datatype=XSD['decimal'])), (self.uri, ROOM['temperatureRetries'], Literal(retries)), ] + def watchPrefixes(self): + # these uris will become dynamic! see note on watchPrefixes + # about eliminating it. + return [(self.uri, ROOM['temperatureF']), + (self.uri, ROOM['temperatureRetries']), + ] + def byteFromFloat(f): return chr(int(min(255, max(0, f * 255)))) @@ -209,6 +262,46 @@ while(Serial.available() < 1) NULL; analogWrite(%(pin)d, Serial.read()); ''' % dict(pin=self.pinNumber) + + def outputWidgets(self): + return [{ + 'element': 'output-slider', + 'min': 0, + 'max': 1, + 'step': 1 / 255, + 'subj': self.uri, + 'pred': ROOM['brightness'], + }] + +@register +class DigitalOutput(DeviceType): + deviceType = ROOM['DigitalOutput'] + def generateSetupCode(self): + return 'pinMode(%(pin)d, OUTPUT); digitalWrite(%(pin)d, LOW);' % { + 'pin': self.pinNumber, + } + + def outputPatterns(self): + return [(self.uri, ROOM['level'], None)] + + def sendOutput(self, statements, write, read): + assert len(statements) == 1 + assert statements[0][:2] == (self.uri, ROOM['level']) + value = {"high": 1, "low": 0}[str(statements[0][2])] + write(chr(value)) + + def generateActionCode(self): + return r''' + while(Serial.available() < 1) NULL; + digitalWrite(%(pin)d, Serial.read()); + ''' % dict(pin=self.pinNumber) + + def outputWidgets(self): + return [{ + 'element': 'output-switch', + 'subj': self.uri, + 'pred': ROOM['level'], + }] @register class ST7576Lcd(DeviceType): @@ -273,14 +366,26 @@ assert len(value) < 254, repr(value) write(chr(len(value)) + value) + def outputWidgets(self): + return [{ + 'element': 'output-fixed-text', + 'cols': 21, + 'rows': 8, + 'subj': self.uri, + 'pred': ROOM['text'], + }] + def generateActionCode(self): return ''' while(Serial.available() < 1) NULL; byte bufSize = Serial.read(); - for (byte i = 0; i < bufSize; i++) { + for (byte i = 0; i < bufSize; ++i) { while(Serial.available() < 1) NULL; newtxt[i] = Serial.read(); } + for (byte i = bufSize; i < sizeof(newtxt); ++i) { + newtxt[i] = 0; + } glcd.clear(); glcd.drawstring(0,0, newtxt); glcd.display();