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:
21
ledd.py
21
ledd.py
@@ -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()
|
||||||
|
@@ -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)
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
2
setup.py
2
setup.py
@@ -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)
|
||||||
|
Reference in New Issue
Block a user