diff --git a/README.md b/README.md index 376f608..a1c0500 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ A command-line tool for send the gcode file to Snapmaker Printers via WiFi conne ## Features: - Support Snapmaker 2 A150/250/350, J1, Artisan - Auto discover machines (UDP broadcast) -- Simulated a OctoPrint server, so that it can be in any slicing software such as Cura/PrusaSlicer/SuperSlicer/ideaMaker send gcode to the printer +- Simulated a OctoPrint server, so that it can be in any slicing software such as Cura/PrusaSlicer/SuperSlicer/OrcaSlicer send gcode to the printer +- Smart pre-heat for switch tools, shutoff nozzles that are no longer in use, and other optimization features for multi-extruders. - No need to click Yes button on the touch screen every time for authorization connect - Support for multiple platforms including win/macOS/Linux/RaspberryPi diff --git a/README.zh-cn.md b/README.zh-cn.md index a3cfeab..1c375f5 100644 --- a/README.zh-cn.md +++ b/README.zh-cn.md @@ -7,7 +7,8 @@ Luban 和 Cura with SnapmakerPlugin 对于新手很友好,但是我的大部 ## 功能 - 支持 Snapmaker 2 A/J1/Artisan 全系列打印机 - 自动发现局域网内所有的 Snapmaker 打印机(和 Luban 相同的协议,使用 UDP 广播) -- 模拟 OctoPrint Server,这样就可以在各种切片软件,比如 Cura/PrusaSlicer/SuperSlicer/ideaMaker 中向 Snapmaker 打印机发送文件 +- 模拟 OctoPrint Server,这样就可以在各种切片软件,比如 Cura/PrusaSlicer/SuperSlicer/OrcaSlicer 中向 Snapmaker 打印机发送文件 +- 为多挤出机提供智能预热、关闭不再使用的喷头等优化功能 - Snapmaker 2 A-Series 第一次连接时需要授权,之后可以直接一步上传 - 支持 macOS/Windows/Linux/RaspberryPi 多个平台 diff --git a/connector.go b/connector.go index c0add42..68e3602 100644 --- a/connector.go +++ b/connector.go @@ -4,6 +4,7 @@ import ( "errors" "io" "net" + "runtime" "time" ) @@ -32,6 +33,7 @@ func (p *Payload) ReadableSize() string { } func (p *Payload) GetContent(fix bool) (cont []byte, err error) { + defer runtime.GC() if fix { cont, err = postProcess(p.File) p.Size = int64(len(cont)) diff --git a/go.mod b/go.mod index bceef0a..a85d89b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/gosuri/uilive v0.0.4 github.com/imroc/req/v3 v3.11.0 - github.com/macdylan/SMFix/fix v0.0.0-20230711071352-9db26cbcb3a3 + github.com/macdylan/SMFix/fix v0.0.0-20230731072358-03b385d0df5a github.com/manifoldco/promptui v0.9.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 783132a..481a013 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/macdylan/SMFix/fix v0.0.0-20230711071352-9db26cbcb3a3 h1:yHR5HciyfOoZyt5S3m3gBLYv+Q6L4iwXgGaJXRd+N04= -github.com/macdylan/SMFix/fix v0.0.0-20230711071352-9db26cbcb3a3/go.mod h1:dnB1MevhW7tICqBpQ2aHpVClwLdmSBUNmfV7jpRmiWw= +github.com/macdylan/SMFix/fix v0.0.0-20230731072358-03b385d0df5a h1:yy0uQ23OaihOPf88+TWqwFPJTdCsPQTfkQBRtYqug44= +github.com/macdylan/SMFix/fix v0.0.0-20230731072358-03b385d0df5a/go.mod h1:dnB1MevhW7tICqBpQ2aHpVClwLdmSBUNmfV7jpRmiWw= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= diff --git a/octoprint.go b/octoprint.go index d71d54d..fd52420 100644 --- a/octoprint.go +++ b/octoprint.go @@ -4,6 +4,7 @@ import ( "log" "net" "net/http" + "strings" "time" ) @@ -11,6 +12,12 @@ const ( maxMemory = 64 << 20 // 64MB ) +var ( + noTrim = false + noShutoff = false + noPreheat = false +) + func LoggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() @@ -51,6 +58,27 @@ func startOctoPrintServer(listenAddr string, printer *Printer) error { } defer file.Close() + // read X-Api-Key header + apiKey := r.Header.Get("X-Api-Key") + if len(apiKey) > 5 { + noTrim = strings.Contains(apiKey, "notrim") + noPreheat = strings.Contains(apiKey, "nopreheat") + noShutoff = strings.Contains(apiKey, "noshutoff") + msg := make([]string, 0, 3) + if noTrim { + msg = append(msg, "-notrim") + } + if noPreheat { + msg = append(msg, "-nopreheat") + } + if noShutoff { + msg = append(msg, "-noshutoff") + } + if len(msg) > 0 { + log.Printf("SMFix with args: %s", strings.Join(msg, " ")) + } + } + // Send the stream to the printer payload := NewPayload(file, fd.Filename, fd.Size) if err := Connector.Upload(printer, payload); err != nil { diff --git a/utils.go b/utils.go index 5c9347c..a74cd56 100644 --- a/utils.go +++ b/utils.go @@ -1,11 +1,13 @@ package main import ( + "bufio" "bytes" "fmt" "io" "os" "regexp" + "strings" "github.com/macdylan/SMFix/fix" ) @@ -43,20 +45,32 @@ func postProcessFile(file_path string) (out []byte, err error) { func postProcess(r io.Reader) (out []byte, err error) { header, errfix := fix.ExtractHeader(r) - out, err = io.ReadAll(r) - if err != nil { - return + if h, ok := r.(io.ReadSeeker); ok { + h.Seek(0, 0) } - /* - if err == fix.ErrIsFixed || err == fix.ErrInvalidGcode { - return out, nil - } + gcodes := make([]string, 0, fix.Params.TotalLines+len(header)+128) + sc := bufio.NewScanner(r) + for sc.Scan() { + gcodes = append(gcodes, sc.Text()) + } + if err = sc.Err(); err != nil { + return nil, err + } - if err != nil { - return out, err + if errfix == nil { + if !noTrim { + gcodes = fix.GcodeTrimLines(gcodes) } - */ + if !noShutoff { + gcodes = fix.GcodeFixShutoff(gcodes) + } + if !noPreheat { + gcodes = fix.GcodeFixPreheat(gcodes) + } + } + + out = []byte(strings.Join(gcodes, "\n")) if len(header) > 25 { return append(bytes.Join(header, []byte("\n")), out...), nil