From 9d6dc0d99b3974c68223e978cbef7a7c0beecece Mon Sep 17 00:00:00 2001 From: aniongithub Date: Mon, 23 Aug 2021 10:32:11 -0700 Subject: [PATCH] Working template for rhasspy based voice-assistant without any site-specific settings --- .env | 2 +- .github/workflows/manual.yml | 2 +- .github/workflows/release.yml | 6 +-- .vscode/settings.json | 5 +++ README.md | 40 ++--------------- configuration.yaml | 11 +++++ etc/rhasspy/bootstrap.conf | 4 ++ etc/rhasspy/bootstrap.sh | 45 +++++++++++++++++++ etc/rhasspy/docker-compose.yaml | 22 +++++++++ .../init.d/00-install-respeaker-driver | 13 ++++++ etc/rhasspy/init.d/01-docker-pull | 3 ++ etc/rhasspy/init.d/02-heartbeat-init | 2 + etc/rhasspy/init.d/03-docker-compose-up | 3 ++ etc/rhasspy/shutdown.d/00-docker-compose-down | 2 + etc/rhasspy/shutdown.d/01-heartbeat-shutdown | 2 + etc/systemd/system/rhasspy.service | 16 +++++++ bootstrap.Pifile => rhasspy.Pifile | 20 ++++++++- 17 files changed, 155 insertions(+), 43 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 configuration.yaml create mode 100644 etc/rhasspy/bootstrap.conf create mode 100755 etc/rhasspy/bootstrap.sh create mode 100644 etc/rhasspy/docker-compose.yaml create mode 100755 etc/rhasspy/init.d/00-install-respeaker-driver create mode 100755 etc/rhasspy/init.d/01-docker-pull create mode 100755 etc/rhasspy/init.d/02-heartbeat-init create mode 100755 etc/rhasspy/init.d/03-docker-compose-up create mode 100755 etc/rhasspy/shutdown.d/00-docker-compose-down create mode 100755 etc/rhasspy/shutdown.d/01-heartbeat-shutdown create mode 100644 etc/systemd/system/rhasspy.service rename bootstrap.Pifile => rhasspy.Pifile (62%) diff --git a/.env b/.env index 1958722..b61f6c9 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ # Initialize any environment variables here # Note that env. substitution takes place on the host. -BOOTSTRAP_HOSTNAME="pi-bootstrap" +BOOTSTRAP_HOSTNAME="rhasspy" diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index b98307c..665e0a0 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -5,7 +5,7 @@ on: inputs: pifile: description: "path/to/pifile (without extension)" - default: bootstrap + default: rhasspy required: true jobs: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 41518f5..3a200a6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,17 +18,17 @@ jobs: - name: Write secrets.env env: SECRETS: ${{ secrets.SECRETS_ENV }} - PIFILE: bootstrap.Pifile + PIFILE: rhasspy.Pifile run: | echo $SECRETS > $(dirname $PIFILE)/secrets.env - name: Build image uses: Nature40/pimod@v0.2.2 with: - pifile: bootstrap.Pifile + pifile: rhasspy.Pifile - name: Upload artifacts uses: actions/upload-artifact@v2 with: name: ${{ github.workflow }}-${{ github.event.release.tag_name }}.zip - path: bootstrap.img \ No newline at end of file + path: rhasspy.img \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a04b218 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "*.yaml": "home-assistant" + } +} \ No newline at end of file diff --git a/README.md b/README.md index 2b106fd..e8c2682 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,5 @@ -# pi-bootstrap +# rhasspy appliance -A repository that shows how to use Pi-Gen and Github Actions to create a ready-to-use Raspberry Pi image that includes connectivity to your home Wi-Fi, custom packages and build steps without opening a terminal or any manual setup. You can do all of this directly within the Github UI, which significantly lowers the barrier of entry for novice users, who don't need to understand a lot of the technical details. +A repository that shows how to use Pi-Bootstrap ready-to-use Raspberry Pi image that has Rhasspy, HomeAssistant and Node-RED ready to use as a voice assistant, including drivers for the [seeed-voicecard](https://github.com/respeaker/seeed-voicecard) based Raspberry Pi hats. -Youtube video explaining the what, why and how. - -[![Bootstrapping the Raspberry Pi using GitHub Actions](http://img.youtube.com/vi/Lc6wvHgMYH4/0.jpg)](http://www.youtube.com/watch?v=Lc6wvHgMYH4 "Bootstrapping the Raspberry Pi using GitHub Actions ") - -:gear: This repository is intended as a basic template for developers who wish to create ready-to-use bootstrap repositories meant for novice users. See [aniongithub/raspotify-appliance](https://github.com/aniongithub/raspotify-appliance) for an example of a repository meant for novice end-users to use directly - -## Module environment variables - -The table below lists variables for each module in pi-bootstrap, confidential variables are marked by 🔑 and should be set in Github repository secret ```SECRET_ENV``` (or ```secrets.env``` if developing locally) while others can be committed to git in ```.env``` - - -| Module | Variable | Description | Default | -| :--------------: | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | -| ```core``` | | Sets up core functions, software, environment, etc. Required to use pi-bootstrap modules | | -| ```hostname``` | | Changes the hostname of your Raspberry Pi | | -| | **BOOTSTRAP_HOSTNAME** | The name with which your Pi will identify itself to any networks | *pi-bootstrap* | -| ```ssh``` | | Enables SSH access | | -| ```password``` | | Changes the password for a specified user for more security | | -| | **BOOTSTRAP_USER** 🔑 | Name of the user to change the password for | *pi* | -| | **BOOTSTRAP_PASSWORD** 🔑 | The password for**${BOOTSTRAP_USER}** on the generated image | *b00tstrap* | -| ```timezone``` | | Sets the timezone of your Raspberry Pi | | -| | **BOOTSTRAP_TIMEZONE** | The[TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) (timezone) where your Raspberry Pi will run | *America/Los_Angeles* | -| ```camera``` | | Enables the Raspberry Pi camera module | | -| | **BOOTSTRAP_GPU_MEM** | Amount of GPU memory (MB) to reserve for camera operation | 128 | -| ```wifi``` | | | | -| | **BOOTSTRAP_WPA_SSID** 🔑 | SSID of your Wi-Fi network | *None* | -| | **BOOTSTRAP_WPA_PASSPHRASE** 🔑 | Passphrase of your Wi-Fi network | *None* | -| | **BOOTSTRAP_WPA_COUNTRY** | Two-character ISO-3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) for your country. | *None* | -| ```docker``` | | Sets up docker and docker-compose | | - -## Usage - -The flowchart below shows simple usage of pi-bootstrap. - -![Usage](assets/pi-bootstrap usage.svg) +:gear: This repository is intended as a template for users who wish to create ready-to-use voice assistants customized for their homes, intents, networking and hardware setup. \ No newline at end of file diff --git a/configuration.yaml b/configuration.yaml new file mode 100644 index 0000000..2260596 --- /dev/null +++ b/configuration.yaml @@ -0,0 +1,11 @@ +# assuming you have only one non-system user +homeassistant: + auth_providers: + - type: homeassistant + - type: trusted_networks + trusted_networks: + - 192.168.68.0/24 + - 127.0.0.1 + - ::1 + allow_bypass_login: true +http: diff --git a/etc/rhasspy/bootstrap.conf b/etc/rhasspy/bootstrap.conf new file mode 100644 index 0000000..6958590 --- /dev/null +++ b/etc/rhasspy/bootstrap.conf @@ -0,0 +1,4 @@ +# Any environment vars we need for our startup/shutdown steps +CONFIG_PATH= +RHASSPY_PROFILES_PATH= +HOMEASSISTANT_CONFIG_PATH= \ No newline at end of file diff --git a/etc/rhasspy/bootstrap.sh b/etc/rhasspy/bootstrap.sh new file mode 100755 index 0000000..c47cdc9 --- /dev/null +++ b/etc/rhasspy/bootstrap.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +set -e + +export SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# Ensure we're running in our current directory +pushd $SCRIPT_DIR +trap "popd; exit" INT TERM EXIT + +# Set up environment configured in our env file +# https://unix.stackexchange.com/a/79077/358706 +set -o allexport +. ./bootstrap.conf +set +o allexport + +# Parse options using getopt +# https://www.codebyamir.com/blog/parse-command-line-arguments-using-getopt +opts=$(getopt \ + --longoptions "start,stop" \ + --name "$(basename "$0")" \ + --options "" \ + -- "$@" +) +eval set --$opts + +while [[ $# -gt 0 ]]; do + case "$1" in + --start) + # Run (in lexical sort-order) all executable scripts within init.d for startup + run-parts --exit-on-error init.d + shift + ;; + + --stop) + # Run (in lexical sort-order) all executable scripts within shutdown.d for shutdown + run-parts --exit-on-error shutdown.d + shift + ;; + + *) + break + ;; + esac +done diff --git a/etc/rhasspy/docker-compose.yaml b/etc/rhasspy/docker-compose.yaml new file mode 100644 index 0000000..46a2091 --- /dev/null +++ b/etc/rhasspy/docker-compose.yaml @@ -0,0 +1,22 @@ +version: "3" +services: + nodered: + image: nodered/node-red + network_mode: host + environment: + TZ: "America/Los_Angeles" + volumes: + - /home/pi/.config/node-red:/data + - /etc/localtime:/etc/localtime:ro + - /etc/TZ:/etc/timezone:ro + - /usr/share/zoneinfo:/usr/share/zoneinfo:ro + rhasspy: + depends_on: + - nodered + image: rhasspy/rhasspy + network_mode: host + volumes: + - /home/pi/.config/rhasspy/profiles:/rhasspy/profiles + devices: + - /dev/snd:/dev/snd + entrypoint: ["/usr/lib/rhasspy/bin/rhasspy-voltron", "--user-profiles", "/rhasspy/profiles", "--profile", "en"] \ No newline at end of file diff --git a/etc/rhasspy/init.d/00-install-respeaker-driver b/etc/rhasspy/init.d/00-install-respeaker-driver new file mode 100755 index 0000000..85f503f --- /dev/null +++ b/etc/rhasspy/init.d/00-install-respeaker-driver @@ -0,0 +1,13 @@ +#!/bin/bash + +if ! lsmod | grep seeed; then + echo "Installing seeed-voicecard driver..." + export LC_ALL=C.UTF-8 + cd /usr/local/src + git clone https://github.com/HinTak/seeed-voicecard.git + cd seeed-voicecard + ./install.sh + reboot --force +else + echo "seeed-voicecard driver installed, continuing..." +fi \ No newline at end of file diff --git a/etc/rhasspy/init.d/01-docker-pull b/etc/rhasspy/init.d/01-docker-pull new file mode 100755 index 0000000..4847503 --- /dev/null +++ b/etc/rhasspy/init.d/01-docker-pull @@ -0,0 +1,3 @@ +#!/bin/bash +docker pull rhasspy/rhasspy +docker pull nodered/node-red \ No newline at end of file diff --git a/etc/rhasspy/init.d/02-heartbeat-init b/etc/rhasspy/init.d/02-heartbeat-init new file mode 100755 index 0000000..7478c86 --- /dev/null +++ b/etc/rhasspy/init.d/02-heartbeat-init @@ -0,0 +1,2 @@ +#!/bin/bash +echo heartbeat > /sys/class/leds/led0/trigger \ No newline at end of file diff --git a/etc/rhasspy/init.d/03-docker-compose-up b/etc/rhasspy/init.d/03-docker-compose-up new file mode 100755 index 0000000..a026b38 --- /dev/null +++ b/etc/rhasspy/init.d/03-docker-compose-up @@ -0,0 +1,3 @@ +#!/bin/bash +TIMEZONE="$(cat /etc/timezone)" \ + docker-compose -f ${SCRIPT_DIR}/docker-compose.yaml up \ No newline at end of file diff --git a/etc/rhasspy/shutdown.d/00-docker-compose-down b/etc/rhasspy/shutdown.d/00-docker-compose-down new file mode 100755 index 0000000..54f5dd2 --- /dev/null +++ b/etc/rhasspy/shutdown.d/00-docker-compose-down @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose -f ${SCRIPT_DIR}/docker-compose.yaml down \ No newline at end of file diff --git a/etc/rhasspy/shutdown.d/01-heartbeat-shutdown b/etc/rhasspy/shutdown.d/01-heartbeat-shutdown new file mode 100755 index 0000000..1ee6f06 --- /dev/null +++ b/etc/rhasspy/shutdown.d/01-heartbeat-shutdown @@ -0,0 +1,2 @@ +#!/bin/bash +echo none > /sys/class/leds/led0/trigger \ No newline at end of file diff --git a/etc/systemd/system/rhasspy.service b/etc/systemd/system/rhasspy.service new file mode 100644 index 0000000..d26ae17 --- /dev/null +++ b/etc/systemd/system/rhasspy.service @@ -0,0 +1,16 @@ +[Unit] +Description=Rhasspy +Requires=docker.service +After=docker.service + +[Service] +Type=forking +ExecStart=/etc/rhasspy/bootstrap.sh --start +ExecStop=/etc/rhasspy/bootstrap.sh --stop +Restart=on-failure +RestartSec=5s +User=root +TimeoutSec=900 + +[Install] +WantedBy=sysinit.target \ No newline at end of file diff --git a/bootstrap.Pifile b/rhasspy.Pifile similarity index 62% rename from bootstrap.Pifile rename to rhasspy.Pifile index 8dc396e..0b8e9c4 100644 --- a/bootstrap.Pifile +++ b/rhasspy.Pifile @@ -21,4 +21,22 @@ source modules/timezone.Pifile # BOOTSTRAP_WPA_SSID, BOOTSTRAP_WPA_PASSPHRASE and BOOTSTRAP_WPA_COUNTRY (defaults: None) # Note: all 3 vars need to be set, otherwise wpa_supplicant.conf will not be generated # and Wi-Fi will be blocked with rfkill -source modules/wifi.Pifile \ No newline at end of file +source modules/wifi.Pifile + +# Increase side of our image to accomodate installs +PUMP 500M + +# Set up docker and docker-compose +source modules/docker.Pifile + +# Install Rhasspy and Node-RED as a docker-compose file managed by a systemd unit +INSTALL etc /etc +RUN systemctl enable rhasspy.service + +# Create empty config dirs accessible to the pi user +RUN install -d -m 0755 -o pi \ + /home/pi/.config/ \ + /home/pi/.config/rhasspy \ + /home/pi/.config/rhasspy/profiles \ + /home/pi/.config/rhasspy/profiles/en +RUN install -d -m 0755 -o pi /home/pi/.config /home/pi/.config/node-red \ No newline at end of file