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()