install.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. #!/bin/bash
  2. # Dune Weaver Touch - One-Command Installer
  3. # This script sets up everything needed to run Dune Weaver Touch on boot
  4. set -e
  5. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  6. ACTUAL_USER="${SUDO_USER:-$USER}"
  7. USER_HOME=$(eval echo ~$ACTUAL_USER)
  8. # Detect Raspberry Pi model
  9. PI_MODEL=$(cat /proc/device-tree/model 2>/dev/null | tr -d '\0' || echo "unknown")
  10. IS_PI5=false
  11. if [[ "$PI_MODEL" == *"Pi 5"* ]]; then
  12. IS_PI5=true
  13. fi
  14. echo "🎯 Dune Weaver Touch - Complete Installation"
  15. echo "============================================="
  16. echo "App directory: $SCRIPT_DIR"
  17. echo "User: $ACTUAL_USER"
  18. echo "Detected: $PI_MODEL"
  19. echo ""
  20. # Check if running as root
  21. if [ "$EUID" -ne 0 ]; then
  22. echo "❌ This installer must be run with sudo privileges"
  23. echo ""
  24. echo "Usage: sudo ./install.sh"
  25. echo ""
  26. exit 1
  27. fi
  28. echo "🔧 Installing system components..."
  29. echo ""
  30. # Function to install system scripts
  31. install_scripts() {
  32. echo "📄 Installing system scripts..."
  33. local scripts=("screen-on" "screen-off" "touch-monitor")
  34. for script in "${scripts[@]}"; do
  35. local source_path="$SCRIPT_DIR/scripts/$script"
  36. local target_path="/usr/local/bin/$script"
  37. if [ -f "$source_path" ]; then
  38. cp "$source_path" "$target_path"
  39. chmod 755 "$target_path"
  40. chown root:root "$target_path"
  41. echo " ✅ $script → $target_path"
  42. else
  43. echo " ⚠️ $script not found at $source_path"
  44. fi
  45. done
  46. echo " 📄 System scripts installed"
  47. }
  48. # Function to setup systemd service
  49. setup_systemd() {
  50. echo "🚀 Setting up systemd service..."
  51. # Update paths in the service file
  52. sed "s|/home/pi/dune-weaver-touch|$SCRIPT_DIR|g" "$SCRIPT_DIR/dune-weaver-touch.service" > /tmp/dune-weaver-touch.service
  53. sed -i "s|User=pi|User=$ACTUAL_USER|g" /tmp/dune-weaver-touch.service
  54. sed -i "s|Group=pi|Group=$ACTUAL_USER|g" /tmp/dune-weaver-touch.service
  55. # Copy service file
  56. cp /tmp/dune-weaver-touch.service /etc/systemd/system/
  57. # Enable service
  58. systemctl daemon-reload
  59. systemctl enable dune-weaver-touch.service
  60. echo " 🚀 Systemd service installed and enabled"
  61. }
  62. # Function to configure boot settings for DSI display
  63. configure_boot_settings() {
  64. echo "🖥️ Configuring boot settings for DSI display..."
  65. local CONFIG_FILE="/boot/firmware/config.txt"
  66. # Fallback to old path if new path doesn't exist
  67. [ ! -f "$CONFIG_FILE" ] && CONFIG_FILE="/boot/config.txt"
  68. if [ ! -f "$CONFIG_FILE" ]; then
  69. echo " ⚠️ config.txt not found, skipping boot configuration"
  70. return
  71. fi
  72. # Backup config.txt
  73. cp "$CONFIG_FILE" "${CONFIG_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
  74. echo " ✅ Backed up config.txt"
  75. # Remove old/conflicting KMS settings
  76. sed -i '/dtoverlay=vc4-fkms-v3d/d' "$CONFIG_FILE"
  77. sed -i '/dtoverlay=vc4-xfkms-v3d/d' "$CONFIG_FILE"
  78. if [ "$IS_PI5" = true ]; then
  79. # Pi 5: KMS is enabled by default, gpu_mem is ignored (dedicated VRAM)
  80. echo " ℹ️ Pi 5 detected - KMS enabled by default, skipping vc4-kms-v3d overlay"
  81. echo " ℹ️ Pi 5 has dedicated VRAM, skipping gpu_mem setting"
  82. else
  83. # Pi 3/4: Add full KMS if not present
  84. if ! grep -q "dtoverlay=vc4-kms-v3d" "$CONFIG_FILE"; then
  85. # Find [all] section or add at end
  86. if grep -q "^\[all\]" "$CONFIG_FILE"; then
  87. sed -i '/^\[all\]/a dtoverlay=vc4-kms-v3d' "$CONFIG_FILE"
  88. else
  89. echo -e "\n[all]\ndtoverlay=vc4-kms-v3d" >> "$CONFIG_FILE"
  90. fi
  91. echo " ✅ Enabled full KMS (vc4-kms-v3d) for eglfs support"
  92. else
  93. echo " ℹ️ Full KMS already enabled"
  94. fi
  95. # Add GPU memory if not present (only for Pi 3/4 with shared memory)
  96. if ! grep -q "gpu_mem=" "$CONFIG_FILE"; then
  97. echo "gpu_mem=128" >> "$CONFIG_FILE"
  98. echo " ✅ Set GPU memory to 128MB"
  99. else
  100. echo " ℹ️ GPU memory already configured"
  101. fi
  102. fi
  103. # Disable splash screens for cleaner boot (all Pi models)
  104. if ! grep -q "disable_splash=1" "$CONFIG_FILE"; then
  105. echo "disable_splash=1" >> "$CONFIG_FILE"
  106. echo " ✅ Disabled rainbow splash"
  107. else
  108. echo " ℹ️ Rainbow splash already disabled"
  109. fi
  110. echo " 🖥️ Boot configuration updated"
  111. }
  112. # Function to setup touch rotation via udev rule
  113. setup_touch_rotation() {
  114. echo "👆 Setting up touchscreen rotation..."
  115. local UDEV_RULE_FILE="/etc/udev/rules.d/99-ft5x06-rotate.rules"
  116. # Create udev rule for FT5x06 touch controller (180° rotation)
  117. cat > "$UDEV_RULE_FILE" << 'EOF'
  118. # Rotate FT5x06 touchscreen 180 degrees using libinput calibration matrix
  119. # Matrix format: a b c d e f 0 0 1
  120. # For 180° rotation: -1 0 1 0 -1 1 0 0 1
  121. # This inverts both X and Y axes (equivalent to 180° rotation)
  122. SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="*generic ft5x06*", \
  123. ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 -1 1 0 0 1"
  124. EOF
  125. chmod 644 "$UDEV_RULE_FILE"
  126. echo " ✅ Touch rotation udev rule created: $UDEV_RULE_FILE"
  127. # Reload udev rules
  128. udevadm control --reload-rules
  129. udevadm trigger
  130. echo " ✅ Udev rules reloaded"
  131. echo " 👆 Touch rotation configured (180°)"
  132. }
  133. # Function to hide mouse cursor
  134. hide_mouse_cursor() {
  135. echo "🖱️ Configuring mouse cursor hiding..."
  136. # Install unclutter for hiding mouse cursor when idle
  137. echo " 📦 Installing unclutter..."
  138. apt install -y unclutter > /dev/null 2>&1
  139. # Create autostart directory if it doesn't exist
  140. local AUTOSTART_DIR="$USER_HOME/.config/autostart"
  141. mkdir -p "$AUTOSTART_DIR"
  142. chown -R "$ACTUAL_USER:$ACTUAL_USER" "$USER_HOME/.config"
  143. # Create unclutter autostart entry
  144. cat > "$AUTOSTART_DIR/unclutter.desktop" << 'EOF'
  145. [Desktop Entry]
  146. Type=Application
  147. Name=Unclutter
  148. Comment=Hide mouse cursor when idle
  149. Exec=unclutter -idle 0.1 -root
  150. Hidden=false
  151. NoDisplay=false
  152. X-GNOME-Autostart-enabled=true
  153. EOF
  154. chown "$ACTUAL_USER:$ACTUAL_USER" "$AUTOSTART_DIR/unclutter.desktop"
  155. echo " 🖱️ Mouse cursor hiding configured"
  156. }
  157. # Function to setup kiosk optimizations
  158. setup_kiosk_optimizations() {
  159. echo "🖥️ Setting up kiosk optimizations..."
  160. local CMDLINE_FILE="/boot/firmware/cmdline.txt"
  161. [ ! -f "$CMDLINE_FILE" ] && CMDLINE_FILE="/boot/cmdline.txt"
  162. # Determine DSI connector name based on Pi model
  163. # Pi 5 uses DSI-2 (separate DRM device), Pi 3/4 use DSI-1
  164. local DSI_CONNECTOR="DSI-1"
  165. if [ "$IS_PI5" = true ]; then
  166. DSI_CONNECTOR="DSI-2"
  167. echo " ℹ️ Pi 5 detected - using DSI-2 connector"
  168. fi
  169. # Configure cmdline.txt for display and boot
  170. if [ -f "$CMDLINE_FILE" ]; then
  171. cp "$CMDLINE_FILE" "${CMDLINE_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
  172. # Add video parameter for DSI display with rotation
  173. # Check for any existing DSI video configuration
  174. if ! grep -q "video=DSI-[0-9]:800x480@60,rotate=180" "$CMDLINE_FILE"; then
  175. sed -i "s/$/ video=${DSI_CONNECTOR}:800x480@60,rotate=180/" "$CMDLINE_FILE"
  176. echo " ✅ DSI display configuration added (${DSI_CONNECTOR}:800x480@60, rotated 180°)"
  177. else
  178. echo " ℹ️ DSI display configuration already present"
  179. fi
  180. # Add quiet splash for cleaner boot
  181. if ! grep -q "quiet splash" "$CMDLINE_FILE"; then
  182. sed -i 's/$/ quiet splash/' "$CMDLINE_FILE"
  183. echo " ✅ Boot splash enabled"
  184. else
  185. echo " ℹ️ Boot splash already enabled"
  186. fi
  187. fi
  188. # Note about auto-login - let user configure manually
  189. echo " ℹ️ Auto-login configuration skipped (manual setup recommended)"
  190. echo " 🖥️ Kiosk optimizations applied"
  191. }
  192. # Function to setup Python virtual environment and install dependencies
  193. setup_python_environment() {
  194. echo "🐍 Setting up Python virtual environment..."
  195. # Install system Qt6 and PySide6 packages for full eglfs support
  196. echo " 📦 Installing system Qt6 and PySide6 packages..."
  197. apt update
  198. apt install -y \
  199. python3-pyside6.qtcore \
  200. python3-pyside6.qtgui \
  201. python3-pyside6.qtqml \
  202. python3-pyside6.qtquick \
  203. python3-pyside6.qtquickcontrols2 \
  204. python3-pyside6.qtquickwidgets \
  205. python3-pyside6.qtwebsockets \
  206. python3-pyside6.qtnetwork \
  207. qml6-module-qtquick \
  208. qml6-module-qtquick-controls \
  209. qml6-module-qtquick-layouts \
  210. qml6-module-qtquick-window \
  211. qml6-module-qtquick-dialogs \
  212. qml6-module-qt-labs-qmlmodels \
  213. qt6-virtualkeyboard-plugin \
  214. qml6-module-qtquick-virtualkeyboard \
  215. qt6-base-dev \
  216. qt6-declarative-dev \
  217. libqt6opengl6 \
  218. libqt6core5compat6 \
  219. libqt6network6 \
  220. libqt6websockets6 > /dev/null 2>&1
  221. echo " ✅ System Qt6/PySide6 packages installed"
  222. # Create virtual environment with system site packages
  223. if [ ! -d "$SCRIPT_DIR/venv" ]; then
  224. echo " 📦 Creating virtual environment with system site packages..."
  225. python3 -m venv --system-site-packages "$SCRIPT_DIR/venv" || {
  226. echo " ⚠️ Could not create virtual environment. Installing python3-venv..."
  227. apt install -y python3-venv python3-full
  228. python3 -m venv --system-site-packages "$SCRIPT_DIR/venv"
  229. }
  230. else
  231. echo " ℹ️ Virtual environment already exists"
  232. fi
  233. # Install non-Qt dependencies from requirements.txt
  234. echo " 📦 Installing Python dependencies..."
  235. "$SCRIPT_DIR/venv/bin/python" -m pip install --upgrade pip > /dev/null 2>&1
  236. "$SCRIPT_DIR/venv/bin/pip" install -r "$SCRIPT_DIR/requirements.txt" > /dev/null 2>&1
  237. # Change ownership to the actual user (not root)
  238. chown -R "$ACTUAL_USER:$ACTUAL_USER" "$SCRIPT_DIR/venv"
  239. echo " 🐍 Python virtual environment ready"
  240. }
  241. # Main installation process
  242. echo "Starting complete installation..."
  243. echo ""
  244. # Install everything
  245. setup_python_environment
  246. install_scripts
  247. setup_systemd
  248. configure_boot_settings
  249. setup_touch_rotation
  250. hide_mouse_cursor
  251. setup_kiosk_optimizations
  252. echo ""
  253. echo "🎉 Installation Complete!"
  254. echo "========================"
  255. echo ""
  256. echo "📟 Detected: $PI_MODEL"
  257. if [ "$IS_PI5" = true ]; then
  258. echo " └─ Using Pi 5 optimized settings (DSI-2, dedicated VRAM)"
  259. fi
  260. echo ""
  261. echo "✅ Python virtual environment created at: $SCRIPT_DIR/venv"
  262. echo "✅ System scripts installed in /usr/local/bin/"
  263. echo "✅ Systemd service configured for auto-start"
  264. echo "✅ Mouse cursor hiding configured (Qt + unclutter)"
  265. echo "✅ Kiosk optimizations applied"
  266. echo ""
  267. echo "🔧 Service Management:"
  268. echo " Start now: sudo systemctl start dune-weaver-touch"
  269. echo " Stop: sudo systemctl stop dune-weaver-touch"
  270. echo " Status: sudo systemctl status dune-weaver-touch"
  271. echo " Logs: sudo journalctl -u dune-weaver-touch -f"
  272. echo ""
  273. echo "🚀 Next Steps:"
  274. echo " 1. ${YELLOW}⚠️ REBOOT REQUIRED${NC} for config.txt changes (vc4-kms-v3d) to take effect"
  275. echo " 2. Configure auto-login (recommended for kiosk mode):"
  276. echo " sudo ./setup-autologin.sh (automated setup)"
  277. echo " OR manually: sudo raspi-config → System Options → Boot/Auto Login → Desktop Autologin"
  278. echo " 3. After reboot, the app will start automatically on boot via systemd service"
  279. echo " 4. Check the logs if you encounter any issues: sudo journalctl -u dune-weaver-touch -f"
  280. echo ""
  281. echo "💡 To start the service now without rebooting:"
  282. echo " sudo systemctl start dune-weaver-touch"
  283. echo ""
  284. echo "🛠️ For development/testing (run manually):"
  285. echo " cd $SCRIPT_DIR"
  286. echo " ./run.sh"
  287. echo ""
  288. echo "⚙️ To change boot/login settings later:"
  289. echo " sudo ./configure-boot.sh"
  290. echo ""
  291. # Ask if user wants to start now
  292. read -p "🤔 Would you like to start the service now? (y/N): " -n 1 -r
  293. echo
  294. if [[ $REPLY =~ ^[Yy]$ ]]; then
  295. echo "🚀 Starting Dune Weaver Touch service..."
  296. systemctl start dune-weaver-touch
  297. sleep 2
  298. systemctl status dune-weaver-touch --no-pager -l
  299. echo ""
  300. echo "✅ Service started! Check the status above."
  301. fi
  302. echo ""
  303. echo "🎯 Installation completed successfully!"