dw 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. #!/bin/bash
  2. #
  3. # Dune Weaver CLI
  4. #
  5. # Usage: dw <command>
  6. #
  7. # Commands:
  8. # install Run initial setup
  9. # start Start Dune Weaver
  10. # stop Stop Dune Weaver
  11. # restart Restart Dune Weaver
  12. # update Pull latest changes and restart
  13. # logs View live logs (Ctrl+C to exit)
  14. # status Show service status
  15. # shell Open a shell with the venv activated
  16. # checkout Switch to a branch and rebuild
  17. # touch Manage touch screen app
  18. # wifi Manage WiFi and hotspot
  19. # flash Flash FluidNC firmware onto ESP32
  20. # help Show this help message
  21. #
  22. set -e
  23. # Colors
  24. RED='\033[0;31m'
  25. GREEN='\033[0;32m'
  26. YELLOW='\033[1;33m'
  27. BLUE='\033[0;34m'
  28. NC='\033[0m'
  29. # Find dune-weaver directory
  30. find_install_dir() {
  31. # Check common locations
  32. if [[ -f "$HOME/dune-weaver/main.py" ]]; then
  33. echo "$HOME/dune-weaver"
  34. elif [[ -f "/home/pi/dune-weaver/main.py" ]]; then
  35. echo "/home/pi/dune-weaver"
  36. elif [[ -f "./main.py" ]]; then
  37. pwd
  38. else
  39. echo ""
  40. fi
  41. }
  42. INSTALL_DIR=$(find_install_dir)
  43. # Check if installed
  44. check_installed() {
  45. if [[ -z "$INSTALL_DIR" ]]; then
  46. echo -e "${RED}Error: Dune Weaver not found${NC}"
  47. echo ""
  48. echo "Please install first:"
  49. echo " git clone https://github.com/tuanchris/dune-weaver --single-branch"
  50. echo " cd dune-weaver"
  51. echo " dw install"
  52. exit 1
  53. fi
  54. }
  55. # Commands
  56. cmd_install() {
  57. if [[ -z "$INSTALL_DIR" ]]; then
  58. # Not installed, check if we're in the right directory
  59. if [[ -f "./main.py" ]] && [[ -f "./requirements.txt" ]]; then
  60. INSTALL_DIR=$(pwd)
  61. else
  62. echo -e "${RED}Error: Run this from the dune-weaver directory${NC}"
  63. echo ""
  64. echo " git clone https://github.com/tuanchris/dune-weaver --single-branch"
  65. echo " cd dune-weaver"
  66. echo " dw install"
  67. exit 1
  68. fi
  69. fi
  70. cd "$INSTALL_DIR"
  71. bash setup-pi.sh "$@"
  72. }
  73. cmd_start() {
  74. check_installed
  75. echo -e "${BLUE}Starting Dune Weaver...${NC}"
  76. sudo systemctl start dune-weaver
  77. echo -e "${GREEN}Started!${NC} Access at http://$(hostname -I | awk '{print $1}')"
  78. }
  79. cmd_stop() {
  80. check_installed
  81. echo -e "${BLUE}Stopping Dune Weaver...${NC}"
  82. sudo systemctl stop dune-weaver
  83. echo -e "${GREEN}Stopped${NC}"
  84. }
  85. cmd_restart() {
  86. check_installed
  87. echo -e "${BLUE}Restarting Dune Weaver...${NC}"
  88. sudo systemctl restart dune-weaver
  89. echo -e "${GREEN}Restarted${NC}"
  90. }
  91. cmd_update() {
  92. check_installed
  93. echo -e "${BLUE}Updating Dune Weaver...${NC}"
  94. cd "$INSTALL_DIR"
  95. # Check if we should skip the pull phase (called after re-exec)
  96. if [[ "$1" != "--continue" ]]; then
  97. echo "Pulling latest code..."
  98. git config --global --add safe.directory "$INSTALL_DIR" 2>/dev/null || true
  99. git pull
  100. # Update dw CLI
  101. echo "Updating dw command..."
  102. sudo cp "$INSTALL_DIR/dw" /usr/local/bin/dw
  103. sudo chmod +x /usr/local/bin/dw
  104. # Re-exec with the new script to ensure new code runs
  105. echo "Restarting with updated CLI..."
  106. exec /usr/local/bin/dw update --continue
  107. fi
  108. # Detect Docker-to-native migration: no venv means first native run
  109. if [[ ! -d "$INSTALL_DIR/.venv" ]]; then
  110. echo ""
  111. echo -e "${YELLOW}Migrating to native deployment (first time setup)...${NC}"
  112. echo "This may take a few minutes."
  113. echo ""
  114. # Install native system dependencies (nginx, python3-venv, gcc, etc.)
  115. echo "Installing system dependencies..."
  116. sudo apt update
  117. sudo DEBIAN_FRONTEND=noninteractive apt install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" \
  118. python3-venv python3-pip python3-dev \
  119. gcc g++ make swig unzip wget \
  120. libjpeg-dev zlib1g-dev \
  121. libgpiod-dev gpiod \
  122. nginx
  123. # Create Python venv
  124. echo "Creating Python virtual environment..."
  125. python3 -m venv .venv
  126. # Stop and remove Docker containers/service if running
  127. if command -v docker &> /dev/null; then
  128. echo "Stopping Docker containers..."
  129. sudo docker compose down 2>/dev/null || true
  130. fi
  131. fi
  132. echo "Updating Python dependencies..."
  133. source .venv/bin/activate
  134. pip install -r requirements.txt
  135. # Update nginx config
  136. echo "Updating nginx config..."
  137. sudo cp "$INSTALL_DIR/nginx/dune-weaver.conf" /etc/nginx/sites-available/dune-weaver.conf
  138. sudo sed -i "s|INSTALL_DIR_PLACEHOLDER|$INSTALL_DIR|g" /etc/nginx/sites-available/dune-weaver.conf
  139. sudo ln -sf /etc/nginx/sites-available/dune-weaver.conf /etc/nginx/sites-enabled/dune-weaver.conf
  140. sudo rm -f /etc/nginx/sites-enabled/default
  141. sudo nginx -t && sudo systemctl restart nginx
  142. # Update systemd service
  143. echo "Updating systemd service..."
  144. sudo cp "$INSTALL_DIR/dune-weaver.service" /etc/systemd/system/dune-weaver.service
  145. sudo sed -i "s|USER_PLACEHOLDER|$USER|g" /etc/systemd/system/dune-weaver.service
  146. sudo sed -i "s|INSTALL_DIR_PLACEHOLDER|$INSTALL_DIR|g" /etc/systemd/system/dune-weaver.service
  147. sudo systemctl daemon-reload
  148. sudo systemctl enable dune-weaver
  149. echo "Restarting service..."
  150. sudo systemctl restart dune-weaver
  151. # Install/update WiFi host scripts if not present
  152. if [[ -f "$INSTALL_DIR/wifi/setup-wifi.sh" ]]; then
  153. if [[ ! -f /usr/local/bin/autohotspot ]]; then
  154. echo ""
  155. echo -e "${BLUE}Installing autohotspot WiFi scripts...${NC}"
  156. sudo bash "$INSTALL_DIR/wifi/setup-wifi.sh"
  157. else
  158. # Always update the script and service files to latest
  159. echo "Updating WiFi host scripts..."
  160. sudo cp "$INSTALL_DIR/wifi/autohotspot" /usr/local/bin/autohotspot
  161. sudo chmod +x /usr/local/bin/autohotspot
  162. # Update service/timer files
  163. sudo cp "$INSTALL_DIR/wifi/autohotspot.service" /etc/systemd/system/autohotspot.service
  164. sudo cp "$INSTALL_DIR/wifi/autohotspot-check.service" /etc/systemd/system/autohotspot-check.service 2>/dev/null || true
  165. sudo cp "$INSTALL_DIR/wifi/autohotspot-check.timer" /etc/systemd/system/autohotspot-check.timer 2>/dev/null || true
  166. sudo systemctl daemon-reload
  167. sudo systemctl enable autohotspot-check.timer 2>/dev/null || true
  168. fi
  169. fi
  170. # Update touch app if installed (check both directory and service exist)
  171. local touch_dir="$INSTALL_DIR/dune-weaver-touch"
  172. if [[ -d "$touch_dir" ]] && systemctl list-unit-files dune-weaver-touch.service 2>/dev/null | grep -q dune-weaver-touch; then
  173. echo ""
  174. echo -e "${BLUE}Updating touch app...${NC}"
  175. cd "$touch_dir"
  176. # Update Python dependencies (code already pulled with main repo)
  177. if [[ -f "requirements.txt" ]] && [[ -d ".venv" ]]; then
  178. echo "Updating touch app dependencies..."
  179. source .venv/bin/activate
  180. pip install -q -r requirements.txt
  181. deactivate
  182. fi
  183. # Restart to apply changes
  184. sudo systemctl restart dune-weaver-touch
  185. echo -e "${GREEN}Touch app updated!${NC}"
  186. fi
  187. echo -e "${GREEN}Update complete!${NC}"
  188. echo ""
  189. echo -e "${YELLOW}Please reload the web page in your browser to see the changes.${NC}"
  190. }
  191. cmd_logs() {
  192. check_installed
  193. # Parse optional line count (e.g., dw logs 100)
  194. local lines="${1:-}"
  195. if [[ -n "$lines" ]]; then
  196. sudo journalctl -u dune-weaver -n "$lines"
  197. else
  198. sudo journalctl -u dune-weaver -f
  199. fi
  200. }
  201. cmd_status() {
  202. check_installed
  203. sudo systemctl status dune-weaver
  204. }
  205. cmd_shell() {
  206. check_installed
  207. cd "$INSTALL_DIR"
  208. echo -e "${BLUE}Activating venv...${NC}"
  209. exec bash --init-file <(echo "source '$INSTALL_DIR/.venv/bin/activate'; cd '$INSTALL_DIR'; echo 'Dune Weaver venv activated. Type \"exit\" to leave.'")
  210. }
  211. # Touch app commands (systemd service)
  212. cmd_touch() {
  213. local subcmd="${1:-help}"
  214. case "$subcmd" in
  215. logs)
  216. local lines="${2:-}"
  217. if [[ -n "$lines" ]]; then
  218. sudo journalctl -u dune-weaver-touch -n "$lines"
  219. else
  220. sudo journalctl -u dune-weaver-touch -f
  221. fi
  222. ;;
  223. restart)
  224. echo -e "${BLUE}Restarting touch app...${NC}"
  225. sudo systemctl restart dune-weaver-touch
  226. echo -e "${GREEN}Touch app restarted${NC}"
  227. ;;
  228. stop)
  229. echo -e "${BLUE}Stopping touch app...${NC}"
  230. sudo systemctl stop dune-weaver-touch
  231. echo -e "${GREEN}Touch app stopped${NC}"
  232. ;;
  233. start)
  234. echo -e "${BLUE}Starting touch app...${NC}"
  235. sudo systemctl start dune-weaver-touch
  236. echo -e "${GREEN}Touch app started${NC}"
  237. ;;
  238. status)
  239. sudo systemctl status dune-weaver-touch
  240. ;;
  241. install)
  242. check_installed
  243. local touch_dir="$INSTALL_DIR/dune-weaver-touch"
  244. if [[ ! -f "$touch_dir/install.sh" ]]; then
  245. echo -e "${RED}Touch app installer not found at $touch_dir/install.sh${NC}"
  246. echo "Make sure you have the dune-weaver-touch directory in your dune-weaver folder."
  247. exit 1
  248. fi
  249. echo -e "${BLUE}Running touch app installer...${NC}"
  250. cd "$touch_dir"
  251. sudo bash install.sh
  252. ;;
  253. help|*)
  254. echo -e "${GREEN}Touch App Commands${NC}"
  255. echo ""
  256. echo "Usage: dw touch <command>"
  257. echo ""
  258. echo "Commands:"
  259. echo " install Install touch app (clone, setup, enable service)"
  260. echo " logs [N] View logs (N lines or follow if omitted)"
  261. echo " restart Restart touch app"
  262. echo " stop Stop touch app"
  263. echo " start Start touch app"
  264. echo " status Show touch app status"
  265. echo " help Show this help message"
  266. ;;
  267. esac
  268. }
  269. cmd_checkout() {
  270. check_installed
  271. local branch="$1"
  272. if [[ -z "$branch" ]]; then
  273. echo -e "${RED}Usage: dw checkout <branch>${NC}"
  274. echo ""
  275. echo "Examples:"
  276. echo " dw checkout main"
  277. echo " dw checkout feature/security-settings-split"
  278. echo ""
  279. echo "Current branch: $(git -C "$INSTALL_DIR" rev-parse --abbrev-ref HEAD)"
  280. exit 1
  281. fi
  282. cd "$INSTALL_DIR"
  283. # Repo may be cloned with --single-branch; fetch the target branch explicitly
  284. echo -e "${BLUE}Fetching branch ${branch}...${NC}"
  285. if ! git fetch origin "$branch" 2>/dev/null; then
  286. echo -e "${RED}Branch '${branch}' not found on remote${NC}"
  287. exit 1
  288. fi
  289. # Checkout: create local tracking branch if it doesn't exist
  290. if git show-ref --verify --quiet "refs/heads/$branch"; then
  291. git checkout "$branch"
  292. git pull
  293. else
  294. git checkout -b "$branch" "origin/$branch"
  295. fi
  296. echo -e "Switched to branch: ${GREEN}${branch}${NC}"
  297. # Update Python dependencies
  298. echo "Updating Python dependencies..."
  299. source .venv/bin/activate
  300. pip install -r requirements.txt
  301. # Update dw CLI from the new branch
  302. sudo cp "$INSTALL_DIR/dw" /usr/local/bin/dw
  303. sudo chmod +x /usr/local/bin/dw
  304. # Restart service
  305. sudo systemctl restart dune-weaver
  306. # Install WiFi scripts if available on this branch but not yet installed
  307. if [[ -f "$INSTALL_DIR/wifi/setup-wifi.sh" ]] && [[ ! -f /usr/local/bin/autohotspot ]]; then
  308. echo ""
  309. echo -e "${BLUE}Installing autohotspot WiFi scripts...${NC}"
  310. sudo bash "$INSTALL_DIR/wifi/setup-wifi.sh"
  311. fi
  312. echo -e "${GREEN}Checkout complete!${NC}"
  313. }
  314. # WiFi / Hotspot commands
  315. cmd_wifi() {
  316. local subcmd="${1:-help}"
  317. case "$subcmd" in
  318. status)
  319. check_installed
  320. echo -e "${BLUE}WiFi Status${NC}"
  321. echo ""
  322. # Show current mode
  323. local mode="unknown"
  324. if [[ -f /tmp/dw-wifi-mode ]]; then
  325. mode=$(cat /tmp/dw-wifi-mode)
  326. fi
  327. echo -e "Mode: ${GREEN}${mode}${NC}"
  328. # Show connected network
  329. local ssid
  330. ssid=$(nmcli -t -f GENERAL.CONNECTION dev show wlan0 2>/dev/null | head -1 | cut -d: -f2)
  331. if [[ -n "$ssid" && "$ssid" != "--" ]]; then
  332. echo -e "Network: ${GREEN}${ssid}${NC}"
  333. fi
  334. # Show IP
  335. local ip
  336. ip=$(nmcli -t -f IP4.ADDRESS dev show wlan0 2>/dev/null | head -1 | cut -d: -f2 | cut -d/ -f1)
  337. if [[ -n "$ip" ]]; then
  338. echo -e "IP: ${GREEN}${ip}${NC}"
  339. fi
  340. ;;
  341. scan)
  342. echo -e "${BLUE}Scanning for WiFi networks...${NC}"
  343. nmcli dev wifi rescan 2>/dev/null || true
  344. sleep 2
  345. nmcli dev wifi list
  346. ;;
  347. connect)
  348. echo -e "${BLUE}Available WiFi networks:${NC}"
  349. nmcli dev wifi rescan 2>/dev/null || true
  350. sleep 2
  351. nmcli dev wifi list
  352. echo ""
  353. read -p "Enter SSID to connect to: " ssid
  354. if [[ -z "$ssid" ]]; then
  355. echo -e "${RED}No SSID provided${NC}"
  356. exit 1
  357. fi
  358. read -sp "Enter password (leave empty for open networks): " password
  359. echo ""
  360. # Delete any stale connection profile for this SSID
  361. sudo nmcli con delete "$ssid" 2>/dev/null || true
  362. if [[ -n "$password" ]]; then
  363. # Create connection with explicit security settings
  364. # (nmcli dev wifi connect can fail on Trixie without key-mgmt)
  365. sudo nmcli con add type wifi ifname wlan0 con-name "$ssid" \
  366. ssid "$ssid" \
  367. wifi-sec.key-mgmt wpa-psk \
  368. wifi-sec.psk "$password"
  369. else
  370. sudo nmcli con add type wifi ifname wlan0 con-name "$ssid" \
  371. ssid "$ssid"
  372. fi
  373. echo -e "${BLUE}Connecting to '$ssid'...${NC}"
  374. if sudo nmcli con up "$ssid"; then
  375. echo -e "${GREEN}Connected!${NC}"
  376. else
  377. echo -e "${RED}Failed to connect. Check password and try again.${NC}"
  378. sudo nmcli con delete "$ssid" 2>/dev/null || true
  379. exit 1
  380. fi
  381. ;;
  382. hotspot)
  383. echo -e "${BLUE}Switching to hotspot mode...${NC}"
  384. sudo nmcli dev disconnect wlan0 2>/dev/null || true
  385. sudo nmcli con up DuneWeaver-Hotspot 2>/dev/null
  386. echo "hotspot" | sudo tee /tmp/dw-wifi-mode > /dev/null
  387. echo -e "${GREEN}Hotspot active!${NC} Connect to the 'Dune Weaver' WiFi network."
  388. ;;
  389. setup)
  390. check_installed
  391. cd "$INSTALL_DIR"
  392. sudo bash wifi/setup-wifi.sh
  393. ;;
  394. help|*)
  395. echo -e "${GREEN}WiFi Commands${NC}"
  396. echo ""
  397. echo "Usage: dw wifi <command>"
  398. echo ""
  399. echo "Commands:"
  400. echo " status Show current WiFi mode and connection"
  401. echo " scan Scan for available networks"
  402. echo " connect Interactive: scan + select + connect"
  403. echo " hotspot Force hotspot mode"
  404. echo " setup Run initial autohotspot setup"
  405. echo " help Show this help message"
  406. ;;
  407. esac
  408. }
  409. cmd_flash() {
  410. check_installed
  411. bash "$INSTALL_DIR/flash-fluidnc.sh"
  412. }
  413. cmd_help() {
  414. echo -e "${GREEN}Dune Weaver CLI${NC}"
  415. echo ""
  416. echo "Usage: dw <command>"
  417. echo ""
  418. echo "Commands:"
  419. echo " install Run initial setup"
  420. echo " start Start Dune Weaver"
  421. echo " stop Stop Dune Weaver"
  422. echo " restart Restart Dune Weaver"
  423. echo " update Pull latest changes and restart"
  424. echo " checkout Switch to a branch and rebuild"
  425. echo " logs [N] View logs (N=number of lines, or follow if omitted)"
  426. echo " status Show service status"
  427. echo " shell Open a shell with the venv activated"
  428. echo " touch Manage touch screen app (run 'dw touch help')"
  429. echo " wifi Manage WiFi and hotspot (run 'dw wifi help')"
  430. echo " flash Flash FluidNC firmware onto connected ESP32"
  431. echo " help Show this help message"
  432. echo ""
  433. if [[ -n "$INSTALL_DIR" ]]; then
  434. echo -e "Install directory: ${BLUE}$INSTALL_DIR${NC}"
  435. fi
  436. }
  437. # Main
  438. case "${1:-help}" in
  439. install)
  440. shift
  441. cmd_install "$@"
  442. ;;
  443. start)
  444. cmd_start
  445. ;;
  446. stop)
  447. cmd_stop
  448. ;;
  449. restart)
  450. cmd_restart
  451. ;;
  452. update)
  453. cmd_update "$2"
  454. ;;
  455. checkout)
  456. cmd_checkout "$2"
  457. ;;
  458. logs)
  459. cmd_logs "$2"
  460. ;;
  461. status)
  462. cmd_status
  463. ;;
  464. shell)
  465. cmd_shell
  466. ;;
  467. touch)
  468. shift
  469. cmd_touch "$@"
  470. ;;
  471. wifi)
  472. shift
  473. cmd_wifi "$@"
  474. ;;
  475. flash)
  476. cmd_flash
  477. ;;
  478. help|--help|-h)
  479. cmd_help
  480. ;;
  481. *)
  482. echo -e "${RED}Unknown command: $1${NC}"
  483. echo ""
  484. cmd_help
  485. exit 1
  486. ;;
  487. esac