intitial
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
configs/*
|
||||||
2
README.md
Normal file
2
README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
## 3D slicer Api
|
||||||
|
This is a simple api that slices 3d files using prusa-slicer, fff and sla modes are supported.
|
||||||
42
cmd/actions.go
Normal file
42
cmd/actions.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
func actions(mux *http.ServeMux) {
|
||||||
|
|
||||||
|
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
if r.Method != http.MethodGet {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte("OK"))
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.HandleFunc("/analyze-fff", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte("OK"))
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.HandleFunc("/analyze-sla", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte("OK"))
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
28
cmd/main.go
Normal file
28
cmd/main.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/net/http2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Your code here
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
|
svr := &http.Server{
|
||||||
|
Addr: fmt.Sprintf("%s:%s", os.Getenv("HOST"), os.Getenv("PORT")),
|
||||||
|
Handler: mux,
|
||||||
|
}
|
||||||
|
http2.ConfigureServer(svr, nil)
|
||||||
|
|
||||||
|
actions(mux) // Register actions with the multiplexer
|
||||||
|
|
||||||
|
fmt.Printf("Starting server on %s:%s\n", os.Getenv("HOST"), os.Getenv("PORT"))
|
||||||
|
err := svr.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
39
docker/Dockerfile
Normal file
39
docker/Dockerfile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
FROM ubuntu:plucky
|
||||||
|
|
||||||
|
RUN echo "deb https://ppa.launchpadcontent.net/longsleep/golang-backports/ubuntu ubuntu-plucky main" | tee /etc/apt/sources.list.d/docker.list
|
||||||
|
RUN apt update
|
||||||
|
|
||||||
|
ENV GO_VERSION=1.24
|
||||||
|
|
||||||
|
RUN apt install -y golang-${GO_VERSION}
|
||||||
|
RUN ln -s "/usr/lib/go-${GO_VERSION}/bin/go" /usr/local/bin/
|
||||||
|
|
||||||
|
RUN apt-get clean && apt-get update && apt-get install -y locales wget
|
||||||
|
RUN locale-gen en_US.UTF-8
|
||||||
|
RUN update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
|
||||||
|
ENV LANG=en_US.UTF-8
|
||||||
|
ENV LC_CTYPE="en_US.UTF-8"
|
||||||
|
ENV LC_NUMERIC="en_US.UTF-8"
|
||||||
|
ENV LC_TIME="en_US.UTF-8"
|
||||||
|
ENV LC_COLLATE="en_US.UTF-8"
|
||||||
|
ENV LC_MONETARY="en_US.UTF-8"
|
||||||
|
ENV LC_MESSAGES="en_US.UTF-8"
|
||||||
|
ENV LC_PAPER="en_US.UTF-8"
|
||||||
|
ENV LC_NAME="en_US.UTF-8"
|
||||||
|
ENV LC_ADDRESS="en_US.UTF-8"
|
||||||
|
ENV LC_TELEPHONE="en_US.UTF-8"
|
||||||
|
ENV LC_MEASUREMENT="en_US.UTF-8"
|
||||||
|
ENV LC_IDENTIFICATION="en_US.UTF-8"
|
||||||
|
ENV LC_ALL=
|
||||||
|
|
||||||
|
RUN apt install -y prusa-slicer
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
COPY ../ .
|
||||||
|
|
||||||
|
RUN go build -o /bin/slic3r-api ./cmd
|
||||||
|
|
||||||
|
RUN rm -rf /build/*
|
||||||
|
|
||||||
|
CMD [ "/bin/slic3r-api" ]
|
||||||
15
docker/docker-compose.yml
Normal file
15
docker/docker-compose.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
services:
|
||||||
|
slic3r-api:
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: docker/Dockerfile
|
||||||
|
command: /bin/bash -c "cd /src && go run ./cmd"
|
||||||
|
volumes:
|
||||||
|
- ../:/src
|
||||||
|
- ../configs:/configs
|
||||||
|
environment:
|
||||||
|
- PORT=3030
|
||||||
|
- HOST=0.0.0.0
|
||||||
|
- CONFIGS=/configs/
|
||||||
|
ports:
|
||||||
|
- 3030:3030
|
||||||
8
go.mod
Normal file
8
go.mod
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module github.com/sotigr/slic3r-api
|
||||||
|
|
||||||
|
go 1.24.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
golang.org/x/net v0.41.0 // indirect
|
||||||
|
golang.org/x/text v0.26.0 // indirect
|
||||||
|
)
|
||||||
4
go.sum
Normal file
4
go.sum
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||||
|
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||||
|
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||||
|
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||||
104
internal/cli/cli.go
Normal file
104
internal/cli/cli.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var re = regexp.MustCompile(`\w|\%|^(\+|,|\.|:|\/|\\|=|_|-|[a-z]|[A-Z]|[0-9]|\s)+$`)
|
||||||
|
|
||||||
|
func validateCliArgument(arg string) bool {
|
||||||
|
return re.Match([]byte(arg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateCliArguments(args []string) bool {
|
||||||
|
for _, p := range args {
|
||||||
|
if !validateCliArgument(p) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func execNoCheck(ctx context.Context, command string, args []string) (string, string, error) {
|
||||||
|
cmd := exec.CommandContext(ctx, command, args...)
|
||||||
|
cmdStr := cmd.String()
|
||||||
|
|
||||||
|
pStdout, err := cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
return "", cmdStr, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pStderr, err := cmd.StderrPipe()
|
||||||
|
if err != nil {
|
||||||
|
return "", cmdStr, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
return "", cmdStr, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout, _ := io.ReadAll(pStdout)
|
||||||
|
stderr, _ := io.ReadAll(pStderr)
|
||||||
|
|
||||||
|
err = cmd.Wait()
|
||||||
|
if err != nil {
|
||||||
|
return "", cmdStr, errors.New(err.Error() + " | " + string(stderr) + " | " + string(stdout))
|
||||||
|
}
|
||||||
|
return string(stdout), cmdStr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pipe struct {
|
||||||
|
Command string
|
||||||
|
Args []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipe) IsSanatory() bool {
|
||||||
|
return validateCliArguments(p.Args) && validateCliArgument(p.Command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipe) Execute(ctx context.Context) (string, string, error) {
|
||||||
|
if !p.IsSanatory() {
|
||||||
|
return "", "", errors.New("failed to execute cli command: " + p.Command + " " + strings.Join(p.Args, " ") + " some arguments are not allowed")
|
||||||
|
} else {
|
||||||
|
return execNoCheck(ctx, p.Command, p.Args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExecuteCLIPipeLine(ctx context.Context, pipes []Pipe) (string, string, error) {
|
||||||
|
|
||||||
|
pipeLen := len(pipes)
|
||||||
|
if pipeLen == 0 {
|
||||||
|
return "", "", errors.New("failed to execute cli command: no pipes provided")
|
||||||
|
}
|
||||||
|
argLen := 0
|
||||||
|
for _, p := range pipes {
|
||||||
|
if !p.IsSanatory() {
|
||||||
|
return "", "", errors.New("failed to execute cli command: " + p.Command + " " + strings.Join(p.Args, " ") + " some arguments are not allowed")
|
||||||
|
}
|
||||||
|
argLen += len(p.Args) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
command := "/bin/sh"
|
||||||
|
var args []string = []string{}
|
||||||
|
args = append(args, "-c")
|
||||||
|
pipeLen -= 1
|
||||||
|
|
||||||
|
cmdArg := ""
|
||||||
|
|
||||||
|
for i, p := range pipes {
|
||||||
|
cmdArg += p.Command + " " + strings.Join(p.Args, " ")
|
||||||
|
if i != pipeLen {
|
||||||
|
cmdArg += " | "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, cmdArg)
|
||||||
|
|
||||||
|
return execNoCheck(ctx, command, args)
|
||||||
|
}
|
||||||
16
notes.txt
Normal file
16
notes.txt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
look at:
|
||||||
|
* https://github.com/prusa3d/PrusaSlicer/wiki/Command-Line-Interface
|
||||||
|
* https://manual.slic3r.org/advanced/command-line
|
||||||
|
|
||||||
|
slice:
|
||||||
|
* prusa-slicer --load config.ini --export-gcode --info part.stl
|
||||||
|
* prusa-slicer --load config.ini --info --export-sla part.stl
|
||||||
|
|
||||||
|
thumbnail:
|
||||||
|
* f3d 'model.stl' --resolution=512,512 -a --anti-aliasing-mode=taa --filename=false --metadata=false --color=#999 -t --grid=false --axis=false --no-background --output='output.png'
|
||||||
|
|
||||||
|
post-process:
|
||||||
|
* this can preview print times for sla: https://github.com/oelmekki/sl1toctb?tab=readme-ov-file
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user