setup_kiosk.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. #!/bin/bash
  2. #############################################
  3. # Dune Weaver Touch - Kiosk Mode Setup Script
  4. # For Raspberry Pi with Freenove 5" DSI Display
  5. # Author: Dune Weaver Team
  6. # Version: 1.0
  7. #############################################
  8. set -e # Exit on error
  9. # Color codes for output
  10. RED='\033[0;31m'
  11. GREEN='\033[0;32m'
  12. YELLOW='\033[1;33m'
  13. NC='\033[0m' # No Color
  14. # Configuration variables
  15. SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
  16. USER_NAME=$(whoami)
  17. HOME_DIR="/home/$USER_NAME"
  18. APP_DIR="$SCRIPT_DIR"
  19. SERVICE_NAME="dune-weaver-kiosk"
  20. VENV_PATH="$APP_DIR/venv/bin/activate"
  21. # Display banner
  22. echo -e "${GREEN}"
  23. echo "================================================"
  24. echo " Dune Weaver Touch - Kiosk Setup"
  25. echo " Freenove 5\" DSI Display (800x480)"
  26. echo "================================================"
  27. echo -e "${NC}"
  28. # Function to detect Raspberry Pi model
  29. detect_pi_model() {
  30. local model=$(cat /proc/cpuinfo | grep "Model" | cut -d ':' -f 2 | sed 's/^ *//')
  31. if [[ $model == *"Pi 3"* ]]; then
  32. echo "3"
  33. elif [[ $model == *"Pi 4"* ]]; then
  34. echo "4"
  35. elif [[ $model == *"Pi 5"* ]]; then
  36. echo "5"
  37. else
  38. echo "unknown"
  39. fi
  40. }
  41. # Function to backup files
  42. backup_file() {
  43. local file=$1
  44. if [ -f "$file" ]; then
  45. cp "$file" "${file}.backup.$(date +%Y%m%d_%H%M%S)"
  46. echo -e "${YELLOW}Backed up: $file${NC}"
  47. fi
  48. }
  49. # Function to setup boot configuration
  50. setup_boot_config() {
  51. echo -e "${GREEN}Configuring boot settings for DSI display...${NC}"
  52. backup_file "/boot/config.txt"
  53. local pi_model=$(detect_pi_model)
  54. echo -e "${GREEN}Detected Raspberry Pi Model: $pi_model${NC}"
  55. # Remove conflicting HDMI settings if they exist
  56. sudo sed -i '/hdmi_force_hotplug/d' /boot/config.txt
  57. sudo sed -i '/hdmi_group/d' /boot/config.txt
  58. sudo sed -i '/hdmi_mode/d' /boot/config.txt
  59. sudo sed -i '/hdmi_cvt/d' /boot/config.txt
  60. sudo sed -i '/hdmi_drive/d' /boot/config.txt
  61. sudo sed -i '/config_hdmi_boost/d' /boot/config.txt
  62. sudo sed -i '/dtoverlay=ads7846/d' /boot/config.txt
  63. # Remove old overlays
  64. sudo sed -i '/dtoverlay=vc4-fkms-v3d/d' /boot/config.txt
  65. sudo sed -i '/dtoverlay=vc4-kms-v3d/d' /boot/config.txt
  66. # Add proper configuration based on Pi model
  67. if [ "$pi_model" == "3" ]; then
  68. # Pi 3 configuration
  69. echo -e "${GREEN}Configuring for Pi 3...${NC}"
  70. cat << EOF | sudo tee -a /boot/config.txt > /dev/null
  71. # Dune Weaver Kiosk - DSI Display Configuration (Pi 3)
  72. dtoverlay=vc4-fkms-v3d
  73. gpu_mem=128
  74. max_framebuffers=2
  75. display_auto_detect=1
  76. disable_overscan=1
  77. display_lcd_rotate=2
  78. EOF
  79. else
  80. # Pi 4/5 configuration
  81. echo -e "${GREEN}Configuring for Pi 4/5...${NC}"
  82. cat << EOF | sudo tee -a /boot/config.txt > /dev/null
  83. # Dune Weaver Kiosk - DSI Display Configuration (Pi 4/5)
  84. dtoverlay=vc4-kms-v3d
  85. gpu_mem=128
  86. max_framebuffers=2
  87. display_auto_detect=1
  88. disable_overscan=1
  89. display_lcd_rotate=2
  90. EOF
  91. fi
  92. # Add common settings
  93. cat << EOF | sudo tee -a /boot/config.txt > /dev/null
  94. # Common settings
  95. dtparam=i2c_arm=on
  96. dtparam=spi=on
  97. enable_uart=1
  98. max_usb_current=1
  99. # Disable splash screens for faster boot
  100. disable_splash=1
  101. EOF
  102. echo -e "${GREEN}Boot configuration updated${NC}"
  103. }
  104. # Function to install dependencies
  105. install_dependencies() {
  106. echo -e "${GREEN}Installing required dependencies...${NC}"
  107. sudo apt-get update
  108. sudo apt-get install -y \
  109. libgles2-mesa \
  110. libgles2-mesa-dev \
  111. libgbm-dev \
  112. libdrm-dev \
  113. libinput-dev \
  114. libudev-dev \
  115. libxkbcommon-dev \
  116. fbset \
  117. evtest \
  118. qtvirtualkeyboard-plugin \
  119. qml-module-qtquick-virtualkeyboard \
  120. qt6-virtualkeyboard-plugin \
  121. qml6-module-qt-labs-qmlmodels || {
  122. echo -e "${YELLOW}Some packages may not be available, continuing...${NC}"
  123. }
  124. echo -e "${GREEN}Dependencies installed${NC}"
  125. }
  126. # Function to create startup script
  127. create_startup_script() {
  128. echo -e "${GREEN}Creating startup script...${NC}"
  129. local pi_model=$(detect_pi_model)
  130. local START_SCRIPT="$APP_DIR/start_kiosk.sh"
  131. cat << 'EOF' > "$START_SCRIPT"
  132. #!/bin/bash
  133. # Dune Weaver Touch Kiosk Startup Script
  134. # Auto-generated by setup_kiosk.sh
  135. # Wait for system to fully boot
  136. sleep 10
  137. # Log file
  138. LOG_FILE="/tmp/dune-weaver-kiosk.log"
  139. exec &> >(tee -a "$LOG_FILE")
  140. echo "========================================="
  141. echo "Starting Dune Weaver Touch Kiosk"
  142. echo "Date: $(date)"
  143. echo "========================================="
  144. # Detect Pi model for platform selection
  145. PI_MODEL=$(cat /proc/cpuinfo | grep "Model" | cut -d ':' -f 2)
  146. # Set working directory
  147. cd "$(dirname "$0")"
  148. # Check if virtual environment exists
  149. if [ ! -f "bin/activate" ]; then
  150. echo "ERROR: Virtual environment not found!"
  151. exit 1
  152. fi
  153. # Activate virtual environment
  154. source bin/activate
  155. # Function to run with LinuxFB (Pi 3 with DSI)
  156. run_linuxfb() {
  157. export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
  158. export QT_QPA_FONTDIR=/usr/share/fonts/truetype
  159. export QT_QPA_FB_HIDECURSOR=1
  160. export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0:rotate=180
  161. # Enable Virtual Keyboard
  162. export QT_IM_MODULE=qtvirtualkeyboard
  163. export QT_VIRTUALKEYBOARD_STYLE=default
  164. export QT_VIRTUALKEYBOARD_LAYOUT_PATH=/usr/share/qt5/qtvirtualkeyboard/layouts
  165. echo "Starting with LinuxFB platform and virtual keyboard..."
  166. python main.py
  167. }
  168. # Function to run with EGLFS (Pi 4/5 with DSI)
  169. run_eglfs() {
  170. export QT_QPA_PLATFORM=eglfs
  171. export QT_QPA_EGLFS_WIDTH=800
  172. export QT_QPA_EGLFS_HEIGHT=480
  173. export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
  174. export QT_QPA_EGLFS_KMS_ATOMIC=1
  175. export QT_QPA_EGLFS_HIDECURSOR=1
  176. export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0:rotate=180
  177. # Enable Virtual Keyboard
  178. export QT_IM_MODULE=qtvirtualkeyboard
  179. export QT_VIRTUALKEYBOARD_STYLE=default
  180. export QT_VIRTUALKEYBOARD_LAYOUT_PATH=/usr/share/qt5/qtvirtualkeyboard/layouts
  181. echo "Starting with EGLFS platform and virtual keyboard..."
  182. python main.py
  183. }
  184. # Check for DRM device (needed for EGLFS)
  185. if [ -e /dev/dri/card0 ] || [ -e /dev/dri/card1 ]; then
  186. echo "DRM device found, using EGLFS"
  187. run_eglfs
  188. else
  189. echo "No DRM device, using LinuxFB"
  190. run_linuxfb
  191. fi
  192. echo "Application exited at $(date)"
  193. EOF
  194. chmod +x "$START_SCRIPT"
  195. echo -e "${GREEN}Startup script created: $START_SCRIPT${NC}"
  196. }
  197. # Function to create systemd service
  198. create_systemd_service() {
  199. echo -e "${GREEN}Creating systemd service...${NC}"
  200. local SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
  201. cat << EOF | sudo tee "$SERVICE_FILE" > /dev/null
  202. [Unit]
  203. Description=Dune Weaver Touch Kiosk Mode
  204. After=multi-user.target graphical.target
  205. Wants=network-online.target
  206. After=network-online.target
  207. [Service]
  208. Type=simple
  209. User=$USER_NAME
  210. Group=$USER_NAME
  211. WorkingDirectory=$APP_DIR
  212. # Auto-restart on failure
  213. Restart=always
  214. RestartSec=10
  215. # Start script
  216. ExecStart=$APP_DIR/start_kiosk.sh
  217. # Stop timeout
  218. TimeoutStopSec=10
  219. # Logging
  220. StandardOutput=journal
  221. StandardError=journal
  222. [Install]
  223. WantedBy=multi-user.target
  224. EOF
  225. # Reload systemd and enable service
  226. sudo systemctl daemon-reload
  227. sudo systemctl enable "${SERVICE_NAME}.service"
  228. echo -e "${GREEN}Systemd service created and enabled${NC}"
  229. }
  230. # Function to create uninstall script
  231. create_uninstall_script() {
  232. echo -e "${GREEN}Creating uninstall script...${NC}"
  233. cat << 'EOF' > "$APP_DIR/uninstall_kiosk.sh"
  234. #!/bin/bash
  235. # Dune Weaver Touch - Kiosk Mode Uninstall Script
  236. set -e
  237. RED='\033[0;31m'
  238. GREEN='\033[0;32m'
  239. YELLOW='\033[1;33m'
  240. NC='\033[0m'
  241. SERVICE_NAME="dune-weaver-kiosk"
  242. echo -e "${YELLOW}Uninstalling Dune Weaver Kiosk Mode...${NC}"
  243. # Stop and disable service
  244. if systemctl list-units --full -all | grep -Fq "${SERVICE_NAME}.service"; then
  245. echo "Stopping and disabling service..."
  246. sudo systemctl stop "${SERVICE_NAME}.service" 2>/dev/null || true
  247. sudo systemctl disable "${SERVICE_NAME}.service" 2>/dev/null || true
  248. sudo rm -f "/etc/systemd/system/${SERVICE_NAME}.service"
  249. sudo systemctl daemon-reload
  250. echo -e "${GREEN}Service removed${NC}"
  251. fi
  252. # Remove startup script
  253. if [ -f "start_kiosk.sh" ]; then
  254. rm -f "start_kiosk.sh"
  255. echo -e "${GREEN}Startup script removed${NC}"
  256. fi
  257. # Restore boot config if backup exists
  258. LATEST_BACKUP=$(ls -t /boot/config.txt.backup.* 2>/dev/null | head -n1)
  259. if [ -n "$LATEST_BACKUP" ]; then
  260. echo -e "${YELLOW}Found backup: $LATEST_BACKUP${NC}"
  261. read -p "Restore boot configuration from backup? (y/n): " -n 1 -r
  262. echo
  263. if [[ $REPLY =~ ^[Yy]$ ]]; then
  264. sudo cp "$LATEST_BACKUP" /boot/config.txt
  265. echo -e "${GREEN}Boot configuration restored${NC}"
  266. echo -e "${YELLOW}Reboot required for changes to take effect${NC}"
  267. fi
  268. fi
  269. echo -e "${GREEN}Kiosk mode uninstalled successfully${NC}"
  270. echo -e "${YELLOW}You may want to reboot your Raspberry Pi${NC}"
  271. EOF
  272. chmod +x "$APP_DIR/uninstall_kiosk.sh"
  273. echo -e "${GREEN}Uninstall script created: $APP_DIR/uninstall_kiosk.sh${NC}"
  274. }
  275. # Function to test the display
  276. test_display() {
  277. echo -e "${GREEN}Testing display configuration...${NC}"
  278. # Check framebuffer
  279. if [ -e /dev/fb0 ]; then
  280. echo -e "${GREEN}✓ Framebuffer device found${NC}"
  281. fbset -i | head -5
  282. else
  283. echo -e "${RED}✗ No framebuffer device found${NC}"
  284. fi
  285. # Check for DRM device
  286. if [ -e /dev/dri/card0 ] || [ -e /dev/dri/card1 ]; then
  287. echo -e "${GREEN}✓ DRM device found${NC}"
  288. ls -la /dev/dri/
  289. else
  290. echo -e "${YELLOW}! No DRM device (normal for Pi 3)${NC}"
  291. fi
  292. # Check touch input
  293. echo -e "${GREEN}Available input devices:${NC}"
  294. ls -la /dev/input/event* 2>/dev/null || echo "No input devices found"
  295. }
  296. # Main installation function
  297. install_kiosk() {
  298. echo -e "${GREEN}Starting Kiosk Mode Installation...${NC}"
  299. # Check if running on Raspberry Pi
  300. if ! grep -q "Raspberry Pi" /proc/cpuinfo; then
  301. echo -e "${YELLOW}Warning: This doesn't appear to be a Raspberry Pi${NC}"
  302. read -p "Continue anyway? (y/n): " -n 1 -r
  303. echo
  304. if [[ ! $REPLY =~ ^[Yy]$ ]]; then
  305. exit 1
  306. fi
  307. fi
  308. # Check if virtual environment exists
  309. if [ ! -f "$VENV_PATH" ]; then
  310. echo -e "${RED}Error: Virtual environment not found at $VENV_PATH${NC}"
  311. echo "Please run this script from the dune-weaver-touch directory"
  312. exit 1
  313. fi
  314. # Install steps
  315. install_dependencies
  316. setup_boot_config
  317. create_startup_script
  318. create_systemd_service
  319. create_uninstall_script
  320. test_display
  321. echo -e "${GREEN}"
  322. echo "================================================"
  323. echo " Installation Complete!"
  324. echo "================================================"
  325. echo -e "${NC}"
  326. echo
  327. echo "Next steps:"
  328. echo "1. Reboot your Raspberry Pi:"
  329. echo " ${GREEN}sudo reboot${NC}"
  330. echo
  331. echo "2. The kiosk will start automatically after reboot"
  332. echo
  333. echo "3. To manually control the service:"
  334. echo " Start: ${GREEN}sudo systemctl start ${SERVICE_NAME}${NC}"
  335. echo " Stop: ${GREEN}sudo systemctl stop ${SERVICE_NAME}${NC}"
  336. echo " Status: ${GREEN}sudo systemctl status ${SERVICE_NAME}${NC}"
  337. echo " Logs: ${GREEN}journalctl -u ${SERVICE_NAME} -f${NC}"
  338. echo
  339. echo "4. To uninstall:"
  340. echo " ${GREEN}./uninstall_kiosk.sh${NC}"
  341. echo
  342. read -p "Reboot now? (y/n): " -n 1 -r
  343. echo
  344. if [[ $REPLY =~ ^[Yy]$ ]]; then
  345. sudo reboot
  346. fi
  347. }
  348. # Parse command line arguments
  349. case "${1:-}" in
  350. uninstall)
  351. if [ -f "$APP_DIR/uninstall_kiosk.sh" ]; then
  352. "$APP_DIR/uninstall_kiosk.sh"
  353. else
  354. echo -e "${RED}Uninstall script not found${NC}"
  355. exit 1
  356. fi
  357. ;;
  358. test)
  359. test_display
  360. ;;
  361. status)
  362. sudo systemctl status "${SERVICE_NAME}.service"
  363. ;;
  364. *)
  365. install_kiosk
  366. ;;
  367. esac