Compare commits

...

3 commits

Author SHA1 Message Date
Chris Frankland-Wright
2e8bc9ac5e updated some masthead and readme
Some checks failed
Build for Raspberry Pi / Build for aarch64 (push) Has been cancelled
2025-08-31 22:13:47 +01:00
Chris Frankland-Wright
3e423416a8 fixed error in naming of service 2025-08-31 21:54:18 +01:00
Chris Frankland-Wright
4a07b29728 removed captive portal for now 2025-08-31 18:42:58 +01:00
4 changed files with 28 additions and 241 deletions

View file

@ -4,13 +4,13 @@
Hachi synchronises timecode-locked systems by decoding incoming LTC (Linear Time Code) and broadcasting it as NTP/PTP — with the dedication our namesake would insist upon.
Created by Chris Frankland-Wright and John Rogers
Created by Chris Frankland-Wright and Chaos Rogers
---
## 📦 Hardware Requirements
- Raspberry Pi 5 (Dev Platform) but should be supported by Pi v3 (or better)
- Raspberry Pi 5 2GB (Dev Platform) but should be supported by Pi v3 (or better)
- Debian Bookworm (64-bit recommended)
- Teensy 4.0 - https://thepihut.com/products/teensy-4-0-headers
- Audio Adapter Board for Teensy 4.0 (Rev D) - https://thepihut.com/products/audio-adapter-board-for-teensy-4-0
@ -32,7 +32,7 @@ Created by Chris Frankland-Wright and John Rogers
## 🖥️ Web Interface & API
When running as a background daemon, TimeTurner provides a web interface for monitoring and configuration.
When running as a background daemon, Hachi provides a web interface for monitoring and configuration.
- **Access**: The web UI is available at `http://<raspberry_pi_ip>:8080`.
- **Functionality**: You can view the real-time sync status, see logs, and change all configuration options directly from your browser.
@ -50,7 +50,7 @@ When running as a background daemon, TimeTurner provides a web interface for mon
## 🚀 Installation
The `setup.sh` script compiles and installs the TimeTurner application. You can run it by cloning the repository with `git` or by using the `curl` command below for a git-free installation.
The `setup.sh` script compiles and installs the Hachi application. You can run it by cloning the repository with `git` or by using the `curl` command below for a git-free installation.
### Prerequisites
@ -86,11 +86,27 @@ The installation script automates the following steps:
After installation is complete, the script will provide instructions to start the service manually or to run the application in its interactive terminal mode.
```bash
The working directory is /opt/timeturner.
Default 'config.yml' installed to /opt/timeturner.
To start the service, run:
sudo systemctl start timeturner.service
To view live logs, run:
journalctl -u timeturner.service -f
To run the interactive TUI instead, simply run from the project directory:
cargo run
Or from anywhere after installation:
timeturner
```
---
## 🔄 Updating
If you installed TimeTurner by cloning the repository with `git`, you can use the `update.sh` script to easily update to the latest version.
If you installed Hachi by cloning the repository with `git`, you can use the `update.sh` script to easily update to the latest version.
**Note**: This script will not work if you used the `curl` one-line command for installation, as that method does not create a Git repository.
@ -113,7 +129,7 @@ chronyc tracking | NTP Tracking
sudo nano /etc/chrony/chrony.conf | Default Chrony Conf File
Add to top:
# Serve the system clock as a reference at stratum10
# Serve the system clock as a reference at stratum1
server 127.127.1.0
allow 127.0.0.0/8
local stratum 1

233
setup.sh
View file

@ -97,7 +97,7 @@ echo "Common build dependencies installed."
# --- Install Python dependencies for testing ---
echo "🐍 Installing Python dependencies for test scripts..."
if [ "$PKG_MANAGER" == "apt" ]; then
# python3-serial is the name for pyserial in apt
# We no longer need hotspot dependencies
sudo apt install -y python3 python3-pip python3-serial
elif [ "$PKG_MANAGER" == "dnf" ]; then
# python3-pyserial is the name for pyserial in dnf
@ -217,237 +217,8 @@ else
fi
# --- Install and configure WiFi hotspot and captive portal ---
echo "📡 Installing and configuring WiFi hotspot and captive portal..."
# --- The entire WiFi hotspot and captive portal section has been removed ---
if [ "$PKG_MANAGER" == "apt" ]; then
# Stop the service if it's running from a previous installation to prevent "Text file busy" error.
echo "Stopping existing nodogsplash service before installation..."
sudo systemctl stop nodogsplash || true
# We will use dnsmasq for DHCP, as the compiled nodogsplash version may not support the internal DHCP server.
# sudo apt-get remove --purge -y dnsmasq || true # This line is no longer needed.
# Install dependencies for hotspot and for building nodogsplash.
# ifupdown is needed to manage /etc/network/interfaces
sudo apt install -y hostapd dnsmasq git libmicrohttpd-dev libjson-c-dev iptables ifupdown
# Force iptables-legacy for nodogsplash
echo "Setting iptables-legacy mode for nodogsplash..."
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
echo "Building and installing nodogsplash from source..."
# Create a temporary directory for the build
BUILD_DIR=$(mktemp -d)
git clone https://github.com/nodogsplash/nodogsplash.git "$BUILD_DIR"
# Run the build in a subshell to isolate the directory change
(
cd "$BUILD_DIR"
make
sudo make install
# Manually install the systemd service file as 'make install' might not do it.
# This makes the script more robust.
if [ -f "debian/nodogsplash.service" ]; then
echo "Manually installing systemd service file..."
sudo cp debian/nodogsplash.service /etc/systemd/system/nodogsplash.service
# Reload systemd to recognize the new service
sudo systemctl daemon-reload
else
echo "⚠️ Warning: nodogsplash.service file not found in source. Cannot set up as a service."
fi
)
# Clean up the build directory
sudo rm -rf "$BUILD_DIR"
echo "✅ nodogsplash installed successfully."
# Disable the standalone hostapd service to let NetworkManager manage it.
# We are now using the classic hostapd service, so unmask it.
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl enable nodogsplash
else
echo "This script is designed for Debian-based systems like Raspberry Pi OS."
echo "Skipping WiFi hotspot setup."
fi
# Stop services to configure
# Ensure services exist before trying to stop them
sudo systemctl stop hostapd || true
sudo systemctl stop dnsmasq || true
# --- Configure networking for AP mode ---
# Set the WiFi country code to prevent radio issues. This is a critical step.
echo "Setting WiFi Country Code to US..."
sudo raspi-config nonint do_wifi_country US
# Tell NetworkManager to ignore wlan0 completely to prevent conflicts.
echo "Configuring NetworkManager to ignore wlan0..."
sudo tee /etc/NetworkManager/conf.d/99-unmanaged-wlan0.conf > /dev/null <<EOF
[keyfile]
unmanaged-devices=interface-name:wlan0
EOF
# Also remove the DNS disabling config as it's no longer relevant for this method
sudo rm -f /etc/NetworkManager/conf.d/99-disable-dns.conf
sudo systemctl reload NetworkManager
# --- Configure networking for AP mode (using /etc/network/interfaces) ---
# 1. Uninstall dhcpcd5 to prevent any conflicts.
echo "Removing dhcpcd5 to switch to /etc/network/interfaces..."
sudo apt-get remove --purge -y dhcpcd5 || true
sudo systemctl disable dhcpcd || true
# 2. Configure a static IP for wlan0 directly in the interfaces file.
echo "Configuring static IP for wlan0 via /etc/network/interfaces..."
sudo tee /etc/network/interfaces > /dev/null <<EOF
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface (Ethernet) - managed by NetworkManager
allow-hotplug eth0
iface eth0 inet dhcp
# Static IP configuration for Fetch-Hachi AP
allow-hotplug wlan0
iface wlan0 inet static
address 10.0.252.1
netmask 255.255.255.0
EOF
# Configure hostapd for the Access Point
echo "Configuring hostapd..."
sudo tee /etc/hostapd/hostapd.conf > /dev/null <<EOF
interface=wlan0
driver=nl80211
ssid=Fetch-Hachi
hw_mode=g
channel=7
ieee80211n=1
wmm_enabled=1
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
EOF
# Point the hostapd service to the new config file.
sudo sed -i 's|#DAEMON_CONF=""|DAEMON_CONF="/etc/hostapd/hostapd.conf"|' /etc/default/hostapd
# Configure dnsmasq for DHCP
echo "Configuring dnsmasq..."
sudo tee /etc/dnsmasq.conf > /dev/null <<EOF
# Listen only on this interface
interface=wlan0
# Don't bind to all interfaces, only the one specified above
bind-interfaces
# Set the IP range for DHCP clients
dhcp-range=10.0.252.10,10.0.252.50,255.255.255.0,24h
# Provide a gateway address
dhcp-option=option:router,10.0.252.1
# Provide a DNS server address
dhcp-option=option:dns-server,10.0.252.1
# For captive portal, resolve all DNS queries to the AP itself
address=/#/10.0.252.1
EOF
# Configure nodogsplash for captive portal
echo "Configuring nodogsplash..."
sudo tee /etc/nodogsplash/nodogsplash.conf > /dev/null <<EOF
GatewayInterface wlan0
GatewayAddress 10.0.252.1
MaxClients 250
AuthIdleTimeout 480
FirewallRuleSet preauthenticated-users {
# Allow DHCP for clients to get an IP address
FirewallRule allow udp port 67
FirewallRule allow udp port 68
# Allow DNS for captive portal detection
FirewallRule allow tcp port 53
FirewallRule allow udp port 53
# Allow HTTP for the captive portal redirect
FirewallRule allow tcp port 80
}
RedirectURL http://10.0.252.1/static/index.html
EOF
# Restart services in the correct order and add delays to prevent race conditions
echo "Restarting services..."
# Stop and disable systemd-resolved to prevent any DNS/DHCP conflicts
echo "Disabling systemd-resolved to ensure dnsmasq has full control..."
sudo systemctl stop systemd-resolved || true
sudo systemctl disable systemd-resolved || true
# Bring up the wlan0 interface manually
echo "Bringing up wlan0 interface..."
sudo ifdown wlan0 || true
sudo ifup wlan0
# Restart hostapd to create the access point
sudo systemctl restart hostapd
# Wait for the interface to come up and get the IP address
echo "Waiting for wlan0 to be configured..."
IP_CHECK=""
# Loop for up to 30 seconds waiting for the IP
for i in {1..15}; do
# The '|| true' prevents the script from exiting if grep finds no match
IP_CHECK=$(ip -4 addr show wlan0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' || true)
if [ "$IP_CHECK" == "10.0.252.1" ]; then
break
fi
echo "Still waiting for IP..."
sleep 2
done
# Check for the IP address before starting nodogsplash
if [ "$IP_CHECK" == "10.0.252.1" ]; then
echo "✅ wlan0 configured with IP $IP_CHECK."
# Add a small delay to ensure the interface is fully ready for dnsmasq
sleep 2
echo "Attempting to start dnsmasq service..."
if ! sudo systemctl restart dnsmasq; then
echo "❌ dnsmasq service failed to start. Displaying logs..."
sleep 2
sudo journalctl -u dnsmasq.service --no-pager -n 50
exit 1
fi
echo "✅ dnsmasq service started successfully."
if command -v nodogsplash &> /dev/null; then
echo "Attempting to start nodogsplash service..."
if ! sudo systemctl restart nodogsplash; then
echo "❌ nodogsplash service failed to start. Displaying logs..."
# Give a moment for logs to be written
sleep 2
sudo journalctl -u nodogsplash.service --no-pager -n 50
echo ""
echo "To debug further, run nodogsplash in the foreground with this command:"
echo " sudo /usr/bin/nodogsplash -f -d 7"
echo ""
exit 1
fi
echo "✅ nodogsplash service started successfully."
fi
else
echo "❌ Error: wlan0 failed to get the static IP 10.0.252.1. Found: '$IP_CHECK'."
echo "Please check 'sudo systemctl status hostapd' and 'cat /etc/network/interfaces'."
exit 1
fi
echo "✅ WiFi hotspot and captive portal configured. SSID: Fetch-Hachi, IP: 10.0.252.1"
echo "Clients will be redirected to http://10.0.252.1/static/index.html"
# 1. Build the release binary
echo "📦 Building release binary with Cargo..."

View file

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NTP TimeTurner</title>
<title>Fetch | Hachi</title>
<link rel="stylesheet" href="style.css">
<link rel="icon" href="favicon.ico" type="image/x-icon">
</head>
@ -129,7 +129,7 @@
</div>
<footer>
<p>
Built by Chris Frankland-Wright and John Rogers | Have Blue Broadcast Media |
Built by Chris Frankland-Wright and Chaos Rogers | Have Blue Broadcast Media |
<a href="https://github.com/cjfranko/NTP-Timeturner" target="_blank" rel="noopener noreferrer">https://github.com/cjfranko/NTP-Timeturner</a>
</p>
</footer>

View file

@ -13,11 +13,11 @@ cargo build --release
# 3. Stop the currently running service to release the file lock
echo "🛑 Stopping TimeTurner service..."
sudo systemctl stop timeturner.service
sudo systemctl stop timeturner.service || true
# 4. Copy the new binary to the installation directory
echo "🚀 Deploying new binary..."
sudo cp target/release/timeturner /opt/timeturner/timeturner
sudo cp target/release/ntp_timeturner /opt/timeturner/timeturner
# 5. Restart the service with the new binary
echo "✅ Restarting TimeTurner service..."