暂存-安装脚本
This commit is contained in:
@@ -5,8 +5,9 @@ After=network.target
|
|||||||
[Service]
|
[Service]
|
||||||
User=1000
|
User=1000
|
||||||
|
|
||||||
WorkingDirectory=/home/lhye200/AIO_3D_Print_Exp/
|
# Placeholder path; installer will replace with actual repository path
|
||||||
ExecStart=/home/lhye200/AIO_3D_Print_Exp/run_huey.sh
|
WorkingDirectory=${REPO_DIR}/
|
||||||
|
ExecStart=${REPO_DIR}/run_huey.sh
|
||||||
|
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ Wants=aio-3d-huey.service network.target
|
|||||||
[Service]
|
[Service]
|
||||||
User=1000
|
User=1000
|
||||||
|
|
||||||
WorkingDirectory=/home/lhye200/AIO_3D_Print_Exp/
|
# Placeholder path; installer will replace with actual repository path
|
||||||
ExecStart=/home/lhye200/AIO_3D_Print_Exp/run_main.sh
|
WorkingDirectory=${REPO_DIR}/
|
||||||
|
ExecStart=${REPO_DIR}/run_main.sh
|
||||||
|
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|||||||
@@ -2,8 +2,12 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
import configparser
|
import configparser
|
||||||
import uuid
|
import uuid
|
||||||
|
import shutil
|
||||||
from app.models import SystemConfig
|
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:
|
class PrusaSlicerEngine:
|
||||||
def __init__(self, print_config_folder=None):
|
def __init__(self, print_config_folder=None):
|
||||||
self.name = "prusa_slicer"
|
self.name = "prusa_slicer"
|
||||||
@@ -13,9 +17,18 @@ class PrusaSlicerEngine:
|
|||||||
|
|
||||||
def _check_available(self):
|
def _check_available(self):
|
||||||
try:
|
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
|
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
|
return False
|
||||||
|
|
||||||
def add_ini_keys(self, config_path, target_section, all_configs):
|
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.
|
Slices via prusa-slicer CLI mapping standard kwargs to PRUSA parameters where possible.
|
||||||
"""
|
"""
|
||||||
try:
|
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
|
# Base command
|
||||||
command = [
|
command = [prusa_bin, '-g', stl_filepath, '--output', gcode_filepath]
|
||||||
"/home/lhye200/AIO_3D_Print_Exp/prusaslicer/prusa-slicer",
|
|
||||||
"-g", stl_filepath,
|
|
||||||
"--output", gcode_filepath
|
|
||||||
]
|
|
||||||
|
|
||||||
# Map quality, infill, supports to PrusaSlicer CLI arguments.
|
# Map quality, infill, supports to PrusaSlicer CLI arguments.
|
||||||
# Example defaults, normally these would load from an .ini or be dynamically matched.
|
# Example defaults, normally these would load from an .ini or be dynamically matched.
|
||||||
|
|||||||
131
install.sh
131
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"
|
echo "Installing AIO_3D_Print_Web_Platform into: $REPO_DIR"
|
||||||
# rm -rf /opt/AIO_3D_Print_Exp
|
echo "Using python: $PYTHON_BIN"
|
||||||
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 "Copy installation files"
|
echo "Stopping services if running (may require sudo)"
|
||||||
# mkdir -p /opt/AIO_3D_Print_Exp
|
sudo systemctl stop aio-3d-main.service 2>/dev/null || true
|
||||||
# cp -r ./. /opt/AIO_3D_Print_Exp/
|
sudo systemctl stop aio-3d-huey.service 2>/dev/null || true
|
||||||
|
|
||||||
echo "Set execute permissions"
|
echo "Creating virtual environment at $VENV_DIR (if missing)"
|
||||||
# chmod +x /opt/AIO_3D_Print_Exp/run_main.sh
|
if [ ! -d "$VENV_DIR" ]; then
|
||||||
# chmod +x /opt/AIO_3D_Print_Exp/run_huey.sh
|
$PYTHON_BIN -m venv "$VENV_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Copy service files"
|
echo "Activating virtualenv and installing Python requirements"
|
||||||
# cp /opt/AIO_3D_Print_Exp/aio-3d-main.service /etc/systemd/system/
|
# shellcheck disable=SC1091
|
||||||
# cp /opt/AIO_3D_Print_Exp/aio-3d-huey.service /etc/systemd/system/
|
source "$VENV_DIR/bin/activate"
|
||||||
cp /home/lhye200/AIO_3D_Print_Exp/aio-3d-main.service /etc/systemd/system/
|
# Detect http(s) proxy (respect both lowercase and uppercase env vars)
|
||||||
cp /home/lhye200/AIO_3D_Print_Exp/aio-3d-huey.service /etc/systemd/system/
|
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"
|
pip_with_proxy() {
|
||||||
systemctl daemon-reload
|
# Usage: pip_with_proxy install [args...]
|
||||||
systemctl enable aio-3d-main.service
|
if [ -n "$PROXY" ] && [ "$1" = "install" ]; then
|
||||||
systemctl enable aio-3d-huey.service
|
shift
|
||||||
systemctl start aio-3d-huey.service
|
pip install --proxy "$PROXY" "$@"
|
||||||
systemctl start aio-3d-main.service
|
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"
|
echo "Installation completed successfully"
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,23 @@
|
|||||||
Flask>=3.0.0
|
Flask>=3.0.0
|
||||||
Flask-SQLAlchemy>=3.1.0
|
Flask-SQLAlchemy
|
||||||
Flask-Login>=0.6.0
|
Flask-Login
|
||||||
Flask-Babel>=4.0.0
|
Flask-Babel
|
||||||
huey>=2.5.0
|
huey
|
||||||
Werkzeug>=3.0.0
|
Werkzeug
|
||||||
trimesh>=4.0.0
|
trimesh
|
||||||
requests>=2.31.0
|
requests
|
||||||
httpx>=0.25.0
|
httpx
|
||||||
gunicorn>=26.0.0
|
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
|
||||||
Reference in New Issue
Block a user