Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ensure shell scripts always have LF line endings, even on Windows
*.sh text eol=lf
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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://<your-pi-ip>` to configure your tally sources


Some Useful Links
Expand Down
27 changes: 27 additions & 0 deletions docs/device_wiring_4wire.md
Original file line number Diff line number Diff line change
@@ -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)
File renamed without changes
File renamed without changes
File renamed without changes
266 changes: 137 additions & 129 deletions docs/sd_card/install.sh
Original file line number Diff line number Diff line change
@@ -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"