From e3e03884890e1f781333c3f4092855a0c1a16904 Mon Sep 17 00:00:00 2001 From: builderjer Date: Sat, 8 Jun 2024 08:48:59 -0600 Subject: [PATCH 1/5] Fix: ReSpeaker 4/6/8 mic leds Multiple animations --- .github/workflows/license_test.yml | 10 + readme.md => README.md | 5 +- ovos_PHAL_plugin_dotstar/__init__.py | 118 ++++---- ovos_PHAL_plugin_dotstar/animations.py | 307 +++++++++++++++++++++ ovos_PHAL_plugin_dotstar/boards.py | 16 -- ovos_PHAL_plugin_dotstar/leds.py | 41 +++ ovos_PHAL_plugin_dotstar/light_patterns.py | 120 -------- requirements.txt | 5 + setup.py | 17 +- 9 files changed, 450 insertions(+), 189 deletions(-) create mode 100644 .github/workflows/license_test.yml rename readme.md => README.md (95%) create mode 100644 ovos_PHAL_plugin_dotstar/animations.py delete mode 100644 ovos_PHAL_plugin_dotstar/boards.py create mode 100644 ovos_PHAL_plugin_dotstar/leds.py delete mode 100644 ovos_PHAL_plugin_dotstar/light_patterns.py diff --git a/.github/workflows/license_test.yml b/.github/workflows/license_test.yml new file mode 100644 index 0000000..72326c5 --- /dev/null +++ b/.github/workflows/license_test.yml @@ -0,0 +1,10 @@ +name: Run License Tests +on: + push: + workflow_dispatch: + pull_request: + branches: + - dev +jobs: + license_tests: + uses: openvoiceos/.github/.github/workflows/license_tests.yml@feat/shared_actions1 diff --git a/readme.md b/README.md similarity index 95% rename from readme.md rename to README.md index 58e06a0..4a49978 100644 --- a/readme.md +++ b/README.md @@ -43,7 +43,7 @@ Add the following to your `~/.config/mycroft/mycroft.conf` file { "PHAL": { "ovos-PHAL-plugin-dotstar": { - "dotstar_hat": "ADAFRUIT2" + "dotstar_hat": "ADAFRUIT2MIC" } } } @@ -62,8 +62,9 @@ There are two pre-existing plugins that either need uninstalled with pip, or bla ### TODO -- [ ] Add more animations +- [x] Add more animations - [ ] User configurable colors +- [ ] 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 dd3d5c8..45f24c1 100644 --- a/ovos_PHAL_plugin_dotstar/__init__.py +++ b/ovos_PHAL_plugin_dotstar/__init__.py @@ -4,6 +4,9 @@ from time import sleep from adafruit_dotstar import DotStar +import board +from gpiozero import LED +from RPi.GPIO import cleanup from ovos_bus_client.message import Message from ovos_plugin_manager.phal import PHALPlugin @@ -11,31 +14,33 @@ from ovos_utils.log import LOG from ovos_config.config import Configuration -from ovos_PHAL.detection import is_respeaker_2mic, is_respeaker_4mic, is_respeaker_6mic +from ovos_i2c_detection import is_wm8960, is_respeaker_4mic, is_respeaker_6mic 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.boards import RESPEAKER2MIC, RESPEAKER4_6_8MIC, ADAFRUIT2MIC +from ovos_PHAL_plugin_dotstar.leds import DotStarLed +from ovos_PHAL_plugin_dotstar.animations import animations -from ovos_PHAL_plugin_dotstar.light_patterns import BreathAnimation , ChaseAnimation +# File defined in ovos-i2csound +# https://github.com/OpenVoiceOS/ovos-i2csound/blob/dev/ovos-i2csound#L76 +I2C_PLATFORM_FILE = "/etc/OpenVoiceOS/i2c_platform" - -I2C_PLATFORM_FILE = "/home/ovos/.config/mycroft/i2c_platform" - -PREDEFINED_CARDS = { - "WM8960": RESPEAKER2MIC, - "RESPEAKER4": RESPEAKER4_6_8MIC, - "RESPEAKER6": RESPEAKER4_6_8MIC, - "ADAFRUIT2": ADAFRUIT2MIC +PREDEFINED_HATS = { + "WM8960": DotStar(board.D11, board.D10, 3, brightness=0.2), + "RESPEAKER4": DotStar(board.D11, board.D10, 12, brightness=0.2), + "RESPEAKER6": DotStar(board.D11, board.D10, 12, brightness=0.2), + "ADAFRUIT2MIC": DotStar(board.D6, board.D5, 3, brightness=0.2) } def check_i2c_platform(): if exists(I2C_PLATFORM_FILE): with open(I2C_PLATFORM_FILE, "r") as f: - platform = f.readline().strip().lower() - if platform in PREDEFINED_CARDS: + platform = f.readline().strip() + LOG.debug(f"platform in check_i2c_platform: {platform}") + if platform in PREDEFINED_HATS: LOG.debug(f"detected {platform} in i2c_platform") return platform return None @@ -49,14 +54,8 @@ def validate(config=None): if config.get("enabled"): LOG.debug("user enabled") return True - # Check for a file created by ovos-i2csound - # https://github.com/OpenVoiceOS/ovos-i2csound/blob/dev/ovos-i2csound#L76 - LOG.debug(f"checking file {I2C_PLATFORM_FILE}") - if check_i2c_platform(): - LOG.debug("checking i2c_platform") - return True # Try a direct hardware check - if is_respeaker_2mic() or is_respeaker_4mic() or is_respeaker_6mic(): + if is_wm8960() or is_respeaker_4mic() or is_respeaker_6mic(): LOG.debug("direct hardware check") return True LOG.debug("no validation") @@ -74,55 +73,76 @@ class DotStarLedControlPlugin(PHALPlugin): def __init__(self, bus=None, config=None): super().__init__(bus=bus, name="ovos-PHAL-plugin-dotstar", config=config) - self.leds = [] + self._enable_pin = None self.active_animation = None self.ds = None # Check and see if there is a configuration for a specific board - if self.config.get("dotstar_hat") and self.config.get("dotstar_hat") in PREDEFINED_CARDS: - LOG.debug(f"loading {self.config.get('dotstar_hat')}") - self.ds = PREDEFINED_CARDS[self.config.get("dotstar_hat")] - - try: - self.ds = PREDEFINED_CARDS[check_i2c_platform()] - except KeyError as e: - LOG.error(e) - except Exception as e: - LOG.error(e) - finally: - if not self.ds: - self.ds = RESPEAKER4_6_8MIC - - LOG.debug("Show activation lights") - self.ds.fill(Color.from_description("mycroft blue").rgb255) + if self.config.get("dotstar_hat"): + ds = self.config.get("dotstar_hat") + if ds in PREDEFINED_HATS: + LOG.debug(f"loading {ds} from config") + try: + self.ds = DotStarLed(PREDEFINED_HATS[ds]) + except Exception as e: + LOG.error(f"Could not load {ds} from config: {e}") + elif isinstance(self.config.get("dotstar_hat"), dict): + try: + self.ds = DotStar( + ds["clock_pin"], ds["led_pin"], ds["num_led"], brightness=ds.get("brightness", 0.2)) + self._enable_pin = ds.get("enable_pin", None) + except Exception as e: + LOG.error(f"Could not create led array: {e}") + else: + try: + self.ds = DotStarLed(PREDEFINED_HATS[check_i2c_platform()]) + except KeyError as e: + LOG.debug(f"check_i2c_platform failed {e}") + except Exception as e: + LOG.error(e) + # No manual configuration and i2csound is not installed or failed + if not self.ds: + # Direct hardware checks + if is_wm8960: + self.ds = DotStarLed(PREDEFINED_HATS["WM8960"]) + elif is_respeaker_4mic: + self.ds = DotStarLed(PREDEFINED_HATS["RESPEAKER4"]) + elif is_respeaker_6mic: + self.ds = DotStarLed(PREDEFINED_HATS["RESPEAKER6"]) + # All else fails, fall back to respeker 4mic + else: + self.ds = DotStarLed(PREDEFINED_HATS["RESPEAKER4"]) + + # Required for ReSpeaker 4/6/8 mic + if not is_wm8960(): + LOG.debug("enable LED's") + cleanup(5) + self._enable_pin = LED(5) + self._enable_pin.on() + + self.ds.fill(Color.from_description("Mycroft blue").rgb255) sleep(1.0) self.on_reset() def on_record_begin(self, message=None): - LOG.debug("recording begin") - self.active_animation = BreathAnimation( - self.ds, Color.from_description("mycroft blue").rgb255) - self.active_animation.run() + self.active_animation = animations["breathe"]( + self.ds, Color.from_description("mycroft blue")) + self.active_animation.start() def on_record_end(self, message=None): - LOG.debug("record end") self.on_reset() def on_audio_output_start(self, message=None): - # for led in self.ds: - LOG.debug("I am talking") - self.active_animation = ChaseAnimation( - self.ds, Color.from_description("mycroft blue").rgb255) - self.active_animation.run() + self.active_animation = animations["blink"]( + self.ds, Color.from_description("mycroft blue"), repeat=True) + self.active_animation.start() def on_audio_output_end(self, message=None): - LOG.debug("done talking") self.on_reset() def on_think(self, message=None): self.on_reset() def on_reset(self, message=None): - LOG.debug("resetting") if self.active_animation: self.active_animation.stop() self.active_animation = None diff --git a/ovos_PHAL_plugin_dotstar/animations.py b/ovos_PHAL_plugin_dotstar/animations.py new file mode 100644 index 0000000..a581188 --- /dev/null +++ b/ovos_PHAL_plugin_dotstar/animations.py @@ -0,0 +1,307 @@ +from abc import abstractmethod +from threading import Event + +from ovos_utils.log import LOG +from time import time +from typing import Optional + +from lingua_franca.util.colors import Color +from lingua_franca.internal import load_language + +from ovos_config.config import Configuration + +from ovos_PHAL_plugin_dotstar.leds import DotStarLed + + +class LedAnimation: + def __init__(self, leds: DotStarLed, **kwargs): + self.leds = leds + self._delay = Event() + # Needed for lingua_franca + self._lang = Configuration().get("lang", "en") + load_language(self._lang) + + @abstractmethod + def start(self, timeout: Optional[int] = None, one_shot: bool = False): + """ + Start the animation. + :param timeout: Optional timeout in seconds after which animation stops + :param one_shot: if True, run animation once and return + """ + + @abstractmethod + def stop(self): + """ + Stop the animation and reset LEDs to black. + """ + + +class BreatheLedAnimation(LedAnimation): + def __init__(self, leds: DotStarLed, color: Color): + """ + Breathing effect where all LEDs dim up and down until timing out + or being stopped. LEDs are turned off after animation. + @param leds: LED object to interact with + @param color: Base color of LEDs + """ + LedAnimation.__init__(self, leds) + self.color = color + self.step = 0.1 + self.step_delay = 0.1 + self.stopping = Event() + + def start(self, timeout=None, one_shot=False): + self.stopping.clear() + end_time = time() + timeout if timeout else None + brightness = 0 + step = self.step + ending = False + while not self.stopping.is_set(): + if brightness >= 1: # Going Down + step = -1 * self.step + elif brightness <= 0: + step = self.step + + brightness += step + brightness = round(brightness, 1) + self.leds.fill(self.color.rgb255 + (brightness,)) + self._delay.wait(self.step_delay) + if one_shot and brightness >= 1: + ending = True + elif ending and brightness <= 0: + self.stopping.set() + elif end_time and time() > end_time: + self.stopping.set() + self.leds.fill(Color.from_description("black".rgb255)) + + def stop(self): + self.stopping.set() + + +class ChaseLedAnimation(LedAnimation): + def __init__(self, leds: DotStarLed, foreground_color: Color, + background_color: Optional[Color] = None): + """ + Chase effect where all LEDs are lit individually in order until timing + out or being stopped. LEDs are turned off after animation. + @param leds: LED object to interact with + @param foreground_color: Color of active LED + @param background_color: Color of inactive LEDs + """ + LedAnimation.__init__(self, leds) + self.foreground_color = foreground_color + self.background_color = background_color or Color.from_description( + "black") + self.step = 0.05 + self.step_delay = 0.1 + self.stopping = Event() + + def start(self, timeout=None, one_shot=False): + self.stopping.clear() + end_time = time() + timeout if timeout else None + + self.leds.fill(self.background_color.rgb255) + while not self.stopping.is_set(): + for led in range(0, self.leds.num_leds): + self.leds.set_led(led, self.foreground_color.rgb255) + self._delay.wait(self.step_delay) + self.leds.set_led(led, self.background_color.rgb255) + if one_shot: + self.stopping.set() + elif end_time and time() > end_time: + self.stopping.set() + self.leds.fill(Color.from_description("black").rgb255) + + def stop(self): + self.stopping.set() + + +class FillLedAnimation(LedAnimation): + def __init__(self, leds: DotStarLed, fill_color: Color, + reverse: bool = False): + """ + Fill effect where LEDs are set to the same color in order. LEDs will + remain lit after the animation. + @param leds: LED object to interact with + @param fill_color: Color to fill LEDs + @param reverse: If true, fill in reverse order + """ + LedAnimation.__init__(self, leds) + self.fill_color = fill_color + self.reverse = reverse + self.step_delay = 0.05 + + def start(self, timeout=None, one_shot=True): + if not one_shot or timeout is not None: + LOG.warning("Fill animation does not support persistent animation") + leds = list(range(0, self.leds.num_leds)) + if self.reverse: + leds.reverse() + for led in leds: + self.leds.set_led(led, self.fill_color.rgb255) + self._delay.wait(self.step_delay) + + def stop(self): + pass + + +class RefillLedAnimation(LedAnimation): + def __init__(self, leds: DotStarLed, fill_color: Color, + reverse: bool = False): + """ + Fill effect in the requested color, followed by fill effect in black. + Animation repeats until timing out or being stopped. LEDs are turned + off after animation. + @param leds: LED object to interact with + @param fill_color: Color to fill LEDs + @param reverse: If true, fill in reverse order + """ + LedAnimation.__init__(self, leds) + self.stopping = Event() + self.fill_color = fill_color + self.fill_animation = FillLedAnimation(leds, fill_color, reverse) + + def start(self, timeout=None, one_shot=False): + self.stopping.clear() + end_time = time() + timeout if timeout else None + + while not self.stopping.is_set(): + self.fill_animation.start() + self.fill_animation.fill_color = Color.from_description("black") + self.fill_animation.start() + self.fill_animation.fill_color = self.fill_color + if one_shot: + self.stopping.set() + elif end_time and time() > end_time: + self.stopping.set() + + def stop(self): + self.stopping.set() + + +class BounceLedAnimation(LedAnimation): + def __init__(self, leds: DotStarLed, fill_color: Color, + reverse: bool = False): + """ + Fill effect in the requested color, followed by reversed fill effect + in black. Animation repeats until timing out or being stopped. + LEDs are turned off after animation. + @param leds: LED object to interact with + @param fill_color: Color to fill LEDs + @param reverse: If true, fill in reverse order + """ + LedAnimation.__init__(self, leds) + self.stopping = Event() + self.fill_color = fill_color + self.fill_animation = FillLedAnimation(leds, fill_color, reverse) + + def start(self, timeout=None, one_shot=False): + self.stopping.clear() + end_time = time() + timeout if timeout else None + + while not self.stopping.is_set(): + self.fill_animation.start() + self.fill_animation.reverse = not self.fill_animation.reverse + self.fill_animation.fill_color = Color.from_description("black") + self.fill_animation.start() + self.fill_animation.reverse = not self.fill_animation.reverse + self.fill_animation.fill_color = self.fill_color + if one_shot: + self.stopping.set() + elif end_time and time() > end_time: + self.stopping.set() + + def stop(self): + self.stopping.set() + + +class BlinkLedAnimation(LedAnimation): + def __init__(self, leds: DotStarLed, color: Color, + num_blinks: int = 2, repeat: bool = False): + """ + Blink LEDs in the requested color, for the requested number of blinks. + If repeating, pause and repeat the effect until timeout or stop event. + @param leds: LED object to interact with + @param color: Color to blink LEDs + @param num_blinks: Number of times to blink LEDs + @param repeat: If true, repeat animation until timeout or stopped + """ + LedAnimation.__init__(self, leds) + self.stopping = Event() + self.color = color + self.num_blinks = num_blinks + self.repeat = repeat + + def start(self, timeout=None, one_shot=False): + self.stopping.clear() + end_time = time() + timeout if timeout else None + + self.leds.fill(Color.from_description("black").rgb255) + self._delay.wait(0.25) + while not self.stopping.is_set(): + for i in range(self.num_blinks): + self.leds.fill(self.color.rgb255) + self._delay.wait(0.1) + self.leds.fill(Color.from_description("black").rgb255) + self._delay.wait(0.1) + if one_shot: + self.stopping.set() + elif self.repeat: + self._delay.wait(.2) + else: + self.stopping.set() + if end_time and time() > end_time: + self.stopping.set() + + def stop(self): + self.stopping.set() + + +class AlternatingLedAnimation(LedAnimation): + def __init__(self, leds: DotStarLed, color: Color): + """ + Show alternating even/odd LEDs + @param leds: LED object to interact with + @param color: Color to blink LEDs + """ + LedAnimation.__init__(self, leds) + self.stopping = Event() + self.color = color + self.delay = 0.5 + + def start(self, timeout: Optional[int] = None, one_shot: bool = False): + evens = True + self.leds.fill(Color.from_description("black").rgb255) + self.stopping.clear() + end_time = time() + timeout if timeout else None + while not self.stopping.is_set(): + for led in range(self.leds.num_leds): + if evens and led % 2 == 0: + self.leds.set_led(led, self.color.rgb255, False) + elif not evens and led % 2 == 1: + self.leds.set_led(led, self.color.rgb255, False) + else: + self.leds.set_led( + led, Color.from_description("black").rgb255, False) + # self.leds.show() + self._delay.wait(self.delay) + evens = not evens + if one_shot and evens: # We did one animation + self.stopping.set() + elif end_time and time() > end_time: + self.stopping.set() + self.leds.fill(Color.from_description("black").rgb255) + + def stop(self): + self.stopping.set() + + +animations = { + 'breathe': BreatheLedAnimation, + 'chase': ChaseLedAnimation, + 'fill': FillLedAnimation, + 'refill': RefillLedAnimation, + 'bounce': BounceLedAnimation, + 'blink': BlinkLedAnimation, + 'alternating': AlternatingLedAnimation +} \ No newline at end of file diff --git a/ovos_PHAL_plugin_dotstar/boards.py b/ovos_PHAL_plugin_dotstar/boards.py deleted file mode 100644 index 62ca4dc..0000000 --- a/ovos_PHAL_plugin_dotstar/boards.py +++ /dev/null @@ -1,16 +0,0 @@ -from adafruit_dotstar import DotStar -import board - -RESPEAKER2MIC = DotStar(board.D11, board.D10, 3, brightness=0.2) -RESPEAKER4_6_8MIC = DotStar(board.D11, board.D10, 12, brightness=0.2) -# RESPEAKER6MIC = DotStar(board.D11, board.D12, 12, brightness=0.2) - -ADAFRUIT2MIC = DotStar(board.D6, board.D5, 3, brightness=0.2) - -preconfig_boards = { - "wm8960": [RESPEAKER2MIC], # ADAFRUIT2MIC], - "respeaker2mic": RESPEAKER2MIC, - "respeaker4mic": RESPEAKER4_6_8MIC, - "respeaker6mic": RESPEAKER4_6_8MIC, - "respeaker8mic": RESPEAKER4_6_8MIC, - "adafruit2mic": ADAFRUIT2MIC} diff --git a/ovos_PHAL_plugin_dotstar/leds.py b/ovos_PHAL_plugin_dotstar/leds.py new file mode 100644 index 0000000..8cf323e --- /dev/null +++ b/ovos_PHAL_plugin_dotstar/leds.py @@ -0,0 +1,41 @@ +from abc import abstractmethod + +from adafruit_dotstar import DotStar +import board + +from ovos_plugin_manager.hardware.led import AbstractLed + + +class DotStarLed(AbstractLed): + def __init__(self, dotstar_led_strip: DotStar): + self.dotstar = dotstar_led_strip + + @property + def num_leds(self): + return self.dotstar.n + + @property + def capabilities(self): + pass + + def set_led(self, led_idx: int, color: tuple, immediate: bool = True): + self.dotstar[led_idx] = color + + def fill(self, color: tuple): + self.dotstar.fill(color) + + def show(self): + self.dotstar.show() + + def shutdown(self): + # TODO: something + pass + + def scale_brightness(color_val: int, bright_val: float) -> float: + """ + Scale an individual color value by a specified brightness. + :param color_val: 0-255 R, G, or B value + :param bright_val: 0.0-1.0 brightness scalar value + :returns: Float modified color value to account for brightness + """ + return min(255.0, round(color_val * bright_val)) diff --git a/ovos_PHAL_plugin_dotstar/light_patterns.py b/ovos_PHAL_plugin_dotstar/light_patterns.py deleted file mode 100644 index 9dba7f1..0000000 --- a/ovos_PHAL_plugin_dotstar/light_patterns.py +++ /dev/null @@ -1,120 +0,0 @@ -from enum import Enum - -from queue import Queue -from threading import Thread, Event -from time import sleep, time - -from lingua_franca.util.colors import Color -from lingua_franca.internal import load_language - -from ovos_config.config import Configuration -from ovos_utils.log import LOG - - -class Animation(): - def __init__(self, speed: float = 0.1, timeout: int = None, one_shot: bool = False): - self._lang = Configuration().get("lang", "en") - load_language(self._lang) - self._speed = speed - self._timeout = timeout - self._one_shot = one_shot - self._delay = Event() - self.alive = True - self.daemon = True - - @property - def speed(self): - return self._speed - - @speed.setter - def speed(self, speed: float): - self._speed = speed - - def run(self): - """Override this method for each animation""" - - def stop(self): - """Override this method for each animation""" - - -class BreathAnimation(Animation): - def __init__(self, led_strip, color: tuple, step: float = 0.1): - """led_strip -> adifruit.DotStar""" - self._led_strip = led_strip - self._color = color - self._step = step - self.stopping = Event() - super().__init__() - - def run(self): - LOG.debug("BreathAnimation running") - ending = False - try: - self.stopping.clear() - step = self._step - brightness = 1.0 - self._led_strip.fill(self._color) - end_time = time() + self._timeout if self._timeout else None - while not self.stopping.is_set(): - if brightness >= 1.0: - step = -1 * self._step - LOG.debug(f"going down: {step}") - if brightness <= 0.1: - step = self._step - LOG.debug(f"going up: {step}") - brightness += step - brightness = round(brightness, 1) - color = self._color + (brightness,) - self._led_strip.fill(color) - self._delay.wait(self.speed) - if self._one_shot and brightness >= 1.0: - ending = True - if ending and brightness <= 0.1: - self.stopping.set() - if end_time and end_time >= time(): - self.stopping.set() - except Exception as e: - LOG.error(f"could not run BreathAnimation: {e}") - - def stop(self): - self.stopping.set() - self._delay.set() - - -class ChaseAnimation(Animation): - def __init__(self, led_strip, fg_color: tuple, bg_color: tuple = None, reverse: bool = False): - self._led_strip = led_strip - self._fg_color = fg_color - self._bg_color = bg_color or Color.from_description("black").rgb255 - self._reverse = reverse - self.stopping = Event() - super().__init__() - - def run(self): - LOG.debug("ChaseAnimation running") - ending = False - try: - self.stopping.clear() - self._led_strip.fill(self._bg_color) - end_time = time() + self._timeout if self._timeout else None - while not self.stopping.is_set(): - leds = list(range(0, self._led_strip.n)) - if self._reverse: - leds.reverse() - for led in leds: - self._led_strip[led] = self._fg_color - try: - self._led_strip[leds.index(led) - 1] = self._bg_color - except IndexError: - self._led_strip[leds[-1]] = self._bg_color - self._delay.wait(self.speed) - if self._one_shot: - self.stopping.set() - if end_time and end_time >= time(): - self.stopping.set() - except Exception as e: - LOG.error(f"Could not run ChaseAnimation: {e}") - - def stop(self): - self.stopping.set() - self._delay.set() diff --git a/requirements.txt b/requirements.txt index 00fdce9..8053ab6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,6 @@ adafruit-circuitpython-dotstar +ovos-plugin-manager>=0.0.1 +ovos-lingua-franca>=0.4.8a8 +ovos-i2c-detection>=0.0.0a5 +gpiozero +rpi-lgpio diff --git a/setup.py b/setup.py index 7ffe591..2da225c 100755 --- a/setup.py +++ b/setup.py @@ -3,6 +3,8 @@ from setuptools import setup +BASEDIR = os.path.abspath(os.path.dirname(__file__)) + def package_files(directory): paths = [] @@ -12,6 +14,18 @@ def package_files(directory): return paths +def required(requirements_file): + """ Read requirements file and remove comments and empty lines. """ + with open(os.path.join(BASEDIR, requirements_file), 'r') as f: + requirements = f.read().splitlines() + if 'MYCROFT_LOOSE_REQUIREMENTS' in os.environ: + print('USING LOOSE REQUIREMENTS!') + requirements = [r.replace('==', '>=').replace( + '~=', '>=') for r in requirements] + return [pkg for pkg in requirements + if pkg.strip() and not pkg.startswith("#")] + + PLUGIN_ENTRY_POINT = 'ovos-PHAL-plugin-dotstar=ovos_PHAL_plugin_dotstar:DotStarLedControlPlugin' setup( name='ovos-PHAL-plugin-dotstar', @@ -23,8 +37,7 @@ def package_files(directory): license='MIT', packages=['ovos_PHAL_plugin_dotstar'], package_data={'': package_files('ovos_PHAL_plugin_dotstar')}, - install_requires=["ovos-plugin-manager>=0.0.1", - "adafruit-circuitpython-dotstar"], + install_requires=required("requirements.txt"), zip_safe=True, include_package_data=True, classifiers=[ From 81c611d88fb4495cea121aff695310b439fa1d8c Mon Sep 17 00:00:00 2001 From: builderjer Date: Sat, 8 Jun 2024 08:56:46 -0600 Subject: [PATCH 2/5] fix requirements.txt until new release of ovos-lingua-franca --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8053ab6..defa9c4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ adafruit-circuitpython-dotstar ovos-plugin-manager>=0.0.1 -ovos-lingua-franca>=0.4.8a8 +ovos-lingua-franca @ git+https://github.com/OpenVoiceOS/ovos-lingua-franca ovos-i2c-detection>=0.0.0a5 gpiozero rpi-lgpio From 6c989c596d0ad06bda7362660d68ff9d36ed2e70 Mon Sep 17 00:00:00 2001 From: builderjer Date: Sat, 8 Jun 2024 09:06:46 -0600 Subject: [PATCH 3/5] fix license test? --- .github/workflows/license_test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/license_test.yml b/.github/workflows/license_test.yml index 72326c5..d2a656a 100644 --- a/.github/workflows/license_test.yml +++ b/.github/workflows/license_test.yml @@ -8,3 +8,5 @@ on: jobs: license_tests: uses: openvoiceos/.github/.github/workflows/license_tests.yml@feat/shared_actions1 + with: + system_deps: python3-lgpio From 6e7251e09953d64b9132b14f2cdc6827debe8e2e Mon Sep 17 00:00:00 2001 From: builderjer Date: Sat, 8 Jun 2024 09:10:11 -0600 Subject: [PATCH 4/5] fix license test? --- .github/workflows/license_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/license_test.yml b/.github/workflows/license_test.yml index d2a656a..d5dac6b 100644 --- a/.github/workflows/license_test.yml +++ b/.github/workflows/license_test.yml @@ -10,3 +10,4 @@ jobs: uses: openvoiceos/.github/.github/workflows/license_tests.yml@feat/shared_actions1 with: system_deps: python3-lgpio + pip_packages: wheel From 9e376f62c82f700afdf8e8124185489d8303a087 Mon Sep 17 00:00:00 2001 From: builderjer Date: Sat, 8 Jun 2024 09:12:03 -0600 Subject: [PATCH 5/5] fix license test? --- .github/workflows/license_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/license_test.yml b/.github/workflows/license_test.yml index d5dac6b..7244cab 100644 --- a/.github/workflows/license_test.yml +++ b/.github/workflows/license_test.yml @@ -9,5 +9,5 @@ jobs: license_tests: uses: openvoiceos/.github/.github/workflows/license_tests.yml@feat/shared_actions1 with: - system_deps: python3-lgpio + system_deps: python3-lgpio liblgpio-dev pip_packages: wheel