Mercurial > code > home > repos > homeauto
changeset 183:634d6e477953
get piNode working, for motionsensor at least
Ignore-this: 53f16373acb0613e01fdf3e98d8425f2
author | drewp@bigasterisk.com |
---|---|
date | Sun, 31 May 2015 22:53:21 -0700 |
parents | 9fff29ebca71 |
children | e052416a2290 |
files | service/piNode/devices.py service/piNode/piNode.py |
diffstat | 2 files changed, 120 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/service/piNode/devices.py Sun May 31 00:56:55 2015 -0700 +++ b/service/piNode/devices.py Sun May 31 22:53:21 2015 -0700 @@ -1,8 +1,15 @@ from __future__ import division -import pigpio -import time + +import time, logging from rdflib import Namespace, RDF, URIRef, Literal +try: + import pigpio +except ImportError: + pigpio = None + + +log = logging.getLogger() ROOM = Namespace('http://projects.bigasterisk.com/room/') class DeviceType(object): @@ -15,16 +22,16 @@ but two sensors on the same onewire bus makes only one device (which yields more statements). """ - for row in graph.query("""SELECT ?dev ?pinNumber WHERE { + for row in graph.query("""SELECT ?dev ?gpioNumber WHERE { ?board :hasPin ?pin . - ?pin :pinNumber ?pinNumber; + ?pin :gpioNumber ?gpioNumber; :connectedTo ?dev . ?dev a ?thisType . } ORDER BY ?dev""", initBindings=dict(board=board, thisType=cls.deviceType), initNs={'': ROOM}): - yield cls(graph, row.dev, pi, int(row.pinNumber)) + yield cls(graph, row.dev, pi, int(row.gpioNumber)) def __init__(self, graph, uri, pi, pinNumber): self.graph, self.uri, self.pi = graph, uri, pi @@ -34,7 +41,7 @@ return { 'uri': self.uri, 'className': self.__class__.__name__, - 'pinNumber': self.pinNumber, + 'pinNumber': getattr(self, 'pinNumber', None), 'outputPatterns': self.outputPatterns(), 'watchPrefixes': self.watchPrefixes(), 'outputWidgets': self.outputWidgets(), @@ -114,6 +121,61 @@ (self.uri, ROOM['seesRecently']), ] + +@register +class RgbStrip(DeviceType): + deviceType = ROOM['RgbStrip'] + + @classmethod + def findInstances(cls, graph, board, pi): + for row in graph.query("""SELECT DISTINCT ?dev ?r ?g ?b WHERE { + ?board + :hasPin ?rpin; + :hasPin ?gpin; + :hasPin ?bpin . + ?dev a :RgbStrip; + :redChannel ?rpin; + :greenChannel ?gpin; + :blueChannel ?bpin . + ?rpin :gpioNumber ?r . + ?gpin :gpioNumber ?g . + ?bpin :gpioNumber ?b . + } ORDER BY ?dev""", + initBindings=dict(board=board), + initNs={'': ROOM}): + log.debug('found rgb %r', row) + yield cls(graph, row.dev, pi, row.r, row.g, row.b) + + def __init__(self, graph, uri, pi, r, g, b): + self.graph, self.uri, self.pi = graph, uri, pi + self.rgb = map(int, [r, g, b]) + + def setup(self): + for i in self.rgb: + self.pi.set_mode(i, pigpio.OUTPUT) + self.pi.set_PWM_frequency(i, 200) + self.pi.set_PWM_dutycycle(i, 0) + + def outputPatterns(self): + return [(self.uri, ROOM['color'], None)] + + def sendOutput(self, statements): + assert len(statements) == 1 + assert statements[0][:2] == (self.uri, ROOM['color']) + + rrggbb = statements[0][2].lstrip('#') + rgb = [int(x, 16) for x in [rrggbb[0:2], rrggbb[2:4], rrggbb[4:6]]] + + for (i, v) in zip(self.rgb, rgb): + self.pi.set_PWM_dutycycle(i, v) + + def outputWidgets(self): + return [{ + 'element': 'output-rgb', + 'subj': self.uri, + 'pred': ROOM['color'], + }] + def makeDevices(graph, board, pi): out = [] for dt in sorted(_knownTypes, key=lambda cls: cls.__name__):
--- a/service/piNode/piNode.py Sun May 31 00:56:55 2015 -0700 +++ b/service/piNode/piNode.py Sun May 31 22:53:21 2015 -0700 @@ -1,16 +1,22 @@ from __future__ import division -import glob, sys, logging, subprocess, socket, os, hashlib, time, tempfile -import shutil, json, socket +import sys, logging, socket, json import cyclone.web -from rdflib import Graph, Namespace, URIRef, Literal, RDF -from rdflib.parser import StringInputSource +from rdflib import Namespace, URIRef, Literal, Graph, RDF from twisted.internet import reactor, task from docopt import docopt logging.basicConfig(level=logging.DEBUG) sys.path.append("/my/site/magma") +sys.path.append("../../../../site/magma") + from stategraph import StateGraph sys.path.append('/home/pi/dim/PIGPIO') -import pigpio +try: + import pigpio +except ImportError: + class pigpio(object): + @staticmethod + def pi(): + return None import devices @@ -21,6 +27,14 @@ hostname = socket.gethostname() +class Config(object): + def __init__(self): + self.graph = Graph() + log.info('read config') + self.graph.parse('config.n3', format='n3') + self.graph.bind('', ROOM) # not working + self.graph.bind('rdf', RDF) + class GraphPage(cyclone.web.RequestHandler): def get(self): g = StateGraph(ctx=ROOM['pi/%s' % hostname]) @@ -41,6 +55,7 @@ self.graph, self.uri = graph, uri self.pi = pigpio.pi() self._devs = devices.makeDevices(graph, self.uri, self.pi) + log.debug('found %s devices', len(self._devs)) self._statementsFromInputs = {} # input device uri: latest statements def startPolling(self): @@ -70,8 +85,26 @@ for s in unused: log.warn(repr(s)) + def currentGraph(self): + g = Graph() + + g.add((HOST[socket.gethostname()], ROOM['connectedTo'], self.uri)) + + for si in self._statementsFromInputs.values(): + for s in si: + g.add(s) + return g + + def description(self): + """for web page""" + return { + 'uri': self.uri, + 'devices': [d.description() for d in self._devs], + 'graph': 'http://sticker:9059/graph', #todo + } + + class OutputPage(cyclone.web.RequestHandler): - def put(self): subj = URIRef(self.get_argument('s')) pred = URIRef(self.get_argument('p')) @@ -79,13 +112,19 @@ turtleLiteral = self.request.body try: obj = Literal(float(turtleLiteral)) - except TypeError: + except ValueError: obj = Literal(turtleLiteral) stmt = (subj, pred, obj) self.settings.board.outputStatements([stmt]) - +class Boards(cyclone.web.RequestHandler): + def get(self): + self.set_header('Content-type', 'application/json') + self.write(json.dumps({ + 'boards': [self.settings.board.description()] + }, indent=2)) + def main(): arg = docopt(""" Usage: piNode.py [options] @@ -108,14 +147,16 @@ thisBoard = URIRef('http://bigasterisk.com/homeauto/node2') board = Board(config.graph, thisBoard, onChange) + board.startPolling() reactor.listenTCP(9059, cyclone.web.Application([ (r"/()", cyclone.web.StaticFileHandler, { - "path": "static", "default_filename": "index.html"}), - (r'/static/(.*)', cyclone.web.StaticFileHandler, {"path": "static"}), + "path": "../arduinoNode/static", "default_filename": "index.html"}), + (r'/static/(.*)', cyclone.web.StaticFileHandler, {"path": "../arduinoNode/static"}), (r"/graph", GraphPage), (r'/output', OutputPage), - (r'/dot', Dot), + (r'/boards', Boards), + #(r'/dot', Dot), ], config=config, board=board)) reactor.run()