Mercurial > code > home > repos > homeauto
diff service/arduinoNode/devices.py @ 971:fbe72d44f15a
only recompile if the C code is new. redo Device class api. single temperature sensor is working
Ignore-this: e78106d25dbb2ac8c5e5d8a81d576358
darcs-hash:20150411084359-312f9-7c50d2f4f21dd9d5a0fa8913873a1e6d7d325118
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sat, 11 Apr 2015 01:43:59 -0700 |
parents | 70a5392b24d3 |
children | d228105749ac |
line wrap: on
line diff
--- a/service/arduinoNode/devices.py Sat Apr 11 01:43:14 2015 -0700 +++ b/service/arduinoNode/devices.py Sat Apr 11 01:43:59 2015 -0700 @@ -1,14 +1,40 @@ -from rdflib import Namespace, RDF, URIRef +from rdflib import Namespace, RDF, URIRef, Literal ROOM = Namespace('http://projects.bigasterisk.com/room/') -class BoardInput(object): - """ - one device that gives us input. this includes processing to make - statements, but this object doesn't store state - """ - def __init__(self, graph, uri): +def readLine(read): + buf = '' + for c in iter(lambda: read(1), '\n'): + buf += c + return buf + +class DeviceType(object): + deviceType = None + @classmethod + def findInstances(cls, graph, board): + """ + return any number of instances of this class for all the separately + controlled devices on the board. Two LEDS makes two instances, + but two sensors on the same onewire bus makes only one device + (which yields more statements). + """ + instances = [] + for row in graph.query("""SELECT ?dev ?pinNumber WHERE { + ?board :hasPin ?pin . + ?pin :pinNumber ?pinNumber; + :connectedTo ?dev . + ?dev a ?thisType . + } ORDER BY ?dev""", + initBindings=dict(board=board, + thisType=cls.deviceType), + initNs={'': ROOM}): + instances.append(cls(graph, row.dev, int(row.pinNumber))) + return instances + + # subclasses may add args to this + def __init__(self, graph, uri, pinNumber): self.graph, self.uri = graph, uri + self.pinNumber = pinNumber def readFromPoll(self, read): """ @@ -17,26 +43,42 @@ input (e.g. IR receiver). Returns rdf statements. """ - raise NotImplementedError + raise NotImplementedError('readFromPoll in %s' % self.__class__) + + def generateIncludes(self): + return [] + def generateArduinoLibs(self): + return [] + + def generateGlobalCode(self): + return '' + def generateSetupCode(self): return '' def generatePollCode(self): + """if this returns nothing, we don't try to poll this device""" return '' - def pinNumber(self, pred=ROOM['pin']): - pinUri = self.graph.value(self.uri, pred) - return int(self.graph.value(pinUri, ROOM['pinNumber'])) + def generateActionCode(self): + """ + if you get called to do your action, this code reads the args you + need and do the right action + """ + return '' + +_knownTypes = set() +def register(deviceType): + _knownTypes.add(deviceType) + return deviceType -_inputForType = {} -def registerInput(deviceType): - def newcls(cls): - _inputForType[deviceType] = cls - return cls - return newcls - -class PingInput(BoardInput): +@register +class PingInput(DeviceType): + @classmethod + def findInstances(cls, graph, board): + return [cls(graph, board, None)] + def generatePollCode(self): return "Serial.write('k');" def readFromPoll(self, read): @@ -44,8 +86,9 @@ raise ValueError('invalid ping response') return [(self.uri, ROOM['ping'], ROOM['ok'])] -@registerInput(deviceType=ROOM['MotionSensor']) -class MotionSensorInput(BoardInput): +@register +class MotionSensorInput(DeviceType): + deviceType = ROOM['MotionSensor'] def generateSetupCode(self): return 'pinMode(%(pin)d, INPUT); digitalWrite(%(pin)d, LOW);' % { 'pin': self.pinNumber(), @@ -64,7 +107,61 @@ return [(self.uri, ROOM['sees'], ROOM['motion'] if motion else ROOM['noMotion'])] -def makeBoardInput(graph, uri): - deviceType = graph.value(uri, RDF.type) - return _inputForType[deviceType](graph, uri) +@register +class OneWire(DeviceType): + deviceType = ROOM['OneWire'] + + def generateIncludes(self): + return ['OneWire.h', 'DallasTemperature.h'] + + def generateArduinoLibs(self): + return ['OneWire', 'DallasTemperature'] + + def generateGlobalCode(self): + # not yet isolated to support multiple OW buses + return ''' +OneWire oneWire(%(pinNumber)s); +DallasTemperature sensors(&oneWire); +DeviceAddress tempSensorAddress; +#define NUM_TEMPERATURE_RETRIES 5 + +void initSensors() { + sensors.begin(); + sensors.getAddress(tempSensorAddress, 0); + sensors.setResolution(tempSensorAddress, 12); +} + ''' % dict(pinNumber=self.pinNumber) + def generatePollCode(self): + return r''' +for (int i=0; i<NUM_TEMPERATURE_RETRIES; i++) { + sensors.requestTemperatures(); + float newTemp = sensors.getTempF(tempSensorAddress); + if (i < NUM_TEMPERATURE_RETRIES-1 && + (newTemp < -100 || newTemp > 180)) { + // too many errors that were fixed by restarting arduino. + // trying repeating this much init + initSensors(); + continue; + } + Serial.print(newTemp); + Serial.print('\n'); + Serial.print((char)i); + break; +} + ''' + + def readFromPoll(self, read): + newTemp = readLine(read) + retries = ord(read(1)) + return [ + (self.uri, ROOM['temperatureF'], Literal(newTemp)), + (self.uri, ROOM['temperatureRetries'], Literal(retries)), + ] + +def makeDevices(graph, board): + out = [] + for dt in sorted(_knownTypes, key=lambda cls: cls.__name__): + out.extend(dt.findInstances(graph, board)) + return out +