changeset 1123:2ff06e28eef0

colplay updates, then it was hacked up to do VU meter mode Ignore-this: 122db2f66f00c0eb505e5c6413c50cc2 darcs-hash:f61d6aee513118c3ebcf6be68ae8b31ae6dc60a7
author drewp <drewp@bigasterisk.com>
date Sun, 29 Jan 2017 00:03:50 -0800
parents 9cb135126a63
children f088e2a02ce4
files service/colplay/colplay.py service/colplay/pattern.png
diffstat 2 files changed, 78 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/service/colplay/colplay.py	Mon Jan 16 16:54:10 2017 -0800
+++ b/service/colplay/colplay.py	Sun Jan 29 00:03:50 2017 -0800
@@ -14,10 +14,27 @@
 from dateutil.tz import tzlocal
 from cyclone.httpclient import fetch
 from webcolors import rgb_to_hex
+from influxdb import InfluxDBClient
 
-logging.basicConfig(level=logging.DEBUG)
+influx = InfluxDBClient('bang', 9060, 'root', 'root', 'main')
+
+def currentAudio(location='brace'):
+    t = time.time()
+    row = list(influx.query("""SELECT mean(value) FROM audioLevel WHERE "location" = '%s' AND time > %ds""" % (location, t - 30)))[0][0]
+    log.debug("query took %.03fms", 1000 * (time.time() - t))
+    base = {'brace': .020,
+            'living': .03,
+    }[location]
+    high = {
+        'brace': .1,
+        'living': .3,
+        }[location]
+    return max(0.0, min(1.0, (row['mean'] - base) / high))
+
+
+logging.basicConfig(level=logging.INFO)
 log = logging.getLogger()
-logging.getLogger('restkit.client').setLevel(logging.WARN)
+logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(logging.WARN)
 
 class Img(object):
     def __init__(self, filename):
@@ -37,19 +54,43 @@
         if os.path.getmtime(self.filename) > self.mtime:
             self.reread()
         return [v * 4 for v in self.img.getpixel((x, y))[:3]]
+
+theaterUrl = 'http://10.1.0.1:9059/output?p=http://projects.bigasterisk.com/room/color&s=http://bigasterisk.com/homeauto/board0/'
         
 lightResource = {
-    'theater0': 'http://bang:9059/output?s=http://bigasterisk.com/homeauto/board0/rgb_right_top_2&p=http://projects.bigasterisk.com/room/color',
+    'theater_left_top_0': theaterUrl + 'rgb_left_top_0',
+    'theater_left_top_1': theaterUrl + 'rgb_left_top_1',
+    'theater_left_top_2': theaterUrl + 'rgb_left_top_2',
+    'theater_right_top_2': theaterUrl + 'rgb_right_top_2',
+    'theater_right_top_1': theaterUrl + 'rgb_right_top_1',
+    'theater_right_top_0': theaterUrl + 'rgb_right_top_0',
+    'theater_left_bottom_0': theaterUrl + 'rgb_left_bottom_0',
+    'theater_left_bottom_1': theaterUrl + 'rgb_left_bottom_1',
+    'theater_left_bottom_2': theaterUrl + 'rgb_left_bottom_2',
+    'theater_right_bottom_2': theaterUrl + 'rgb_right_bottom_2',
+    'theater_right_bottom_1': theaterUrl + 'rgb_right_bottom_1',
+    'theater_right_bottom_0': theaterUrl + 'rgb_right_bottom_0',
     }
 
 lightYPos = {
-    'theater0' : 135,
+    'theater_left_top_0': 130,
+    'theater_left_top_1': 132,
+    'theater_left_top_2': 134,
+    'theater_right_top_2': 135,
+    'theater_right_top_1': 137,
+    'theater_right_top_0': 139,
+    'theater_left_bottom_0': 153,
+    'theater_left_bottom_1': 156,
+    'theater_left_bottom_2': 159,
+    'theater_right_bottom_2': 162,
+    'theater_right_bottom_1': 165,
+    'theater_right_bottom_0': 168,
 }
 
 def hexFromRgb(rgb):
     return rgb_to_hex(tuple([x // 4 for x in rgb])).encode('ascii')
 
-def setColor(lightName, rgb, _req):
+def setColor(lightName, rgb):
     """takes 10-bit r,g,b
 
     returns even if the server is down
@@ -57,33 +98,27 @@
     log.debug("setColor(%r,%r)", lightName, rgb)
   
     serv = lightResource[lightName]
-    try:
-        h = hexFromRgb(rgb)
-        log.debug("put %r to %r", h, serv)
-        r = _req(method='PUT', url=serv, body=h,
-             headers={"content-type":"text/plain"})
-        return r
-    except Exception, e:
-        log.warn("Talking to: %r" % serv)
-        log.warn(e)
-        return None
 
-def setColorAsync(lightName, rgb):
-    """
-    uses twisted http, return deferred or sometimes None when there
-    was a warning
-    """
-    def _req(method, url, body, headers):
-        d = fetch(url=url, method=method, postdata=body,
-                  headers=dict((k,[v]) for k,v in headers.items()))
-        @d.addErrback
-        def err(e):
-            log.warn("http client error on %s: %s" % (url, e))
-            raise e
-        return d
-    setColor(lightName, rgb, _req=_req)
+    h = hexFromRgb(rgb)
+    log.debug("put %r to %r", h, serv)
+    t1 = time.time()
+    d = fetch(url=serv, method='PUT', postdata=h,
+              headers={'content-type': ['text/plain']})
+
+    def err(e):
+        log.warn("http client error on %s: %s" % (serv, e))
+        raise e
+    d.addErrback(err)
 
 
+    def done(ret):
+        log.debug('put took %.1fms', 1000 * (time.time() - t1))
+    d.addCallback(done)
+    return d
+
+
+pxPerHour = 100
+    
 class LightState(object):
     def __init__(self):
         self.lastUpdateTime = 0
@@ -101,16 +136,26 @@
         try:
             now = datetime.now(tzlocal())
             hr = now.hour + now.minute / 60 + now.second / 3600
-            x = int(((hr - 12) % 24) * 50)
+            x = int(((hr - 12) % 24) * pxPerHour) % 2400
             log.debug("x = %s", x)
 
-            for name, ypos in lightYPos.items():
+            audioLevel = currentAudio('brace')
+            log.debug('level = %s', audioLevel)
+            for i, (name, ypos) in enumerate(sorted(lightYPos.items())):
+
+                if i / len(lightYPos) < audioLevel:
+                    setColor(name, (500, 0, 0))
+                else:
+                    setColor(name, (0, 0, 0))
+                continue
+                
                 if now > self.autosetAfter[name]:
                     c = self.img.getColor(x, ypos)
-                    setColorAsync(name, c)
+                    d = setColor(name, c)
             self.lastUpdateTime = time.time()
         except Exception:
             self.lastError = traceback.format_exc()
+            log.error(self.lastError)
             self.lastErrorTime = time.time()
             
             
@@ -127,7 +172,7 @@
             ), indent=4))
 
 lightState = LightState()
-task.LoopingCall(lightState.step).start(1)
+task.LoopingCall(lightState.step).start(3)#3600 / pxPerHour)
 log.info("listening http on 9051")
 reactor.listenTCP(9051, cyclone.web.Application([
     (r'/', IndexHandler),
Binary file service/colplay/pattern.png has changed