From 91bedce2d73e8ce20b79c514ce78bdc2a15548e4 Mon Sep 17 00:00:00 2001 From: lhye200 Date: Fri, 15 May 2026 12:08:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E5=AD=98-=E5=AE=89=E8=A3=85=E8=84=9A?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aio-3d-huey.service | 5 +- aio-3d-main.service | 5 +- .../slice_engines/prusa_slicer_engine.py | 48 ++++++- install.sh | 131 ++++++++++++++---- requirements.txt | 31 +++-- 5 files changed, 175 insertions(+), 45 deletions(-) diff --git a/aio-3d-huey.service b/aio-3d-huey.service index 79b1444..35ee00c 100644 --- a/aio-3d-huey.service +++ b/aio-3d-huey.service @@ -5,8 +5,9 @@ After=network.target [Service] User=1000 -WorkingDirectory=/home/lhye200/AIO_3D_Print_Exp/ -ExecStart=/home/lhye200/AIO_3D_Print_Exp/run_huey.sh +# Placeholder path; installer will replace with actual repository path +WorkingDirectory=${REPO_DIR}/ +ExecStart=${REPO_DIR}/run_huey.sh Restart=always RestartSec=5 diff --git a/aio-3d-main.service b/aio-3d-main.service index a2f0dbe..3b5a423 100644 --- a/aio-3d-main.service +++ b/aio-3d-main.service @@ -6,8 +6,9 @@ Wants=aio-3d-huey.service network.target [Service] User=1000 -WorkingDirectory=/home/lhye200/AIO_3D_Print_Exp/ -ExecStart=/home/lhye200/AIO_3D_Print_Exp/run_main.sh +# Placeholder path; installer will replace with actual repository path +WorkingDirectory=${REPO_DIR}/ +ExecStart=${REPO_DIR}/run_main.sh Restart=always RestartSec=5 diff --git a/app/utils/slice_engines/prusa_slicer_engine.py b/app/utils/slice_engines/prusa_slicer_engine.py index 30fde2f..f5ca070 100644 --- a/app/utils/slice_engines/prusa_slicer_engine.py +++ b/app/utils/slice_engines/prusa_slicer_engine.py @@ -2,8 +2,12 @@ import os import subprocess import configparser import uuid +import shutil from app.models import SystemConfig +# Default PrusaSlicer AppImage (aarch64) download URL +PRUSA_DOWNLOAD_URL = "https://github.com/davidk/PrusaSlicer-ARM.AppImage/releases/download/version_2.9.4/PrusaSlicer-2.9.4-aarch64-full.AppImage" + class PrusaSlicerEngine: def __init__(self, print_config_folder=None): self.name = "prusa_slicer" @@ -13,9 +17,18 @@ class PrusaSlicerEngine: def _check_available(self): try: - result = subprocess.run(["prusa-slicer", "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + # Prefer explicit environment variable, then PATH, then a bundled AppImage under the repo + prusa_bin = os.environ.get('PRUSA_SLICER_BIN') or shutil.which('prusa-slicer') or shutil.which('prusa-slicer.exe') + if not prusa_bin: + repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) + local_appimage = os.path.join(repo_root, 'prusaslicer', os.path.basename(PRUSA_DOWNLOAD_URL)) + if os.path.isfile(local_appimage) and os.access(local_appimage, os.X_OK): + prusa_bin = local_appimage + if not prusa_bin: + return False + result = subprocess.run([prusa_bin, "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) return b"Usage:" in result.stdout or b"Slic3r" in result.stdout or b"PrusaSlicer" in result.stdout or result.returncode == 0 - except (FileNotFoundError, OSError): + except Exception: return False def add_ini_keys(self, config_path, target_section, all_configs): @@ -31,12 +44,33 @@ class PrusaSlicerEngine: Slices via prusa-slicer CLI mapping standard kwargs to PRUSA parameters where possible. """ try: + # Determine prusa-slicer binary location (env -> PATH -> bundled appimage in repo) + repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) + prusa_env = os.environ.get('PRUSA_SLICER_BIN') + candidates = [] + if prusa_env: + candidates.append(prusa_env) + which_bin = shutil.which('prusa-slicer') or shutil.which('prusa-slicer.exe') + if which_bin: + candidates.append(which_bin) + candidates.extend([ + os.path.join(repo_root, 'prusaslicer', 'prusa-slicer'), + os.path.join(repo_root, 'prusaslicer', os.path.basename(PRUSA_DOWNLOAD_URL)), + os.path.join(repo_root, os.path.basename(PRUSA_DOWNLOAD_URL)) + ]) + + prusa_bin = None + for c in candidates: + if c and os.path.isfile(c) and os.access(c, os.X_OK): + prusa_bin = c + break + + if not prusa_bin: + # fallback to plain name so subprocess will try PATH and give a clear error + prusa_bin = 'prusa-slicer' + # Base command - command = [ - "/home/lhye200/AIO_3D_Print_Exp/prusaslicer/prusa-slicer", - "-g", stl_filepath, - "--output", gcode_filepath - ] + command = [prusa_bin, '-g', stl_filepath, '--output', gcode_filepath] # Map quality, infill, supports to PrusaSlicer CLI arguments. # Example defaults, normally these would load from an .ini or be dynamically matched. diff --git a/install.sh b/install.sh index 4db28bf..ef70179 100755 --- a/install.sh +++ b/install.sh @@ -1,34 +1,115 @@ -#!/bin/bash +#!/usr/bin/env bash +set -euo pipefail -echo "Start installation AIO_3D_Print_Exp" +REPO_DIR="$(cd "$(dirname "$0")" && pwd)" +VENV_DIR="$REPO_DIR/venv" +PYTHON_BIN="${PYTHON:-python3}" +PRUSA_URL="https://github.com/davidk/PrusaSlicer-ARM.AppImage/releases/download/version_2.9.4/PrusaSlicer-2.9.4-aarch64-full.AppImage" +PRUSA_DIR="$REPO_DIR/prusaslicer" +PRUSA_FILE="$PRUSA_DIR/$(basename "$PRUSA_URL")" -echo "Clean existing installation" -# rm -rf /opt/AIO_3D_Print_Exp -systemctl stop aio-3d-main.service -systemctl stop aio-3d-huey.service -# rm -rf /etc/systemd/system/aio-3d-main.service -# rm -rf /etc/systemd/system/aio-3d-huey.service +echo "Installing AIO_3D_Print_Web_Platform into: $REPO_DIR" +echo "Using python: $PYTHON_BIN" -echo "Copy installation files" -# mkdir -p /opt/AIO_3D_Print_Exp -# cp -r ./. /opt/AIO_3D_Print_Exp/ +echo "Stopping services if running (may require sudo)" +sudo systemctl stop aio-3d-main.service 2>/dev/null || true +sudo systemctl stop aio-3d-huey.service 2>/dev/null || true -echo "Set execute permissions" -# chmod +x /opt/AIO_3D_Print_Exp/run_main.sh -# chmod +x /opt/AIO_3D_Print_Exp/run_huey.sh +echo "Creating virtual environment at $VENV_DIR (if missing)" +if [ ! -d "$VENV_DIR" ]; then + $PYTHON_BIN -m venv "$VENV_DIR" +fi -echo "Copy service files" -# cp /opt/AIO_3D_Print_Exp/aio-3d-main.service /etc/systemd/system/ -# cp /opt/AIO_3D_Print_Exp/aio-3d-huey.service /etc/systemd/system/ -cp /home/lhye200/AIO_3D_Print_Exp/aio-3d-main.service /etc/systemd/system/ -cp /home/lhye200/AIO_3D_Print_Exp/aio-3d-huey.service /etc/systemd/system/ +echo "Activating virtualenv and installing Python requirements" +# shellcheck disable=SC1091 +source "$VENV_DIR/bin/activate" +# Detect http(s) proxy (respect both lowercase and uppercase env vars) +PROXY="" +if [ -n "${HTTPS_PROXY:-}" ]; then + PROXY="$HTTPS_PROXY" +elif [ -n "${https_proxy:-}" ]; then + PROXY="$https_proxy" +elif [ -n "${HTTP_PROXY:-}" ]; then + PROXY="$HTTP_PROXY" +elif [ -n "${http_proxy:-}" ]; then + PROXY="$http_proxy" +fi -echo "Reload systemd daemon" -systemctl daemon-reload -systemctl enable aio-3d-main.service -systemctl enable aio-3d-huey.service -systemctl start aio-3d-huey.service -systemctl start aio-3d-main.service +pip_with_proxy() { + # Usage: pip_with_proxy install [args...] + if [ -n "$PROXY" ] && [ "$1" = "install" ]; then + shift + pip install --proxy "$PROXY" "$@" + else + pip "$@" + fi +} + +pip_with_proxy install --upgrade pip setuptools wheel +if [ -f "$REPO_DIR/requirements.txt" ]; then + pip_with_proxy install -r "$REPO_DIR/requirements.txt" +else + echo "Warning: requirements.txt not found in $REPO_DIR" +fi + +echo "Ensure run scripts are executable" +chmod +x "$REPO_DIR/run_main.sh" "$REPO_DIR/run_huey.sh" + +echo "Checking PrusaSlicer AppImage (optional)" +mkdir -p "$PRUSA_DIR" +if [ ! -f "$PRUSA_FILE" ]; then + echo "Downloading PrusaSlicer AppImage to $PRUSA_FILE" + if command -v curl >/dev/null 2>&1; then + if [ -n "$PROXY" ]; then + curl -x "$PROXY" -L -o "$PRUSA_FILE" "$PRUSA_URL" + else + curl -L -o "$PRUSA_FILE" "$PRUSA_URL" + fi + elif command -v wget >/dev/null 2>&1; then + if [ -n "$PROXY" ]; then + env HTTP_PROXY="$PROXY" HTTPS_PROXY="$PROXY" wget -O "$PRUSA_FILE" "$PRUSA_URL" + else + wget -O "$PRUSA_FILE" "$PRUSA_URL" + fi + else + echo "Warning: neither curl nor wget found; cannot download PrusaSlicer AppImage automatically." + fi + if [ -f "$PRUSA_FILE" ]; then + chmod +x "$PRUSA_FILE" + fi +else + echo "PrusaSlicer AppImage already present: $PRUSA_FILE" +fi + +echo "Prepare and install systemd service files (requires sudo)" +for svc in "aio-3d-main.service" "aio-3d-huey.service"; do + SRC="$REPO_DIR/$svc" + if [ ! -f "$SRC" ]; then + echo "Warning: $SRC not found, skipping" + continue + fi + + if [ "$svc" = "aio-3d-main.service" ]; then + EXEC="$REPO_DIR/run_main.sh" + else + EXEC="$REPO_DIR/run_huey.sh" + fi + + TMPFILE="/tmp/$svc" + awk -v wd="$REPO_DIR" -v exec="$EXEC" ' + { if ($0 ~ /^WorkingDirectory=/) { print "WorkingDirectory=" wd; next } \ + if ($0 ~ /^ExecStart=/) { print "ExecStart=" exec; next } \ + print $0 }' "$SRC" > "$TMPFILE" + + echo "Installing $svc -> /etc/systemd/system/$svc" + sudo cp "$TMPFILE" "/etc/systemd/system/$svc" +done + +echo "Reloading systemd daemon and enabling services" +sudo systemctl daemon-reload +sudo systemctl enable aio-3d-main.service aio-3d-huey.service || true +sudo systemctl restart aio-3d-huey.service || true +sudo systemctl restart aio-3d-main.service || true echo "Installation completed successfully" diff --git a/requirements.txt b/requirements.txt index 4ad1ba5..73a8127 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,23 @@ Flask>=3.0.0 -Flask-SQLAlchemy>=3.1.0 -Flask-Login>=0.6.0 -Flask-Babel>=4.0.0 -huey>=2.5.0 -Werkzeug>=3.0.0 -trimesh>=4.0.0 -requests>=2.31.0 -httpx>=0.25.0 -gunicorn>=26.0.0 \ No newline at end of file +Flask-SQLAlchemy +Flask-Login +Flask-Babel +huey +Werkzeug +trimesh +requests +httpx +gunicorn>=26.0.0 + +# Numeric & STL handling +numpy>=1.25.0 +numpy-stl>=3.0.0 + +# WebSocket support used by printer routes +flask-sock>=0.6.0 +websockets>=11.0.0 + +# Optional / heavy dependencies for STL simplification (may require system libraries) +# pymeshlab +# open3d +# pyfqmr \ No newline at end of file