From 9f71fe4311930478b285f038d333711a4c97c180 Mon Sep 17 00:00:00 2001 From: Giovanni Harting Date: Tue, 28 Jul 2015 07:50:46 +0200 Subject: [PATCH] added missing licence headers switched from elsif salad to decorations, I'm loving it! general cleanup removed some debug output not needed anymore --- LedD/__init__.py | 15 +++ LedD/controller.py | 16 ++++ LedD/daemon.py | 182 ++++++++++++++++++++++++++----------- LedD/decorators.py | 33 +++++++ LedD/effects/__init__.py | 15 +++ LedD/effects/baseeffect.py | 15 +++ README.md | 19 +++- start.py | 16 ++++ 8 files changed, 258 insertions(+), 53 deletions(-) create mode 100644 LedD/decorators.py diff --git a/LedD/__init__.py b/LedD/__init__.py index e69de29..22cc96d 100644 --- a/LedD/__init__.py +++ b/LedD/__init__.py @@ -0,0 +1,15 @@ +# LEDD Project +# Copyright (C) 2015 LEDD Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . \ No newline at end of file diff --git a/LedD/controller.py b/LedD/controller.py index 2f25a28..82aeeda 100644 --- a/LedD/controller.py +++ b/LedD/controller.py @@ -1,3 +1,19 @@ +# LEDD Project +# Copyright (C) 2015 LEDD Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from json import JSONEncoder import smbus diff --git a/LedD/daemon.py b/LedD/daemon.py index 65bb3f8..c7e4621 100644 --- a/LedD/daemon.py +++ b/LedD/daemon.py @@ -24,13 +24,16 @@ import sys import traceback import time -from . import controller +from LedD import controller +from LedD.decorators import add_action class Daemon: daemonSection = 'daemon' databaseSection = 'db' instance = None + """:type : Daemon """ + action_dict = {} def __init__(self): Daemon.instance = self @@ -94,67 +97,142 @@ class Daemon: c.close() self.check_db() + @add_action(action_dict) + def set_color(self, req_json): + """ + Part of the Color API. Used to set color of a stripe. + Required JSON parameters: stripe ID: sid; HSV values: h,s,v + :param req_json: dict of request json + """ + # TODO: add adapter setting stripe with color here + print("recieved action: {}".format(req_json['action'])) + + @add_action(action_dict) + def add_controller(self, req_json): + """ + Part of the Color API. Used to add a controller. + Required JSON parameters: channels; i2c_dev: number of i2c device (e.g. /dev/i2c-1 would be i2c_dev = 1); + address: hexdecimal address of controller on i2c bus, e.g. 0x40 + :param req_json: dict of request json + """ + print("recieved action: {}".format(req_json['action'])) + try: + ncontroller = controller.Controller(Daemon.instance.sqldb, req_json['channels'], + req_json['i2c_dev'], req_json['address']) + except OSError as e: + print("Error opening i2c device!") + rjson = { + 'success': False, + 'message': "Error while opening i2c device", + 'message_detail': os.strerror(e.errno), + 'ref': req_json['ref'] + } + return json.dumps(rjson) + + self.controllers.append(ncontroller) + + rjson = { + 'success': True, + 'cid': ncontroller.id, + 'ref': req_json['ref'] + } + + return json.dumps(rjson) + + @add_action(action_dict) + def get_color(self, req_json): + """ + Part of the Color API. Used to get the currect color of an stripe. + Required JSON parameters: stripeid: sid + :param req_json: dict of request json + """ + print("recieved action: {}".format(req_json['action'])) + # TODO: Add get color logic + + @add_action(action_dict) + def add_stripes(self, req_json): + """ + Part of the Color API. Used to add stripes. + Required JSON parameters: + :param req_json: dict of request json + """ + print("recieved action: {}".format(req_json['action'])) + if "stripes" in req_json: + for stripe in req_json['stripes']: + # TODO: add stripe here + print(len(req_json['stripes'])) + + @add_action(action_dict) + def get_controllers(self, req_json): + """ + Part of the Color API. Used to get all registered controllers known to the daemon. + Required JSON parameters: none + :param req_json: dict of request json + """ + print("recieved action: {}".format(req_json['action'])) + + rjson = { + 'success': True, + 'ccount': len(Daemon.instance.controllers), + 'controller': Daemon.instance.controllers, + 'ref': req_json['ref'] + } + + return json.dumps(rjson, cls=controller.ControllerEncoder) + + @add_action(action_dict) + def connection_check(self, req_json): + """ + Part of the Color API. Used to query all channels on a specified controller. + Required JSON parameters: controller id: cid + :param req_json: dict of request json + """ + print("recieved action: {}".format(req_json['action'])) + + result = next(filter(lambda x: x.id == req_json['cid'], self.controllers), None) + """ :type : Controller """ + + if result is not None: + for i in range(result.channels): + print("set channel {}={}".format(i, "1")) + result.set_channel(i, 1) + time.sleep(2) + result.set_channel(i, 0) + + rjson = { + 'success': True, + 'ref': req_json['ref'] + } + + return json.dumps(rjson) + class ConnectionHandler(asyncore.dispatcher_with_send): def handle_read(self): data = self.recv(5120) self.debug = True + + def no_action_found(self, req_json): + rjson = { + 'success': False, + 'message': "No action found", + 'ref': req_json['ref'] + } + return json.dumps(rjson) + if data: - print(data) try: json_decoded = json.loads(data.decode()) print(json.dumps(json_decoded, sort_keys=True, indent=4, separators=(',', ': '))) - if "action" in json_decoded: - if json_decoded['action'] == "set_color": + if "action" in json_decoded and "ref" in json_decoded: + return_data = Daemon.instance.action_dict.get(json_decoded['action'], no_action_found)( + self=Daemon.instance, + req_json=json_decoded) - # TODO: add adapter setting stripe with color here - print("recieved action: {}".format(json_decoded['action'])) - elif json_decoded['action'] == "add_controller": - print("recieved action: {}".format(json_decoded['action'])) - ncontroller = None - try: - ncontroller = controller.Controller(Daemon.instance.sqldb, json_decoded['channels'], - json_decoded['i2c_dev'], json_decoded['address']) - except OSError: - print("Error opening i2c device!") - - self.send("{}\n".format(ncontroller.id).encode()) - Daemon.instance.controllers.append(ncontroller) - elif json_decoded['action'] == "get_color": - # TODO: add stripe color get logic - print("recieved action: {}".format(json_decoded['action'])) - elif json_decoded['action'] == "add_stripes": - if "stripes" in json_decoded: - for stripe in json_decoded['stripes']: - # TODO: add stripe here - print(len(json_decoded['stripes'])) - elif json_decoded['action'] == "get_controllers": - rjson = { - 'status': 'success', - 'ccount': len(Daemon.instance.controllers), - 'controller': Daemon.instance.controllers - } - self.send("{}\n".format(json.dumps(rjson, cls=controller.ControllerEncoder)).encode()) - elif json_decoded['action'] == "connection_check": - result = next(filter(lambda x: x.id == json_decoded['id'], Daemon.instance.controllers), - None) - """ :type : Controller """ - - if result is not None: - print("we can do it!") - for i in range(result.channels): - print("set channel {}={}".format(i, "1")) - result.set_channel(i, 1) - time.sleep(2) - result.set_channel(i, 0) - - rjson = { - 'status': 'success' - } - - self.send("{}\n".format(json.dumps(rjson, cls=controller.ControllerEncoder)).encode()) + if return_data is not None: + self.send("{}\n".format(return_data).encode()) else: - print("no action found, ignoring") + print("no action or ref value found, ignoring") except TypeError as e: print("No valid JSON found: {}".format(e)) traceback.print_exc(file=sys.stdout) @@ -175,4 +253,4 @@ class Daemon: if pair is not None: sock, addr = pair print('Incoming connection from %s' % repr(addr)) - handler = Daemon.ConnectionHandler(sock) + handler = Daemon.ConnectionHandler(sock) \ No newline at end of file diff --git a/LedD/decorators.py b/LedD/decorators.py new file mode 100644 index 0000000..bbc2cbb --- /dev/null +++ b/LedD/decorators.py @@ -0,0 +1,33 @@ +# LEDD Project +# Copyright (C) 2015 LEDD Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +def add_action(actiondict): + """ + Decorator used to add functions to action dict + :param actiondict: dict to add to + :type actiondict: dict + """ + + def wrap(f): + actiondict[f.__name__] = f + + def wrapped_f(*args): + f(*args) + + return wrapped_f + + return wrap \ No newline at end of file diff --git a/LedD/effects/__init__.py b/LedD/effects/__init__.py index e69de29..22cc96d 100644 --- a/LedD/effects/__init__.py +++ b/LedD/effects/__init__.py @@ -0,0 +1,15 @@ +# LEDD Project +# Copyright (C) 2015 LEDD Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . \ No newline at end of file diff --git a/LedD/effects/baseeffect.py b/LedD/effects/baseeffect.py index e69de29..22cc96d 100644 --- a/LedD/effects/baseeffect.py +++ b/LedD/effects/baseeffect.py @@ -0,0 +1,15 @@ +# LEDD Project +# Copyright (C) 2015 LEDD Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . \ No newline at end of file diff --git a/README.md b/README.md index 13bd842..afe00f1 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,23 @@ LedD is a daemon for interfacing LED stripes written in python3. It provides an - an open effects github repository with simple download-and-run system - automatic enumeration of the connected controller devices, restart/reset and status querys -### License +### Plugins + +Plugin functionality is planned as we provide APIs for effects and plugins to use. Here are some we are going to provide if they are finished. + +- plugins + - lux sensor (TSL2591) for providing information if lights need to be turned on + - start/stop hook so you can switch your LED power supply + - planned hook points for plugins include + - start/stop + - set color (for e.g. gamma correction) +- effects + - pulse + - fade + - drop + - blink + - strobe (as far as possible) + +#### License This project is licensed under the conditions of the GNU GPL 3.0. diff --git a/start.py b/start.py index 77d5c72..bd0af26 100644 --- a/start.py +++ b/start.py @@ -1,3 +1,19 @@ +# LEDD Project +# Copyright (C) 2015 LEDD Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from pkgutil import iter_modules if "smbus" not in (name for loader, name, ispkg in iter_modules()):