added set_all_channel method

reintroduced caching of stripes & controllers
added session cleanup handling
renamed --daemon to --detach for better understanding
added coloredlogs to make logs better readable and more appealing
This commit is contained in:
Giovanni Harting
2015-10-15 13:26:36 +02:00
parent 4c052b8edb
commit 01ba0a4d2c
4 changed files with 82 additions and 28 deletions

21
ledd.py
View File

@@ -1,3 +1,5 @@
#!/usr/bin/python3
# LEDD Project # LEDD Project
# Copyright (C) 2015 LEDD Team # Copyright (C) 2015 LEDD Team
# #
@@ -17,16 +19,16 @@
"""LedD Daemon """LedD Daemon
Usage: Usage:
ledd.py [--daemon] [-d | --debug] [-v | --verbose] ledd.py [--detach] [-d | --debug] [-v | --verbose]
ledd.py -h | --help ledd.py -h | --help
ledd.py --version ledd.py --version
Options: Options:
-h --help Show this screen. -h --help Show this screen.
--version Show version. --version Show version.
-d --debug Show debug output. (not recommended for daily use) -d --debug Show debug output. (not recommended)
-v --verbose Be verbose. -v --verbose Be verbose.
--daemon Run in daemon mode. --detach Detach after start.
""" """
import logging import logging
@@ -34,8 +36,12 @@ import sys
import os import os
from pkgutil import iter_modules from pkgutil import iter_modules
import coloredlogs
from docopt import docopt from docopt import docopt
import ledd.daemon
import ledd
if "smbus" not in (name for loader, name, ispkg in iter_modules()): if "smbus" not in (name for loader, name, ispkg in iter_modules()):
print("smbus not found, installing replacement") print("smbus not found, installing replacement")
@@ -62,9 +68,6 @@ if "smbus" not in (name for loader, name, ispkg in iter_modules()):
sys.modules['smbus'] = SMBusModule sys.modules['smbus'] = SMBusModule
sys.modules['smbus'].SMBus = SMBus sys.modules['smbus'].SMBus = SMBus
import ledd.daemon
import ledd
def pid_exists(processid): def pid_exists(processid):
if processid < 0: if processid < 0:
@@ -89,10 +92,8 @@ if __name__ == "__main__":
if arguments['--debug']: if arguments['--debug']:
lvl = logging.DEBUG lvl = logging.DEBUG
logging.basicConfig(level=lvl,
format="[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] %(message)s",
datefmt="%H:%M:%S")
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
coloredlogs.install(level=lvl)
try: try:
with open('ledd.pid', 'r') as f: with open('ledd.pid', 'r') as f:
@@ -106,7 +107,7 @@ if __name__ == "__main__":
except FileNotFoundError: except FileNotFoundError:
pass pass
if arguments['--daemon']: if arguments['--detach']:
wdir = os.path.dirname(os.path.realpath(__file__)) wdir = os.path.dirname(os.path.realpath(__file__))
try: try:
pid = os.fork() pid = os.fork()

View File

@@ -76,6 +76,10 @@ class Controller(Base):
4095)) 4095))
self.bus.write_word_data(self._address, LED0_ON_L + 4 * channel, 0) self.bus.write_word_data(self._address, LED0_ON_L + 4 * channel, 0)
def set_all_channel(self, val):
self.bus.write_word_data(self._address, ALLLED_OFF_L, int(val * 4095))
self.bus.write_word_data(self._address, ALLLED_ON_L, 0)
@staticmethod @staticmethod
def gamma_correct(gamma, val, maxval): def gamma_correct(gamma, val, maxval):
corrected = int(pow(float(val) / float(maxval), float(gamma)) * float(maxval) + 0.5) corrected = int(pow(float(val) / float(maxval), float(gamma)) * float(maxval) + 0.5)

View File

@@ -26,7 +26,6 @@ from jsonrpc import JSONRPCResponseManager, dispatcher
from jsonrpc.exceptions import JSONRPCError, JSONRPCInvalidParams from jsonrpc.exceptions import JSONRPCError, JSONRPCInvalidParams
import spectra import spectra
from sqlalchemy.exc import OperationalError from sqlalchemy.exc import OperationalError
from sqlalchemy.orm.exc import NoResultFound from sqlalchemy.orm.exc import NoResultFound
from ledd import VERSION from ledd import VERSION
@@ -42,6 +41,8 @@ daemonSection = 'daemon'
databaseSection = 'db' databaseSection = 'db'
""" :type : asyncio.BaseEventLoop """ """ :type : asyncio.BaseEventLoop """
effects = [] effects = []
stripes = []
controller = []
def run(): def run():
@@ -66,6 +67,13 @@ def run():
log.debug(Controller.query.all()) log.debug(Controller.query.all())
logging.getLogger("asyncio").setLevel(log.getEffectiveLevel()) logging.getLogger("asyncio").setLevel(log.getEffectiveLevel())
# Load to cache
global controller, stripes
controller = Controller.query.all()
for c in controller:
stripes.extend(c.stripes)
# sigterm handler # sigterm handler
def sigterm_handler(): def sigterm_handler():
raise SystemExit raise SystemExit
@@ -76,13 +84,13 @@ def run():
# TODO: check all plugins for existing hooks # TODO: check all plugins for existing hooks
# main loop # main loop
global loop global loop, server
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
coro = loop.create_server(LedDProtocol, coro = loop.create_server(LedDProtocol,
config.get(daemonSection, 'host', fallback='0.0.0.0'), config.get(daemonSection, 'host', fallback='0.0.0.0'),
config.get(daemonSection, 'port', fallback=1425)) config.get(daemonSection, 'port', fallback=1425))
global server
server = loop.run_until_complete(coro) server = loop.run_until_complete(coro)
log.info("Start phase finished; starting main loop")
loop.run_forever() loop.run_forever()
except (KeyboardInterrupt, SystemExit): except (KeyboardInterrupt, SystemExit):
log.info("Exiting") log.info("Exiting")
@@ -90,7 +98,8 @@ def run():
os.remove("ledd.pid") os.remove("ledd.pid")
except FileNotFoundError: except FileNotFoundError:
pass pass
# TODO: close engine? session.commit()
session.close()
if server is not None: if server is not None:
server.close() server.close()
if loop is not None: if loop is not None:
@@ -109,7 +118,7 @@ def check_db():
db_version = Meta.get_version() db_version = Meta.get_version()
if db_version is not None: if db_version is not None:
log.info("DB connection established; db-version=%s", db_version) log.info("DB connection established; db_version=%s", db_version)
return True return True
except OperationalError: except OperationalError:
return False return False
@@ -186,16 +195,39 @@ def set_color(**kwargs):
if "sid" not in kwargs or "hsv" not in kwargs: if "sid" not in kwargs or "hsv" not in kwargs:
return JSONRPCInvalidParams() return JSONRPCInvalidParams()
try: stripe = get_stripe(kwargs['sid'])
stripe = Stripe.query.filter(Stripe.id == kwargs['sid']).one()
if stripe:
stripe.set_color(spectra.hsv(kwargs['hsv']['h'], kwargs['hsv']['s'], kwargs['hsv']['v'])) stripe.set_color(spectra.hsv(kwargs['hsv']['h'], kwargs['hsv']['s'], kwargs['hsv']['v']))
except NoResultFound: else:
log.warning("Stripe not found: id=%s", kwargs['sid']) log.warning("Stripe not found: id=%s", kwargs['sid'])
return JSONRPCError(-1003, "Stripeid not found") return JSONRPCError(-1003, "Stripeid not found")
return "" return ""
@dispatcher.add_method
def set_color_all(**kwargs):
"""
Part of the Color API. Used to set brightness of all stripes a controller owns.
Required parameters: controller id: cid, value: v
"""
if "cid" not in kwargs or "v" not in kwargs:
return JSONRPCInvalidParams()
try:
c = get_controller(kwargs['cid'])
""" :type c: ledd.controller.Controller """
c.set_all_channel(kwargs['v'])
except NoResultFound:
log.warning("Controller not found: id=%s", kwargs['cid'])
return JSONRPCError(-1002, "Controller not found")
return ""
@dispatcher.add_method @dispatcher.add_method
def add_controller(**kwargs): def add_controller(**kwargs):
""" """
@@ -217,6 +249,8 @@ def add_controller(**kwargs):
session.add(ncontroller) session.add(ncontroller)
session.commit() session.commit()
controller.append(ncontroller)
return {'cid': ncontroller.id} return {'cid': ncontroller.id}
@@ -230,9 +264,9 @@ def get_color(**kwargs):
if "sid" not in kwargs: if "sid" not in kwargs:
return JSONRPCInvalidParams() return JSONRPCInvalidParams()
try: stripe = get_stripe(kwargs['sid'])
stripe = Stripe.query.filter(Stripe.id == kwargs['sid']).one()
except NoResultFound: if not stripe:
log.warning("Stripe not found: id=%s", kwargs['sid']) log.warning("Stripe not found: id=%s", kwargs['sid'])
return JSONRPCError(-1003, "Stripeid not found") return JSONRPCError(-1003, "Stripeid not found")
@@ -249,10 +283,11 @@ def add_stripe(**kwargs):
if "name" not in kwargs or "rgb" not in kwargs or "map" not in kwargs or "cid" not in kwargs: if "name" not in kwargs or "rgb" not in kwargs or "map" not in kwargs or "cid" not in kwargs:
return JSONRPCInvalidParams() return JSONRPCInvalidParams()
c = Controller.query.filter(Controller.id == int(kwargs['cid'])).first() c = get_controller(kwargs['cid'])
""" :type c: ledd.controller.Controller """ """ :type c: ledd.controller.Controller """
if c is None: if c is None:
log.warning("Controller not found: id=%s", kwargs['cid'])
return JSONRPCError(-1002, "Controller not found") return JSONRPCError(-1002, "Controller not found")
s = Stripe(name=kwargs['name'], rgb=bool(kwargs['rgb']), s = Stripe(name=kwargs['name'], rgb=bool(kwargs['rgb']),
@@ -260,7 +295,9 @@ def add_stripe(**kwargs):
s.controller = c s.controller = c
log.debug("Added stripe %s to controller %s; new len %s", s.id, c.id, len(c.stripes)) log.debug("Added stripe %s to controller %s; new len %s", s.id, c.id, len(c.stripes))
session.add(s)
session.commit() session.commit()
stripes.append(s)
return {'sid': s.id} return {'sid': s.id}
@@ -273,8 +310,8 @@ def get_stripes(**kwargs):
""" """
rjson = { rjson = {
'ccount': len(Controller.query.all()), 'ccount': len(controller),
'controller': Controller.query.all() 'controller': controller
} }
return rjson return rjson
@@ -290,11 +327,11 @@ def test_channel(**kwargs):
if "cid" not in kwargs or "channel" not in kwargs or "value" not in kwargs: if "cid" not in kwargs or "channel" not in kwargs or "value" not in kwargs:
return JSONRPCInvalidParams() return JSONRPCInvalidParams()
result = Controller.query.filter(Controller.id == kwargs['cid']).first() contr = get_controller(kwargs['cid'])
""" :type : ledd.controller.Controller """ """ :type : ledd.controller.Controller """
if result is not None: if contr is not None:
result.set_channel(kwargs['channel'], kwargs['value'], 2.8) contr.set_channel(kwargs['channel'], kwargs['value'], 2.8)
else: else:
return JSONRPCError(-1002, "Controller not found") return JSONRPCError(-1002, "Controller not found")
@@ -311,6 +348,18 @@ def discover(**kwargs):
return {'version': VERSION} return {'version': VERSION}
def get_stripe(sid):
for s in stripes:
if s.id == sid:
return s
def get_controller(cid):
for c in controller:
if c.id == cid:
return c
class LedDProtocol(asyncio.Protocol): class LedDProtocol(asyncio.Protocol):
transport = None transport = None

View File

@@ -25,6 +25,6 @@ setup(name='LedD',
license='GPLv3', license='GPLv3',
packages=['ledd'], packages=['ledd'],
install_requires=[ install_requires=[
'nose', 'spectra', 'docopt', 'jsonrpc', 'sqlalchemy', 'nose', 'spectra', 'docopt', 'jsonrpc', 'sqlalchemy', 'coloredlogs'
], ],
zip_safe=False) zip_safe=False)