Skip to content

Commit

Permalink
local uncommited changes
Browse files Browse the repository at this point in the history
  • Loading branch information
saerdnaer committed Feb 26, 2017
1 parent 3dc2736 commit 2f850fe
Show file tree
Hide file tree
Showing 2 changed files with 304 additions and 0 deletions.
116 changes: 116 additions & 0 deletions animations/effects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import acabsl
import random
import time

alphabet = {
'_': ((0,0,0,0,0),(0,0,0,0,0),(0,0,0,0,0),(0,0,0,0,0),(0,0,0,0,0),(0,0,0,0,0)),
'A': ((0,0,1,1,0),(0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,1,1,1),(0,1,0,0,1)),
'B': ((0,1,1,1,0),(0,1,0,0,1),(0,1,1,1,0),(0,1,0,0,1),(0,1,0,0,1),(0,1,1,1,0)),
'C': ((0,0,1,1,1),(0,1,0,0,0),(0,1,0,0,0),(0,1,0,0,0),(0,1,0,0,0),(0,0,1,1,1)),
'D': ((0,1,1,1,0),(0,0,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,1,1,0)),
'E': ((0,0,1,1,1),(0,1,0,0,0),(0,1,0,0,0),(0,1,1,1,0),(0,1,0,0,0),(0,0,1,1,1)),
'F': ((0,0,1,1,1),(0,1,0,0,0),(0,1,0,0,0),(0,1,1,1,0),(0,1,0,0,0),(0,1,0,0,0)),
'G': ((0,0,1,1,0),(0,1,0,0,0),(0,1,0,1,1),(0,1,0,0,1),(0,1,0,0,1),(0,0,1,1,1)),
'H': ((0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,1,1,1),(0,1,0,0,1),(0,1,0,0,1)),
'I': ((1,1,1,1,1),(0,0,1,0,0),(0,0,1,0,0),(0,0,1,0,0),(0,0,1,0,0),(1,1,1,1,1)),
'J': ((0,1,1,1,1),(0,0,0,0,1),(0,0,0,0,1),(0,0,0,0,1),(0,1,0,0,1),(0,0,1,1,0)),
'K': ((0,1,0,0,1),(0,1,0,0,1),(0,1,0,1,0),(0,1,1,0,0),(0,1,0,1,0),(0,1,0,0,1)),
'L': ((0,1,0,0,0),(0,1,0,0,0),(0,1,0,0,0),(0,1,0,0,0),(0,1,0,0,0),(0,1,1,1,1)),
'M': ((1,0,0,0,1),(1,1,0,1,1),(1,0,1,0,1),(1,0,0,0,1),(1,0,0,0,1),(1,0,0,0,1)),
'N': ((0,1,0,0,1),(0,1,1,0,1),(0,1,1,0,1),(0,1,0,1,1),(0,1,0,1,1),(0,1,0,0,1)),
'O': ((0,0,1,1,0),(0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,0,1,1,0)),
'P': ((0,1,1,1,0),(0,1,0,0,1),(0,1,0,0,1),(0,1,1,1,0),(0,1,0,0,0),(0,1,0,0,0)),
'Q': ((0,0,1,1,0),(0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,0,1,1),(0,0,1,1,1)),
'R': ((0,1,1,1,0),(0,1,0,0,1),(0,1,0,0,1),(0,1,1,1,0),(0,1,0,1,0),(0,1,0,0,1)),
'S': ((0,0,1,1,1),(0,1,0,0,0),(0,1,0,0,0),(0,0,1,1,1),(0,0,0,0,1),(0,1,1,1,0)),
'T': ((1,1,1,1,1),(1,0,1,0,0),(0,0,1,0,0),(0,0,1,0,0),(0,0,1,0,0),(0,0,1,0,0)),
'U': ((0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,1,1,1)),
'V': ((1,0,0,0,1),(1,0,0,0,1),(1,0,0,0,1),(0,1,0,1,0),(0,1,0,1,0),(0,0,1,0,0)),
'W': ((1,0,0,0,1),(1,0,0,0,1),(1,0,1,0,1),(1,0,1,0,1),(1,1,0,1,1),(1,0,0,0,1)),
'X': ((1,0,0,0,1),(0,1,0,1,0),(0,1,0,1,0),(0,0,1,0,1),(0,1,0,1,0),(1,0,0,0,1)),
'Y': ((1,0,0,0,1),(1,0,0,0,1),(0,1,0,1,0),(0,1,0,1,0),(0,0,1,0,0),(0,0,1,0,0)),
'Z': ((0,1,1,1,1),(0,0,0,0,1),(0,0,0,1,0),(0,0,1,0,0),(0,1,0,0,0),(0,1,1,1,1)),
'1': ((0,0,0,1,0),(0,0,1,1,0),(0,0,0,1,0),(0,0,0,1,0),(0,0,0,1,0),(0,0,0,1,0)),
'2': ((0,0,1,1,0),(0,1,0,0,1),(0,0,0,0,1),(0,0,0,1,0),(0,0,1,0,0),(0,1,1,1,1)),
'3': ((0,1,1,1,0),(0,0,0,0,1),(0,0,0,1,0),(0,0,1,1,0),(0,0,0,0,1),(0,1,1,1,0)),
'4': ((0,1,0,0,1),(0,1,0,0,1),(0,1,0,0,1),(0,1,1,1,1),(0,0,0,0,1),(0,0,0,0,1)),
'5': ((0,1,1,1,1),(0,1,0,0,0),(0,1,1,1,0),(0,0,0,0,1),(0,0,0,0,1),(0,1,1,1,0)),
'6': ((0,0,1,1,1),(0,1,0,0,0),(0,1,1,1,0),(0,1,0,0,1),(0,1,0,0,1),(0,0,1,1,0)),
'7': ((0,1,1,1,1),(0,1,0,0,1),(0,0,0,0,1),(0,0,0,1,0),(0,0,1,0,0),(0,0,1,0,0)),
'8': ((0,0,1,1,0),(0,1,0,0,1),(0,1,0,1,0),(0,0,1,0,1),(0,1,0,0,1),(0,0,1,1,0)),
'9': ((0,0,1,1,0),(0,1,0,0,1),(0,1,0,0,1),(0,0,1,1,1),(0,0,0,0,1),(0,1,1,1,0)),
':': ((0,0,0,0,0),(0,0,0,0,0),(0,0,1,0,0),(0,0,0,0,0),(0,0,1,0,0),(0,0,0,0,0)),
'@': ((0,0,1,1,1),(0,1,0,0,0),(0,1,1,1,0),(0,1,1,0,1),(0,1,0,0,1),(0,0,1,1,0)),
'.': ((0,0,0,0,0),(0,0,0,0,0),(0,0,0,0,0),(0,0,0,0,0),(0,0,1,1,0),(0,0,1,1,0)),
'#': ((0,0,0,0,0),(0,1,0,1,0),(1,1,1,1,1),(0,1,0,1,0),(1,1,1,1,1),(0,1,0,1,0)),
'+': ((0,0,1,0,0),(0,0,1,0,0),(1,1,1,1,1),(0,0,1,0,0),(0,0,1,0,0),(0,0,1,0,0)),
'*': ((0,0,0,0,0),(1,0,1,0,1),(0,1,1,1,0),(1,1,1,1,1),(0,1,1,1,0),(1,0,1,0,1)),
'/': ((0,0,0,0,1),(0,0,0,1,0),(0,0,1,0,0),(0,0,1,0,0),(0,1,0,0,0),(1,0,0,0,0)),
'-': ((0,0,0,0,0),(0,0,0,0,0),(0,0,0,0,0),(0,1,1,1,1),(0,0,0,0,0),(0,0,0,0,0)),
'=': ((0,0,0,0,0),(0,0,0,0,0),(0,1,1,1,1),(0,0,0,0,0),(0,1,1,1,1),(0,0,0,0,0)),
}

def set_single(x,y,r,g,b,fade_time=0, wall=0):
acabsl.send(x,y,r,g,b,fade_time, wall)

def set_all(r,g,b,fade_time=0):
for w in range(acabsl.NOOFWALLS):
for x in range(acabsl.WALLSIZEX):
for y in range(acabsl.WALLSIZEY):
acabsl.send(x,y,r,g,b,fade_time,w)
acabsl.update()

def blink(colour, repetition, duration):
for i in range(repetition):
set_all(*colour, fade_time = 0.8)
time.sleep(duration)
if (i + 1) < repetition:
set_all(0,42,42, fade_time = 0.8)
time.sleep(duration)

def text(text, repetitions = 1, colour = (0,42,42), interval = 0.3, marquee = True):
text = text.upper()
matrix = []
for i in range(len(text)):
if text[i] not in alphabet:
continue
for j in range(len(alphabet[text[i]][0])):
matrix.append([])
for k in range(len(alphabet[text[i]])-1,-1,-1):
matrix[-1].append(alphabet[text[i]][k][j])
matrix.append([0]*len(alphabet[text[i]]))
for i in range(repetitions):
for j in range(0 if not marquee else (- acabsl.WALLSIZEX), len(matrix)):
for x in range(acabsl.WALLSIZEX):
for y in range(acabsl.WALLSIZEY):
if x+j < len(matrix) and x+j >= 0 and matrix[x+j][y] == 1:
set_single(x, acabsl.WALLSIZEY-1-y, *colour, fade_time = interval/2.)
else:
set_single(x, acabsl.WALLSIZEY-1-y, 0, 0, 0, fade_time = interval/2.)
acabsl.update()
time.sleep(interval)

def rain(steps = 23, interval = 0.3):
drops = []
infinite = False
if steps == 0:
infinite = True
while infinite or (steps > 0):
new_drops = []
for drop in drops:
if drop[1] > 0:
new_drops.append([drop[0],drop[1]-1])
drops = new_drops
drops.append([random.randint(0,acabsl.WALLSIZEX-1),acabsl.WALLSIZEY-1])
for x in range(acabsl.WALLSIZEX):
for y in range(acabsl.WALLSIZEY):
if [x,y] in drops:
set_single(x,acabsl.WALLSIZEY-1-y,0,0,255, 0.7)
else:
set_single(x,acabsl.WALLSIZEY-1-y,0,0,0, 0.7)
acabsl.update()
steps -= 1
time.sleep(interval)
188 changes: 188 additions & 0 deletions animations/toto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
#!/usr/bin/env python3

import urllib.request
import argparse
import json
import logging
import os
import effects

from time import sleep

TEST_PAYLOAD="""txt|col:#blue|msg:hallo|rep:1\\nseq|id:5\\nblink|col:#red"""
TEST_PAYLOAD_II="""seq|id:rain\\nseq|id:23\\nblink"""
TEST_SEARCH = [
"""[
{
"name": "acab",
"payload": "%s",
"ts": 123
}, {
"name": "acab",
"payload": "%s",
"ts": 124
}
]""" % (TEST_PAYLOAD, TEST_PAYLOAD_II)
]

logger = logging.getLogger()
formatter = logging.Formatter(
"%(asctime)s - %(levelname)-8s - %(message)s"
)

stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)

logger.setLevel(logging.WARNING)

def hexColourToTuple(colour):
if colour.startswith("#"):
colour = colour[1:]
try:
int(colour,16)
except ValueError:
colourMapping = {
"blue": "0000CC",
"red": "CC0000",
"green": "00CC00",
"white": "CCCCCC",
"black": "000000",
"yellow": "CCCC00",
}
if colour in colourMapping:
colour = colourMapping[colour]
else:
colour = "000000"
result = []
for i in range(3):
result.append(int(colour[i*2:i*2+2],16))
return tuple(result)

class Handler:
def __init__(self, base_url, key, secret, debug = False):
self.base_url = base_url
self.key = key
self.secret = secret
self.last = None
self.debug = debug

def parsePayload(self, payload):
instructions = []
for line in payload.splitlines():
line = line.split("|")
if not line:
continue
command = line.pop(0)
instructions.append({"cmd": command})
for arg in line:
key,value = arg.split(":")
instructions[-1][key] = value
logging.debug(instructions)
return instructions

def apiGet(self, url, **params):
query = "%s%s?key=%s&secret=%s" % ( self.base_url, url, self.key, self.secret ) + \
"".join(["&%s=%s" % ( key, value ) for key, value in params.items()])
logger.debug("api query '%s'", query)
response = urllib.request.urlopen(query).read().decode("utf-8")
logger.debug("api response '%s'", response)
json_obj = json.loads(response)
return json_obj

def getLast(self, since=None):
return self.apiGet("/last")["ts"]

def getSearch(self, since = None):
if self.debug:
return json.loads(TEST_SEARCH[0])
else:
return self.apiGet("/search", since = since if since else self.last)

def initiateLast(self):
self.last = self.getLast()

def search(self):
search_result = self.getSearch()
playlist = []
logger.debug("search result: %s", search_result)
for item in search_result:
self.last = item["ts"]
playlist.append(self.parsePayload(item["payload"]))
return playlist

def processTXT(self, msg, col = "#002A2A", rep = 1):
col = hexColourToTuple(col)
effects.text(msg, int(rep), col)

def processSEQ(self, seq_id):
logger.debug(seq_id)
if seq_id == "rain":
effects.rain()

def processBlink(self, col = "#blue", rep = 1, dur = 1):
col = hexColourToTuple(col)
effects.blink(col, int(rep), int(dur))

def processPlaylist(self, playlist):
if not playlist:
logger.debug("empty playlist")
return
logger.info("new playlist: %s" % str(playlist))
for action in playlist:
for instruction in action:
cmd = instruction.pop("cmd")
if cmd == "txt":
self.processTXT(**instruction)
elif cmd == "seq":
if "id" in instruction:
instruction["seq_id"] = instruction.pop("id")
self.processSEQ(**instruction)
elif cmd == "blink":
self.processBlink(**instruction)

def loop(self, interval):
self.initiateLast()

try:
while True:
try:
playlist = self.search()
logger.debug("new playlist: %s", playlist)
self.processPlaylist(playlist)

sleep(interval)
except Exception as e:
if self.debug:
raise e
logger.error(e)
sleep(interval)
except KeyboardInterrupt:
logger.info("exiting")


if __name__=="__main__":
parser = argparse.ArgumentParser(description='TOTO ACAB Actuator')
parser.add_argument('--verbose', '-v', action='store_true', help='Verbose mode')
parser.add_argument('--debug', '-d', action='store_true', help='Debug mode')
parser.add_argument('--simulate', '-s', action='store_true', help='Use predefined responses')
parser.add_argument('--log', '-l', help='Logfile')
parser.add_argument('--base-url', default='https://example', help='Base URL for TOTO server')
parser.add_argument('--check-interval', default=1, type=int, help='Interval in seconds for checking backend for new payloads')
parser.add_argument('key', help='API Key')
parser.add_argument('secret', help='API Secret')
args = parser.parse_args()

if args.log:
file_handler = logging.FileHandler(args.log,"a")
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)


if args.verbose:
logger.setLevel(logging.INFO)
if args.debug:
logger.setLevel(logging.DEBUG)

handler = Handler(args.base_url, args.key, args.secret, args.simulate)
handler.loop(args.check_interval)

0 comments on commit 2f850fe

Please sign in to comment.