Mercurial > louis > mq > lightsd
changeset 491:6b153374b871
start this python bridge between a monome and lightsd
author | Louis Opter <kalessin@kalessin.fr> |
---|---|
date | Sun, 04 Sep 2016 22:42:09 -0700 |
parents | b5efb1c879c6 |
children | 6fce645a848a |
files | add_monolight.patch series |
diffstat | 2 files changed, 182 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/add_monolight.patch Sun Sep 04 22:42:09 2016 -0700 @@ -0,0 +1,181 @@ +# HG changeset patch +# Parent 4734caf1ac9fbbb1cad0363e207b9b065db1fb57 +Start a script to control bulbs through a Monome + +diff --git a/.hgignore b/.hgignore +--- a/.hgignore ++++ b/.hgignore +@@ -2,3 +2,4 @@ + .*\.py[co]$ + ^build + ^pcaps ++.*\.egg-info$ +diff --git a/monolight/monolight/__init__.py b/monolight/monolight/__init__.py +new file mode 100644 +diff --git a/monolight/monolight/cli.py b/monolight/monolight/cli.py +new file mode 100644 +--- /dev/null ++++ b/monolight/monolight/cli.py +@@ -0,0 +1,85 @@ ++import asyncio ++import click ++import locale ++import monome ++import os ++import subprocess ++import random ++ ++ENCODING = locale.getpreferredencoding() ++ ++ ++FADERS_MAX_VALUE = 100 ++ ++ ++class Faders(monome.Monome): ++ def __init__(self): ++ super().__init__('/faders') ++ ++ def ready(self): ++ self.led_all(0) ++ self.led_row(0, self.height - 1, [1] * self.width) ++ ++ self.row_values = [] ++ row_value = 0 ++ for i in range(self.height): ++ self.row_values.append(int(round(row_value))) ++ row_value += FADERS_MAX_VALUE / (self.height - 1) ++ ++ self.values = [random.randint(0, FADERS_MAX_VALUE) for f in range(self.width)] ++ self.faders = [asyncio.async(self.fade_to(f, 0)) for f in range(self.width)] ++ ++ def grid_key(self, x, y, s): ++ if s == 1: ++ self.faders[x].cancel() ++ self.faders[x] = asyncio.async(self.fade_to(x, self.row_to_value(y))) ++ ++ def value_to_row(self, value): ++ return sorted([ ++ i for i in range(self.height)], ++ key=lambda i: abs(self.row_values[i] - value) ++ )[0] ++ ++ def row_to_value(self, row): ++ return self.row_values[self.height - 1 - row] ++ ++ @asyncio.coroutine ++ def fade_to(self, x, new_value): ++ while self.values[x] != new_value: ++ if self.values[x] < new_value: ++ self.values[x] += 1 ++ else: ++ self.values[x] -= 1 ++ col = [0 if c > self.value_to_row(self.values[x]) else 1 for c in range(self.height)] ++ col.reverse() ++ self.led_col(x, 0, col) ++ yield from asyncio.sleep(1/100) ++ ++ ++def get_lightsd_rundir(): ++ try: ++ lightsdrundir = subprocess.check_output(["lightsd", "--rundir"]) ++ except Exception as ex: ++ click.echo( ++ "Couldn't infer lightsd's runtime directory, is lightsd installed? " ++ "({})\nTrying build/socket…".format(ex), ++ err=True ++ ) ++ lightscdir = os.path.realpath(__file__).split(os.path.sep)[:-2] ++ lightsdrundir = os.path.join(*[os.path.sep] + lightscdir + ["build"]) ++ else: ++ lightsdrundir = lightsdrundir.decode(ENCODING).strip() ++ ++ return lightsdrundir ++ ++LIGHTSD_SOCKET = "unix://" + os.path.join(get_lightsd_rundir(), "socket") ++ ++ ++@click.command() ++@click.option("--serialoscd-host", default="127.0.0.1") ++@click.option("--serialoscd-port", type=click.IntRange(0, 2**16 - 1)) ++@click.option("--lightsd-url", default=LIGHTSD_SOCKET) ++def main(serialoscd_host, serialoscd_port, lightsd_url): ++ loop = asyncio.get_event_loop() ++ asyncio.async(monome.create_serialosc_connection(Faders), loop=loop) ++ loop.run_forever() +diff --git a/monolight/monolight/lightsc.py b/monolight/monolight/lightsc.py +new file mode 100644 +--- /dev/null ++++ b/monolight/monolight/lightsc.py +@@ -0,0 +1,16 @@ ++# Copyright (c) 2016, Louis Opter <louis@opter.org> ++# ++# This file is part of lighstd. ++# ++# lighstd 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. ++# ++# lighstd 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 lighstd. If not, see <http://www.gnu.org/licenses/>. +diff --git a/monolight/setup.py b/monolight/setup.py +new file mode 100644 +--- /dev/null ++++ b/monolight/setup.py +@@ -0,0 +1,51 @@ ++# Copyright (c) 2016, Louis Opter <louis@opter.org> ++# ++# This file is part of lighstd. ++# ++# lighstd 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. ++# ++# lighstd 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 lighstd. If not, see <http://www.gnu.org/licenses/>. ++ ++import setuptools ++ ++version = "0.0.1.dev0" ++ ++setuptools.setup( ++ name="monolight", ++ version=version, ++ description="A Monome UI to control smart bulbs using lightsd", ++ author="Louis Opter", ++ author_email="louis@opter.org", ++ packages=setuptools.find_packages(exclude=['tests', 'tests.*']), ++ include_package_data=True, ++ entry_points={ ++ "console_scripts": [ ++ "monolight = monolight.cli:main", ++ ], ++ }, ++ install_requires=[ ++ "click~=6.6", ++ "pymonome~=0.8.2", ++ ], ++ tests_require=[ ++ "doubles~=1.1.3", ++ "freezegun~=0.3.5", ++ "pytest~=3.0", ++ ], ++ extras_require={ ++ "dev": [ ++ "flake8", ++ "pdbpp", ++ "pep8", ++ ], ++ }, ++)