#!/bin/bash ############################################# # Dune Weaver Touch - Kiosk Mode Setup Script # For Raspberry Pi with Freenove 5" DSI Display # Author: Dune Weaver Team # Version: 1.0 ############################################# set -e # Exit on error # Color codes for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Configuration variables SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" USER_NAME=$(whoami) HOME_DIR="/home/$USER_NAME" APP_DIR="$SCRIPT_DIR" SERVICE_NAME="dune-weaver-kiosk" VENV_PATH="$APP_DIR/bin/activate" # Display banner echo -e "${GREEN}" echo "================================================" echo " Dune Weaver Touch - Kiosk Setup" echo " Freenove 5\" DSI Display (800x480)" echo "================================================" echo -e "${NC}" # Function to detect Raspberry Pi model detect_pi_model() { local model=$(cat /proc/cpuinfo | grep "Model" | cut -d ':' -f 2 | sed 's/^ *//') if [[ $model == *"Pi 3"* ]]; then echo "3" elif [[ $model == *"Pi 4"* ]]; then echo "4" elif [[ $model == *"Pi 5"* ]]; then echo "5" else echo "unknown" fi } # Function to backup files backup_file() { local file=$1 if [ -f "$file" ]; then cp "$file" "${file}.backup.$(date +%Y%m%d_%H%M%S)" echo -e "${YELLOW}Backed up: $file${NC}" fi } # Function to setup boot configuration setup_boot_config() { echo -e "${GREEN}Configuring boot settings for DSI display...${NC}" backup_file "/boot/config.txt" local pi_model=$(detect_pi_model) echo -e "${GREEN}Detected Raspberry Pi Model: $pi_model${NC}" # Remove conflicting HDMI settings if they exist sudo sed -i '/hdmi_force_hotplug/d' /boot/config.txt sudo sed -i '/hdmi_group/d' /boot/config.txt sudo sed -i '/hdmi_mode/d' /boot/config.txt sudo sed -i '/hdmi_cvt/d' /boot/config.txt sudo sed -i '/hdmi_drive/d' /boot/config.txt sudo sed -i '/config_hdmi_boost/d' /boot/config.txt sudo sed -i '/dtoverlay=ads7846/d' /boot/config.txt # Remove old overlays sudo sed -i '/dtoverlay=vc4-fkms-v3d/d' /boot/config.txt sudo sed -i '/dtoverlay=vc4-kms-v3d/d' /boot/config.txt # Add proper configuration based on Pi model if [ "$pi_model" == "3" ]; then # Pi 3 configuration echo -e "${GREEN}Configuring for Pi 3...${NC}" cat << EOF | sudo tee -a /boot/config.txt > /dev/null # Dune Weaver Kiosk - DSI Display Configuration (Pi 3) dtoverlay=vc4-fkms-v3d gpu_mem=128 max_framebuffers=2 display_auto_detect=1 disable_overscan=1 EOF else # Pi 4/5 configuration echo -e "${GREEN}Configuring for Pi 4/5...${NC}" cat << EOF | sudo tee -a /boot/config.txt > /dev/null # Dune Weaver Kiosk - DSI Display Configuration (Pi 4/5) dtoverlay=vc4-kms-v3d gpu_mem=128 max_framebuffers=2 display_auto_detect=1 disable_overscan=1 EOF fi # Add common settings cat << EOF | sudo tee -a /boot/config.txt > /dev/null # Common settings dtparam=i2c_arm=on dtparam=spi=on enable_uart=1 max_usb_current=1 # Disable splash screens for faster boot disable_splash=1 EOF echo -e "${GREEN}Boot configuration updated${NC}" } # Function to install dependencies install_dependencies() { echo -e "${GREEN}Installing required dependencies...${NC}" sudo apt-get update sudo apt-get install -y \ libgles2-mesa \ libgles2-mesa-dev \ libgbm-dev \ libdrm-dev \ libinput-dev \ libudev-dev \ libxkbcommon-dev \ fbset \ evtest \ qtvirtualkeyboard-plugin \ qml-module-qtquick-virtualkeyboard \ qt6-virtualkeyboard-plugin \ qml6-module-qt-labs-qmlmodels || { echo -e "${YELLOW}Some packages may not be available, continuing...${NC}" } echo -e "${GREEN}Dependencies installed${NC}" } # Function to create startup script create_startup_script() { echo -e "${GREEN}Creating startup script...${NC}" local pi_model=$(detect_pi_model) local START_SCRIPT="$APP_DIR/start_kiosk.sh" cat << 'EOF' > "$START_SCRIPT" #!/bin/bash # Dune Weaver Touch Kiosk Startup Script # Auto-generated by setup_kiosk.sh # Wait for system to fully boot sleep 10 # Log file LOG_FILE="/tmp/dune-weaver-kiosk.log" exec &> >(tee -a "$LOG_FILE") echo "=========================================" echo "Starting Dune Weaver Touch Kiosk" echo "Date: $(date)" echo "=========================================" # Detect Pi model for platform selection PI_MODEL=$(cat /proc/cpuinfo | grep "Model" | cut -d ':' -f 2) # Set working directory cd "$(dirname "$0")" # Check if virtual environment exists if [ ! -f "bin/activate" ]; then echo "ERROR: Virtual environment not found!" exit 1 fi # Activate virtual environment source bin/activate # Function to run with LinuxFB (Pi 3 with DSI) run_linuxfb() { export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0 export QT_QPA_FONTDIR=/usr/share/fonts/truetype export QT_QPA_FB_HIDECURSOR=1 export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0:rotate=0 # Enable Virtual Keyboard export QT_IM_MODULE=qtvirtualkeyboard export QT_VIRTUALKEYBOARD_STYLE=default export QT_VIRTUALKEYBOARD_LAYOUT_PATH=/usr/share/qt5/qtvirtualkeyboard/layouts echo "Starting with LinuxFB platform and virtual keyboard..." python main.py } # Function to run with EGLFS (Pi 4/5 with DSI) run_eglfs() { export QT_QPA_PLATFORM=eglfs export QT_QPA_EGLFS_WIDTH=800 export QT_QPA_EGLFS_HEIGHT=480 export QT_QPA_EGLFS_INTEGRATION=eglfs_kms export QT_QPA_EGLFS_KMS_ATOMIC=1 export QT_QPA_EGLFS_HIDECURSOR=1 export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0:rotate=0 # Enable Virtual Keyboard export QT_IM_MODULE=qtvirtualkeyboard export QT_VIRTUALKEYBOARD_STYLE=default export QT_VIRTUALKEYBOARD_LAYOUT_PATH=/usr/share/qt5/qtvirtualkeyboard/layouts echo "Starting with EGLFS platform and virtual keyboard..." python main.py } # Check for DRM device (needed for EGLFS) if [ -e /dev/dri/card0 ] || [ -e /dev/dri/card1 ]; then echo "DRM device found, using EGLFS" run_eglfs else echo "No DRM device, using LinuxFB" run_linuxfb fi echo "Application exited at $(date)" EOF chmod +x "$START_SCRIPT" echo -e "${GREEN}Startup script created: $START_SCRIPT${NC}" } # Function to create systemd service create_systemd_service() { echo -e "${GREEN}Creating systemd service...${NC}" local SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" cat << EOF | sudo tee "$SERVICE_FILE" > /dev/null [Unit] Description=Dune Weaver Touch Kiosk Mode After=multi-user.target graphical.target Wants=network-online.target After=network-online.target [Service] Type=simple User=$USER_NAME Group=$USER_NAME WorkingDirectory=$APP_DIR # Auto-restart on failure Restart=always RestartSec=10 # Start script ExecStart=$APP_DIR/start_kiosk.sh # Stop timeout TimeoutStopSec=10 # Logging StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF # Reload systemd and enable service sudo systemctl daemon-reload sudo systemctl enable "${SERVICE_NAME}.service" echo -e "${GREEN}Systemd service created and enabled${NC}" } # Function to create uninstall script create_uninstall_script() { echo -e "${GREEN}Creating uninstall script...${NC}" cat << 'EOF' > "$APP_DIR/uninstall_kiosk.sh" #!/bin/bash # Dune Weaver Touch - Kiosk Mode Uninstall Script set -e RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' SERVICE_NAME="dune-weaver-kiosk" echo -e "${YELLOW}Uninstalling Dune Weaver Kiosk Mode...${NC}" # Stop and disable service if systemctl list-units --full -all | grep -Fq "${SERVICE_NAME}.service"; then echo "Stopping and disabling service..." sudo systemctl stop "${SERVICE_NAME}.service" 2>/dev/null || true sudo systemctl disable "${SERVICE_NAME}.service" 2>/dev/null || true sudo rm -f "/etc/systemd/system/${SERVICE_NAME}.service" sudo systemctl daemon-reload echo -e "${GREEN}Service removed${NC}" fi # Remove startup script if [ -f "start_kiosk.sh" ]; then rm -f "start_kiosk.sh" echo -e "${GREEN}Startup script removed${NC}" fi # Restore boot config if backup exists LATEST_BACKUP=$(ls -t /boot/config.txt.backup.* 2>/dev/null | head -n1) if [ -n "$LATEST_BACKUP" ]; then echo -e "${YELLOW}Found backup: $LATEST_BACKUP${NC}" read -p "Restore boot configuration from backup? (y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then sudo cp "$LATEST_BACKUP" /boot/config.txt echo -e "${GREEN}Boot configuration restored${NC}" echo -e "${YELLOW}Reboot required for changes to take effect${NC}" fi fi echo -e "${GREEN}Kiosk mode uninstalled successfully${NC}" echo -e "${YELLOW}You may want to reboot your Raspberry Pi${NC}" EOF chmod +x "$APP_DIR/uninstall_kiosk.sh" echo -e "${GREEN}Uninstall script created: $APP_DIR/uninstall_kiosk.sh${NC}" } # Function to test the display test_display() { echo -e "${GREEN}Testing display configuration...${NC}" # Check framebuffer if [ -e /dev/fb0 ]; then echo -e "${GREEN}✓ Framebuffer device found${NC}" fbset -i | head -5 else echo -e "${RED}✗ No framebuffer device found${NC}" fi # Check for DRM device if [ -e /dev/dri/card0 ] || [ -e /dev/dri/card1 ]; then echo -e "${GREEN}✓ DRM device found${NC}" ls -la /dev/dri/ else echo -e "${YELLOW}! No DRM device (normal for Pi 3)${NC}" fi # Check touch input echo -e "${GREEN}Available input devices:${NC}" ls -la /dev/input/event* 2>/dev/null || echo "No input devices found" } # Main installation function install_kiosk() { echo -e "${GREEN}Starting Kiosk Mode Installation...${NC}" # Check if running on Raspberry Pi if ! grep -q "Raspberry Pi" /proc/cpuinfo; then echo -e "${YELLOW}Warning: This doesn't appear to be a Raspberry Pi${NC}" read -p "Continue anyway? (y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi fi # Check if virtual environment exists if [ ! -f "$VENV_PATH" ]; then echo -e "${RED}Error: Virtual environment not found at $VENV_PATH${NC}" echo "Please run this script from the dune-weaver-touch directory" exit 1 fi # Install steps install_dependencies setup_boot_config create_startup_script create_systemd_service create_uninstall_script test_display echo -e "${GREEN}" echo "================================================" echo " Installation Complete!" echo "================================================" echo -e "${NC}" echo echo "Next steps:" echo "1. Reboot your Raspberry Pi:" echo " ${GREEN}sudo reboot${NC}" echo echo "2. The kiosk will start automatically after reboot" echo echo "3. To manually control the service:" echo " Start: ${GREEN}sudo systemctl start ${SERVICE_NAME}${NC}" echo " Stop: ${GREEN}sudo systemctl stop ${SERVICE_NAME}${NC}" echo " Status: ${GREEN}sudo systemctl status ${SERVICE_NAME}${NC}" echo " Logs: ${GREEN}journalctl -u ${SERVICE_NAME} -f${NC}" echo echo "4. To uninstall:" echo " ${GREEN}./uninstall_kiosk.sh${NC}" echo read -p "Reboot now? (y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then sudo reboot fi } # Parse command line arguments case "${1:-}" in uninstall) if [ -f "$APP_DIR/uninstall_kiosk.sh" ]; then "$APP_DIR/uninstall_kiosk.sh" else echo -e "${RED}Uninstall script not found${NC}" exit 1 fi ;; test) test_display ;; status) sudo systemctl status "${SERVICE_NAME}.service" ;; *) install_kiosk ;; esac