diff --git a/.github/workflows/license_test.yml b/.github/workflows/license_test.yml index 7244cab..d105ce0 100644 --- a/.github/workflows/license_test.yml +++ b/.github/workflows/license_test.yml @@ -9,5 +9,4 @@ jobs: license_tests: uses: openvoiceos/.github/.github/workflows/license_tests.yml@feat/shared_actions1 with: - system_deps: python3-lgpio liblgpio-dev pip_packages: wheel diff --git a/README.md b/README.md index 4a49978..e84fa36 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,60 @@ And restart OVOS Your LED's on your Adafruit voicebonnet will now show the same prompts as the ReSpeaker devices. +## Custom Configuration + +Colors and animations can be configured in `~/.config/mycroft/mycroft.conf` + +```json +{ + "PHAL": { + "ovos-PHAL-plugin-dotstar": { + "main_color": "Mycroft blue", + "background_color": "OVOS red", + "listen_animation": "breath", + "talking_animation": "blink" + } + } +} +``` + +`main_color` -> str: +``` + rgb value -> "32, 195, 63" + name -> "blue" + hex value -> "#22A7F0" +``` + +`background_color` -> str +``` + rgb value -> "32, 195, 63" + name -> "red" + hex value -> "#FF1A1A" +``` + +`listen_animation` -> str: +``` + one of: + 'breathe' + 'chase' + 'fill' + 'refill' + 'bounce' + 'blink' + 'alternating' +``` + +`talking_animation` -> str: +``` + one of: + 'breathe' + 'chase' + 'fill' + 'refill' + 'bounce' + 'blink' + 'alternating' +``` ## Conflicts With There are two pre-existing plugins that either need uninstalled with pip, or blacklisted in your `mycroft.conf` file. @@ -63,8 +117,9 @@ There are two pre-existing plugins that either need uninstalled with pip, or bla ### TODO - [x] Add more animations -- [ ] User configurable colors -- [ ] User configurable animations +- [x] User configurable colors +- [ ] Theme support +- [x] User configurable animations - [ ] Add github tests and automation Please enjoy this plugin and don't be afraid to create an [issue](#) if you run into any problems. diff --git a/ovos_PHAL_plugin_dotstar/__init__.py b/ovos_PHAL_plugin_dotstar/__init__.py index 45f24c1..90a66a5 100644 --- a/ovos_PHAL_plugin_dotstar/__init__.py +++ b/ovos_PHAL_plugin_dotstar/__init__.py @@ -19,7 +19,6 @@ from lingua_franca.util.colors import Color from lingua_franca.internal import load_language -# from ovos_PHAL_plugin_dotstar.boards import RESPEAKER2MIC, RESPEAKER4_6_8MIC, ADAFRUIT2MIC from ovos_PHAL_plugin_dotstar.leds import DotStarLed from ovos_PHAL_plugin_dotstar.animations import animations @@ -119,21 +118,75 @@ def __init__(self, bus=None, config=None): self._enable_pin = LED(5) self._enable_pin.on() - self.ds.fill(Color.from_description("Mycroft blue").rgb255) + self.ds.fill(self.main_color.rgb255) sleep(1.0) self.on_reset() + @property + def main_color(self): + color = self.config.get( + "main_color", Color.from_description("Mycroft blue")) + if isinstance(color, str): + try: + color = eval(color) + color = Color.from_rgb(color[0], color[1], color[2]) + except Exception as e: + LOG.debug(f"Exception caught in eval {e}") + try: + LOG.debug(color) + color = Color.from_hex(color) + LOG.debug(color) + except Exception as e: + LOG.debug(f"Exception caught in description {e}") + try: + color = Color.from_description(color) + except Exception as e: + LOG.warning(f"could not set color to {color}: {e}") + color = Color.from_description("Mycroft blue") + return color + + @property + def background_color(self): + color = self.config.get( + "background_color", Color.from_description("OVOS red")) + if isinstance(color, str): + try: + color = eval(color) + color = Color.from_rgb(color[0], color[1], color[2]) + except Exception as e: + LOG.debug(f"Exception caught in eval {e}") + try: + color = Color.from_description(color) + except Exception as e: + LOG.debug(f"Exception caught in description {e}") + try: + color = Color.from_hex(color) + except Exception as e: + LOG.warning(f"could not set color to {color}: {e}") + color = Color.from_description("OVOS red") + return color + + @property + def listen_animation(self): + return self.config.get("listen_animation", "breathe") + + @property + def talking_animation(self): + return self.config.get("talking_animation", "blink") + def on_record_begin(self, message=None): - self.active_animation = animations["breathe"]( - self.ds, Color.from_description("mycroft blue")) + self.active_animation = animations[self.listen_animation]( + self.ds, self.main_color) self.active_animation.start() def on_record_end(self, message=None): self.on_reset() def on_audio_output_start(self, message=None): - self.active_animation = animations["blink"]( - self.ds, Color.from_description("mycroft blue"), repeat=True) + LOG.debug(animations[self.talking_animation]) + self.active_animation = animations[self.talking_animation]( + self.ds, self.main_color, repeat=True) + LOG.debug(self.active_animation) self.active_animation.start() def on_audio_output_end(self, message=None): diff --git a/ovos_PHAL_plugin_dotstar/animations.py b/ovos_PHAL_plugin_dotstar/animations.py index a581188..29e44c3 100644 --- a/ovos_PHAL_plugin_dotstar/animations.py +++ b/ovos_PHAL_plugin_dotstar/animations.py @@ -37,7 +37,7 @@ def stop(self): class BreatheLedAnimation(LedAnimation): - def __init__(self, leds: DotStarLed, color: Color): + def __init__(self, leds: DotStarLed, color: Color, **kwargs): """ Breathing effect where all LEDs dim up and down until timing out or being stopped. LEDs are turned off after animation. @@ -80,7 +80,7 @@ def stop(self): class ChaseLedAnimation(LedAnimation): def __init__(self, leds: DotStarLed, foreground_color: Color, - background_color: Optional[Color] = None): + background_color: Optional[Color] = None, **kwargs): """ Chase effect where all LEDs are lit individually in order until timing out or being stopped. LEDs are turned off after animation. @@ -118,7 +118,7 @@ def stop(self): class FillLedAnimation(LedAnimation): def __init__(self, leds: DotStarLed, fill_color: Color, - reverse: bool = False): + reverse: bool = False, **kwargs): """ Fill effect where LEDs are set to the same color in order. LEDs will remain lit after the animation. @@ -147,7 +147,7 @@ def stop(self): class RefillLedAnimation(LedAnimation): def __init__(self, leds: DotStarLed, fill_color: Color, - reverse: bool = False): + reverse: bool = False, **kwargs): """ Fill effect in the requested color, followed by fill effect in black. Animation repeats until timing out or being stopped. LEDs are turned @@ -181,7 +181,7 @@ def stop(self): class BounceLedAnimation(LedAnimation): def __init__(self, leds: DotStarLed, fill_color: Color, - reverse: bool = False): + reverse: bool = False, **kwargs): """ Fill effect in the requested color, followed by reversed fill effect in black. Animation repeats until timing out or being stopped. @@ -190,6 +190,7 @@ def __init__(self, leds: DotStarLed, fill_color: Color, @param fill_color: Color to fill LEDs @param reverse: If true, fill in reverse order """ + LOG.debug("bouncing") LedAnimation.__init__(self, leds) self.stopping = Event() self.fill_color = fill_color @@ -217,7 +218,7 @@ def stop(self): class BlinkLedAnimation(LedAnimation): def __init__(self, leds: DotStarLed, color: Color, - num_blinks: int = 2, repeat: bool = False): + num_blinks: int = 2, repeat: bool = False, **kwargs): """ Blink LEDs in the requested color, for the requested number of blinks. If repeating, pause and repeat the effect until timeout or stop event. @@ -258,7 +259,7 @@ def stop(self): class AlternatingLedAnimation(LedAnimation): - def __init__(self, leds: DotStarLed, color: Color): + def __init__(self, leds: DotStarLed, color: Color, **kwargs): """ Show alternating even/odd LEDs @param leds: LED object to interact with diff --git a/requirements.txt b/requirements.txt index defa9c4..8053ab6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ adafruit-circuitpython-dotstar ovos-plugin-manager>=0.0.1 -ovos-lingua-franca @ git+https://github.com/OpenVoiceOS/ovos-lingua-franca +ovos-lingua-franca>=0.4.8a8 ovos-i2c-detection>=0.0.0a5 gpiozero rpi-lgpio