dirkse 8 rokov pred
rodič
commit
d6766e921d
9 zmenil súbory, kde vykonal 156 pridanie a 66 odobranie
  1. 1 0
      alexa/app/domo.py
  2. 1 0
      alexa/app/server.py
  3. 6 0
      alexa/app/utils.py
  4. 2 0
      hosts.yml
  5. 1 18
      matrix/Dockerfile
  6. 121 28
      matrix/pixelreceiver.py
  7. 4 1
      services.yml
  8. 2 2
      vaping/Dockerfile
  9. 18 17
      vaping/config.yml

+ 1 - 0
alexa/app/domo.py

@@ -10,6 +10,7 @@ import time
 import requests
 
 from ameise import app, ask, log
+from utils import write_text_matrix
 
 from flask_ask import Ask, statement, question, session, context
 

+ 1 - 0
alexa/app/server.py

@@ -15,6 +15,7 @@ from ameise import app, ask, log
 # Intents
 import domo
 import chef
+import speller
 
 WELCOME = [
     'Hast du einen Wunsch?',

+ 6 - 0
alexa/app/utils.py

@@ -1,3 +1,4 @@
+import socket
 
 import requests
 from flask_ask import Ask, statement, context
@@ -11,3 +12,8 @@ def get_alexa_location():
     r = requests.get(URL, headers=HEADER)
     if r.status_code == 200:
         return(r.json())
+
+def write_text_matrix(text):
+    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+    sock.sendto(b'\2' + text.encode('utf-8'), ('blaubeere.fritz.box', 10000))
+    sock.close()

+ 2 - 0
hosts.yml

@@ -26,4 +26,6 @@ all:
       ansible_ssh_host: 192.168.178.24
     erdbeere:
       ansible_ssh_host: 192.168.178.29
+    waldbeere:
+      ansible_ssh_host: waldbeere.fritz.box
 

+ 1 - 18
matrix/Dockerfile

@@ -20,6 +20,7 @@ RUN apt-get update && apt-get install -y \
         vim \
         git \
         mc \
+        htop \
         python \
         python-dev \
         python-pip \
@@ -48,24 +49,6 @@ RUN jupyter nbextension enable --py --sys-prefix widgetsnbextension
 
 
 VOLUME /root/notebooks
-
-# Add Tini. Tini operates as a process subreaper for jupyter. This prevents kernel crashes.
-ENV TINI_VERSION 0.14.0
-ENV CFLAGS="-DPR_SET_CHILD_SUBREAPER=36 -DPR_GET_CHILD_SUBREAPER=37"
-
-ADD https://github.com/krallin/tini/archive/v${TINI_VERSION}.tar.gz /root/v${TINI_VERSION}.tar.gz
-RUN apt-get install -y cmake
-RUN tar zxvf v${TINI_VERSION}.tar.gz \
-        && cd tini-${TINI_VERSION} \
-        && cmake . \
-        && make \
-        && cp tini /usr/bin/. \
-        && cd .. \
-        && rm -rf "./tini-${TINI_VERSION}" \
-        && rm "./v${TINI_VERSION}.tar.gz"
-
-ENTRYPOINT ["/usr/bin/tini", "--"]
-
 EXPOSE 8888
 
 CMD ["jupyter", "notebook", "--allow-root"]

+ 121 - 28
matrix/pixelreceiver.py

@@ -2,6 +2,7 @@ from __future__ import print_function, absolute_import, division
 
 print('receiver start')
 import sys
+import time
 
 import socket
 import traceback
@@ -10,27 +11,84 @@ from path import Path
 
 from rgbmatrix import RGBMatrix, RGBMatrixOptions
 from rgbmatrix import graphics
+from PIL import Image
+
+def asc_desc_modulation(x, interval, clamp=0.1):
+    sub_idx = x % interval
+    if sub_idx < interval / 2:
+        f = (x % interval) / interval
+    else:
+        f = (interval - x % interval) / interval
+    f = max(clamp, f)
+    modulate = lambda c: (int(c[0] * f), int(c[1] * f), int(c[2] * f))
+    return modulate
+
+def Color(colorstring):
+    """ convert #RRGGBB to an (R, G, B) tuple """
+    colorstring = colorstring.strip()
+    if colorstring[0] == '#': colorstring = colorstring[1:]
+    if len(colorstring) != 6:
+        raise ValueError, "input #%s is not in #RRGGBB format" % colorstring
+    r, g, b = colorstring[:2], colorstring[2:4], colorstring[4:]
+    r, g, b = [int(n, 16) for n in (r, g, b)]
+    return (r, g, b)
 
 class Renderer(object):
-    def __init__(self):
+    def __init__(self, textColor=(255, 255, 255), brightness=255):
+        print('initializing renderer')
+        self._color = textColor
+        self.setup()
+
+        self._brightness = brightness
+        self.set_brightness(brightness)
+
+    def set_brightness(self, value):
+        self._brightness = value
+        self.matrix.brightness = value
+
+    def setup(self):
         o = RGBMatrixOptions()
         o.chain_length = 4
         self.matrix = RGBMatrix(options=o)
         self.canvas = self.matrix.CreateFrameCanvas()
+        self.color = graphics.Color(*self._color)
+
+    def destroy(self):
+        del self.canvas
+        del self.matrix
+        del self.color
 
     def swap(self):
         self.canvas = self.matrix.SwapOnVSync(self.canvas)
         self.canvas.Clear()
 
+    def progress(self, step=0, total=0):
+        c = self.canvas
+        w, h = c.width, c.height
+        col = Color('#AACCFF')
+        if total > 0:
+            padding = ' ' * (len(str(total-1)) - len(str(step+1)))
+            s_len = graphics.DrawText(c, fonts['10x20'], 0, 20, self.color, '%s%s' % (padding, step+1))
+            w = w - s_len
+
+            stepsize = max(1, int(w / total))
+            for x in range(w):
+                modulate = asc_desc_modulation(x, stepsize)
+                for y in range(h):
+                    c.SetPixel(s_len + x, y, *modulate(col))
+                if  x > ((step + 1) / total) * w:
+                    break
+        self.swap()
+
     def print_text(self, text):
-        graphics.DrawText(self.canvas, fonts['10x20'], 0, 20, textColor, text)
+        graphics.DrawText(self.canvas, fonts['10x20'], 0, 20, self.color, text)
         self.swap()
 
     def scroll_text(self, text, loop=1):
         pos = self.canvas.width
         i = 1
         while True:
-            len = graphics.DrawText(self.canvas, fonts['10x20'], pos, 20, textColor, text)
+            len = graphics.DrawText(self.canvas, fonts['10x20'], pos, 20, self.color, text)
             pos -= 1
             if (pos + len < 0):
                 pos = self.canvas.width
@@ -42,31 +100,54 @@ class Renderer(object):
             self.swap()
 
 
-    def fit_text(self, text, width=128):
+    def fit_text(self, text, width=None, fade=None):
+        if width is None:
+            width = self.canvas.width
+
         ff = reversed(sorted(fonts.items(), key=lambda e: int(e[0].split('x')[0])))
         temp_canvas = self.matrix.CreateFrameCanvas()
         for name, font in ff:
-            w = graphics.DrawText(temp_canvas, font, 0, -100, textColor, text)
+            w = graphics.DrawText(temp_canvas, font, 0, -100, self.color, text)
             if w < width:
                 break
         else:
             print('str len %s exceeds space' % w)
 
-        graphics.DrawText(self.canvas, font, 0, 20, textColor, text)
-        self.swap()
+        if fade:
+            t = time.time()
+            while time.time() < t + fade:
+                x = 1 - ((time.time() - t) / fade)
+                #~ self.matrix.brightness = self._brightness * x
+                c = graphics.Color(int(self.color.red * x), int(self.color.green * x), int(self.color.blue * x))
+                graphics.DrawText(self.canvas, font, 0, 20, c, text)
+                self.swap()
+                time.sleep(0.02)
+
+        else:
+            graphics.DrawText(self.canvas, font, 0, 20, self.color, text)
+            self.swap()
 
 
 try:
     fonts = {}
-    for f in Path('/matrix/fonts').files('*.bdf'):
+    fo = graphics.Font()
+    fo.LoadFont('/matrix/fonts/10x20.bdf')
+    fonts['10x20'] = fo
+
+    r = Renderer(textColor=(96, 128, 255))
+    print('loading fonts')
+    files = Path('/matrix/fonts').files('*.bdf')
+
+    for i, f in enumerate(files):
+        #~ if i % 3 != 0:
+            #~ continue
+        r.progress(i, len(files))
         if not f.namebase.split('x')[0].isdigit() or not f.namebase[-1].isdigit():
             continue
         fo = graphics.Font()
         fo.LoadFont(f)
         fonts[f.namebase] = fo
-
-    textColor = graphics.Color(96, 128, 255)
-    r = Renderer()
+    r.progress(0, 0)
 
     # Create a TCP/IP socket
     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
@@ -75,25 +156,37 @@ try:
     server_address = ('0.0.0.0', 10000)
     print('starting up on %s port %s' % server_address)
     sock.bind(server_address)
-    r.fit_text('Matrix ready.')
-
-    r.fit_text('111')
-
+    r.fit_text('Matrix ready.', fade=4)
 
     while True:
-        print('waiting to receive message')
-        data, address = sock.recvfrom(4096)
-
-        print('received %s bytes from %s' % (len(data), address))
-        method = ord(data[0])
-        data = data[1:]
-
-        if method == 0:
-            r.print_text(data.decode('utf-8'))
-        elif method == 1:
-            r.scroll_text(data.decode('utf-8'))
-        elif method == 2:
-            r.fit_text(data.decode('utf-8'))
+        try:
+            print('waiting to receive message')
+            data, address = sock.recvfrom(4096)
+
+            method = ord(data[0])
+            print('received %s bytes from %s [method: %s]' % (len(data), address, method))
+
+            r.set_brightness(255)
+
+            data = data[1:]
+
+            if method == 0:
+                r.print_text(data.decode('utf-8'))
+            elif method == 1:
+                r.scroll_text(data.decode('utf-8'))
+            elif method == 2:
+                r.fit_text(data.decode('utf-8'))
+            elif method == 10:
+                r.progress(ord(data[0]), ord(data[1]))
+
+            elif method == 255:
+                # kill SwapOnVSync
+                r.destroy()
+                # XXX: how to re-setup
+                #~ r.setup()
+        except Exception:
+            print(traceback.format_exc())
+
 
 except Exception:
     print(traceback.format_exc())

+ 4 - 1
services.yml

@@ -173,6 +173,7 @@ matrix: # interface with RGB LED-Matrix
   #~ fqdn: alexa.cere.duckdns.org
   host: blaubeere
   docker:
+    init: true
     build: matrix
     # matrix driver needs access to /dev/mem
     privileged: true
@@ -211,9 +212,11 @@ matrix: # interface with RGB LED-Matrix
     pydemo3: bindings/python/samples/simple-square.py -c 4 --led-show-refresh
     # tail logs of pixelreceiver (udp server)
     pixel_logs: tail -f /pixel/receive.log
+    # kill pixel receiver
+    pixel_kill: pkill -f "python -u /pixelreceiver.py"
 
 vaping:
-  host: erdbeere
+  host: waldbeere
   docker:
     build: vaping
     ports: 6080:7021

+ 2 - 2
vaping/Dockerfile

@@ -13,6 +13,6 @@ RUN pip install vaping
 COPY config.yml /vaping/config.yml
 EXPOSE 7021
 
-CMD rm -f /vaping/vaping.pid && vaping --home=/vaping/ --debug  --verbose start
+CMD rm -f /vaping/vaping.pid && vaping --home=/vaping/ --debug  start
 
-HEALTHCHECK --interval=10s CMD curl -I -s localhost:7021 | grep "200 OK"
+HEALTHCHECK --interval=100s CMD curl -I -s localhost:7021 | grep "200 OK"

+ 18 - 17
vaping/config.yml

@@ -31,30 +31,24 @@ probes:
           color: orange
     raspi:
       hosts:
-        - host: 192.168.178.49
+        - host: blaubeere.fritz.box
           name: Blaubeere
           color: red
-        - host: 192.168.178.43
+        - host: himbeere.fritz.box
           name: Himbeere
           color: blue
     repeater:
       hosts:
-        - host: 192.168.178.64
+        - host: 192.168.178.25
           name: Repeater1750-1
-          color: red
-        - host: 192.168.178.34
-          name: Repeater7330
-          color: blue
-        - host: 192.168.178.24
-          name: Fritzbox7490
           color: orange
-        - host: 192.168.178.38
+        - host: 192.168.178.26
           name: Repeater1750-2
           color: green
 
     pc:
       hosts:
-        - host: 192.168.178.36
+        - host: 192.168.178.20
           name: cbase
           color: red
         - host: 192.168.178.28
@@ -64,8 +58,12 @@ probes:
           name: cg-x250
           color: orange
         - host: 192.168.178.22
-          name: christine-macbook
+          name: cr-mac
           color: green
+        - host: 192.168.178.41
+          name: lr-mac
+          color: magenta
+
 
     mobil:
       hosts:
@@ -76,20 +74,23 @@ probes:
           name: cg-android
           color: blue
         - host: 192.168.178.45
-          name: elise-ip4
+          name: cr-ip4
           color: orange
+        - host: 192.168.178.40
+          name: er-ip4
+          color: green
     sonos:
       hosts:
-        - host: 192.168.178.23
+        - host: 192.168.178.31
           name: connect
           color: red
-        - host: 192.168.178.26
+        - host: 192.168.178.29
           name: p3
           color: blue
-        - host: 192.168.178.31
+        - host: 192.168.178.77
           name: p5
           color: orange
-        - host: 192.168.178.25
+        - host: 192.168.178.37
           name: amp
           color: green