Skip to content

Commit

Permalink
Merge pull request #2 from OpenVoiceOS/bug/4-6-8mic_leds
Browse files Browse the repository at this point in the history
Fix: not displaying on 4/6/8 mic HAT's
  • Loading branch information
builderjer authored Jun 8, 2024
2 parents a408b34 + 9e376f6 commit 46b0bc7
Show file tree
Hide file tree
Showing 9 changed files with 453 additions and 189 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/license_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
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
with:
system_deps: python3-lgpio liblgpio-dev
pip_packages: wheel
5 changes: 3 additions & 2 deletions readme.md → README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
Expand All @@ -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.
118 changes: 69 additions & 49 deletions ovos_PHAL_plugin_dotstar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,43 @@
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
from ovos_plugin_manager.templates.phal import PHALValidator
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
Expand All @@ -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")
Expand All @@ -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
Expand Down
Loading

0 comments on commit 46b0bc7

Please sign in to comment.