From f645043561ac3f402501a1c2639c27a33552e0de Mon Sep 17 00:00:00 2001 From: "derek.smithson" Date: Sat, 14 Feb 2026 17:01:47 -0700 Subject: [PATCH 1/3] fix: ensure install.sh uses LF line endings for Linux compatibility Add .gitattributes to force LF endings on shell scripts, fixing "No such file or directory" errors when running on a Raspberry Pi from a Windows-authored script. Co-Authored-By: Claude Opus 4.6 --- .gitattributes | 2 + docs/sd_card/install.sh | 266 +++++++++++++++++++++------------------- 2 files changed, 139 insertions(+), 129 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..403ff24 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Ensure shell scripts always have LF line endings, even on Windows +*.sh text eol=lf diff --git a/docs/sd_card/install.sh b/docs/sd_card/install.sh index b7b7e51..91761df 100644 --- a/docs/sd_card/install.sh +++ b/docs/sd_card/install.sh @@ -1,129 +1,137 @@ -#!/bin/bash -set -euo pipefail - -# Spyder Tally Controller - Install Script -# This script installs the Spyder Tally Controller application on a Raspberry Pi. -# It auto-detects architecture (arm64 vs arm32) and installs the correct binary. -# -# Usage: -# tar xzf spyder-tally-linux-arm64.tar.gz # (or linux-arm) -# cd spyder-tally-linux-arm64/ # (or linux-arm) -# sudo ./install.sh - -INSTALL_DIR="/opt/spyder-tally" -SERVICE_NAME="SpyderTallies" - -# --- Preflight checks --- - -if [ "$(id -u)" -ne 0 ]; then - echo "Error: This script must be run as root (use sudo ./install.sh)" - exit 1 -fi - -# Determine the real user who invoked sudo -INSTALL_USER="${SUDO_USER:-$(whoami)}" -if [ "$INSTALL_USER" = "root" ]; then - echo "Error: Please run this script with sudo from a regular user account, not as root directly." - exit 1 -fi - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" - -# --- Architecture detection --- - -ARCH="$(uname -m)" -case "$ARCH" in - aarch64) - EXPECTED_RID="linux-arm64" - ;; - armv7l|armv6l) - EXPECTED_RID="linux-arm" - ;; - *) - echo "Error: Unsupported architecture '$ARCH'. Expected aarch64 (arm64) or armv7l/armv6l (arm32)." - exit 1 - ;; -esac - -# Check that the binary in this package matches the detected architecture -if [ ! -f "$SCRIPT_DIR/bin/SpyderTallyControllerWebApp" ]; then - echo "Error: Binary not found at $SCRIPT_DIR/bin/SpyderTallyControllerWebApp" - echo "" - echo "Detected architecture: $ARCH ($EXPECTED_RID)" - echo "Make sure you downloaded the correct package for your Pi:" - echo " - Raspberry Pi 4/5 (64-bit OS): spyder-tally-linux-arm64.tar.gz" - echo " - Raspberry Pi 3 or older (32-bit OS): spyder-tally-linux-arm.tar.gz" - exit 1 -fi - -echo "=== Spyder Tally Controller Installer ===" -echo "Detected architecture: $ARCH ($EXPECTED_RID)" -echo "Installing as user: $INSTALL_USER" -echo "Install directory: $INSTALL_DIR" -echo "" - -# --- Stop existing service if running --- - -if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then - echo "Stopping existing $SERVICE_NAME service..." - systemctl stop "$SERVICE_NAME" -fi - -# --- Enable I2C --- - -echo "Enabling I2C interface..." -if command -v raspi-config &> /dev/null; then - raspi-config nonint do_i2c 0 -else - echo " Warning: raspi-config not found - skipping I2C setup." - echo " You may need to enable I2C manually if not already enabled." -fi - -# --- Install application --- - -echo "Installing application to $INSTALL_DIR..." -mkdir -p "$INSTALL_DIR" - -# Copy binary -cp "$SCRIPT_DIR/bin/SpyderTallyControllerWebApp" "$INSTALL_DIR/" -chmod +x "$INSTALL_DIR/SpyderTallyControllerWebApp" - -# Copy static web assets (CSS, JS, images, etc.) -if [ -d "$SCRIPT_DIR/bin/wwwroot" ]; then - cp -r "$SCRIPT_DIR/bin/wwwroot" "$INSTALL_DIR/" - echo " Installed static web assets" -fi - -# Copy default config files (only if they don't already exist, to preserve user settings on upgrade) -for config_file in appConfig.json deviceConfig.json; do - if [ ! -f "$INSTALL_DIR/$config_file" ]; then - cp "$SCRIPT_DIR/$config_file" "$INSTALL_DIR/" - echo " Created default $config_file" - else - echo " Keeping existing $config_file (not overwriting)" - fi -done - -# Set ownership so the service user can write config files -chown -R "$INSTALL_USER":"$INSTALL_USER" "$INSTALL_DIR" - -# --- Install systemd service --- - -echo "Installing systemd service..." -sed "s/__USER__/$INSTALL_USER/g" "$SCRIPT_DIR/SpyderTallies.service" > /etc/systemd/system/SpyderTallies.service -systemctl daemon-reload -systemctl enable "$SERVICE_NAME" -systemctl start "$SERVICE_NAME" - -# --- Done --- - -echo "" -echo "=== Installation complete! ===" -echo "" -echo "The Spyder Tally Controller is now running." -echo " Web UI: http://$(hostname -I | awk '{print $1}')" -echo "" -echo "Useful commands:" -echo " sudo systemctl status $SERVICE_NAME # Check service status" -echo " sudo systemctl restart $SERVICE_NAME # Restart the service" -echo " sudo journalctl -u $SERVICE_NAME -f # Tail the log" +#!/bin/bash +set -euo pipefail + +# Spyder Tally Controller - Install Script +# This script installs the Spyder Tally Controller application on a Raspberry Pi. +# It auto-detects architecture (arm64 vs arm32) and installs the correct binary. +# +# Usage: +# tar xzf spyder-tally-linux-arm64.tar.gz # (or linux-arm) +# cd spyder-tally-linux-arm64/ # (or linux-arm) +# sudo ./install.sh + +INSTALL_DIR="/opt/spyder-tally" +SERVICE_NAME="SpyderTallies" + +# --- Preflight checks --- + +if [ "$(id -u)" -ne 0 ]; then + echo "Error: This script must be run as root (use sudo ./install.sh)" + exit 1 +fi + +# Determine the real user who invoked sudo +INSTALL_USER="${SUDO_USER:-$(whoami)}" +if [ "$INSTALL_USER" = "root" ]; then + echo "Error: Please run this script with sudo from a regular user account, not as root directly." + exit 1 +fi + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# --- Architecture detection --- + +ARCH="$(uname -m)" +case "$ARCH" in + aarch64) + EXPECTED_RID="linux-arm64" + ;; + armv7l|armv6l) + EXPECTED_RID="linux-arm" + ;; + *) + echo "Error: Unsupported architecture '$ARCH'. Expected aarch64 (arm64) or armv7l/armv6l (arm32)." + exit 1 + ;; +esac + +# Check that the binary in this package matches the detected architecture +if [ ! -f "$SCRIPT_DIR/bin/SpyderTallyControllerWebApp" ]; then + echo "Error: Binary not found at $SCRIPT_DIR/bin/SpyderTallyControllerWebApp" + echo "" + echo "Detected architecture: $ARCH ($EXPECTED_RID)" + echo "Make sure you downloaded the correct package for your Pi:" + echo " - Raspberry Pi 4/5 (64-bit OS): spyder-tally-linux-arm64.tar.gz" + echo " - Raspberry Pi 3 or older (32-bit OS): spyder-tally-linux-arm.tar.gz" + exit 1 +fi + +echo "=== Spyder Tally Controller Installer ===" +echo "Detected architecture: $ARCH ($EXPECTED_RID)" +echo "Installing as user: $INSTALL_USER" +echo "Install directory: $INSTALL_DIR" +echo "" + +# --- Stop existing service if running --- + +if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then + echo "Stopping existing $SERVICE_NAME service..." + systemctl stop "$SERVICE_NAME" +fi + +# --- Install nginx --- + +echo "Installing nginx..." +apt-get update -qq +apt-get install -y -qq nginx > /dev/null + +# --- Enable I2C --- + +echo "Enabling I2C interface..." +if command -v raspi-config &> /dev/null; then + raspi-config nonint do_i2c 0 +else + echo " Warning: raspi-config not found - skipping I2C setup." + echo " You may need to enable I2C manually if not already enabled." +fi + +# --- Install application --- + +echo "Installing application to $INSTALL_DIR..." +mkdir -p "$INSTALL_DIR" + +# Copy binary +cp "$SCRIPT_DIR/bin/SpyderTallyControllerWebApp" "$INSTALL_DIR/" +chmod +x "$INSTALL_DIR/SpyderTallyControllerWebApp" + +# Copy default config files (only if they don't already exist, to preserve user settings on upgrade) +for config_file in appConfig.json deviceConfig.json; do + if [ ! -f "$INSTALL_DIR/$config_file" ]; then + cp "$SCRIPT_DIR/$config_file" "$INSTALL_DIR/" + echo " Created default $config_file" + else + echo " Keeping existing $config_file (not overwriting)" + fi +done + +# Set ownership so the service user can write config files +chown -R "$INSTALL_USER":"$INSTALL_USER" "$INSTALL_DIR" + +# --- Install nginx config --- + +echo "Installing nginx configuration..." +cp "$SCRIPT_DIR/nginx.conf" /etc/nginx/nginx.conf +nginx -t -q +systemctl restart nginx +systemctl enable nginx + +# --- Install systemd service --- + +echo "Installing systemd service..." +sed "s/__USER__/$INSTALL_USER/g" "$SCRIPT_DIR/SpyderTallies.service" > /etc/systemd/system/SpyderTallies.service +systemctl daemon-reload +systemctl enable "$SERVICE_NAME" +systemctl start "$SERVICE_NAME" + +# --- Done --- + +echo "" +echo "=== Installation complete! ===" +echo "" +echo "The Spyder Tally Controller is now running." +echo " Web UI: http://$(hostname -I | awk '{print $1}')" +echo "" +echo "Useful commands:" +echo " sudo systemctl status $SERVICE_NAME # Check service status" +echo " sudo systemctl restart $SERVICE_NAME # Restart the service" +echo " sudo journalctl -u $SERVICE_NAME -f # Tail the log" From 142d216e63b3e58faad857117b836b84651b31b8 Mon Sep 17 00:00:00 2001 From: "derek.smithson" Date: Sat, 14 Feb 2026 17:22:05 -0700 Subject: [PATCH 2/3] docs: update README with step-by-step build and install instructions Replace the old blog-post-only reference in the 'Building your own Device' section with a numbered guide covering hardware wiring, SD card imaging, and automated installer usage. Co-Authored-By: Claude Opus 4.6 --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3fc51c6..99064e3 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,23 @@ The video below walks through the device hardware and software, providing an ove Building your own Device ================= -All the instructions needed to get a device built and programmed are contained as a blog post on my Knighware.net website, and you can view that post [here](https://www.knightware.net/?p=4086). The post walks through the hardware needed to build your own device, the wiring for that hardware, and even configuring an SD card image containing the configured tally application. +You can also check out the [blog post on Knightware.net](https://www.knightware.net/?p=4086) which walks through the hardware and build process in detail. + +### 4-Relay Setup + +1. Gather your hardware (Raspberry Pi, 4-relay module, jumper wires, power supply, and optionally an LCD display) +2. Wire up the device following the [4-relay wiring guide](docs/device_wiring_4wire.md) +3. Image an SD card using [Raspberry Pi Imager](https://www.raspberrypi.com/software/) with Raspberry Pi OS (Lite is fine) +4. Boot the Pi, connect it to your network, and SSH in +5. Download and run the installer: + ```bash + wget https://github.com/dsmithson/SpyderTallyController/releases/latest/download/spyder-tally-linux-arm.tar.gz + tar xzf spyder-tally-linux-arm.tar.gz + cd spyder-tally-linux-arm/ + sudo ./install.sh + ``` + For 64-bit Raspberry Pi OS (Pi 4/5), use `spyder-tally-linux-arm64.tar.gz` instead. +6. Open a browser to `http://` to configure your tally sources Some Useful Links From 5338cabc8f5f81562034ca3698174063534ea7cc Mon Sep 17 00:00:00 2001 From: Derek Smithson Date: Sat, 14 Feb 2026 17:23:03 -0700 Subject: [PATCH 3/3] chore: updating README.md with wiring guide and install instructions --- docs/device_wiring_4wire.md | 27 ++++++++++++++++++++++ docs/{ => images}/Wiring-LCD-Display.png | Bin docs/{ => images}/Wiring-LCD-Relay.png | Bin docs/{ => images}/Wiring-Pinout-Table.png | Bin 4 files changed, 27 insertions(+) create mode 100644 docs/device_wiring_4wire.md rename docs/{ => images}/Wiring-LCD-Display.png (100%) rename docs/{ => images}/Wiring-LCD-Relay.png (100%) rename docs/{ => images}/Wiring-Pinout-Table.png (100%) diff --git a/docs/device_wiring_4wire.md b/docs/device_wiring_4wire.md new file mode 100644 index 0000000..af41a1a --- /dev/null +++ b/docs/device_wiring_4wire.md @@ -0,0 +1,27 @@ +# Wiring up the Raspberry Pi (4-relay version) + +This doc shows how to wire up the Raspberry Pi to the 4-relay version of the device. The wiring is the same for the 8-relay version, but you will have more relays to connect. +This docuemnt assumes you have the following components: +- Raspberry Pi (any model with GPIO pins will work, but the 4-relay version is designed for the Raspberry Pi 4) +- 4-relay module (or 8-relay module if you are using the 8-relay version) +- Jumper wires +- Power supply for the Raspberry Pi (and the relay module if it requires a separate power supply) +- LCD Display (you can skip this if you are not using an LCD display) + +## Overal Wiring Pinout + +The Raspberry Pi GPIO pins are used to control the relay module and the LCD display. The pinout is as follows: + +![Pinout Diagram](images/Wiring-Pinout-Table.png) + +## Wiring the Relay Module + +Follow the connection diagrams below to connect the relay module to the Raspberry Pi: + +![Relay Wiring](images/Wiring-LCD-Relay.png) + +## Wiring the LCD Display + +If you are using an LCD display, connect it to the Raspberry Pi as follows: + +![LCD Wiring](images/Wiring-LCD-Display.png) \ No newline at end of file diff --git a/docs/Wiring-LCD-Display.png b/docs/images/Wiring-LCD-Display.png similarity index 100% rename from docs/Wiring-LCD-Display.png rename to docs/images/Wiring-LCD-Display.png diff --git a/docs/Wiring-LCD-Relay.png b/docs/images/Wiring-LCD-Relay.png similarity index 100% rename from docs/Wiring-LCD-Relay.png rename to docs/images/Wiring-LCD-Relay.png diff --git a/docs/Wiring-Pinout-Table.png b/docs/images/Wiring-Pinout-Table.png similarity index 100% rename from docs/Wiring-Pinout-Table.png rename to docs/images/Wiring-Pinout-Table.png